twoapple-reboot/test/wrap6502.d
2012-03-30 15:11:41 -04:00

159 lines
2.6 KiB
D

module test.wrap6502;
public import d6502.nmosundoc : NmosUndoc;
public import d6502.cmos : Cmos;
import test.base;
// True if T is the type of a cpu.
template isCpu(T)
{
enum isCpu = __traits(hasMember, T, "_isCpuBase");
}
// True if the cpu type T represents a 6502.
template isNMOS(T)
{
enum isNMOS = __traits(hasMember, T, "_isNMOS");
}
// True if the cpu type T represents a 65C02.
template isCMOS(T)
{
enum isCMOS = __traits(hasMember, T, "_isCMOS");
}
// True if the cpu type T accesses memory on every cycle.
template isStrict(T)
{
enum isStrict = __traits(hasMember, T, "_isStrict");
}
// True if the cpu type T
template isCumulative(T)
{
enum isCumulative = __traits(hasMember, T, "_isCumulative");
}
template CPU(string type, bool strict, bool cumulative)
{
static if (type == "65c02" || type == "65C02")
alias Cmos!(strict, cumulative) CPU;
else static if (type == "6502")
alias NmosUndoc!(strict, cumulative) CPU;
else static assert(0);
}
/*
* Connects a cpu and memory.
*/
void connectCpu(T)(T cpu, ref TestMemory mem)
if (isCpu!T)
{
static if (isCumulative!T)
void tick(int cycles) {}
else
void tick() {}
cpu.memoryRead = &mem.read;
cpu.memoryWrite = &mem.write;
cpu.tick = &tick;
}
class StopException : Exception { this(string msg) { super(msg); } }
void runUntilBRK(T)(T cpu)
if (isCpu!T)
{
assert(cpu.memoryRead !is null);
auto wrappedRead = cpu.memoryRead;
ubyte read(ushort addr)
{
if (addr == 0xFFFE) throw new StopException("BRK");
return wrappedRead(addr);
}
cpu.memoryRead = &read;
try { cpu.run(true); } catch (StopException e) {}
}
void runOneOpcode(T)(T cpu)
if (isCpu!T)
{
cpu.run(false);
}
void setPC(T)(T cpu, int addr)
if (isCpu!T)
{
cpu.programCounter = cast(ushort)addr;
}
ushort getPC(T)(T cpu)
if (isCpu!T)
{
return cpu.programCounter;
}
void setSP(T)(T cpu, int val)
if (isCpu!T)
{
cpu.stackPointer = cast(ubyte)val;
}
ushort getSP(T)(T cpu)
if (isCpu!T)
{
return 0x100 | cpu.stackPointer;
}
void setX(T)(T cpu, int val)
if (isCpu!T)
{
cpu.xIndex = cast(ubyte)val;
}
ubyte getX(T)(T cpu)
if (isCpu!T)
{
return cpu.xIndex;
}
void setY(T)(T cpu, int val)
if (isCpu!T)
{
cpu.yIndex = cast(ubyte)val;
}
ubyte getY(T)(T cpu)
if (isCpu!T)
{
return cpu.yIndex;
}
void setFlag(T)(T cpu, Flag f)
if (isCpu!T)
{
cpu.flag.fromByte(cpu.flag.toByte() | f);
}
void clearFlag(T)(T cpu, Flag f)
if (isCpu!T)
{
cpu.flag.fromByte(cpu.flag.toByte() & ~f);
}
bool getFlag(T)(T cpu, Flag f)
if (isCpu!T)
{
return (cpu.flag.toByte() & f) != 0;
}