mirror of
https://github.com/edmccard/twoapple-reboot.git
synced 2024-10-31 21:07:57 +00:00
141 lines
3.9 KiB
D
141 lines
3.9 KiB
D
/+
|
|
+ d6502/base.d
|
|
+
|
|
+ Copyright: 2007 Gerald Stocker
|
|
+
|
|
+ This file is part of Twoapple.
|
|
+
|
|
+ Twoapple 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 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; if not, write to the Free Software
|
|
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+/
|
|
|
|
module d6502.base;
|
|
|
|
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
|
|
{
|
|
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]);
|
|
}
|
|
|
|
ubyte delegate(ushort addr) memoryRead;
|
|
void delegate(ushort addr, ubyte val) memoryWrite;
|
|
debug(disassemble)
|
|
{
|
|
string delegate(ushort addr) memoryName;
|
|
}
|
|
version(CycleAccuracy) void delegate() tick;
|
|
version(CumulativeCycles) void delegate(int cycles) ticks;
|
|
|
|
abstract void run(bool continuous);
|
|
abstract void stop();
|
|
version(CycleAccuracy) abstract bool checkFinalCycle();
|
|
abstract void resetLow();
|
|
abstract void nmiLow(bool signalLow);
|
|
abstract void irqLow(bool signalLow);
|
|
}
|
|
|