Beispiel #1
0
        partial void Execute_LoadCommand()
        {
            var openFileDialog = new Microsoft.Win32.OpenFileDialog()
            {
                Filter = "HEX file (*.hex)|*.hex"
            };

            var result = openFileDialog.ShowDialog();

            if (result ?? false)
            {
                var fileName = openFileDialog.FileName;
                var(RAM, startAddr, endAddr) = HexFileLoader.Read(fileName, new byte[64 * 1024]);
                _basicBus = new BasicBus(RAM);
                RawMemory = _basicBus.RAM;
                _cpu.ConnectToBus(_basicBus);
                Memory         = BuildMemoryMap();
                _cpu.PC        = startAddr;
                ProgramCounter = _cpu.PC.ToString("X4");
                MemoryMapRow   = GetMemoryMapRow(startAddr);
                var disassembly = _cpu.Disassemble(startAddr, endAddr);
                DisAsm      = GetDisassembedProgram(disassembly);
                SelectedRow = startAddr.ToString("X4");
            }
        }
Beispiel #2
0
        public void LoadAwithValueWhenOperationIsLDAn()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0x3E },
                { 0x0081, 0x02 },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            // Load 2 into register A, which starts out having a value of 3...
            var cpu = new Z80()
            {
                A = 0x03, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            cpu.Step();

            Assert.Equal(0x02, cpu.A);

            // No affect on Condition Flags
            FlagsUnchanged(cpu);
        }
Beispiel #3
0
        private void HandleStrayOpCodes2()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xDD },
                { 0x0081, 0xDD },
                { 0x0082, 0xDD },
                { 0x0083, 0xFD },
                { 0x0084, 0xDD }, // LD IX &1000
                { 0x0085, 0x21 },
                { 0x0086, 0x00 },
                { 0x0087, 0x10 },
                { 0x0088, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x00, IX = 0x00, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            while (cpu.PC < 0x0088)
            {
                cpu.Step();
            }

            Assert.Equal(0x1000, cpu.IX);
        }
Beispiel #4
0
        public void LoadRfromA()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xED },
                { 0x0081, 0x4F },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x17, R = 0x00, IFF2 = true, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            cpu.Step();

            Assert.Equal(0x17, cpu.A);
            Assert.Equal(0x17, cpu.R);

            // No affect on Condition Flags
            FlagsUnchanged(cpu);
        }
Beispiel #5
0
        private void SwapRegistersWithEXX()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xD9 }, // EXX
                { 0x0081, 0x00 },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                B = 0x11, C = 0x22, D = 0x12, E = 0x23, H = 0x14, L = 0x24, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.Equal(0x0000, cpu.BC);
            Assert.Equal(0x1122, cpu.BC1);
            Assert.Equal(0x0000, cpu.DE);
            Assert.Equal(0x1223, cpu.DE1);
            Assert.Equal(0x0000, cpu.HL);
            Assert.Equal(0x1424, cpu.HL1);

            FlagsUnchanged(cpu);
        }
Beispiel #6
0
        private void SwapAFandAFPrime()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0x08 }, // EX AF,AF'
                { 0x0081, 0x00 },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x11, F = (Flags)0x22, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.Equal(0x0000, cpu.AF);
            Assert.Equal(0x1122, cpu.AF1);
            FlagsUnchanged(cpu);
        }
Beispiel #7
0
        private void SwapDEandHL()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xEB }, // EX DE,HL
                { 0x0081, 0x00 },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                D = 0x11, E = 0x22, H = 0x33, L = 0x44, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.Equal(0x3344, cpu.DE);
            Assert.Equal(0x1122, cpu.HL);
            FlagsUnchanged(cpu);
        }
Beispiel #8
0
        private void JumpToIY()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xFD }, // JR IY
                { 0x0081, 0xE9 },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },
                { 0x0085, 0x00 },
                { 0x0086, 0x00 }, // <- jump here
                { 0x0087, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x00, IY = 0x0086, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.Equal(0x086, cpu.PC);
            FlagsUnchanged(cpu);
        }
Beispiel #9
0
        private void EnableInterruptBySettingIFF()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xFB }, // EI
                { 0x0081, 0x00 },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x00, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.True(cpu.IFF1);
            Assert.True(cpu.IFF2);
        }
Beispiel #10
0
        private void JumpForwardFourForJRNZPositiveSix_NotZeroSet()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0x20 }, // JR NZ $+6
                { 0x0081, 0x04 }, // Assembler with compensate for PC incrementing twice
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },
                { 0x0085, 0x00 },
                { 0x0086, 0x00 }, // <- jump here
                { 0x0087, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x00, PC = 0x0080
            };

            cpu.F = (Flags)0b00000000; // Reset Z flag
            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.Equal(0x086, cpu.PC);
        }
Beispiel #11
0
        private void DoNotJumpForwardFourForJRCPositiveSix_CarryNotSet()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0x38 }, // JR C $+6
                { 0x0081, 0x04 }, // Assembler with compensate for PC incrementing twice
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },
                { 0x0085, 0x00 },
                { 0x0086, 0x00 },
                { 0x0087, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x00, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.Equal(0x082, cpu.PC);
            FlagsUnchanged(cpu);
        }
Beispiel #12
0
        private void NotJumpBackFourForDJNZ_WhenZero()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x007C, 0x00 }, // <- jump here
                { 0x007D, 0x00 },
                { 0x007E, 0x00 },
                { 0x007F, 0x00 },
                { 0x0080, 0x10 }, // DJNZ $-4
                { 0x0081, 0xFA }, // Assembler with compensate for PC incrementing twice
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },
                { 0x0085, 0x00 },
                { 0x0086, 0x00 },
                { 0x0087, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                B = 0x01, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.Equal(0x082, cpu.PC);
        }
Beispiel #13
0
        private void DisassembleArithmetic1HexFileCorrectly()
        {
            var fakeBus = A.Fake <IBus>();

            var expectedDisassembly = new Dictionary <ushort, string>
            {
                { 0x0080, "LD A,&05" },
                { 0x0082, "LD B,&0A" },
                { 0x0084, "ADD A,B" },
                { 0x0085, "ADD A,A" },
                { 0x0086, "LD C,&0F" },
                { 0x0088, "SUB A,C" },
                { 0x0089, "LD H,&08" },
                { 0x008B, "LD L,&FF" },
                { 0x008D, "LD (HL),A" },
                { 0x008E, "NOP" },
            };

            var ram = HexFileReader.Read("../../../HexFiles/Arithmetic1.hex");

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => ram[addr]);

            var cpu = new Z80()
            {
                A = 0x00, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            var disassembledCode = cpu.Disassemble(0x0080, 0x008E);

            Assert.Equal(expectedDisassembly, disassembledCode);
        }
Beispiel #14
0
        private void LoadProgramCounterWithAddressForJPNN()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xC3 }, // JP 0191h
                { 0x0081, 0x91 },
                { 0x0082, 0x01 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },

                { 0x0190, 0x00 },
                { 0x0191, 0x00 }, // <- jump here
                { 0x0192, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x00, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.Equal(0x0191, cpu.PC);
            FlagsUnchanged(cpu);
        }
Beispiel #15
0
        private void DisassembleMultiplicationHexFileCorrectly()
        {
            var fakeBus = A.Fake <IBus>();
            var ram     = HexFileReader.Read("../../../HexFiles/Multiplication.hex");

            var expectedDisassembly = new Dictionary <ushort, string>
            {
                { 0x8000, "LD BC,&0015" },
                { 0x8003, "LD B,&08" },
                { 0x8005, "LD DE,&002A" },
                { 0x8008, "LD D,&00" },
                { 0x800A, "LD HL,&0000" },
                { 0x800D, "SRL C" },
                { 0x800F, "JR C,$+3" },
                { 0x8011, "ADD HL,DE" },
                { 0x8012, "SLA E" },
                { 0x8014, "RL D" },
                { 0x8016, "DEC B" },
                { 0x8017, "JP NZ,&800D" },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => ram[addr]);


            var cpu = new Z80()
            {
                A = 0x00, PC = 0x8000
            };

            cpu.ConnectToBus(fakeBus);
            var disassembledCode = cpu.Disassemble(0x8000, 0x8017);

            Assert.Equal(expectedDisassembly, disassembledCode);
        }
Beispiel #16
0
        private void SetInterruptMode2()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xED }, // IM 2
                { 0x0081, 0x5E },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x00, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.True(cpu.InterruptMode == InterruptMode.Mode2);
        }
Beispiel #17
0
        private void DisassembleDDCBandFDCBOpcodesCorrectly()
        {
            var fakeBus = A.Fake <IBus>();
            var ram     = HexFileReader.Read("../../../HexFiles/TestDDCBandFDCB.hex");

            var expectedDisassembly = new Dictionary <ushort, string>
            {
                { 0x8000, "RL (IX+2)" },
                { 0x8004, "RL (IY-3)" },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => ram[addr]);


            var cpu = new Z80()
            {
                A = 0x00, PC = 0x8000
            };

            cpu.ConnectToBus(fakeBus);
            var disassembledCode = cpu.Disassemble(0x8000, 0x8007);

            Assert.Equal(expectedDisassembly, disassembledCode);
        }
Beispiel #18
0
        private void DecrementRegisterFlagsTest2()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0x15 },
                { 0x0081, 0x00 },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                D = 0x80, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            cpu.Step();

            Assert.Equal(0x7F, cpu.D);

            Assert.True((cpu.F & Z80.Flags.N) == Z80.Flags.N);
            Assert.False((cpu.F & Z80.Flags.Z) == Z80.Flags.Z);
            Assert.False((cpu.F & Z80.Flags.S) == Z80.Flags.S);
            Assert.True((cpu.F & Z80.Flags.H) == Z80.Flags.H);
            Assert.True((cpu.F & Z80.Flags.P) == Z80.Flags.P);
            Assert.False((cpu.F & Z80.Flags.C) == Z80.Flags.C);
            Assert.True((cpu.F & Z80.Flags.U) == Z80.Flags.U);
            Assert.True((cpu.F & Z80.Flags.X) == Z80.Flags.X);
        }
Beispiel #19
0
        static void Main(string[] args)
        {
            var ram = new byte[65536];

            Array.Clear(ram, 0, ram.Length);
            var romData = File.ReadAllBytes(_rom);

            if (romData.Length != 16384)
            {
                throw new InvalidOperationException("Not a valid ROM file");
            }

            Array.Copy(romData, ram, 16384);
            _cpu = new Z80();
            IBus simpleBus = new SimpleBus(ram);

            _cpu.ConnectToBus(simpleBus);

            Console.Clear();

            while (!(Console.KeyAvailable && (Console.ReadKey(true).Key == ConsoleKey.Escape)))
            {
                try
                {
                    _cpu.Step();
                    Console.Write($"\rPC: {_cpu.PC.ToString("X4")}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(ex.StackTrace);
                    Console.ReadLine();
                }
            }

            Console.WriteLine();
            Console.WriteLine();

            for (var i = 0x4000; i < 0x5800; i++)
            {
                if (i % 16 == 0)
                {
                    Console.Write("{0:X4} | ", i);
                }
                {
                    Console.Write("{0:x2} ", ram[i]);
                }

                if (i % 8 == 7)
                {
                    Console.Write("  ");
                }

                if (i % 16 == 15)
                {
                    Console.WriteLine();
                }
            }
        }
Beispiel #20
0
        public void LoadAWithNegative7WhenSubtracting6And12AndCarryFlagSetForOpcodeSBCAN()
        {
            // ======================================
            // Testing a negative result: 6 - 12 - 1 = -6
            // ======================================

            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xDE }, // SBC A, n
                { 0x0081, 0x0C }, // n = 12
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },

                // Data
                { 0x08FB, 0x00 },
                { 0x08FC, 0x00 },
                { 0x08FD, 0x00 },
                { 0x08FE, 0x00 },
                { 0x08FF, 0x00 },
                { 0x0900, 0x00 },
                { 0x0901, 0x00 },
                { 0x0902, 0x00 },
                { 0x0903, 0x00 },
                { 0x0904, 0x00 },
                { 0x0905, 0x00 },
                { 0x0906, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x06, F = Z80.Flags.C, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            cpu.Step();

            Assert.Equal(0xF9, cpu.A);
            sbyte signedResult = (sbyte)cpu.A;

            Assert.Equal(-7, signedResult);
            Assert.True((cpu.F & Z80.Flags.N) == Z80.Flags.N); // Set due to a subtraction

            Assert.False((cpu.F & Z80.Flags.Z) == Z80.Flags.Z);
            Assert.True((cpu.F & Z80.Flags.S) == Z80.Flags.S);
            Assert.True((cpu.F & Z80.Flags.H) == Z80.Flags.H);
            Assert.False((cpu.F & Z80.Flags.P) == Z80.Flags.P);
            Assert.True((cpu.F & Z80.Flags.C) == Z80.Flags.C);

            Assert.True((cpu.F & Z80.Flags.U) == Z80.Flags.U);
            Assert.True((cpu.F & Z80.Flags.X) == Z80.Flags.X);
        }
Beispiel #21
0
        private void DecrementValueAtLocationPointedToByIYPlusDFlagsTest()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xFD },
                { 0x0081, 0x35 },
                { 0x0082, 0x03 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },

                // Data
                { 0x08FB, 0x00 },
                { 0x08FC, 0x00 },
                { 0x08FD, 0x00 },
                { 0x08FE, 0x00 },
                { 0x08FF, 0x00 }, // <- (IX)
                { 0x0900, 0x00 },
                { 0x0901, 0x00 },
                { 0x0902, 0x80 }, // <- (IX+3)
                { 0x0903, 0x00 },
                { 0x0904, 0x00 },
                { 0x0905, 0x00 },
                { 0x0906, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);
            A.CallTo(() => fakeBus.Write(A <ushort> ._, A <byte> ._))
            .Invokes((ushort addr, byte data) => UpdateMemory(addr, data));

            var cpu = new Z80()
            {
                A = 0x00, IY = 0x08FF, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            cpu.Step();

            Assert.Equal(0x7F, program[(ushort)(cpu.IY + 3)]);

            Assert.True((cpu.F & Z80.Flags.N) == Z80.Flags.N);
            Assert.False((cpu.F & Z80.Flags.Z) == Z80.Flags.Z);
            Assert.False((cpu.F & Z80.Flags.S) == Z80.Flags.S);
            Assert.True((cpu.F & Z80.Flags.H) == Z80.Flags.H);
            Assert.True((cpu.F & Z80.Flags.P) == Z80.Flags.P);
            Assert.False((cpu.F & Z80.Flags.C) == Z80.Flags.C);
            Assert.True((cpu.F & Z80.Flags.U) == Z80.Flags.U);
            Assert.True((cpu.F & Z80.Flags.X) == Z80.Flags.X);

            void UpdateMemory(ushort addr, byte data)
            {
                program[addr] = data;
            }
        }
Beispiel #22
0
        public Results RunTests()
        {
            ReadFuseTestsFile();
            ReadFuseExpectedFile();
            _cpu = new Z80();

            foreach (var test in _tests)
            {
                var testName = test.Key;
                var opCode   = testName.Split('_')[0];

                _cpu.Reset(true);

                var isExtendedNopTest = opCode == "dd00" || opCode == "fddd00";

                if (_cpu.IsOpCodeSupported(opCode) || isExtendedNopTest)
                {
                    // Run test
                    var testToRun = test.Value;
                    var registers = testToRun.Registers;
                    var memory    = testToRun.Memory;
                    var states    = testToRun.States;

                    InitialiseRegisters(registers);
                    InitialiseMemory(memory);
                    InitialiseStates(states);
                    _cpu.ConnectToBus(_bus);

                    var runToAddress = _expected[testName].Registers[11];

                    do
                    {
                        _cpu.Step();
                    } while (_cpu.PC < runToAddress);

                    var(pass, details) = CompareActualWithExpected(_expected[testName]);

                    if (pass)
                    {
                        _passing.Add(testName);
                    }
                    else
                    {
                        _failing.Add(testName, details);
                    }
                }
                else
                {
                    _notImplemented.Add(testName);
                }
            }

            return(new Results(_passing, _failing, _notImplemented));
        }
Beispiel #23
0
        public void LoadAWithThreeWhenSubtracting8And5ForOpcodeSUBAN()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xD6 }, // SUB A, n
                { 0x0081, 0x05 }, // n = 5
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },

                // Data
                { 0x08FB, 0x00 },
                { 0x08FC, 0x00 },
                { 0x08FD, 0x00 },
                { 0x08FE, 0x00 },
                { 0x08FF, 0x00 },
                { 0x0900, 0x00 },
                { 0x0901, 0x00 },
                { 0x0902, 0x00 },
                { 0x0903, 0x00 },
                { 0x0904, 0x00 },
                { 0x0905, 0x00 },
                { 0x0906, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x08, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            cpu.Step();

            Assert.Equal(0x03, cpu.A);
            sbyte signedResult = (sbyte)cpu.A;

            Assert.Equal(3, signedResult);
            Assert.True((cpu.F & Z80.Flags.N) == Z80.Flags.N); // Set due to a subtraction

            Assert.False((cpu.F & Z80.Flags.Z) == Z80.Flags.Z);
            Assert.False((cpu.F & Z80.Flags.S) == Z80.Flags.S);
            Assert.False((cpu.F & Z80.Flags.H) == Z80.Flags.H);
            Assert.False((cpu.F & Z80.Flags.P) == Z80.Flags.P);
            Assert.False((cpu.F & Z80.Flags.C) == Z80.Flags.C);

            Assert.False((cpu.F & Z80.Flags.U) == Z80.Flags.U);
            Assert.False((cpu.F & Z80.Flags.X) == Z80.Flags.X);
        }
Beispiel #24
0
        public void LoadMemoryLocationPointedToByHLwithValueInAccumulator()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0x77 },
                { 0x0081, 0x00 },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },

                // Data
                { 0x08FB, 0x00 },
                { 0x08FC, 0x00 },
                { 0x08FD, 0x00 },
                { 0x08FE, 0x00 },
                { 0x08FF, 0x00 }, // (HL)
                { 0x0900, 0x00 },
                { 0x0901, 0x00 },
                { 0x0902, 0x00 },
                { 0x0903, 0x00 },
                { 0x0904, 0x00 },
                { 0x0905, 0x00 },
                { 0x0906, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);
            A.CallTo(() => fakeBus.Write(A <ushort> ._, A <byte> ._))
            .Invokes((ushort addr, byte data) => UpdateMemory(addr, data));

            // Load the value in register A (0x11), into the memory location pointed to by (HL)...
            var cpu = new Z80()
            {
                A = 0x11, H = 0x08, L = 0xFF, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            cpu.Step();

            Assert.Equal(0x11, program[0x08FF]);

            // No affect on Condition Flags
            FlagsUnchanged(cpu);

            void UpdateMemory(ushort addr, byte data)
            {
                program[addr] = data;
            }
        }
Beispiel #25
0
        public void LoadMemoryLocationPointedToByIYplusDwithValueN_GivenDisNegative()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xFD },
                { 0x0081, 0x36 },
                { 0x0082, 0xFE },
                { 0x0083, 0xBB },
                { 0x0084, 0x00 },

                // Data
                { 0x08FB, 0x00 },
                { 0x08FC, 0x00 },
                { 0x08FD, 0x00 }, // <- d = -2
                { 0x08FE, 0x00 },
                { 0x08FF, 0x00 }, // (IY)
                { 0x0900, 0x00 },
                { 0x0901, 0x00 },
                { 0x0902, 0x00 },
                { 0x0903, 0x00 },
                { 0x0904, 0x00 },
                { 0x0905, 0x00 },
                { 0x0906, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);
            A.CallTo(() => fakeBus.Write(A <ushort> ._, A <byte> ._))
            .Invokes((ushort addr, byte data) => UpdateMemory(addr, data));

            var cpu = new Z80()
            {
                A = 0x0F, IY = 0x08FF, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            cpu.Step();

            Assert.Equal(0xBB, program[0x08FF - 2]);

            // No affect on Condition Flags
            FlagsUnchanged(cpu);

            void UpdateMemory(ushort addr, byte data)
            {
                program[addr] = data;
            }
        }
Beispiel #26
0
        public void LoadAWith7WhenSubtracting4FromBAndCarryFlagSetForOpcodeSBCAR()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0x98 }, //SBC A, B
                { 0x0081, 0x00 },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },

                // Data
                { 0x08FB, 0x00 },
                { 0x08FC, 0x00 },
                { 0x08FD, 0x00 },
                { 0x08FE, 0x00 },
                { 0x08FF, 0x00 },
                { 0x0900, 0x00 },
                { 0x0901, 0x00 },
                { 0x0902, 0x00 },
                { 0x0903, 0x00 },
                { 0x0904, 0x00 },
                { 0x0905, 0x00 },
                { 0x0906, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x0C, B = 0x04, F = Z80.Flags.C, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            cpu.Step();

            Assert.Equal(0x07, cpu.A);
            Assert.True((cpu.F & Z80.Flags.N) == Z80.Flags.N);

            Assert.False((cpu.F & Z80.Flags.Z) == Z80.Flags.Z);
            Assert.False((cpu.F & Z80.Flags.S) == Z80.Flags.S);
            Assert.False((cpu.F & Z80.Flags.H) == Z80.Flags.H);
            Assert.False((cpu.F & Z80.Flags.P) == Z80.Flags.P);
            Assert.False((cpu.F & Z80.Flags.C) == Z80.Flags.C);

            Assert.False((cpu.F & Z80.Flags.U) == Z80.Flags.U);
            Assert.False((cpu.F & Z80.Flags.X) == Z80.Flags.X);
        }
Beispiel #27
0
        public void LoadAWith6WhenSubtractingLocationPointedToByIXFrom10ForOpcodeSUBAIXD_GivenDisNegative()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xDD },
                { 0x0081, 0x96 }, // SUB A, (IX+d)
                { 0x0082, 0xFE }, // d = -2
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },

                // Data
                { 0x08FB, 0x00 },
                { 0x08FC, 0x00 },
                { 0x08FD, 0x04 }, // (IX-2)
                { 0x08FE, 0x00 },
                { 0x08FF, 0x00 }, // <- (IX)
                { 0x0900, 0x00 },
                { 0x0901, 0x00 },
                { 0x0902, 0x00 },
                { 0x0903, 0x00 },
                { 0x0904, 0x00 },
                { 0x0905, 0x00 },
                { 0x0906, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x0A, IX = 0x08FF, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            cpu.Step();

            Assert.Equal(0x06, cpu.A);
            Assert.True((cpu.F & Z80.Flags.N) == Z80.Flags.N);

            Assert.False((cpu.F & Z80.Flags.Z) == Z80.Flags.Z);
            Assert.False((cpu.F & Z80.Flags.S) == Z80.Flags.S);
            Assert.False((cpu.F & Z80.Flags.H) == Z80.Flags.H);
            Assert.False((cpu.F & Z80.Flags.P) == Z80.Flags.P);
            Assert.False((cpu.F & Z80.Flags.C) == Z80.Flags.C);

            Assert.False((cpu.F & Z80.Flags.U) == Z80.Flags.U);
            Assert.False((cpu.F & Z80.Flags.X) == Z80.Flags.X);
        }
Beispiel #28
0
        public void LoadAWith9WhenSubtracting4FromLocationPointedToByIYForOpcodeSBCAHL_GivenDisPositive()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xFD },
                { 0x0081, 0x9E }, // SBC A, (IY+d)
                { 0x0082, 0x03 }, // d = 3
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },

                // Data
                { 0x08FB, 0x00 },
                { 0x08FC, 0x00 },
                { 0x08FD, 0x00 },
                { 0x08FE, 0x00 },
                { 0x08FF, 0x00 }, // <- (IY)
                { 0x0900, 0x00 },
                { 0x0901, 0x00 },
                { 0x0902, 0x04 }, // (IY+3)
                { 0x0903, 0x00 },
                { 0x0904, 0x00 },
                { 0x0905, 0x00 },
                { 0x0906, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x0E, IY = 0x08FF, F = Z80.Flags.C, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);
            cpu.Step();

            Assert.Equal(0x09, cpu.A);
            Assert.True((cpu.F & Z80.Flags.N) == Z80.Flags.N);

            Assert.False((cpu.F & Z80.Flags.Z) == Z80.Flags.Z);
            Assert.False((cpu.F & Z80.Flags.S) == Z80.Flags.S);
            Assert.False((cpu.F & Z80.Flags.H) == Z80.Flags.H);
            Assert.False((cpu.F & Z80.Flags.P) == Z80.Flags.P);
            Assert.False((cpu.F & Z80.Flags.C) == Z80.Flags.C);

            Assert.False((cpu.F & Z80.Flags.U) == Z80.Flags.U);
            Assert.True((cpu.F & Z80.Flags.X) == Z80.Flags.X);
        }
Beispiel #29
0
        private void UnsetZeroFlagWhenFalseForCPIYD2()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xFD }, // CP (IY+3)
                { 0x0081, 0xBE },
                { 0x0082, 0x03 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },

                // Data
                { 0x08FB, 0x00 },
                { 0x08FC, 0x00 },
                { 0x08FD, 0x00 },
                { 0x08FE, 0x00 },
                { 0x08FF, 0x00 }, // <- (IY)
                { 0x0900, 0x00 },
                { 0x0901, 0x00 },
                { 0x0902, 0x02 },
                { 0x0903, 0x00 },
                { 0x0904, 0x00 },
                { 0x0905, 0x00 },
                { 0x0906, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x01, IY = 0x08FF, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.Equal(0x01, cpu.A);
            Assert.True((cpu.F & Z80.Flags.N) == Z80.Flags.N);
            Assert.False((cpu.F & Z80.Flags.Z) == Z80.Flags.Z);
            Assert.True((cpu.F & Z80.Flags.S) == Z80.Flags.S); // Negative comparison
            Assert.True((cpu.F & Z80.Flags.H) == Z80.Flags.H); // Borrow from bit 4
            Assert.False((cpu.F & Z80.Flags.P) == Z80.Flags.P);
            Assert.True((cpu.F & Z80.Flags.C) == Z80.Flags.C); // Borrow from "bit 8"
            Assert.False((cpu.F & Z80.Flags.U) == Z80.Flags.U);
            Assert.False((cpu.F & Z80.Flags.X) == Z80.Flags.X);
        }
Beispiel #30
0
        private void SetZeroFlagWhenTrueForCPHL()
        {
            var fakeBus = A.Fake <IBus>();

            var program = new Dictionary <ushort, byte>
            {
                // Program Code
                { 0x0080, 0xBE }, // CP (HL)
                { 0x0081, 0x00 },
                { 0x0082, 0x00 },
                { 0x0083, 0x00 },
                { 0x0084, 0x00 },

                // Data
                { 0x08FB, 0x00 },
                { 0x08FC, 0x00 },
                { 0x08FD, 0x00 },
                { 0x08FE, 0x00 },
                { 0x08FF, 0x01 }, // <- (HL)
                { 0x0900, 0x00 },
                { 0x0901, 0x00 },
                { 0x0902, 0x00 },
                { 0x0903, 0x00 },
                { 0x0904, 0x00 },
                { 0x0905, 0x00 },
                { 0x0906, 0x00 },
            };

            A.CallTo(() => fakeBus.Read(A <ushort> ._, A <bool> ._))
            .ReturnsLazily((ushort addr, bool ro) => program[addr]);

            var cpu = new Z80()
            {
                A = 0x01, H = 0x08, L = 0xFF, PC = 0x0080
            };

            cpu.ConnectToBus(fakeBus);

            cpu.Step();

            Assert.Equal(0x01, cpu.A);
            Assert.True((cpu.F & Z80.Flags.N) == Z80.Flags.N);
            Assert.True((cpu.F & Z80.Flags.Z) == Z80.Flags.Z);
            Assert.False((cpu.F & Z80.Flags.S) == Z80.Flags.S);
            Assert.False((cpu.F & Z80.Flags.H) == Z80.Flags.H);
            Assert.False((cpu.F & Z80.Flags.P) == Z80.Flags.P);
            Assert.False((cpu.F & Z80.Flags.C) == Z80.Flags.C);
            Assert.False((cpu.F & Z80.Flags.U) == Z80.Flags.U);
            Assert.False((cpu.F & Z80.Flags.X) == Z80.Flags.X);
        }