summaryrefslogtreecommitdiff
path: root/native/Noddybox.Emulation.EightBit.Z80.Test/TestMachine.cs
diff options
context:
space:
mode:
Diffstat (limited to 'native/Noddybox.Emulation.EightBit.Z80.Test/TestMachine.cs')
-rw-r--r--native/Noddybox.Emulation.EightBit.Z80.Test/TestMachine.cs260
1 files changed, 258 insertions, 2 deletions
diff --git a/native/Noddybox.Emulation.EightBit.Z80.Test/TestMachine.cs b/native/Noddybox.Emulation.EightBit.Z80.Test/TestMachine.cs
index 09e868b..b5d7810 100644
--- a/native/Noddybox.Emulation.EightBit.Z80.Test/TestMachine.cs
+++ b/native/Noddybox.Emulation.EightBit.Z80.Test/TestMachine.cs
@@ -26,7 +26,7 @@ namespace Noddybox.Emulation.EightBit.Z80.Test
{
private readonly byte[] mem = new byte[0x10000];
private readonly Z80Cpu z80 = new Z80Cpu();
- private readonly Clock clock = new Clock(100000, 50);
+ private readonly Clock clock = new Clock(uint.MaxValue, uint.MaxValue);
private void Output(ConsoleColor pen, ConsoleColor paper, string format, params object[] p)
{
@@ -36,6 +36,21 @@ namespace Noddybox.Emulation.EightBit.Z80.Test
Console.ResetColor();
}
+ private Queue<Register16> Decode(string i)
+ {
+ Queue<Register16> l = new Queue<Register16>();
+
+ foreach (string s in i.Split(new char[] {' ', '\t'}, StringSplitOptions.RemoveEmptyEntries))
+ {
+ if (s != "-1")
+ {
+ l.Enqueue(new Register16(UInt16.Parse(s, System.Globalization.NumberStyles.HexNumber)));
+ }
+ }
+
+ return l;
+ }
+
byte IMemory.Read(ushort address)
{
Output(ConsoleColor.Green, ConsoleColor.Black, "Reading {0:X2} from {1:X4}", mem[address], address);
@@ -59,9 +74,250 @@ namespace Noddybox.Emulation.EightBit.Z80.Test
Output(ConsoleColor.Red, ConsoleColor.DarkGray, "Writing {0:X2} to device {1:X4}", value, device);
}
- public TestMachine(string name, List<string> input, List<string> expected)
+ public bool Run(string name, Queue<string> input, Queue<string> expected)
{
Output(ConsoleColor.Black, ConsoleColor.White, "Running test {0}", name);
+
+ Queue<Register16> line = Decode(input.Dequeue());
+ Register16 r = line.Dequeue();
+
+ z80.Acummulator = r.high;
+ z80.StatusFlags = (Z80Flags)r.low;
+
+ z80.BC_Register = line.Dequeue();
+ z80.DE_Register = line.Dequeue();
+ z80.HL_Register = line.Dequeue();
+
+ z80.AF_Alternate = line.Dequeue();
+ z80.BC_Alternate = line.Dequeue();
+ z80.DE_Alternate = line.Dequeue();
+ z80.HL_Alternate = line.Dequeue();
+
+ z80.IX_Register = line.Dequeue();
+ z80.IY_Register = line.Dequeue();
+ z80.StackPointer = line.Dequeue().reg;
+ z80.ProgramCounter = line.Dequeue().reg;
+
+ line = Decode(input.Dequeue());
+
+ z80.InterruptVector = line.Dequeue().low;
+ z80.Refresh = line.Dequeue().low;
+ z80.IFF1_Register = (line.Dequeue().reg != 0);
+ z80.IFF2_Register = (line.Dequeue().reg != 0);
+ z80.IM_Register = line.Dequeue().low;
+ z80.HaltLine = (line.Dequeue().reg != 0);
+
+ int cyclesToRun = Convert.ToInt32(line.Dequeue().reg.ToString("X"));
+
+ while(input.Count > 0)
+ {
+ line = Decode(input.Dequeue());
+
+ if (line.Count > 1)
+ {
+ ushort addr = line.Dequeue().reg;
+
+ foreach (Register16 b in line)
+ {
+ mem[addr++] = b.low;
+ }
+ }
+ }
+
+ while(clock.Ticks < cyclesToRun)
+ {
+ z80.Step();
+ }
+
+ bool ok = true;
+
+ while(expected.Peek().StartsWith(" "))
+ {
+ Output(ConsoleColor.DarkGray, ConsoleColor.Black, "Not yet handled - {0}", expected.Dequeue());
+ }
+
+ line = Decode(expected.Dequeue());
+
+ r = line.Dequeue();
+ if (r.high != z80.Acummulator)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in A, got {1:X}", r.high, z80.Acummulator);
+ ok = false;
+ }
+
+ if ((Z80Flags)r.low != z80.StatusFlags)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0} in F, got {1}", (Z80Flags)r.low, z80.StatusFlags);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.reg != z80.BC_Register.reg)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in BC, got {1:X}", r.reg, z80.BC_Register.reg);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.reg != z80.DE_Register.reg)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in DE, got {1:X}", r.reg, z80.DE_Register.reg);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.reg != z80.HL_Register.reg)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in HL, got {1:X}", r.reg, z80.HL_Register.reg);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.reg != z80.AF_Alternate.reg)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in AF', got {1:X}", r.reg, z80.AF_Alternate.reg);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.reg != z80.BC_Alternate.reg)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in BC', got {1:X}", r.reg, z80.BC_Alternate.reg);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.reg != z80.DE_Alternate.reg)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in DE', got {1:X}", r.reg, z80.DE_Alternate.reg);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.reg != z80.HL_Alternate.reg)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in HL', got {1:X}", r.reg, z80.HL_Alternate.reg);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.reg != z80.IX_Register.reg)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in IX, got {1:X}", r.reg, z80.IX_Register.reg);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.reg != z80.IY_Register.reg)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in IY, got {1:X}", r.reg, z80.IY_Register.reg);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.reg != z80.StackPointer)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in SP, got {1:X}", r.reg, z80.StackPointer);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.reg != z80.ProgramCounter)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in PC, got {1:X}", r.reg, z80.ProgramCounter);
+ ok = false;
+ }
+
+ line = Decode(expected.Dequeue());
+
+ r = line.Dequeue();
+ if (r.low != z80.InterruptVector)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in I, got {1:X}", r.low, z80.InterruptVector);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.low != z80.Refresh)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in R, got {1:X}", r.low, z80.Refresh);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if ((r.reg != 0) != z80.IFF1_Register)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0} in IFF1, got {1}", (r.reg != 0), z80.IFF1_Register);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if ((r.reg != 0) != z80.IFF2_Register)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0} in IFF2, got {1}", (r.reg != 0), z80.IFF2_Register);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if (r.low != z80.IM_Register)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} in IM, got {1:X}", r.low, z80.IM_Register);
+ ok = false;
+ }
+
+ r = line.Dequeue();
+ if ((r.reg != 0) != z80.HaltLine)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0} in HALT, got {1}", (r.reg != 0), z80.HaltLine);
+ ok = false;
+ }
+
+ int cyclesToTest = Convert.ToInt32(line.Dequeue().reg.ToString("X"));
+
+ if (cyclesToTest != clock.Ticks)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0} cycles, got {1}", cyclesToTest, clock.Ticks);
+ ok = false;
+ }
+
+ while (expected.Count > 0)
+ {
+ line = Decode(expected.Dequeue());
+
+ if (line.Count > 1)
+ {
+ ushort addr = line.Dequeue().reg;
+
+ foreach (Register16 b in line)
+ {
+ if (mem[addr] != b.low)
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Expected {0:X} at location {1:X}, got {2:X}", b.low, addr, mem[addr]);
+ ok = false;
+ }
+
+ addr++;
+ }
+ }
+ }
+
+ if (ok)
+ {
+ Output(ConsoleColor.Yellow, ConsoleColor.Black, "Test passed");
+ }
+ else
+ {
+ Output(ConsoleColor.Red, ConsoleColor.Black, "Test FAILED");
+ }
+
+ Console.WriteLine();
+
+ return ok;
+ }
+
+ public TestMachine()
+ {
+ z80.Initialise(this, this, clock);
}
}
}