Update to v103r02 release.

byuu says:

Changelog:

  - fc/apu: improved phase duty cycle emulation (mode 3 is 25% phase
    inverted; counter decrements)
  - md/apu: power/reset do not cancel 68K bus requests
  - md/apu: 68K is not granted bus access on Z80 power/reset
  - md/controller: replaced System::Peripherals with ControllerPort
    concept
  - md/controller: CTRL port is now read-write, maintains value across
    controller changes (and soon, soft resets)
  - md/psg: PSG sampling rate unintentionally modified¹
  - processor/spc700: improve cycle timing of (indirect),y instructions
    [Overload]
  - processor/spc700: idle() cycles actually read from the program
    counter; much like the 6502 [Overload]
      - some of the idle() cycles should read from other addresses; this
        still needs to be supported
  - processor/spc700: various cleanups to instruction function naming
  - processor/z80: prefix state (HL→IX,IY override) can now be
    serialized
  - icarus: fix install rule for certain platforms (it wasn't buggy on
    FreeBSD, but was on Linux?)

¹: the clock speed of the PSG is oscillator/15. But I was setting the
sampling rate to oscillator/15/16, which was around 223KHz. I am not
sure whether the PSG should be outputting at 3MHz or 223KHz. Amazingly
... I don't really hear a difference either way `o_O` I didn't actually
mean to make this change; I just noticed it after comparing the diff
between r01 and r02. If this turns out to be wrong, set

    stream = Emulator::audio.createStream(1, frequency() / 16.0);

in md/psg.cpp to revert this change.
This commit is contained in:
Tim Allen 2017-06-27 11:18:28 +10:00
parent ecc7e899e0
commit 3517d5c4a4
27 changed files with 477 additions and 461 deletions

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "103.01";
static const string Version = "103.02";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -8,13 +8,18 @@ auto APU::Pulse::clock() -> uint8 {
if(!sweep.checkPeriod()) return 0;
if(lengthCounter == 0) return 0;
static const uint dutyTable[] = {1, 2, 4, 6};
uint8 result = (dutyCounter < dutyTable[duty]) ? envelope.volume() : 0;
static const uint dutyTable[4][8] = {
{0, 1, 0, 0, 0, 0, 0, 0}, //12.5%
{0, 1, 1, 0, 0, 0, 0, 0}, //25.0%
{0, 1, 1, 1, 1, 0, 0, 0}, //50.0%
{1, 0, 0, 1, 1, 1, 1, 1}, //25.0% (inverted)
};
uint8 result = dutyTable[duty][dutyCounter] ? envelope.volume() : 0;
if(sweep.pulsePeriod < 0x008) result = 0;
if(--periodCounter == 0) {
periodCounter = (sweep.pulsePeriod + 1) * 2;
dutyCounter++;
dutyCounter--;
}
return result;

View File

@ -54,14 +54,16 @@ auto APU::enable(bool value) -> void {
auto APU::power() -> void {
Z80::bus = &busAPU;
Z80::power();
create(APU::Enter, system.colorburst());
memory::fill(&state, sizeof(State));
bus->grant(false);
create(APU::Enter, system.frequency() / 15.0);
state = {};
}
auto APU::reset() -> void {
create(APU::Enter, system.colorburst());
memory::fill(&r, sizeof(Registers));
memory::fill(&state, sizeof(State));
Z80::power();
bus->grant(false);
create(APU::Enter, system.frequency() / 15.0);
state = {};
}
}

View File

@ -73,13 +73,13 @@ auto BusCPU::readIO(uint24 addr) -> uint16 {
| 0 << 0 //0 = Model 1; 1 = Model 2+
);
case 0xa10002: return peripherals.controllerPort1->readData();
case 0xa10004: return peripherals.controllerPort2->readData();
case 0xa10006: return peripherals.extensionPort->readData();
case 0xa10002: return controllerPort1.readData();
case 0xa10004: return controllerPort2.readData();
case 0xa10006: return extensionPort.readData();
case 0xa10008: return peripherals.controllerPort1->readControl();
case 0xa1000a: return peripherals.controllerPort2->readControl();
case 0xa1000c: return peripherals.extensionPort->readControl();
case 0xa10008: return controllerPort1.readControl();
case 0xa1000a: return controllerPort2.readControl();
case 0xa1000c: return extensionPort.readControl();
case 0xa11100: return !busAPU.granted();
}
@ -89,13 +89,13 @@ auto BusCPU::readIO(uint24 addr) -> uint16 {
auto BusCPU::writeIO(uint24 addr, uint16 data) -> void {
switch(addr & ~1) {
case 0xa10002: return peripherals.controllerPort1->writeData(data);
case 0xa10004: return peripherals.controllerPort2->writeData(data);
case 0xa10006: return peripherals.extensionPort->writeData(data);
case 0xa10002: return controllerPort1.writeData(data);
case 0xa10004: return controllerPort2.writeData(data);
case 0xa10006: return extensionPort.writeData(data);
case 0xa10008: return peripherals.controllerPort1->writeControl(data);
case 0xa1000a: return peripherals.controllerPort2->writeControl(data);
case 0xa1000c: return peripherals.extensionPort->writeControl(data);
case 0xa10008: return controllerPort1.writeControl(data);
case 0xa1000a: return controllerPort2.writeControl(data);
case 0xa1000c: return extensionPort.writeControl(data);
case 0xa11100: return busAPU.request(data.bit(0));
case 0xa11200: return apu.enable(data.bit(0));

View File

@ -2,6 +2,9 @@
namespace MegaDrive {
ControllerPort controllerPort1;
ControllerPort controllerPort2;
ControllerPort extensionPort;
#include "gamepad/gamepad.cpp"
Controller::Controller(uint port) : port(port) {
@ -15,9 +18,9 @@ Controller::~Controller() {
auto Controller::Enter() -> void {
while(true) {
scheduler.synchronize();
if(peripherals.controllerPort1->active()) peripherals.controllerPort1->main();
if(peripherals.controllerPort2->active()) peripherals.controllerPort2->main();
if(peripherals.extensionPort->active()) peripherals.extensionPort->main();
if(controllerPort1.controller->active()) controllerPort1.controller->main();
if(controllerPort2.controller->active()) controllerPort2.controller->main();
if(extensionPort.controller->active()) extensionPort.controller->main();
}
}
@ -26,4 +29,51 @@ auto Controller::main() -> void {
synchronize(cpu);
}
//
auto ControllerPort::connect(uint device) -> void {
if(!system.loaded()) return;
delete controller;
switch(device) { default:
case ID::Device::None: controller = new Controller(port); break;
case ID::Device::Gamepad: controller = new Gamepad(port); break;
}
cpu.peripherals.reset();
cpu.peripherals.append(controllerPort1.controller);
cpu.peripherals.append(controllerPort2.controller);
cpu.peripherals.append(extensionPort.controller);
}
auto ControllerPort::readData() -> uint8 {
return controller->readData();
}
auto ControllerPort::writeData(uint8 data) -> void {
return controller->writeData(data);
}
auto ControllerPort::readControl() -> uint8 {
return control;
}
auto ControllerPort::writeControl(uint8 data) -> void {
control = data;
}
auto ControllerPort::power(uint port) -> void {
this->port = port;
control = 0x00;
}
auto ControllerPort::unload() -> void {
delete controller;
controller = nullptr;
}
auto ControllerPort::serialize(serializer& s) -> void {
s.integer(control);
}
}

View File

@ -8,10 +8,29 @@ struct Controller : Thread {
virtual auto readData() -> uint8 { return 0xff; }
virtual auto writeData(uint8 data) -> void {}
virtual auto readControl() -> uint8 { return 0x00; }
virtual auto writeControl(uint8 data) -> void {}
const uint port;
};
struct ControllerPort {
auto connect(uint device) -> void;
auto readData() -> uint8;
auto writeData(uint8 data) -> void;
auto readControl() -> uint8;
auto writeControl(uint8 data) -> void;
auto power(uint port) -> void;
auto unload() -> void;
auto serialize(serializer&) -> void;
uint port;
uint8 control;
Controller* controller = nullptr;
};
extern ControllerPort controllerPort1;
extern ControllerPort controllerPort2;
extern ControllerPort extensionPort;
#include "gamepad/gamepad.hpp"

View File

@ -68,9 +68,9 @@ auto CPU::lower(Interrupt interrupt) -> void {
auto CPU::power() -> void {
M68K::bus = &busCPU;
M68K::power();
create(CPU::Enter, system.colorburst() * 15.0 / 7.0);
create(CPU::Enter, system.frequency() / 7.0);
memory::fill(&state, sizeof(State));
state = {};
state.interruptPending.bit((uint)Interrupt::Reset) = 1;
}

View File

@ -100,7 +100,9 @@ auto Interface::unload() -> void {
}
auto Interface::connect(uint port, uint device) -> void {
peripherals.connect(port, device);
if(port == ID::Port::Controller1) controllerPort1.connect(settings.controllerPort1 = device);
if(port == ID::Port::Controller2) controllerPort2.connect(settings.controllerPort2 = device);
if(port == ID::Port::Extension) extensionPort.connect(settings.extensionPort = device);
}
auto Interface::power() -> void {

View File

@ -35,7 +35,7 @@ auto PSG::step(uint clocks) -> void {
}
auto PSG::power() -> void {
create(PSG::Enter, system.colorburst() / 16.0);
create(PSG::Enter, system.frequency() / 15.0);
stream = Emulator::audio.createStream(1, frequency());
stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0);
stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::LowPass, 2840.0);

View File

@ -1,55 +0,0 @@
Peripherals peripherals;
auto Peripherals::unload() -> void {
delete controllerPort1;
delete controllerPort2;
delete extensionPort;
controllerPort1 = nullptr;
controllerPort2 = nullptr;
extensionPort = nullptr;
}
auto Peripherals::reset() -> void {
connect(ID::Port::Controller1, settings.controllerPort1);
connect(ID::Port::Controller2, settings.controllerPort2);
connect(ID::Port::Extension, settings.extensionPort);
}
auto Peripherals::connect(uint port, uint device) -> void {
if(port == ID::Port::Controller1) {
settings.controllerPort1 = device;
if(!system.loaded()) return;
delete controllerPort1;
switch(device) { default:
case ID::Device::None: controllerPort1 = new Controller(0); break;
case ID::Device::Gamepad: controllerPort1 = new Gamepad(0); break;
}
}
if(port == ID::Port::Controller2) {
settings.controllerPort2 = device;
if(!system.loaded()) return;
delete controllerPort2;
switch(device) { default:
case ID::Device::None: controllerPort2 = new Controller(1); break;
case ID::Device::Gamepad: controllerPort2 = new Gamepad(1); break;
}
}
if(port == ID::Port::Extension) {
settings.extensionPort = device;
if(!system.loaded()) return;
delete extensionPort;
switch(device) { default:
case ID::Device::None: extensionPort = new Controller(2); break;
}
}
cpu.peripherals.reset();
cpu.peripherals.append(controllerPort1);
cpu.peripherals.append(controllerPort2);
cpu.peripherals.append(extensionPort);
}

View File

@ -63,6 +63,9 @@ auto System::serializeAll(serializer& s) -> void {
vdp.serialize(s);
psg.serialize(s);
ym2612.serialize(s);
controllerPort1.serialize(s);
controllerPort2.serialize(s);
extensionPort.serialize(s);
}
auto System::serialize(serializer& s) -> void {

View File

@ -5,7 +5,6 @@ namespace MegaDrive {
System system;
Scheduler scheduler;
Cheat cheat;
#include "peripherals.cpp"
#include "serialization.cpp"
auto System::run() -> void {
@ -32,15 +31,15 @@ auto System::load(Emulator::Interface* interface, maybe<Region> region) -> bool
if(cartridge.region() == "NTSC-J") {
information.region = Region::NTSCJ;
information.colorburst = Emulator::Constants::Colorburst::NTSC;
information.frequency = Emulator::Constants::Colorburst::NTSC * 15.0;
}
if(cartridge.region() == "NTSC-U") {
information.region = Region::NTSCU;
information.colorburst = Emulator::Constants::Colorburst::NTSC;
information.frequency = Emulator::Constants::Colorburst::NTSC * 15.0;
}
if(cartridge.region() == "PAL") {
information.region = Region::PAL;
information.colorburst = Emulator::Constants::Colorburst::PAL * 4.0 / 5.0;
information.frequency = Emulator::Constants::Colorburst::PAL * 12.0;
}
serializeInit();
@ -53,7 +52,9 @@ auto System::save() -> void {
}
auto System::unload() -> void {
peripherals.unload();
controllerPort1.unload();
controllerPort2.unload();
extensionPort.unload();
cartridge.unload();
}
@ -74,7 +75,13 @@ auto System::power() -> void {
ym2612.power();
scheduler.primary(cpu);
peripherals.reset();
controllerPort1.power(ID::Port::Controller1);
controllerPort2.power(ID::Port::Controller2);
extensionPort.power(ID::Port::Extension);
controllerPort1.connect(settings.controllerPort1);
controllerPort2.connect(settings.controllerPort2);
extensionPort.connect(settings.extensionPort);
}
}

View File

@ -7,7 +7,7 @@ struct System {
auto loaded() const -> bool { return information.loaded; }
auto region() const -> Region { return information.region; }
auto colorburst() const -> double { return information.colorburst; }
auto frequency() const -> double { return information.frequency; }
auto run() -> void;
auto runToSave() -> void;
@ -31,23 +31,12 @@ private:
string manifest;
bool loaded = false;
Region region = Region::NTSCJ;
double colorburst = Emulator::Constants::Colorburst::NTSC;
double frequency = Emulator::Constants::Colorburst::NTSC * 15.0;
uint serializeSize = 0;
} information;
};
struct Peripherals {
auto unload() -> void;
auto reset() -> void;
auto connect(uint port, uint device) -> void;
Controller* controllerPort1 = nullptr;
Controller* controllerPort2 = nullptr;
Controller* extensionPort = nullptr;
};
extern System system;
extern Peripherals peripherals;
auto Region::NTSCJ() -> bool { return system.region() == System::Region::NTSCJ; }
auto Region::NTSCU() -> bool { return system.region() == System::Region::NTSCU; }

View File

@ -68,7 +68,7 @@ auto VDP::refresh() -> void {
}
auto VDP::power() -> void {
create(VDP::Enter, system.colorburst() * 15.0 / 2.0);
create(VDP::Enter, system.frequency() / 2.0);
memory::fill(&io, sizeof(IO));
memory::fill(&latch, sizeof(Latch));

View File

@ -155,7 +155,7 @@ auto YM2612::step(uint clocks) -> void {
}
auto YM2612::power() -> void {
create(YM2612::Enter, system.colorburst() * 15.0 / 7.0);
create(YM2612::Enter, system.frequency() / 7.0);
stream = Emulator::audio.createStream(2, frequency() / 144.0);
stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::HighPass, 20.0);
stream->addFilter(Emulator::Filter::Order::First, Emulator::Filter::Type::LowPass, 2840.0);

View File

@ -7,14 +7,14 @@ auto SPC700::instruction() -> void {
op(0x01, JST, 0)
op(0x02, SET, 0)
op(0x03, BBS, 0)
op(0x04, DirectPageRead, fp(OR), A)
op(0x04, DirectRead, fp(OR), A)
op(0x05, AbsoluteRead, fp(OR), A)
op(0x06, IndirectXRead, fp(OR))
op(0x07, IndirectPageXRead, fp(OR))
op(0x07, IndexedIndirectRead, fp(OR), X)
op(0x08, ImmediateRead, fp(OR), A)
op(0x09, DirectPageWriteDirectPage, fp(OR))
op(0x0a, AbsoluteModifyBit, 0)
op(0x0b, DirectPageModify, fp(ASL))
op(0x09, DirectWriteDirect, fp(OR))
op(0x0a, AbsoluteBitModify, 0)
op(0x0b, DirectModify, fp(ASL))
op(0x0c, AbsoluteModify, fp(ASL))
op(0x0d, Push, P)
op(0x0e, TSBAbsolute)
@ -23,78 +23,78 @@ auto SPC700::instruction() -> void {
op(0x11, JST, 1)
op(0x12, CLR, 0)
op(0x13, BBC, 0)
op(0x14, DirectPageIndexedRead, fp(OR), A, X)
op(0x14, DirectIndexedRead, fp(OR), A, X)
op(0x15, AbsoluteIndexedRead, fp(OR), X)
op(0x16, AbsoluteIndexedRead, fp(OR), Y)
op(0x17, IndirectPageYRead, fp(OR))
op(0x18, DirectPageWriteImmediate, fp(OR))
op(0x17, IndirectIndexedRead, fp(OR), Y)
op(0x18, DirectWriteImmediate, fp(OR))
op(0x19, IndirectXWriteIndirectY, fp(OR))
op(0x1a, DirectPageModifyWord, -1)
op(0x1b, DirectPageXModify, fp(ASL))
op(0x1a, DirectModifyWord, -1)
op(0x1b, DirectIndexedModify, fp(ASL), X)
op(0x1c, ImpliedModify, fp(ASL), A)
op(0x1d, ImpliedModify, fp(DEC), X)
op(0x1e, AbsoluteRead, fp(CMP), X)
op(0x1f, JMPIndirectAbsoluteX)
op(0x1f, JMPIndirectX)
op(0x20, FlagClear, PF)
op(0x21, JST, 2)
op(0x22, SET, 1)
op(0x23, BBS, 1)
op(0x24, DirectPageRead, fp(AND), A)
op(0x24, DirectRead, fp(AND), A)
op(0x25, AbsoluteRead, fp(AND), A)
op(0x26, IndirectXRead, fp(AND))
op(0x27, IndirectPageXRead, fp(AND))
op(0x27, IndexedIndirectRead, fp(AND), X)
op(0x28, ImmediateRead, fp(AND), A)
op(0x29, DirectPageWriteDirectPage, fp(AND))
op(0x2a, AbsoluteModifyBit, 1)
op(0x2b, DirectPageModify, fp(ROL))
op(0x29, DirectWriteDirect, fp(AND))
op(0x2a, AbsoluteBitModify, 1)
op(0x2b, DirectModify, fp(ROL))
op(0x2c, AbsoluteModify, fp(ROL))
op(0x2d, Push, A)
op(0x2e, BNEDirectPage)
op(0x2e, BNEDirect)
op(0x2f, Branch, true)
op(0x30, Branch, NF == 1)
op(0x31, JST, 3)
op(0x32, CLR, 1)
op(0x33, BBC, 1)
op(0x34, DirectPageIndexedRead, fp(AND), A, X)
op(0x34, DirectIndexedRead, fp(AND), A, X)
op(0x35, AbsoluteIndexedRead, fp(AND), X)
op(0x36, AbsoluteIndexedRead, fp(AND), Y)
op(0x37, IndirectPageYRead, fp(AND))
op(0x38, DirectPageWriteImmediate, fp(AND))
op(0x37, IndirectIndexedRead, fp(AND), Y)
op(0x38, DirectWriteImmediate, fp(AND))
op(0x39, IndirectXWriteIndirectY, fp(AND))
op(0x3a, DirectPageModifyWord, +1)
op(0x3b, DirectPageXModify, fp(ROL))
op(0x3a, DirectModifyWord, +1)
op(0x3b, DirectIndexedModify, fp(ROL), A)
op(0x3c, ImpliedModify, fp(ROL), A)
op(0x3d, ImpliedModify, fp(INC), X)
op(0x3e, DirectPageRead, fp(CMP), X)
op(0x3e, DirectRead, fp(CMP), X)
op(0x3f, JSRAbsolute)
op(0x40, FlagSet, PF)
op(0x41, JST, 4)
op(0x42, SET, 2)
op(0x43, BBS, 2)
op(0x44, DirectPageRead, fp(EOR), A)
op(0x44, DirectRead, fp(EOR), A)
op(0x45, AbsoluteRead, fp(EOR), A)
op(0x46, IndirectXRead, fp(EOR))
op(0x47, IndirectPageXRead, fp(EOR))
op(0x47, IndexedIndirectRead, fp(EOR), X)
op(0x48, ImmediateRead, fp(EOR), A)
op(0x49, DirectPageWriteDirectPage, fp(EOR))
op(0x4a, AbsoluteModifyBit, 2)
op(0x4b, DirectPageModify, fp(LSR))
op(0x49, DirectWriteDirect, fp(EOR))
op(0x4a, AbsoluteBitModify, 2)
op(0x4b, DirectModify, fp(LSR))
op(0x4c, AbsoluteModify, fp(LSR))
op(0x4d, Push, X)
op(0x4e, TRBAbsolute)
op(0x4f, JSPDirectPage)
op(0x4f, JSPDirect)
op(0x50, Branch, VF == 0)
op(0x51, JST, 5)
op(0x52, CLR, 2)
op(0x53, BBC, 2)
op(0x54, DirectPageIndexedRead, fp(EOR), A, X)
op(0x54, DirectIndexedRead, fp(EOR), A, X)
op(0x55, AbsoluteIndexedRead, fp(EOR), X)
op(0x56, AbsoluteIndexedRead, fp(EOR), Y)
op(0x57, IndirectPageYRead, fp(EOR))
op(0x58, DirectPageWriteImmediate, fp(EOR))
op(0x57, IndirectIndexedRead, fp(EOR), Y)
op(0x58, DirectWriteImmediate, fp(EOR))
op(0x59, IndirectXWriteIndirectY, fp(EOR))
op(0x5a, DirectPageReadWord, fp(CPW))
op(0x5b, DirectPageXModify, fp(LSR))
op(0x5a, DirectReadWord, fp(CPW))
op(0x5b, DirectIndexedModify, fp(LSR), X)
op(0x5c, ImpliedModify, fp(LSR), A)
op(0x5d, Transfer, A, X)
op(0x5e, AbsoluteRead, fp(CMP), Y)
@ -103,62 +103,62 @@ auto SPC700::instruction() -> void {
op(0x61, JST, 6)
op(0x62, SET, 3)
op(0x63, BBS, 3)
op(0x64, DirectPageRead, fp(CMP), A)
op(0x64, DirectRead, fp(CMP), A)
op(0x65, AbsoluteRead, fp(CMP), A)
op(0x66, IndirectXRead, fp(CMP))
op(0x67, IndirectPageXRead, fp(CMP))
op(0x67, IndexedIndirectRead, fp(CMP), X)
op(0x68, ImmediateRead, fp(CMP), A)
op(0x69, DirectPageWriteDirectPage, fp(CMP))
op(0x6a, AbsoluteModifyBit, 3)
op(0x6b, DirectPageModify, fp(ROR))
op(0x69, DirectWriteDirect, fp(CMP))
op(0x6a, AbsoluteBitModify, 3)
op(0x6b, DirectModify, fp(ROR))
op(0x6c, AbsoluteModify, fp(ROR))
op(0x6d, Push, Y)
op(0x6e, BNEDirectPageDecrement)
op(0x6e, BNEDirectDecrement)
op(0x6f, RTS)
op(0x70, Branch, VF == 1)
op(0x71, JST, 7)
op(0x72, CLR, 3)
op(0x73, BBC, 3)
op(0x74, DirectPageIndexedRead, fp(CMP), A, X)
op(0x74, DirectIndexedRead, fp(CMP), A, X)
op(0x75, AbsoluteIndexedRead, fp(CMP), X)
op(0x76, AbsoluteIndexedRead, fp(CMP), Y)
op(0x77, IndirectPageYRead, fp(CMP))
op(0x78, DirectPageWriteImmediate, fp(CMP))
op(0x77, IndirectIndexedRead, fp(CMP), Y)
op(0x78, DirectWriteImmediate, fp(CMP))
op(0x79, IndirectXWriteIndirectY, fp(CMP))
op(0x7a, DirectPageReadWord, fp(ADW))
op(0x7b, DirectPageXModify, fp(ROR))
op(0x7a, DirectReadWord, fp(ADW))
op(0x7b, DirectIndexedModify, fp(ROR), X)
op(0x7c, ImpliedModify, fp(ROR), A)
op(0x7d, Transfer, X, A)
op(0x7e, DirectPageRead, fp(CMP), Y)
op(0x7e, DirectRead, fp(CMP), Y)
op(0x7f, RTI)
op(0x80, FlagSet, CF)
op(0x81, JST, 8)
op(0x82, SET, 4)
op(0x83, BBS, 4)
op(0x84, DirectPageRead, fp(ADC), A)
op(0x84, DirectRead, fp(ADC), A)
op(0x85, AbsoluteRead, fp(ADC), A)
op(0x86, IndirectXRead, fp(ADC))
op(0x87, IndirectPageXRead, fp(ADC))
op(0x87, IndexedIndirectRead, fp(ADC), X)
op(0x88, ImmediateRead, fp(ADC), A)
op(0x89, DirectPageWriteDirectPage, fp(ADC))
op(0x8a, AbsoluteModifyBit, 4)
op(0x8b, DirectPageModify, fp(DEC))
op(0x89, DirectWriteDirect, fp(ADC))
op(0x8a, AbsoluteBitModify, 4)
op(0x8b, DirectModify, fp(DEC))
op(0x8c, AbsoluteModify, fp(DEC))
op(0x8d, ImmediateRead, fp(LD), Y)
op(0x8e, PLP)
op(0x8f, DirectPageWriteImmediate, fp(ST))
op(0x8f, DirectWriteImmediate, fp(ST))
op(0x90, Branch, CF == 0)
op(0x91, JST, 9)
op(0x92, CLR, 4)
op(0x93, BBC, 4)
op(0x94, DirectPageIndexedRead, fp(ADC), A, X)
op(0x94, DirectIndexedRead, fp(ADC), A, X)
op(0x95, AbsoluteIndexedRead, fp(ADC), X)
op(0x96, AbsoluteIndexedRead, fp(ADC), Y)
op(0x97, IndirectPageYRead, fp(ADC))
op(0x98, DirectPageWriteImmediate, fp(ADC))
op(0x97, IndirectIndexedRead, fp(ADC), Y)
op(0x98, DirectWriteImmediate, fp(ADC))
op(0x99, IndirectXWriteIndirectY, fp(ADC))
op(0x9a, DirectPageReadWord, fp(SBW))
op(0x9b, DirectPageXModify, fp(DEC))
op(0x9a, DirectReadWord, fp(SBW))
op(0x9b, DirectIndexedModify, fp(DEC), X)
op(0x9c, ImpliedModify, fp(DEC), A)
op(0x9d, Transfer, S, X)
op(0x9e, DIV)
@ -167,46 +167,46 @@ auto SPC700::instruction() -> void {
op(0xa1, JST, 10)
op(0xa2, SET, 5)
op(0xa3, BBS, 5)
op(0xa4, DirectPageRead, fp(SBC), A)
op(0xa4, DirectRead, fp(SBC), A)
op(0xa5, AbsoluteRead, fp(SBC), A)
op(0xa6, IndirectXRead, fp(SBC))
op(0xa7, IndirectPageXRead, fp(SBC))
op(0xa7, IndexedIndirectRead, fp(SBC), X)
op(0xa8, ImmediateRead, fp(SBC), A)
op(0xa9, DirectPageWriteDirectPage, fp(SBC))
op(0xaa, AbsoluteModifyBit, 5)
op(0xab, DirectPageModify, fp(INC))
op(0xa9, DirectWriteDirect, fp(SBC))
op(0xaa, AbsoluteBitModify, 5)
op(0xab, DirectModify, fp(INC))
op(0xac, AbsoluteModify, fp(INC))
op(0xad, ImmediateRead, fp(CMP), Y)
op(0xae, Pull, A)
op(0xaf, STAIndirectXIncrement)
op(0xaf, IndirectXIncrementWrite, A)
op(0xb0, Branch, CF == 1)
op(0xb1, JST, 11)
op(0xb2, CLR, 5)
op(0xb3, BBC, 5)
op(0xb4, DirectPageIndexedRead, fp(SBC), A, X)
op(0xb4, DirectIndexedRead, fp(SBC), A, X)
op(0xb5, AbsoluteIndexedRead, fp(SBC), X)
op(0xb6, AbsoluteIndexedRead, fp(SBC), Y)
op(0xb7, IndirectPageYRead, fp(SBC))
op(0xb8, DirectPageWriteImmediate, fp(SBC))
op(0xb7, IndirectIndexedRead, fp(SBC), Y)
op(0xb8, DirectWriteImmediate, fp(SBC))
op(0xb9, IndirectXWriteIndirectY, fp(SBC))
op(0xba, DirectPageReadWord, fp(LDW))
op(0xbb, DirectPageXModify, fp(INC))
op(0xba, DirectReadWord, fp(LDW))
op(0xbb, DirectIndexedModify, fp(INC), X)
op(0xbc, ImpliedModify, fp(INC), A)
op(0xbd, Transfer, X, S)
op(0xbe, DAS)
op(0xbf, LDAIndirectXIncrement)
op(0xbf, IndirectXIncrementRead, A)
op(0xc0, FlagClear, IF)
op(0xc1, JST, 12)
op(0xc2, SET, 6)
op(0xc3, BBS, 6)
op(0xc4, DirectPageWrite, A)
op(0xc4, DirectWrite, A)
op(0xc5, AbsoluteWrite, A)
op(0xc6, STAIndirectX)
op(0xc7, STAIndirectPageX)
op(0xc6, IndirectXWrite, A)
op(0xc7, IndexedIndirectWrite, A, X)
op(0xc8, ImmediateRead, fp(CMP), X)
op(0xc9, AbsoluteWrite, X)
op(0xca, AbsoluteModifyBit, 6)
op(0xcb, DirectPageWrite, Y)
op(0xca, AbsoluteBitModify, 6)
op(0xcb, DirectWrite, Y)
op(0xcc, AbsoluteWrite, Y)
op(0xcd, ImmediateRead, fp(LD), X)
op(0xce, Pull, X)
@ -215,30 +215,30 @@ auto SPC700::instruction() -> void {
op(0xd1, JST, 13)
op(0xd2, CLR, 6)
op(0xd3, BBC, 6)
op(0xd4, DirectPageIndexedWrite, A, X)
op(0xd4, DirectIndexedWrite, A, X)
op(0xd5, AbsoluteIndexedWrite, X)
op(0xd6, AbsoluteIndexedWrite, Y)
op(0xd7, STAIndirectPageY)
op(0xd8, DirectPageWrite, X)
op(0xd9, DirectPageIndexedWrite, X, Y)
op(0xda, STWDirectPage)
op(0xdb, DirectPageIndexedWrite, Y, X)
op(0xd7, IndirectIndexedWrite, A, Y)
op(0xd8, DirectWrite, X)
op(0xd9, DirectIndexedWrite, X, Y)
op(0xda, STWDirect)
op(0xdb, DirectIndexedWrite, Y, X)
op(0xdc, ImpliedModify, fp(DEC), Y)
op(0xdd, Transfer, Y, A)
op(0xde, BNEDirectPageX)
op(0xde, BNEDirectX)
op(0xdf, DAA)
op(0xe0, CLV)
op(0xe1, JST, 14)
op(0xe2, SET, 7)
op(0xe3, BBS, 7)
op(0xe4, DirectPageRead, fp(LD), A)
op(0xe4, DirectRead, fp(LD), A)
op(0xe5, AbsoluteRead, fp(LD), A)
op(0xe6, IndirectXRead, fp(LD))
op(0xe7, IndirectPageXRead, fp(LD))
op(0xe7, IndexedIndirectRead, fp(LD), X)
op(0xe8, ImmediateRead, fp(LD), A)
op(0xe9, AbsoluteRead, fp(LD), X)
op(0xea, AbsoluteModifyBit, 7)
op(0xeb, DirectPageRead, fp(LD), Y)
op(0xea, AbsoluteBitModify, 7)
op(0xeb, DirectRead, fp(LD), Y)
op(0xec, AbsoluteRead, fp(LD), Y)
op(0xed, CMC)
op(0xee, Pull, Y)
@ -247,14 +247,14 @@ auto SPC700::instruction() -> void {
op(0xf1, JST, 15)
op(0xf2, CLR, 7)
op(0xf3, BBC, 7)
op(0xf4, DirectPageIndexedRead, fp(LD), A, X)
op(0xf4, DirectIndexedRead, fp(LD), A, X)
op(0xf5, AbsoluteIndexedRead, fp(LD), X)
op(0xf6, AbsoluteIndexedRead, fp(LD), Y)
op(0xf7, IndirectPageYRead, fp(LD))
op(0xf8, DirectPageRead, fp(LD), X)
op(0xf9, DirectPageIndexedRead, fp(LD), X, Y)
op(0xfa, DirectPageWriteDirectPage, fp(ST))
op(0xfb, DirectPageIndexedRead, fp(LD), Y, X)
op(0xf7, IndirectIndexedRead, fp(LD), Y)
op(0xf8, DirectRead, fp(LD), X)
op(0xf9, DirectIndexedRead, fp(LD), X, Y)
op(0xfa, DirectWriteDirect, fp(ST))
op(0xfb, DirectIndexedRead, fp(LD), Y, X)
op(0xfc, ImpliedModify, fp(INC), Y)
op(0xfd, Transfer, A, Y)
op(0xfe, BNEYDecrement)

View File

@ -1,124 +1,4 @@
auto SPC700::instructionImpliedModify(fps op, uint8& target) -> void {
idle();
target = alu(target);
}
auto SPC700::instructionAbsoluteModify(fps op) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
uint8 data = read(absolute);
write(absolute, alu(data));
}
auto SPC700::instructionDirectPageModify(fps op) -> void {
uint8 direct = fetch();
uint8 data = load(direct);
store(direct, alu(data));
}
auto SPC700::instructionDirectPageModifyWord(int adjust) -> void {
uint8 direct = fetch();
uint16 data = load(direct) + adjust;
store(direct++, data >> 0);
data += load(direct) << 8;
store(direct++, data >> 8);
ZF = data == 0;
NF = data & 0x8000;
}
auto SPC700::instructionDirectPageXModify(fps op) -> void {
uint8 direct = fetch();
idle();
uint8 data = load(direct + X);
store(direct + X, alu(data));
}
auto SPC700::instructionBranch(bool take) -> void {
uint8 data = fetch();
if(!take) return;
idle();
idle();
PC += (int8)data;
}
auto SPC700::instructionPull(uint8& data) -> void {
idle();
idle();
data = pull();
}
auto SPC700::instructionPush(uint8 data) -> void {
idle();
idle();
push(data);
}
auto SPC700::instructionAbsoluteRead(fpb op, uint8& target) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
uint8 data = read(absolute);
target = alu(target, data);
}
auto SPC700::instructionAbsoluteIndexedRead(fpb op, uint8& index) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
idle();
uint8 data = read(absolute + index);
A = alu(A, data);
}
auto SPC700::instructionImmediateRead(fpb op, uint8& target) -> void {
uint8 data = fetch();
target = alu(target, data);
}
auto SPC700::instructionDirectPageRead(fpb op, uint8& target) -> void {
uint8 direct = fetch();
uint8 data = load(direct);
target = alu(target, data);
}
auto SPC700::instructionDirectPageIndexedRead(fpb op, uint8& target, uint8& index) -> void {
uint8 direct = fetch();
idle();
uint8 data = load(direct + index);
target = alu(target, data);
}
auto SPC700::instructionDirectPageReadWord(fpw op) -> void {
uint8 direct = fetch();
uint16 data = load(direct++);
if(op != &SPC700::algorithmCPW) idle();
data |= load(direct++) << 8;
YA = alu(YA, data);
}
auto SPC700::instructionIndirectPageXRead(fpb op) -> void {
uint8 direct = fetch() + X;
idle();
uint16 absolute = load(direct++);
absolute |= load(direct++) << 8;
uint8 data = read(absolute);
A = alu(A, data);
}
auto SPC700::instructionIndirectPageYRead(fpb op) -> void {
uint8 direct = fetch();
idle();
uint16 absolute = load(direct++);
absolute |= load(direct++) << 8;
uint8 data = read(absolute + Y);
A = alu(A, data);
}
auto SPC700::instructionIndirectXRead(fpb op) -> void {
idle();
uint8 data = load(X);
A = alu(A, data);
}
auto SPC700::instructionAbsoluteModifyBit(uint3 mode) -> void {
auto SPC700::instructionAbsoluteBitModify(uint3 mode) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
uint3 bit = absolute >> 13;
@ -158,6 +38,127 @@ auto SPC700::instructionAbsoluteModifyBit(uint3 mode) -> void {
}
}
auto SPC700::instructionAbsoluteRead(fpb op, uint8& target) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
uint8 data = read(absolute);
target = alu(target, data);
}
auto SPC700::instructionAbsoluteModify(fps op) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
uint8 data = read(absolute);
write(absolute, alu(data));
}
auto SPC700::instructionAbsoluteWrite(uint8& data) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
read(absolute);
write(absolute, data);
}
auto SPC700::instructionAbsoluteIndexedRead(fpb op, uint8& index) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
idle();
uint8 data = read(absolute + index);
A = alu(A, data);
}
auto SPC700::instructionAbsoluteIndexedWrite(uint8& index) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
idle();
absolute += index;
read(absolute);
write(absolute, A);
}
auto SPC700::instructionBranch(bool take) -> void {
uint8 data = fetch();
if(!take) return;
idle();
idle();
PC += (int8)data;
}
auto SPC700::instructionDirectRead(fpb op, uint8& target) -> void {
uint8 direct = fetch();
uint8 data = load(direct);
target = alu(target, data);
}
auto SPC700::instructionDirectModify(fps op) -> void {
uint8 direct = fetch();
uint8 data = load(direct);
store(direct, alu(data));
}
auto SPC700::instructionDirectWrite(uint8& data) -> void {
uint8 direct = fetch();
load(direct);
store(direct, data);
}
auto SPC700::instructionDirectWriteDirect(fpb op) -> void {
uint8 source = fetch();
uint8 rhs = load(source);
uint8 target = fetch();
uint8 lhs;
if(op != &SPC700::algorithmST) lhs = load(target);
lhs = alu(lhs, rhs);
op != &SPC700::algorithmCMP ? store(target, lhs) : idle();
}
auto SPC700::instructionDirectWriteImmediate(fpb op) -> void {
uint8 immediate = fetch();
uint8 direct = fetch();
uint8 data = load(direct);
data = alu(data, immediate);
op != &SPC700::algorithmCMP ? store(direct, data) : idle();
}
auto SPC700::instructionDirectReadWord(fpw op) -> void {
uint8 direct = fetch();
uint16 data = load(direct++);
if(op != &SPC700::algorithmCPW) idle();
data |= load(direct++) << 8;
YA = alu(YA, data);
}
auto SPC700::instructionDirectModifyWord(int adjust) -> void {
uint8 direct = fetch();
uint16 data = load(direct) + adjust;
store(direct++, data >> 0);
data += load(direct) << 8;
store(direct++, data >> 8);
ZF = data == 0;
NF = data & 0x8000;
}
auto SPC700::instructionDirectIndexedRead(fpb op, uint8& target, uint8& index) -> void {
uint8 direct = fetch();
idle();
uint8 data = load(direct + index);
target = alu(target, data);
}
auto SPC700::instructionDirectIndexedModify(fps op, uint8& index) -> void {
uint8 direct = fetch();
idle();
uint8 data = load(direct + index);
store(direct + index, alu(data));
}
auto SPC700::instructionDirectIndexedWrite(uint8& data, uint8& index) -> void {
uint8 direct = fetch() + index;
idle();
load(direct);
store(direct, data);
}
auto SPC700::instructionFlagClear(bool& flag) -> void {
idle();
if(&flag == &IF) idle();
@ -170,59 +171,76 @@ auto SPC700::instructionFlagSet(bool& flag) -> void {
flag = 1;
}
auto SPC700::instructionTransfer(uint8& from, uint8& to) -> void {
idle();
to = from;
if(&to == &S) return;
ZF = to == 0;
NF = to & 0x80;
auto SPC700::instructionImmediateRead(fpb op, uint8& target) -> void {
uint8 data = fetch();
target = alu(target, data);
}
auto SPC700::instructionAbsoluteWrite(uint8& data) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
auto SPC700::instructionImpliedModify(fps op, uint8& target) -> void {
idle();
target = alu(target);
}
auto SPC700::instructionIndexedIndirectRead(fpb op, uint8& index) -> void {
uint8 direct = fetch() + index;
idle();
uint16 absolute = load(direct++);
absolute |= load(direct++) << 8;
uint8 data = read(absolute);
A = alu(A, data);
}
auto SPC700::instructionIndexedIndirectWrite(uint8& data, uint8& index) -> void {
uint8 direct = fetch() + index;
idle();
uint16 absolute = load(direct++);
absolute |= load(direct++) << 8;
read(absolute);
write(absolute, data);
}
auto SPC700::instructionAbsoluteIndexedWrite(uint8& index) -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
idle();
absolute += index;
read(absolute);
write(absolute, A);
}
auto SPC700::instructionDirectPageWrite(uint8& data) -> void {
auto SPC700::instructionIndirectIndexedRead(fpb op, uint8& index) -> void {
uint8 direct = fetch();
load(direct);
store(direct, data);
}
auto SPC700::instructionDirectPageIndexedWrite(uint8& data, uint8& index) -> void {
uint8 direct = fetch() + index;
uint16 absolute = load(direct++);
absolute |= load(direct++) << 8;
idle();
load(direct);
store(direct, data);
uint8 data = read(absolute + index);
A = alu(A, data);
}
auto SPC700::instructionDirectPageWriteImmediate(fpb op) -> void {
uint8 immediate = fetch();
auto SPC700::instructionIndirectIndexedWrite(uint8& data, uint8& index) -> void {
uint8 direct = fetch();
uint8 data = load(direct);
data = alu(data, immediate);
op != &SPC700::algorithmCMP ? store(direct, data) : idle();
uint16 absolute = load(direct++);
absolute |= load(direct++) << 8;
idle();
read(absolute + index);
write(absolute + index, data);
}
auto SPC700::instructionDirectPageWriteDirectPage(fpb op) -> void {
uint8 source = fetch();
uint8 rhs = load(source);
uint8 target = fetch();
uint8 lhs;
if(op != &SPC700::algorithmST) lhs = load(target);
lhs = alu(lhs, rhs);
op != &SPC700::algorithmCMP ? store(target, lhs) : idle();
auto SPC700::instructionIndirectXRead(fpb op) -> void {
idle();
uint8 data = load(X);
A = alu(A, data);
}
auto SPC700::instructionIndirectXWrite(uint8& data) -> void {
idle();
load(X);
store(X, data);
}
auto SPC700::instructionIndirectXIncrementRead(uint8& data) -> void {
idle();
data = load(X++);
idle();
ZF = data == 0;
NF = data & 0x80;
}
auto SPC700::instructionIndirectXIncrementWrite(uint8& data) -> void {
idle();
idle();
store(X++, data);
}
auto SPC700::instructionIndirectXWriteIndirectY(fpb op) -> void {
@ -233,6 +251,26 @@ auto SPC700::instructionIndirectXWriteIndirectY(fpb op) -> void {
op != &SPC700::algorithmCMP ? store(X, lhs) : idle();
}
auto SPC700::instructionPull(uint8& data) -> void {
idle();
idle();
data = pull();
}
auto SPC700::instructionPush(uint8 data) -> void {
idle();
idle();
push(data);
}
auto SPC700::instructionTransfer(uint8& from, uint8& to) -> void {
idle();
to = from;
if(&to == &S) return;
ZF = to == 0;
NF = to & 0x80;
}
//
auto SPC700::instructionBBC(uint3 bit) -> void {
@ -257,7 +295,7 @@ auto SPC700::instructionBBS(uint3 bit) -> void {
PC += (int8)displacement;
}
auto SPC700::instructionBNEDirectPage() -> void {
auto SPC700::instructionBNEDirect() -> void {
uint8 direct = fetch();
uint8 data = load(direct);
uint8 displacement = fetch();
@ -268,7 +306,7 @@ auto SPC700::instructionBNEDirectPage() -> void {
PC += (int8)displacement;
}
auto SPC700::instructionBNEDirectPageDecrement() -> void {
auto SPC700::instructionBNEDirectDecrement() -> void {
uint8 direct = fetch();
uint8 data = load(direct);
store(direct, --data);
@ -279,7 +317,7 @@ auto SPC700::instructionBNEDirectPageDecrement() -> void {
PC += (int8)displacement;
}
auto SPC700::instructionBNEDirectPageX() -> void {
auto SPC700::instructionBNEDirectX() -> void {
uint8 direct = fetch();
idle();
uint8 data = load(direct + X);
@ -398,7 +436,7 @@ auto SPC700::instructionJMPAbsolute() -> void {
PC = absolute;
}
auto SPC700::instructionJMPIndirectAbsoluteX() -> void {
auto SPC700::instructionJMPIndirectX() -> void {
uint16 absolute = fetch();
absolute |= fetch() << 8;
idle();
@ -408,7 +446,7 @@ auto SPC700::instructionJMPIndirectAbsoluteX() -> void {
PC = pc;
}
auto SPC700::instructionJSPDirectPage() -> void {
auto SPC700::instructionJSPDirect() -> void {
uint8 direct = fetch();
idle();
idle();
@ -440,14 +478,6 @@ auto SPC700::instructionJST(uint4 vector) -> void {
PC = pc;
}
auto SPC700::instructionLDAIndirectXIncrement() -> void {
idle();
A = load(X++);
idle();
ZF = A == 0;
NF = A & 0x80;
}
auto SPC700::instructionMUL() -> void {
idle();
idle();
@ -499,37 +529,6 @@ auto SPC700::instructionSET(uint3 bit) -> void {
store(direct, data);
}
auto SPC700::instructionSTAIndirectPageX() -> void {
uint8 direct = fetch() + X;
idle();
uint16 absolute = load(direct++);
absolute |= load(direct++) << 8;
read(absolute);
write(absolute, A);
}
auto SPC700::instructionSTAIndirectPageY() -> void {
uint8 direct = fetch();
uint16 absolute = load(direct++);
absolute |= load(direct++) << 8;
idle();
absolute += Y;
read(absolute);
write(absolute, A);
}
auto SPC700::instructionSTAIndirectX() -> void {
idle();
load(X);
store(X, A);
}
auto SPC700::instructionSTAIndirectXIncrement() -> void {
idle();
idle();
store(X++, A);
}
auto SPC700::instructionSTP() -> void {
r.stp = true;
while(r.stp && !synchronizing()) {
@ -538,7 +537,7 @@ auto SPC700::instructionSTP() -> void {
}
}
auto SPC700::instructionSTWDirectPage() -> void {
auto SPC700::instructionSTWDirect() -> void {
uint8 direct = fetch();
load(direct);
store(direct++, A);

View File

@ -1,3 +1,7 @@
auto SPC700::idle() -> void {
read(PC);
}
auto SPC700::fetch() -> uint8 {
return read(PC++);
}

View File

@ -3,7 +3,6 @@
namespace Processor {
struct SPC700 {
virtual auto idle() -> void = 0;
virtual auto read(uint16 addr) -> uint8 = 0;
virtual auto write(uint16 addr, uint8 data) -> void = 0;
virtual auto synchronizing() const -> bool = 0;
@ -17,6 +16,7 @@ struct SPC700 {
auto instruction() -> void;
//memory.cpp
auto idle() -> void;
auto fetch() -> uint8;
auto pull() -> uint8;
auto push(uint8 data) -> void;
@ -48,40 +48,45 @@ struct SPC700 {
using fpb = auto (SPC700::*)(uint8, uint8) -> uint8;
using fpw = auto (SPC700::*)(uint16, uint16) -> uint16;
auto instructionImpliedModify(fps, uint8&) -> void;
auto instructionAbsoluteModify(fps) -> void;
auto instructionDirectPageModify(fps) -> void;
auto instructionDirectPageModifyWord(int) -> void;
auto instructionDirectPageXModify(fps) -> void;
auto instructionBranch(bool) -> void;
auto instructionPull(uint8&) -> void;
auto instructionPush(uint8) -> void;
auto instructionAbsoluteBitModify(uint3) -> void;
auto instructionAbsoluteRead(fpb, uint8&) -> void;
auto instructionAbsoluteModify(fps) -> void;
auto instructionAbsoluteWrite(uint8&) -> void;
auto instructionAbsoluteIndexedRead(fpb, uint8&) -> void;
auto instructionImmediateRead(fpb, uint8&) -> void;
auto instructionDirectPageRead(fpb, uint8&) -> void;
auto instructionDirectPageIndexedRead(fpb, uint8&, uint8&) -> void;
auto instructionDirectPageReadWord(fpw) -> void;
auto instructionIndirectPageXRead(fpb) -> void;
auto instructionIndirectPageYRead(fpb) -> void;
auto instructionIndirectXRead(fpb) -> void;
auto instructionAbsoluteModifyBit(uint3) -> void;
auto instructionAbsoluteIndexedWrite(uint8&) -> void;
auto instructionBranch(bool) -> void;
auto instructionDirectRead(fpb, uint8&) -> void;
auto instructionDirectModify(fps) -> void;
auto instructionDirectWrite(uint8&) -> void;
auto instructionDirectWriteDirect(fpb) -> void;
auto instructionDirectWriteImmediate(fpb) -> void;
auto instructionDirectReadWord(fpw) -> void;
auto instructionDirectModifyWord(int) -> void;
auto instructionDirectIndexedRead(fpb, uint8&, uint8&) -> void;
auto instructionDirectIndexedModify(fps, uint8&) -> void;
auto instructionDirectIndexedWrite(uint8&, uint8&) -> void;
auto instructionFlagClear(bool&) -> void;
auto instructionFlagSet(bool&) -> void;
auto instructionTransfer(uint8&, uint8&) -> void;
auto instructionAbsoluteWrite(uint8&) -> void;
auto instructionAbsoluteIndexedWrite(uint8&) -> void;
auto instructionDirectPageWrite(uint8&) -> void;
auto instructionDirectPageIndexedWrite(uint8&, uint8&) -> void;
auto instructionDirectPageWriteImmediate(fpb) -> void;
auto instructionDirectPageWriteDirectPage(fpb) -> void;
auto instructionImmediateRead(fpb, uint8&) -> void;
auto instructionImpliedModify(fps, uint8&) -> void;
auto instructionIndexedIndirectRead(fpb, uint8&) -> void;
auto instructionIndexedIndirectWrite(uint8&, uint8&) -> void;
auto instructionIndirectIndexedRead(fpb, uint8&) -> void;
auto instructionIndirectIndexedWrite(uint8&, uint8&) -> void;
auto instructionIndirectXRead(fpb) -> void;
auto instructionIndirectXWrite(uint8&) -> void;
auto instructionIndirectXIncrementRead(uint8&) -> void;
auto instructionIndirectXIncrementWrite(uint8&) -> void;
auto instructionIndirectXWriteIndirectY(fpb) -> void;
auto instructionPull(uint8&) -> void;
auto instructionPush(uint8) -> void;
auto instructionTransfer(uint8&, uint8&) -> void;
auto instructionBBC(uint3) -> void;
auto instructionBBS(uint3) -> void;
auto instructionBNEDirectPage() -> void;
auto instructionBNEDirectPageDecrement() -> void;
auto instructionBNEDirectPageX() -> void;
auto instructionBNEDirect() -> void;
auto instructionBNEDirectDecrement() -> void;
auto instructionBNEDirectX() -> void;
auto instructionBNEYDecrement() -> void;
auto instructionBRK() -> void;
auto instructionCLR(uint3) -> void;
@ -91,23 +96,18 @@ struct SPC700 {
auto instructionDAS() -> void;
auto instructionDIV() -> void;
auto instructionJMPAbsolute() -> void;
auto instructionJMPIndirectAbsoluteX() -> void;
auto instructionJSPDirectPage() -> void;
auto instructionJMPIndirectX() -> void;
auto instructionJSPDirect() -> void;
auto instructionJSRAbsolute() -> void;
auto instructionJST(uint4) -> void;
auto instructionLDAIndirectXIncrement() -> void;
auto instructionMUL() -> void;
auto instructionNOP() -> void;
auto instructionPLP() -> void;
auto instructionRTI() -> void;
auto instructionRTS() -> void;
auto instructionSET(uint3) -> void;
auto instructionSTAIndirectPageX() -> void;
auto instructionSTAIndirectPageY() -> void;
auto instructionSTAIndirectX() -> void;
auto instructionSTAIndirectXIncrement() -> void;
auto instructionSTP() -> void;
auto instructionSTWDirectPage() -> void;
auto instructionSTWDirect() -> void;
auto instructionTRBAbsolute() -> void;
auto instructionTSBAbsolute() -> void;
auto instructionWAI() -> void;

View File

@ -2,8 +2,8 @@ auto Z80::instruction() -> void {
//todo: return instruction() could cause stack crash from recursion
//but this is needed to prevent IRQs from firing between prefixes and opcodes
auto code = opcode();
if(code == 0xdd) { r.hlp = &r.ix; return instruction(); }
if(code == 0xfd) { r.hlp = &r.iy; return instruction(); }
if(code == 0xdd) { prefix = Prefix::ix; return instruction(); }
if(code == 0xfd) { prefix = Prefix::iy; return instruction(); }
if(r.ei) {
r.ei = 0;
@ -11,7 +11,7 @@ auto Z80::instruction() -> void {
r.iff2 = 1;
}
if(code == 0xcb && r.hlp != &r.hl) {
if(code == 0xcb && prefix != Prefix::hl) {
uint16 addr = HL + (int8)operand();
wait(1);
instructionCBd(addr, opcode());
@ -23,7 +23,7 @@ auto Z80::instruction() -> void {
instruction(code);
}
r.hlp = &r.hl;
prefix = Prefix::hl;
}
#define op(id, name, ...) case id: return instruction##name(__VA_ARGS__);

View File

@ -1,7 +1,7 @@
#define AF r.af.word
#define BC r.bc.word
#define DE r.de.word
#define HL r.hlp->word //virtual HL (overridden by IX/IY prefixes)
#define HL (prefix == Prefix::ix ? r.ix.word : prefix == Prefix::iy ? r.iy.word : r.hl.word)
#define A r.af.byte.hi
#define F r.af.byte.lo
@ -9,8 +9,8 @@
#define C r.bc.byte.lo
#define D r.de.byte.hi
#define E r.de.byte.lo
#define H r.hlp->byte.hi
#define L r.hlp->byte.lo
#define H (prefix == Prefix::ix ? r.ix.byte.hi : prefix == Prefix::iy ? r.iy.byte.hi : r.hl.byte.hi)
#define L (prefix == Prefix::ix ? r.ix.byte.lo : prefix == Prefix::iy ? r.iy.byte.lo : r.hl.byte.lo)
#define _HL r.hl.word //true HL (ignores IX/IY prefixes)
#define _H r.hl.byte.hi

View File

@ -17,8 +17,7 @@ auto Z80::serialize(serializer& s) -> void {
s.integer(r.iff1);
s.integer(r.iff2);
s.integer(r.im);
//todo: r.hlp is not serializable
s.integer((uint&)prefix);
}
auto Z80::Bus::serialize(serializer& s) -> void {

View File

@ -12,10 +12,8 @@ namespace Processor {
#include "serialization.cpp"
auto Z80::power() -> void {
memory::fill(&r, sizeof(Registers));
r.hlp = &r.hl;
bus->request(false);
bus->grant(true);
r = {};
prefix = Prefix::hl;
}
auto Z80::irq(bool maskable, uint16 pc, uint8 extbus) -> bool {

View File

@ -242,10 +242,10 @@ struct Z80 {
bool iff1; //interrupt flip-flop 1
bool iff2; //interrupt flip-flop 2
uint2 im; //interrupt mode (0-2)
Pair* hlp = nullptr;
} r;
enum class Prefix : uint { hl, ix, iy } prefix = Prefix::hl;
Bus* bus = nullptr;
};

View File

@ -173,11 +173,6 @@ auto SMP::writeBus(uint16 addr, uint8 data) -> void {
writeRAM(addr, data); //all writes, even to MMIO registers, appear on bus
}
auto SMP::idle() -> void {
step(24);
cycleEdge();
}
auto SMP::read(uint16 addr) -> uint8 {
step(12);
uint8 data = readBus(addr);

View File

@ -52,7 +52,6 @@ private:
auto readBus(uint16 addr) -> uint8;
auto writeBus(uint16 addr, uint8 data) -> void;
auto idle() -> void override;
auto read(uint16 addr) -> uint8 override;
auto write(uint16 addr, uint8 data) -> void override;

View File

@ -45,7 +45,7 @@ ifeq ($(platform),macosx)
else ifneq ($(filter $(platform),linux bsd),)
mkdir -p $(prefix)/share/$(name)/Database/
if [ -f out/$(name) ]; then cp out/$(name) $(prefix)/bin/$(name); fi
cp -R Database/ $(prefix)/share/$(name)/Database/
cp -R Database/* $(prefix)/share/$(name)/Database/
endif
uninstall: