From d100f706fc92c8e7662c64e6d40b43aff58451a2 Mon Sep 17 00:00:00 2001 From: edmccard Date: Sat, 14 Apr 2012 07:28:11 -0400 Subject: [PATCH] Integrate new cpu --- src/Makefile | 5 +- src/d6502/base.d | 164 --------- src/d6502/cmos.d | 266 --------------- src/d6502/cpu.d | 751 ------------------------------------------ src/d6502/nmosbase.d | 71 ---- src/d6502/nmosundoc.d | 365 -------------------- src/system/base.d | 238 +++++-------- src/twoapple.d | 22 +- src/ui/mainwindow.d | 4 +- 9 files changed, 97 insertions(+), 1789 deletions(-) delete mode 100644 src/d6502/base.d delete mode 100644 src/d6502/cmos.d delete mode 100644 src/d6502/cpu.d delete mode 100644 src/d6502/nmosbase.d delete mode 100644 src/d6502/nmosundoc.d diff --git a/src/Makefile b/src/Makefile index e8b8661..74bd283 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,12 +1,13 @@ COMPILE_OPTS = -op -Jdata -I$(GTKD)/src \ -I$(GTKD)/srcgl -I$(DERELICT)/import \ - -inline -release -O -noboundscheck + -inline -release -O -noboundscheck \ + -version=OpNestedSwitch LINK_OPTS = -L-lpthread -L-lGL -L-ldl -L-lX11 \ -L-L$(GTKD) -L-lgtkd -L-lgtkdgl \ -L-L$(DERELICT)/lib -L-lDerelictSDL -L-lDerelictUtil -ALL_SRC = $(shell find -name "*.d" \! -path "./cpu/*") +ALL_SRC = $(shell find -name "*.d" \! -name "ctfe*") all: ${ALL_SRC} dmd $(COMPILE_OPTS) ${ALL_SRC} -oftwoapple ${LINK_OPTS} diff --git a/src/d6502/base.d b/src/d6502/base.d deleted file mode 100644 index 1085e19..0000000 --- a/src/d6502/base.d +++ /dev/null @@ -1,164 +0,0 @@ -/+ - + d6502/base.d - + - + Copyright: 2007 Gerald Stocker - + - + This file is part of twoapple-reboot. - + - + twoapple-reboot is free software; you can redistribute it and/or modify - + it under the terms of the GNU General Public License as published by - + the Free Software Foundation; either version 2 of the License, or - + (at your option) any later version. - + - + twoapple-reboot is distributed in the hope that it will be useful, - + but WITHOUT ANY WARRANTY; without even the implied warranty of - + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - + GNU General Public License for more details. - + - + You should have received a copy of the GNU General Public License - + along with twoapple-reboot; if not, write to the Free Software - + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - +/ - -module d6502.base; - -enum Strict : bool -{ - no, yes -} - -enum Cumulative : bool -{ - no, yes -} - -string hexByte(int decByte) -{ - int highNybble = (decByte & 0xF0) >> 4; - int lowNybble = decByte & 0x0F; - - string digits = "0123456789ABCDEF"; - - return digits[highNybble..(highNybble + 1)] ~ - digits[lowNybble..(lowNybble + 1)]; -} - -final class StatusRegister -{ - bool carry, decimal, interrupt, overflow; - ubyte zero_, negative_; - - ubyte toByte() - { - return (carry ? 0x01 : 0) | - ((zero_ == 0) ? 0x02 : 0) | - (interrupt ? 0x04 : 0) | - (decimal ? 0x08 : 0) | - 0x30 | // break and reserved both set - (overflow ? 0x40 : 0) | - (negative_ & 0x80); - } - - void fromByte(ubyte val) - { - carry = ((val & 0x01) != 0); - zero_ = ((val & 0x02) ? 0 : 1); - interrupt = ((val & 0x04) != 0); - decimal = ((val & 0x08) != 0); - overflow = ((val & 0x40) != 0); - negative_ = val; - } -} - -class CpuBase(bool strict, bool cumulative) -{ - enum _isCpuBase = true; - static if (strict) enum _isStrict = true; - static if (cumulative) enum _isCumulative = true; - - static string AbstractOpcodes() - { - string abstractOpcodes; - for (int op = 0; op < 256; ++op) - abstractOpcodes ~= "abstract void opcode" ~ hexByte(op) ~ "();\n"; - return abstractOpcodes; - } - - mixin(AbstractOpcodes()); - - ushort programCounter; - ubyte accumulator, xIndex, yIndex, stackPointer; - StatusRegister flag; - - bool signalActive, irqActive, resetActive, nmiActive, nmiArmed; - - ushort opcodePC; - ubyte opcode, operand1, operand2; - - final ubyte[] save() - { - ubyte[] data = new ubyte[12]; - data[0] = programCounter & 0xFF; - data[1] = programCounter >> 8; - data[2] = accumulator; - data[3] = xIndex; - data[4] = yIndex; - data[5] = stackPointer; - data[6] = flag.toByte(); - data[7] = (signalActive ? 1 : 0); - data[8] = (irqActive ? 1 : 0); - data[9] = (resetActive ? 1 : 0); - data[10] = (nmiActive ? 1 : 0); - data[11] = (nmiArmed ? 1 : 0); - return data; - } - - final void restore(ubyte[] data) - { - assert (data.length >= 12); - - programCounter = data[0] | (data[1] << 8); - accumulator = data[2]; - xIndex = data[3]; - yIndex = data[4]; - stackPointer = data[5]; - flag.fromByte(data[6]); - signalActive = ((data[7] == 0) ? false : true); - irqActive = ((data[8] == 0) ? false : true); - resetActive = ((data[9] == 0) ? false : true); - nmiActive = ((data[10] == 0) ? false : true); - nmiArmed = ((data[11] == 0) ? false : true); - } - - final void reboot() - { - restore([0, 0, 0, 0, 0, 0xFF, 0, 0, 0, 0, 0, 1]); - } - - struct _Mem - { - ubyte delegate(ushort addr) read; - void delegate(ushort addr, ubyte val) write; - } - _Mem memory; - - struct _Clock - { - static if (cumulative) - void delegate(int cycles) tick; - else - void delegate() tick; - } - _Clock clock; - - debug(disassemble) - { - string delegate(ushort addr) memoryName; - } - - abstract void run(bool continuous); - abstract void stop(); - abstract void resetLow(); - abstract void nmiLow(bool signalLow); - abstract void irqLow(bool signalLow); -} diff --git a/src/d6502/cmos.d b/src/d6502/cmos.d deleted file mode 100644 index f736676..0000000 --- a/src/d6502/cmos.d +++ /dev/null @@ -1,266 +0,0 @@ -/+ - + d6502/cmos.d - + - + Copyright: 2007 Gerald Stocker - + - + This file is part of twoapple-reboot. - + - + twoapple-reboot is free software; you can redistribute it and/or modify - + it under the terms of the GNU General Public License as published by - + the Free Software Foundation; either version 2 of the License, or - + (at your option) any later version. - + - + twoapple-reboot is distributed in the hope that it will be useful, - + but WITHOUT ANY WARRANTY; without even the implied warranty of - + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - + GNU General Public License for more details. - + - + You should have received a copy of the GNU General Public License - + along with twoapple-reboot; if not, write to the Free Software - + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - +/ - -module d6502.cmos; - -import d6502.base; -import d6502.cpu; - -class Cmos(bool strict, bool cumulative) : Cpu!(strict, cumulative) -{ - enum _isCMOS = true; - - this() - { - super(); - spuriousAddress = &programCounter; - } - - final override void do_IRQ_or_NMI(ushort vector) - { - super.do_IRQ_or_NMI(vector); - flag.decimal = false; - } - - final override void doReset() - { - super.doReset(); - flag.decimal = false; - } - - final override void dec_addWithCarry(ubyte val) - { - super.dec_addWithCarry(val); - peek(programCounter); - // TODO: fix this - static if (cumulative) tick(1); - flag.zero_ = flag.negative_ = accumulator; - } - - final override void dec_subWithCarry(ubyte val) - { - int a = accumulator; - int al = (a & 0x0F) - (val & 0x0F) - !flag.carry; - a = a - val - !flag.carry; - if (a < 0) - a = a - 0x60; - if (al < 0) - a = a - 0x06; - - uint diff = accumulator - val - !flag.carry; - flag.overflow = - ((accumulator ^ diff) & 0x80) && - ((accumulator ^ val) & 0x80); - flag.carry = (diff < 0x100); - - peek(programCounter); - // TODO: fix this - static if (cumulative) tick(1); - flag.zero_ = flag.negative_ = accumulator = cast(ubyte)a; - } - - final void addrZeropageI() - { - ubyte vector = readByteOperand(); - primaryAddress = readWord(vector, cast(ubyte)(vector + 1)); - } - - final void addrNone() - { - static if (cumulative) tick(totalCycles); - } - - final ubyte testSet(ubyte val) - { - flag.zero_ = val & accumulator; - return val | accumulator; - } - - final ubyte testReset(ubyte val) - { - flag.zero_ = val & accumulator; - return val & ~accumulator; - } - - static string RMW(string action) - { - return "peek(primaryAddress);\n" ~ - "writeFinal(primaryAddress, (flag.zero_ = flag.negative_ = " ~ - action ~ "(readVal = read(primaryAddress))));\n"; - } - - static string TestModify(string action) - { - return "peek(primaryAddress);\n" ~ - "writeFinal(primaryAddress, " ~ - action ~ "(readVal = read(primaryAddress)));\n"; - } - - static string ReadNOP() - { - return "readVal = readFinal(primaryAddress);\n"; - } - - static string ManualAddress(string name, int[] opcodes, - string mode) - { - string modes = "[[\"" ~ name ~ "\", \"NA\"], \n"; - for (int op = 0; op < opcodes.length; ++op) - { - int opcode = opcodes[op]; - modes ~= "[\"" ~ hexByte(opcode) ~ "\", \"" ~ mode ~ "\"]"; - if (op != (opcodes.length - 1)) modes ~= ", "; - modes ~= "\n"; - } - return modes ~ "]\n"; - } - - mixin(Opcode(mixin(Type2Address( - "ASL", "Read", [0x06, 0x0E, 0x16, 0x1E])), - RMW("shiftLeft"))); - mixin(Opcode(mixin(Type2Address( - "LSR", "Read", [0x46, 0x4E, 0x56, 0x5E])), - RMW("shiftRight"))); - mixin(Opcode(mixin(Type2Address( - "ROL", "Read", [0x26, 0x2E, 0x36, 0x3E])), - RMW("rotateLeft"))); - mixin(Opcode(mixin(Type2Address( - "ROR", "Read", [0x66, 0x6E, 0x76, 0x7E])), - RMW("rotateRight"))); - mixin(Opcode(mixin(Type2Address( - "INC", "Read", [0xE6, 0xEE, 0xF6])), - RMW("increment"))); - mixin(Opcode(mixin(Type2Address( - "DEC", "Read", [0xC6, 0xCE, 0xD6])), - RMW("decrement"))); - mixin(Opcode(mixin(Type2Address( - "INC", "Write", [0xFE])), - RMW("increment"))); - mixin(Opcode(mixin(Type2Address( - "DEC", "Write", [0xDE])), - RMW("decrement"))); - - - mixin(Opcode(mixin(Type2Address( - "BIT", "Read", [0x34, 0x3C])), - BitTest())); - mixin(Opcode([["ORA", "Read"], ["12", "ZeropageI()"]], - Read("accumulator |="))); - mixin(Opcode([["AND", "Read"], ["32", "ZeropageI()"]], - Read("accumulator &="))); - mixin(Opcode([["EOR", "Read"], ["52", "ZeropageI()"]], - Read("accumulator ^="))); - mixin(Opcode([["LDA", "Read"], ["B2", "ZeropageI()"]], - Read("accumulator ="))); - mixin(Opcode([["CMP", "Read"], ["D2", "ZeropageI()"]], - Compare("accumulator"))); - mixin(Opcode([["ADC", "Read"], ["72", "ZeropageI()"]], - Decimal("addWithCarry"))); - mixin(Opcode([["SBC", "Read"], ["F2", "ZeropageI()"]], - Decimal("subWithCarry"))); - mixin(Opcode([["STA", "Write"], ["92", "ZeropageI()"]], - Write("accumulator"))); - - mixin(RegisterOpcode("DEA", "3A", "accumulator -= 1")); - mixin(RegisterOpcode("INA", "1A", "accumulator += 1")); - mixin(SimpleOpcode("PHX", "DA", "push(xIndex)")); - mixin(SimpleOpcode("PHY", "5A", "push(yIndex)")); - mixin(RegisterOpcode("PLX", "FA", "xIndex = pull()")); - mixin(RegisterOpcode("PLY", "7A", "yIndex = pull()")); - mixin(BranchOpcode("BRA", "80", "true")); - - mixin(Opcode([["TRB", "Read"], - ["14", "Zeropage()"], ["1C", "Absolute"]], - TestModify("testReset"))); - mixin(Opcode(mixin(Type2Address( - "TSB", "Read", [0x04, 0x0C])), - TestModify("testSet"))); - mixin(Opcode([["STZ", "Write"], - ["64", "Zeropage()"], ["74", "ZeropageX()"], - ["9C", "Absolute()"], ["9E", "AbsoluteX(true)"]], - Write("0"))); - - mixin(Opcode(mixin(ManualAddress( - "NOP", [0x02, 0x22, 0x42, 0x62, 0x82, 0xC2, 0xE2], - "Immediate")), - ReadNOP())); - mixin(Opcode(mixin(ManualAddress( - "NOP", [0x44], - "Zeropage()")), - ReadNOP())); - mixin(Opcode(mixin(ManualAddress( - "NOP", [0x54, 0xD4, 0xF4], - "ZeropageX()")), - ReadNOP())); - mixin(Opcode(mixin(ManualAddress( - "NOP", [0xDC, 0xFC], - "AbsoluteX(false)")), - ReadNOP())); - mixin(Opcode(mixin(ManualAddress( - "NOP", [0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, - 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, 0x07, 0x17, 0x27, 0x37, - 0x47, 0x57, 0x67, 0x77, 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, - 0xE7, 0xF7, 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, - 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, 0x0F, 0x1F, - 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, 0x8F, 0x9F, 0xAF, 0xBF, - 0xCF, 0xDF, 0xEF, 0xFF], "None()")), - "")); - - /* NOP8 */ - void opcode5C() - { - readByteOperand(); - peek(programCounter++); - peek(0xFF00 | operand1); - peek(0xFFFF); - peek(0xFFFF); - peek(0xFFFF); - peek(0xFFFF); - static if (cumulative) tick(totalCycles); - } - - /* JMP ($$$$) */ - override void opcode6C() - { - ushort vector = readWordOperand(); - peek(programCounter); - programCounter = readWord(vector, cast(ushort)(vector + 1)); - static if (cumulative) tick(totalCycles); - } - - /* JMP ($$$$,X) */ - void opcode7C() - { - baseAddress = readWordOperand(); - peek(programCounter); - ushort vector = cast(ushort)(baseAddress + xIndex); - programCounter = readWord(vector, cast(ushort)(vector + 1)); - static if (cumulative) tick(totalCycles); - } - - /* BIT #$$ */ - void opcode89() - { - readVal = operand1 = readFinal(programCounter++); - flag.zero_ = accumulator & readVal; - } -} diff --git a/src/d6502/cpu.d b/src/d6502/cpu.d deleted file mode 100644 index e226afa..0000000 --- a/src/d6502/cpu.d +++ /dev/null @@ -1,751 +0,0 @@ -/+ - + d6502/cpu.d - + - + Copyright: 2007 Gerald Stocker - + - + This file is part of twoapple-reboot. - + - + twoapple-reboot is free software; you can redistribute it and/or modify - + it under the terms of the GNU General Public License as published by - + the Free Software Foundation; either version 2 of the License, or - + (at your option) any later version. - + - + twoapple-reboot is distributed in the hope that it will be useful, - + but WITHOUT ANY WARRANTY; without even the implied warranty of - + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - + GNU General Public License for more details. - + - + You should have received a copy of the GNU General Public License - + along with twoapple-reboot; if not, write to the Free Software - + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - +/ - -module d6502.cpu; - -import d6502.base; - -class Cpu(bool strict, bool cumulative) : CpuBase!(strict, cumulative) -{ - static string InitOpcodes() - { - string initCalls; - for (int op = 0; op < 256; ++op) - { - initCalls ~= "opcodes[0x" ~ hexByte(op) ~ "] = &opcode" ~ - hexByte(op) ~ ";\n"; - } - return initCalls; - } - - this() - { - mixin(InitOpcodes()); - flag = new StatusRegister(); - } - - const ushort STACK_BASE = 0x0100; - const ushort NMI_VECTOR = 0xFFFA; - const ushort RESET_VECTOR = 0xFFFC; - const ushort IRQ_VECTOR = 0xFFFE; - - void delegate()[256] opcodes; - bool continueExecution; - static if (cumulative) int totalCycles; - - - debug(disassemble) - { - import hacking.debugger; - import std.stdio; - } - final override void run(bool continuous) - { - assert ((memory.read !is null) && (memory.write !is null)); - assert (clock.tick !is null); - - continueExecution = continuous; - do - { - if (signalActive) handleSignals(); - - static if (cumulative) totalCycles = 0; - opcodePC = programCounter; - opcode = read(programCounter++); - - /+ TODO: call sync delegate +/ - - opcodes[opcode](); - debug(disassemble) - { - writefln(Debugger.disassemble(this, cmosMap) - ~ Debugger.displayRegisters(this)); - } - } while (continueExecution); - } - - final override void stop() - { - continueExecution = false; - } - - final override void resetLow() - { - resetActive = signalActive = true; - } - - final override void nmiLow(bool signalLow) - { - nmiActive = signalLow; - if (!signalLow) nmiArmed = true; - signalActive = testSignals(); - } - - final override void irqLow(bool signalLow) - { - irqActive = signalLow; - signalActive = testSignals(); - } - - final bool testSignals() - { - return (resetActive || nmiActive || irqActive); - } - - final void handleSignals() - { - bool checkNMI() - { - if (nmiActive && nmiArmed) - { - nmiArmed = false; - return true; - } - return false; - } - - if (resetActive) doReset(); - else if (checkNMI()) do_IRQ_or_NMI(NMI_VECTOR); - else if ((!flag.interrupt) && irqActive) do_IRQ_or_NMI(IRQ_VECTOR); - } - - void do_IRQ_or_NMI(ushort vector) - { - doInterrupt(vector, (flag.toByte() & ~0x10)); - } - - final void doInterrupt(ushort vector, ubyte statusByte) - { - pushWord(programCounter); - push(statusByte); - flag.interrupt = true; - programCounter = readWord(vector, cast(ushort)(vector + 1)); - static if (cumulative) clock.tick(totalCycles); - } - - void doReset() - { - static if (cumulative) - { - totalCycles += 2; - } - else - { - clock.tick(); clock.tick(); - } - - peek(STACK_BASE + stackPointer); - --stackPointer; - peek(STACK_BASE + stackPointer); - --stackPointer; - peek(STACK_BASE + stackPointer); - --stackPointer; - - flag.interrupt = true; - resetActive = false; - signalActive = testSignals(); - - programCounter = readWord(RESET_VECTOR, RESET_VECTOR + 1); - static if (cumulative) clock.tick(totalCycles); - } - - final ubyte read(ushort addr) - { - static if (cumulative) ++totalCycles; - else clock.tick(); - return memory.read(addr); - } - - final void write(ushort addr, ubyte val) - { - static if (cumulative) ++totalCycles; - else clock.tick(); - memory.write(addr, val); - } - - final void peek(ushort addr) - { - static if (cumulative) ++totalCycles; - else clock.tick(); - static if (strict) memory.read(addr); - } - - final void poke(ushort addr, ubyte val) - { - static if (cumulative) ++totalCycles; - else clock.tick(); - static if (strict) memory.write(addr, val); - } - - final ubyte readFinal(ushort addr) - { - static if (cumulative) clock.tick(++totalCycles); - else - { - clock.tick(); - } - return memory.read(addr); - } - - final void writeFinal(ushort addr, ubyte val) - { - static if (cumulative) clock.tick(++totalCycles); - else - { - clock.tick(); - } - memory.write(addr, val); - } - - final ushort readWord(ushort addrLo, ushort addrHi) - { - ushort word = read(addrLo); - return word | (read(addrHi) << 8); - } - - final void push(ubyte val) - { - write((STACK_BASE + stackPointer), val); - --stackPointer; - /+ TODO: call stack overflow delegate +/ - } - - - final void pushWord(ushort val) - { - push(val >> 8); - push(val & 0xFF); - } - - final ubyte readStack() - { - ++stackPointer; - /+ TODO: call stack underflow delegate +/ - return read(STACK_BASE + stackPointer); - } - - final ubyte pull() - { - peek(STACK_BASE + stackPointer); - return readStack(); - } - - final ushort pullWord() - { - ushort word = pull(); - return word | (readStack() << 8); - } - - final ubyte readByteOperand() - { - return (operand1 = read(programCounter++)); - } - - final ushort readWordOperand() - { - operand1 = read(programCounter++); - operand2 = read(programCounter++); - return (operand1 | (operand2 << 8)); - } - - ushort* spuriousAddress; - ushort badAddress, baseAddress, primaryAddress; - ubyte readVal, writeVal; - - final ushort tryShortcut(bool noShortcut, ushort goodAddress) - { - badAddress = (baseAddress & 0xFF00) | cast(ubyte)goodAddress; - if (badAddress != goodAddress) - peek(*spuriousAddress); - else if (noShortcut) - peek(goodAddress); - return goodAddress; - } - - final void addrRelative(byte offset) - { - peek(programCounter); - baseAddress = programCounter; - programCounter = tryShortcut(false, - cast(ushort)(programCounter + offset)); - } - - final void addrZeropage() - { - primaryAddress = readByteOperand(); - } - - final void addrAbsolute() - { - primaryAddress = readWordOperand(); - } - - final void addrZeropageX() - { - baseAddress = badAddress = readByteOperand(); - peek(*spuriousAddress); - primaryAddress = cast(ubyte)(baseAddress + xIndex); - } - - final void addrZeropageY() - { - baseAddress = badAddress = readByteOperand(); - peek(*spuriousAddress); - primaryAddress = cast(ubyte)(baseAddress + yIndex); - } - - final void addrIndirectX() - { - baseAddress = badAddress = readByteOperand(); - peek(*spuriousAddress); - ushort vector = cast(ubyte)(baseAddress + xIndex); - primaryAddress = readWord(vector, cast(ubyte)(vector + 1)); - } - - final void addrAbsoluteX(bool write) - { - baseAddress = readWordOperand(); - primaryAddress = tryShortcut(write, - cast(ushort)(baseAddress + xIndex)); - } - - final void addrAbsoluteY(bool write) - { - baseAddress = readWordOperand(); - primaryAddress = tryShortcut(write, - cast(ushort)(baseAddress + yIndex)); - } - - final void addrIndirectY(bool write) - { - ubyte vector = readByteOperand(); - baseAddress = readWord(vector, cast(ubyte)(vector + 1)); - primaryAddress = tryShortcut(write, - cast(ushort)(baseAddress + yIndex)); - } - - void dec_addWithCarry(ubyte val) - { - int a = accumulator; - int al = (a & 0x0F) + (val & 0x0F) + flag.carry; - if (al >= 0x0A) - al = ((al + 0x06) & 0x0F) + 0x10; - a = (a & 0xF0) + (val & 0xF0) + al; - - flag.negative_ = cast(ubyte)a; - flag.zero_ = cast(ubyte)(accumulator + val + flag.carry); - flag.overflow = - (!((accumulator ^ val) & 0x80)) && ((val ^ a) & 0x80); - - if (a >= 0xA0) - a = a + 0x60; - - flag.carry = (a >= 0x100); - accumulator = cast(ubyte)a; - } - - void dec_subWithCarry(ubyte val) - { - int a = accumulator; - int al = (a & 0x0F) - (val & 0x0F) - !flag.carry; - if (al < 0) - al = ((al - 0x06) & 0x0F) - 0x10; - a = (a & 0xF0) - (val & 0xF0) + al; - if (a < 0) - a = a - 0x60; - - uint diff = accumulator - val - !flag.carry; - flag.overflow = - ((accumulator ^ diff) & 0x80) && - ((accumulator ^ val) & 0x80); - flag.carry = (diff < 0x100); - flag.zero_ = flag.negative_ = cast(ubyte)diff; - - accumulator = cast(ubyte)a; - } - - final void hex_addWithCarry(ubyte val) - { - uint sum = accumulator + val + flag.carry; - - flag.overflow = - (!((accumulator ^ val) & 0x80)) && ((val ^ sum) & 0x80); - flag.carry = (sum > 0xFF); - - flag.zero_ = flag.negative_ = (accumulator = cast(ubyte)sum); - } - - final void hex_subWithCarry(ubyte val) - { - uint diff = accumulator - val - (flag.carry ? 0 : 1); - - flag.overflow = - ((accumulator ^ diff) & 0x80) && - ((accumulator ^ val) & 0x80); - flag.carry = (diff < 0x100); - - flag.zero_ = flag.negative_ = (accumulator = cast(ubyte)diff); - } - - final ubyte compare(ubyte reg, ubyte val) - { - flag.carry = (reg >= val); - return cast(ubyte)(reg - val); - } - - final void bitTest(ubyte val) - { - flag.negative_ = val; - flag.zero_ = accumulator & val; - flag.overflow = ((val & 0x40) != 0); - } - - final ubyte shiftLeft(ubyte val) - { - flag.carry = (val > 0x7F); - return cast(ubyte)(val << 1); - } - - final ubyte rotateLeft(ubyte val) - { - bool oldCarry = flag.carry; - flag.carry = (val > 0x7F); - val = cast(ubyte)(val << 1 | (oldCarry ? 1 : 0)); - return val; - } - - final ubyte shiftRight(ubyte val) - { - flag.carry = ((val & 0x01) != 0); - return val >> 1; - } - - final ubyte rotateRight(ubyte val) - { - bool oldCarry = flag.carry; - flag.carry = ((val & 0x01) != 0); - val = (val >> 1 | (oldCarry ? 0x80 : 0)); - return val; - } - - final ubyte increment(ubyte val) - { - return cast(ubyte)(val + 1); - } - - final ubyte decrement(ubyte val) - { - return cast(ubyte)(val - 1); - } - - static string SimpleOpcode(string name, string opcode, string action) - { - string code = "peek(programCounter);\n"; - code ~= (action == "") ? "" : (action ~ ";"); - static if (cumulative) code ~= "clock.tick(totalCycles);\n"; - return "override void opcode" ~ opcode ~ "()\n{\n" ~ code ~ "\n}\n"; - } - - static string UpdateNZ(string action) - { - return "flag.zero_ = flag.negative_ = (" ~ action ~ ");" ~ "\n"; - } - - static string RegisterOpcode(string name, string opcode, string action) - { - string code = "peek(programCounter);\n"; - code ~= UpdateNZ(action); - static if (cumulative) code ~= "clock.tick(totalCycles);\n"; - return "override void opcode" ~ opcode ~ "()\n{\n" ~ code ~ "}\n"; - } - - static string BranchOpcode(string name, string opcode, string action) - { - string code = "readByteOperand();\n" ~ - "if (" ~ action ~ ") addrRelative(cast(byte)operand1);\n"; - static if (cumulative) code ~= "clock.tick(totalCycles);\n"; - return "override void opcode" ~ opcode ~ "()\n{\n" ~ code ~ "}\n"; - } - - static string Type1Address(string name, string rw, int[] opcodes) - { - string type = (rw == "Write") ? "true" : "false"; - string modes = "[[\"" ~ name ~ "\", \"" ~ rw ~ "\"], \n"; - for (int op = 0; op < opcodes.length; ++op) - { - int opcode = opcodes[op]; - modes ~= "[\"" ~ hexByte(opcode) ~ "\", \""; - final switch ((opcode & 0b00011100) >> 2) - { - case 0: - modes ~= "IndirectX()"; - break; - case 1: - modes ~= "Zeropage()"; - break; - case 2: - modes ~= "Immediate"; - break; - case 3: - modes ~= "Absolute()"; - break; - case 4: - modes ~= "IndirectY("~ type ~ ")"; - break; - case 5: - modes ~= "ZeropageX()"; - break; - case 6: - modes ~= "AbsoluteY(" ~ type ~ ")"; - break; - case 7: - modes ~= "AbsoluteX(" ~ type ~ ")"; - break; - } - modes ~= "\"]"; - if (op != (opcodes.length - 1)) modes ~= ", "; - modes ~= "\n"; - } - return modes ~ "]\n"; - } - - static string Type2Address(string name, string rw, int[] opcodes) - { - string type = (rw == "Write") ? "true" : "false"; - string index = (name[2] == 'X') ? "Y" : "X"; - string modes = "[[\"" ~ name ~ "\", \"" ~ rw ~ "\"], \n"; - for (int op = 0; op < opcodes.length; ++op) - { - int opcode = opcodes[op]; - modes ~= "[\"" ~ hexByte(opcode) ~ "\", \""; - final switch ((opcode & 0b00011100) >> 2) - { - case 0: - modes ~= "Immediate"; - break; - case 1: - modes ~= "Zeropage()"; - break; - case 3: - modes ~= "Absolute()"; - break; - case 5: - modes ~= "Zeropage" ~ index ~ "()"; - break; - case 7: - modes ~= "Absolute" ~ index ~ "(" ~ type ~ ")"; - break; - } - modes ~= "\"]"; - if (op != (opcodes.length - 1)) modes ~= ", "; - modes ~= "\n"; - } - return modes ~ "]\n"; - } - - static string Opcode(string[][] details, string action) - { - string methods; - for (int op = 1; op < details.length; ++op) - { - methods ~= "override void opcode" ~ details[op][0] ~ "()\n{\n"; - if (details[op][1] == "Immediate") - { - methods ~= "primaryAddress = programCounter++;\n" ~ - action ~ "operand1 = readVal;\n"; - } - else - { - methods ~= "addr" ~ details[op][1] ~ ";\n" ~ action; - } - methods ~= "}\n"; - } - return methods; - } - - static string Read(string action) - { - return UpdateNZ(action ~ " (readVal = readFinal(primaryAddress))"); - } - - static string Decimal(string action) - { - string code = action ~ "(readVal = readFinal(primaryAddress));\n"; - return "if (flag.decimal) dec_" ~ code ~ - "else hex_" ~ code; - } - - static string Compare(string action) - { - return UpdateNZ("compare(" ~ action ~ - ", (readVal = readFinal(primaryAddress)))"); - } - - static string Write(string action) - { - return "writeFinal(primaryAddress, " ~ action ~ ");\n"; - } - - static string BitTest() - { - return "bitTest(readVal = readFinal(primaryAddress));\n"; - } - - mixin(SimpleOpcode("CLC", "18", "flag.carry = false")); - mixin(SimpleOpcode("SEC", "38", "flag.carry = true")); - mixin(SimpleOpcode("CLI", "58", "flag.interrupt = false")); - mixin(SimpleOpcode("SEI", "78", "flag.interrupt = true")); - mixin(SimpleOpcode("CLV", "B8", "flag.overflow = false")); - mixin(SimpleOpcode("CLD", "D8", "flag.decimal = false")); - mixin(SimpleOpcode("SED", "F8", "flag.decimal = true")); - - mixin(SimpleOpcode("NOP", "EA", "")); - - mixin(SimpleOpcode("PHP", "08", "push(flag.toByte())")); - mixin(SimpleOpcode("PLP", "28", "flag.fromByte(pull())")); - mixin(SimpleOpcode("PHA", "48", "push(accumulator)")); - mixin(SimpleOpcode("TXS", "9A", "stackPointer = xIndex")); - - mixin(RegisterOpcode("PLA", "68", "accumulator = pull()")); - mixin(RegisterOpcode("TSX", "BA", "xIndex = stackPointer")); - - mixin(RegisterOpcode("TAX", "AA", "xIndex = accumulator")); - mixin(RegisterOpcode("TXA", "8A", "accumulator = xIndex")); - mixin(RegisterOpcode("DEX", "CA", "xIndex -= 1")); - mixin(RegisterOpcode("INX", "E8", "xIndex += 1")); - mixin(RegisterOpcode("TAY", "A8", "yIndex = accumulator")); - mixin(RegisterOpcode("TYA", "98", "accumulator = yIndex")); - mixin(RegisterOpcode("DEY", "88", "yIndex -= 1")); - mixin(RegisterOpcode("INY", "C8", "yIndex += 1")); - - mixin(BranchOpcode("BPL", "10", "flag.negative_ < 0x80")); - mixin(BranchOpcode("BMI", "30", "flag.negative_ > 0x7F")); - mixin(BranchOpcode("BVC", "50", "!flag.overflow")); - mixin(BranchOpcode("BVS", "70", "flag.overflow")); - mixin(BranchOpcode("BCC", "90", "!flag.carry")); - mixin(BranchOpcode("BCS", "B0", "flag.carry")); - mixin(BranchOpcode("BNE", "D0", "flag.zero_ != 0")); - mixin(BranchOpcode("BEQ", "F0", "flag.zero_ == 0")); - - mixin(RegisterOpcode("ASL A", "0A", - "accumulator = shiftLeft(accumulator)")); - mixin(RegisterOpcode("ROL A", "2A", - "accumulator = rotateLeft(accumulator)")); - mixin(RegisterOpcode("LSR A", "4A", - "accumulator = shiftRight(accumulator)")); - mixin(RegisterOpcode("ROR A", "6A", - "accumulator = rotateRight(accumulator)")); - - mixin(Opcode(mixin(Type1Address( - "LDA", "Read", [0xA1, 0xA5, 0xA9, 0xAD, 0xB1, 0xB5, 0xB9, 0xBD])), - Read("accumulator ="))); - mixin(Opcode(mixin(Type1Address( - "ORA", "Read", [0x01, 0x05, 0x09, 0x0D, 0x11, 0x15, 0x19, 0x1D])), - Read("accumulator |="))); - mixin(Opcode(mixin(Type1Address( - "AND", "Read", [0x21, 0x25, 0x29, 0x2D, 0x31, 0x35, 0x39, 0x3D])), - Read("accumulator &="))); - mixin(Opcode(mixin(Type1Address( - "EOR", "Read", [0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D])), - Read("accumulator ^="))); - mixin(Opcode(mixin(Type1Address( - "ADC", "Read", [0x61, 0x65, 0x69, 0x6D, 0x71, 0x75, 0x79, 0x7D])), - Decimal("addWithCarry"))); - mixin(Opcode(mixin(Type1Address( - "SBC", "Read", [0xE1, 0xE5, 0xE9, 0xED, 0xF1, 0xF5, 0xF9, 0xFD])), - Decimal("subWithCarry"))); - mixin(Opcode(mixin(Type1Address( - "CMP", "Read", [0xC1, 0xC5, 0xC9, 0xCD, 0xD1, 0xD5, 0xD9, 0xDD])), - Compare("accumulator"))); - mixin(Opcode(mixin(Type1Address( - "STA", "Write", [0x81, 0x85, 0x8D, 0x91, 0x95, 0x99, 0x9D])), - Write("accumulator"))); - - mixin(Opcode(mixin(Type2Address( - "LDX", "Read", [0xA2, 0xA6, 0xAE, 0xB6, 0xBE])), - Read("xIndex ="))); - mixin(Opcode(mixin(Type2Address( - "LDY", "Read", [0xA0, 0xA4, 0xAC, 0xB4, 0xBC])), - Read("yIndex ="))); - mixin(Opcode(mixin(Type2Address( - "CPX", "Read", [0xE0, 0xE4, 0xEC])), - Compare("xIndex"))); - mixin(Opcode(mixin(Type2Address( - "CPY", "Read", [0xC0, 0xC4, 0xCC])), - Compare("yIndex"))); - mixin(Opcode(mixin(Type2Address( - "STX", "Write", [0x86, 0x8E, 0x96])), - Write("xIndex"))); - mixin(Opcode(mixin(Type2Address( - "STY", "Write", [0x84, 0x8C, 0x94])), - Write("yIndex"))); - mixin(Opcode(mixin(Type2Address( - "BIT", "Read", [0x24, 0x2C])), - BitTest())); - - /* BRK */ - final override void opcode00() - { - peek(programCounter); - ++programCounter; - doInterrupt(IRQ_VECTOR, flag.toByte()); - } - - /* JSR */ - final override void opcode20() - { - ushort finalAddress = (operand1 = read(programCounter++)); - - peek(STACK_BASE + stackPointer); - pushWord(programCounter); - - finalAddress |= ((operand2 = read(programCounter)) << 8); - static if (cumulative) clock.tick(totalCycles); - programCounter = finalAddress; - } - - /* RTI */ - final override void opcode40() - { - peek(programCounter); - flag.fromByte(pull()); - programCounter = readStack() | (readStack() << 8); - static if (cumulative) clock.tick(totalCycles); - } - - /* JMP $$$$ */ - final override void opcode4C() - { - programCounter = readWordOperand(); - static if (cumulative) clock.tick(totalCycles); - } - - /* RTS */ - final override void opcode60() - { - peek(programCounter); - programCounter = pullWord(); - peek(programCounter); - static if (cumulative) clock.tick(totalCycles); - ++programCounter; - } -} diff --git a/src/d6502/nmosbase.d b/src/d6502/nmosbase.d deleted file mode 100644 index 2a2e2b9..0000000 --- a/src/d6502/nmosbase.d +++ /dev/null @@ -1,71 +0,0 @@ -/+ - + d6502/nmosbase.d - + - + Copyright: 2007 Gerald Stocker - + - + This file is part of twoapple-reboot. - + - + twoapple-reboot is free software; you can redistribute it and/or modify - + it under the terms of the GNU General Public License as published by - + the Free Software Foundation; either version 2 of the License, or - + (at your option) any later version. - + - + twoapple-reboot is distributed in the hope that it will be useful, - + but WITHOUT ANY WARRANTY; without even the implied warranty of - + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - + GNU General Public License for more details. - + - + You should have received a copy of the GNU General Public License - + along with twoapple-reboot; if not, write to the Free Software - + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - +/ - -module d6502.nmosbase; - -import d6502.cpu; - -class NmosBase(bool strict, bool cumulative) : Cpu!(strict, cumulative) -{ - enum _isNMOS = true; - - this() - { - super(); - spuriousAddress = &badAddress; - } - - static string RMW(string action) - { - return "poke(primaryAddress, (readVal = read(primaryAddress)));\n" ~ - "writeFinal(primaryAddress, flag.zero_ = flag.negative_ = " ~ - action ~ "(readVal));\n"; - } - - mixin(Opcode(mixin(Type2Address( - "ASL", "Write", [0x06, 0x0E, 0x16, 0x1E])), - RMW("shiftLeft"))); - mixin(Opcode(mixin(Type2Address( - "LSR", "Write", [0x46, 0x4E, 0x56, 0x5E])), - RMW("shiftRight"))); - mixin(Opcode(mixin(Type2Address( - "ROL", "Write", [0x26, 0x2E, 0x36, 0x3E])), - RMW("rotateLeft"))); - mixin(Opcode(mixin(Type2Address( - "ROR", "Write", [0x66, 0x6E, 0x76, 0x7E])), - RMW("rotateRight"))); - mixin(Opcode(mixin(Type2Address( - "INC", "Write", [0xE6, 0xEE, 0xF6, 0xFE])), - RMW("increment"))); - mixin(Opcode(mixin(Type2Address( - "DEC", "Write", [0xC6, 0xCE, 0xD6, 0xDE])), - RMW("decrement"))); - - /* JMP ($$$$) */ - override void opcode6C() - { - ushort vector = readWordOperand(); - programCounter = readWord(vector, - (vector & 0xFF00) | cast(ubyte)(vector + 1)); - static if (cumulative) tick(totalCycles); - } -} diff --git a/src/d6502/nmosundoc.d b/src/d6502/nmosundoc.d deleted file mode 100644 index abea573..0000000 --- a/src/d6502/nmosundoc.d +++ /dev/null @@ -1,365 +0,0 @@ -/+ - + d6502/nmosundoc.d - + - + Copyright: 2007 Gerald Stocker - + - + This file is part of twoapple-reboot. - + - + twoapple-reboot is free software; you can redistribute it and/or modify - + it under the terms of the GNU General Public License as published by - + the Free Software Foundation; either version 2 of the License, or - + (at your option) any later version. - + - + twoapple-reboot is distributed in the hope that it will be useful, - + but WITHOUT ANY WARRANTY; without even the implied warranty of - + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - + GNU General Public License for more details. - + - + You should have received a copy of the GNU General Public License - + along with twoapple-reboot; if not, write to the Free Software - + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - +/ - -module d6502.nmosundoc; - -import d6502.base; -import d6502.nmosbase; - -class NmosUndoc(bool strict, bool cumulative) : NmosBase!(strict, cumulative) -{ - this() - { - super(); - } - - final void addrHalt() - { - programCounter--; - /* TODO: check with the timer how many ticks until it would - * stop me? */ - static if (cumulative) tick(totalCycles); - } - - final void addrImplied() - { - peek(programCounter); - static if (cumulative) tick(totalCycles); - } - - final void strange(ubyte val) - { - version(Commodore64) - { - ubyte hiAddr = cast(ubyte)((primaryAddress >> 8) + 1); - val = val & hiAddr; - ushort addr = (badAddress == primaryAddress) ? primaryAddress : - ((val << 8) | (primaryAddress & 0xFF)); - writeFinal(addr, val); - } - else - { - ubyte hiAddr = cast(ubyte)((baseAddress >> 8) + 1); - writeFinal(primaryAddress, val & hiAddr); - } - } - - static string UndocAddress(string name, string rw, int[] opcodes) - { - string type = (rw == "Write") ? "true" : "false"; - string modes = "[[\"" ~ name ~ "\", \"" ~ rw ~ "\"], \n"; - string index = (name[2] == 'X') ? "Y" : "X"; - for (int op = 0; op < opcodes.length; ++op) - { - int opcode = opcodes[op]; - modes ~= "[\"" ~ hexByte(opcode) ~ "\", \""; - final switch ((opcode & 0b00011100) >> 2) - { - case 0: - modes ~= "IndirectX()"; - break; - case 1: - modes ~= "Zeropage()"; - break; - case 3: - modes ~= "Absolute()"; - break; - case 4: - modes ~= "IndirectY("~ type ~ ")"; - break; - case 5: - modes ~= "Zeropage" ~ index ~ "()"; - break; - case 7: - modes ~= "AbsoluteY(" ~ type ~ ")"; - break; - } - modes ~= "\"]"; - if (op != (opcodes.length - 1)) modes ~= ", "; - modes ~= "\n"; - } - return modes ~ "]\n"; - } - - static string ManualAddress(string name, int[] opcodes, - string mode) - { - string modes = "[[\"" ~ name ~ "\", \"NA\"], \n"; - for (int op = 0; op < opcodes.length; ++op) - { - int opcode = opcodes[op]; - modes ~= "[\"" ~ hexByte(opcode) ~ "\", \"" ~ mode ~ "\"]"; - if (op != (opcodes.length - 1)) modes ~= ", "; - modes ~= "\n"; - } - return modes ~ "]\n"; - } - - static string Halt() - { - /+ TODO: have this do something useful +/ - return "\n"; - } - - static string ReadNOP() - { - return "readVal = readFinal(primaryAddress);\n"; - } - - static string RMW_Read(string action1, string action2) - { - return "poke(primaryAddress, (readVal = read(primaryAddress)));\n" ~ - "writeFinal(primaryAddress, flag.zero_ = flag.negative_ = " ~ - "(writeVal = " ~ action1 ~ "(readVal)));\n" ~ - action2 ~ " writeVal;\n"; - } - - static string RMW_Compare(string action1, string action2) - { - return "poke(primaryAddress, (readVal = read(primaryAddress)));\n" ~ - "writeFinal(primaryAddress, " ~ - "(writeVal = " ~ action1 ~ "(readVal)));\n" ~ - "flag.zero_ = flag.negative_ = " ~ - "compare(" ~ action2 ~ ", writeVal);\n"; - } - - static string RMW_Decimal(string action1, string action2) - { - return "poke(primaryAddress, (readVal = read(primaryAddress)));\n" ~ - "writeFinal(primaryAddress, flag.zero_ = flag.negative_ = " ~ - "(writeVal = " ~ action1 ~ "(readVal)));\n" ~ - "if (flag.decimal) dec_" ~ action2 ~ "(writeVal);\n" ~ - "else hex_" ~ action2 ~ "(writeVal);\n"; - } - - mixin(Opcode(mixin(ManualAddress( - "HLT", [0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 0x92, 0xB2, - 0xD2, 0xF2], "Halt()")), - Halt())); - - mixin(Opcode(mixin(ManualAddress( - "NOP", [0x1A, 0x3A, 0x5A, 0x7A, 0xDA, 0xFA], "Implied()")), - "")); - mixin(Opcode(mixin(ManualAddress( - "NOP", [0x0C], - "Absolute()")), - ReadNOP())); - mixin(Opcode(mixin(ManualAddress( - "NOP", [0x1C, 0x3C, 0x5C, 0x7C, 0xDC, 0xFC], - "AbsoluteX(false)")), - ReadNOP())); - mixin(Opcode(mixin(ManualAddress( - "NOP", [0x80, 0x82, 0x89, 0xC2, 0xE2], - "Immediate")), - ReadNOP())); - mixin(Opcode(mixin(ManualAddress( - "NOP", [0x04, 0x44, 0x64], - "Zeropage()")), - ReadNOP())); - mixin(Opcode(mixin(ManualAddress( - "NOP", [0x14, 0x34, 0x54, 0x74, 0xD4, 0xF4], - "ZeropageX()")), - ReadNOP())); - - mixin(Opcode(mixin(UndocAddress( - "LAX", "Read", [0xA3, 0xA7, 0xAF, 0xB3, 0xB7, 0xBF])), - Read("accumulator = xIndex ="))); - mixin(Opcode(mixin(UndocAddress( - "SAX", "Write", [0x83, 0x87, 0x97, 0x8F])), - Write("accumulator & xIndex"))); - - mixin(Opcode(mixin(Type1Address( - "ASO", "Write", [0x03, 0x07, 0x0F, 0x13, 0x17, 0x1B, 0x1F])), - RMW_Read("shiftLeft", "accumulator |="))); - mixin(Opcode(mixin(Type1Address( - "RLA", "Write", [0x23, 0x27, 0x2F, 0x33, 0x37, 0x3B, 0x3F])), - RMW_Read("rotateLeft", "accumulator &="))); - mixin(Opcode(mixin(Type1Address( - "LSE", "Write", [0x43, 0x47, 0x4F, 0x53, 0x57, 0x5B, 0x5F])), - RMW_Read("shiftRight", "accumulator ^="))); - mixin(Opcode(mixin(Type1Address( - "DCM", "Write", [0xC3, 0xC7, 0xCF, 0xD3, 0xD7, 0xDB, 0xDF])), - RMW_Compare("decrement", "accumulator"))); - mixin(Opcode(mixin(Type1Address( - "RRA", "Write", [0x63, 0x67, 0x6F, 0x73, 0x77, 0x7B, 0x7F])), - RMW_Decimal("rotateRight", "addWithCarry"))); - mixin(Opcode(mixin(Type1Address( - "INS", "Write", [0xE3, 0xE7, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF])), - RMW_Decimal("increment", "subWithCarry"))); - - /* ANC #$$ */ - override void opcode0B() - { - readVal = operand1 = readFinal(programCounter); - flag.zero_ = flag.negative_ = (accumulator = readVal); - flag.carry = (flag.negative_ > 0x7F); - } - - /* ANC #$$ */ - override void opcode2B() - { - readVal = operand1 = readFinal(programCounter); - flag.zero_ = flag.negative_ = (accumulator = readVal); - flag.carry = (flag.negative_ > 0x7F); - } - - /* ALR #$$ */ - override void opcode4B() - { - readVal = operand1 = readFinal(programCounter); - flag.zero_ = flag.negative_ = - (accumulator = shiftRight(accumulator & readVal)); - } - - /* ARR #$$ */ - override void opcode6B() - { - readVal = operand1 = readFinal(programCounter); - ubyte val = readVal & accumulator; - if (flag.decimal) { - ubyte temp = cast(ubyte)((val >> 1) + (flag.carry ? 0x80 : 0)); - flag.zero_ = flag.negative_ = temp; - flag.overflow = (((temp ^ val) & 0x40) != 0); - if ((readVal & 0x0F) + (val & 0x01) > 5) - temp = (temp & 0xF0) + ((temp + 0x6) & 0x0F); - if (val + (val & 0x10) >= 0x60) - { - temp += 0x60; - flag.carry = true; - } - else - flag.carry = false; - accumulator = temp; - } - else { - accumulator = cast(ubyte)((val >> 1) + (flag.carry ? 0x80 : 0)); - flag.zero_ = flag.negative_ = accumulator; - val >>= 7; - flag.carry = (val != 0); - flag.overflow = ((val ^ ((accumulator >> 5) & 1)) != 0); - } - } - - /* ANE #$$ */ - override void opcode8B() - { - // unstable - readVal = operand1 = readFinal(programCounter++); - - version(Atari8Bit) - { - flag.zero_ = flag.negative_ = - (accumulator & xIndex & readVal); - accumulator &= xIndex & (operand1 | 0xEF); - } - else - { - flag.zero_ = flag.negative_ = - (accumulator &= (xIndex & readVal)); - } - } - - /* SHA ($$),Y */ - void opcode93() - { - addrIndirectY(true); - strange(accumulator & xIndex); - } - - /* SHA $$$$,Y */ - void opcode9F() - { - addrAbsoluteY(true); - strange(accumulator & xIndex); - } - - /* SHS $$$$,Y */ - void opcode9B() - { - addrAbsoluteY(true); - strange(stackPointer = (accumulator & xIndex)); - } - - /* SHY $$$$,X */ - void opcode9C() - { - addrAbsoluteX(true); - strange(yIndex); - } - - /* SHX $$$$,Y */ - void opcode9E() - { - addrAbsoluteY(true); - strange(xIndex); - } - - /* LAX #$$ */ - override void opcodeAB() - { - readVal = operand1 = readFinal(programCounter); - - version(Commodore128) - { - // not unstable? - flag.zero_ = flag.negative_ = - (accumulator = readVal); - } - else - { - // unstable - version(Commodore64) - { - accumulator |= 0xEE; - } - flag.zero_ = flag.negative_ = - (accumulator &= readVal); - } - xIndex = accumulator; - } - - /* LAS $$$$,Y */ - override void opcodeBB() - { - addrAbsoluteY(false); - readVal = readFinal(primaryAddress); - - flag.zero_ = flag.negative_ = - (xIndex = accumulator = (stackPointer & readVal)); - } - - /* SBX #$$ */ - override void opcodeCB() - { - readVal = operand1 = readFinal(programCounter++); - xIndex &= accumulator; - flag.zero_ = flag.negative_ = compare(xIndex, readVal); - } - - /* SBC #$$ */ - override void opcodeEB() - { - readVal = operand1 = readFinal(programCounter++); - if (flag.decimal) dec_subWithCarry(readVal); - else hex_subWithCarry(readVal); - } -} diff --git a/src/system/base.d b/src/system/base.d index 417773b..844cc77 100644 --- a/src/system/base.d +++ b/src/system/base.d @@ -24,9 +24,7 @@ module system.base; import timer; import memory; -import d6502.base; - -private alias d6502.base.CpuBase!(Strict.no, Cumulative.no) CpuBase; +import cpu.d6502; import ui.sound; import ui.inputevents; @@ -36,14 +34,31 @@ import system.video; import iomem; import video.base; import system.peripheral; +import ioummu; -class System + +class SystemBase +{ + Video video_; + + abstract void reboot(); + abstract void reset(); + abstract uint checkpoint(); + abstract uint sinceCheckpoint(uint cp); + abstract void execute(); +} + +class System(string chip) : SystemBase { Timer timer; Timer.Cycle deviceCycle; AddressDecoder decoder; SoftSwitchPage switches; - CpuBase cpu; + + Cpu!(chip, AddressDecoder, Timer) cpu; + // XXX + bool* cpuRun, signalActive, resetLow; + IOMem ioMem; Peripherals peripherals; @@ -73,15 +88,15 @@ class System } } - Video video_; Memory memory_; IO io_; - abstract IO newIO(); - abstract CpuBase newCpu(); - abstract Video newVideo(ubyte[] vidRom); - abstract IOMem newIOMem(); - abstract Peripherals newPeripherals(); + static if (chip == "65C02") + { + AuxiliaryCard auxCard; + MMU mmu; + IOU iou; + } this(ubyte[] romDump) { @@ -91,7 +106,10 @@ class System initIO(null); // XXX where is vidRom passed in? decoder.nullRead = &video_.scanner.floatingBus; - peripherals = newPeripherals(); + static if (chip == "6502") + peripherals = new Peripherals_II(); + else + peripherals = new Peripherals_IIe(); peripherals.install(decoder, memory_.mainRom); ioMem.initialize(decoder, switches, timer, peripherals); @@ -99,15 +117,22 @@ class System switches.setFloatingBus(&video_.scanner.floatingBus); } - void reboot() + override void reboot() { - cpu.reboot(); + // XXX replace + //cpu.reboot(); deviceCycle.restart(); memory_.reboot(); ioMem.reboot(); io_.reboot(); peripherals.reboot(); video_.reboot(); + + static if (chip == "65C02") + { + auxCard.reboot(); + mmu.reboot(); + } } void initTimer() @@ -120,56 +145,92 @@ class System void initMemory(ubyte[] romDump) { + static if (chip == "65C02") + { + mmu = new MMU(); + mmu.ioMem = new IOMem_IIe(); + mmu.ioMem.setRom(romDump); + } memory_ = new Memory(romDump); decoder = new AddressDecoder(); switches = new SoftSwitchPage(); decoder.installSwitches(switches); decoder.install(memory_.mainRam); decoder.install(memory_.mainRom); - ioMem = newIOMem(); + static if (chip == "6502") + ioMem = new IOMem(); + else + { + ioMem = mmu.ioMem; + auxCard = new Extended80ColumnCard(); + mmu.init(switches, auxCard, decoder, memory_.mainRam, + memory_.mainRom); + } } void initCpu() { - cpu = newCpu(); + cpu = new Cpu!(chip, AddressDecoder, Timer)(decoder, timer); + // XXX + cpuRun = &cpu.keepRunning; + signalActive = &cpu.signalActive; + resetLow = &cpu.resetLow; + debug(disassemble) cpu.memoryName = &decoder.memoryReadName; - cpu.clock.tick = &timer.tick; timer.onPrimaryStop(&primaryStop); - cpu.memory.read = &decoder.read; - cpu.memory.write = &decoder.write; } void initIO(ubyte[] vidRom) { - io_ = newIO(); - video_ = newVideo(vidRom); + static if (chip == "6502") + { + io_ = new IO_II(switches, timer, deviceCycle); + video_ = new Video_II(switches, memory_.vidPages, timer, vidRom, + &io_.kbd.peekLatch, decoder); + } + else + { + io_ = new IO_IIe(switches, timer, deviceCycle); + video_ = new Video_IIe(switches, memory_.vidPages, timer, vidRom, + &io_.kbd.peekLatch, auxCard.vidPages); + iou = new IOU(io_, video_.signal); + iou.initSwitches(switches); + mmu.initIO(video_.scanner, &io_.kbd.peekLatch); + } } bool primaryStop() { - cpu.stop(); + *cpuRun = false; return true; } - void reset() + override void reset() { + static if (chip == "65C02") + { + auxCard.reset(); + mmu.reset(); + } + peripherals.reset(); - cpu.resetLow(); + *signalActive = true; + *resetLow = true; } - uint checkpoint() + override uint checkpoint() { return timer.primaryCounter.currentLength; } - uint sinceCheckpoint(uint cp) + override uint sinceCheckpoint(uint cp) { uint currentLength = timer.primaryCounter.currentLength; return ((currentLength == timer.primaryCounter.startLength) ? cp : (cp - currentLength)); } - void execute() + override void execute() { cpu.run(true); @@ -181,126 +242,3 @@ class System // XXX peripherals get notification } } - -class II : System -{ - import d6502.nmosundoc : NmosUndoc; - - int revision; - - this(ubyte[] romDump) - { - // XXX FIXME XXX - revision = int.max; - super(romDump); - } - - CpuBase newCpu() - { - return new NmosUndoc!(Strict.no, Cumulative.no)(); - } - - IO newIO() - { - return new IO_II(switches, timer, deviceCycle); - } - - Video newVideo(ubyte[] vidRom) - { - return new Video_II(switches, memory_.vidPages, timer, vidRom, - &io_.kbd.peekLatch, decoder); - } - - IOMem newIOMem() - { - return new IOMem(); - } - - Peripherals newPeripherals() - { - return new Peripherals_II(); - } -} - -import ioummu; - -class IIe : System -{ - import d6502.cmos : Cmos; - - AuxiliaryCard auxCard; - MMU mmu; - IOU iou; - - this(ubyte[] romDump) - { - // XXX if different or no aux card? - //auxMemory = new Memory(); - super(romDump); - } - - void reboot() - { - super.reboot(); - auxCard.reboot(); - mmu.reboot(); - } - - void reset() - { - auxCard.reset(); - mmu.reset(); - super.reset(); - } - - CpuBase newCpu() - { - // XXX this is enhanced - return new Cmos!(Strict.no, Cumulative.no)(); - } - - IO newIO() - { - return new IO_IIe(switches, timer, deviceCycle); - } - - Video newVideo(ubyte[] vidRom) - { - return new Video_IIe(switches, memory_.vidPages, timer, vidRom, - &io_.kbd.peekLatch, auxCard.vidPages); - } - - IOMem newIOMem() - { - return mmu.ioMem; - } - - Peripherals newPeripherals() - { - return new Peripherals_IIe(); - } - - void initMemory(ubyte[] romDump) - { - mmu = new MMU(); - mmu.ioMem = new IOMem_IIe(); - mmu.ioMem.setRom(romDump); - - super.initMemory(romDump); - - // XXX XXX XXX - // allow for different card from config - auxCard = new Extended80ColumnCard(); - - mmu.init(switches, auxCard, decoder, memory_.mainRam, - memory_.mainRom); - } - - void initIO(ubyte[] vidRom) - { - super.initIO(vidRom); - iou = new IOU(io_, video_.signal); - iou.initSwitches(switches); - mmu.initIO(video_.scanner, &io_.kbd.peekLatch); - } -} diff --git a/src/twoapple.d b/src/twoapple.d index 80bbb18..68e4fa5 100644 --- a/src/twoapple.d +++ b/src/twoapple.d @@ -20,7 +20,7 @@ import std.stdio; -import d6502.base; +import cpu.d6502; import timer; import memory; import system.base; @@ -39,20 +39,6 @@ import peripheral.diskii; import peripheral.langcard; import peripheral.saturn128; -class TestSystem : II -{ - this(ubyte[] romDump) - { - super(romDump); - } - - void setRom(ubyte[] rom_data) - { - uint rom_len = cast(uint)rom_data.length; - memory_.mainRom.data_[0..12288] = rom_data[(rom_len - 12288)..rom_len]; - } -} - import std.file; import std.string; import device.speaker; @@ -86,11 +72,11 @@ void main(string[] args) TwoappleFile romFile = TwoappleFilePicker.open("ROM file", &checkRomFile); if (romFile is null) return; - System sys; + SystemBase sys; if ((args.length > 1) && (args[1] == "--iie")) - sys = new IIe(cast(ubyte[])std.file.read(romFile.fileName)); + sys = new System!"65C02"(cast(ubyte[])std.file.read(romFile.fileName)); else - sys = new II(cast(ubyte[])std.file.read(romFile.fileName)); + sys = new System!"6502"(cast(ubyte[])std.file.read(romFile.fileName)); appWindow.initSystem(sys); // XXX hack appWindow.configChanged = true; diff --git a/src/ui/mainwindow.d b/src/ui/mainwindow.d index 99982a5..f2f38be 100644 --- a/src/ui/mainwindow.d +++ b/src/ui/mainwindow.d @@ -54,7 +54,7 @@ class TwoappleMainWindow : MainWindow import gtk.Alignment; import peripheral.base; - System system; + SystemBase system; Label speedLabel; ToolItem speedItem; @@ -122,7 +122,7 @@ class TwoappleMainWindow : MainWindow } } - void initSystem(System sys) + void initSystem(SystemBase sys) { showAll(); system = sys;