示例#1
0
        public MainViewModel()
        {
            //Console = Console.Default();
            var mmu = new Mmu();
            Console = new Console(
                new Cpu(mmu), mmu,
                new Gpu(mmu,
                    // TODO make palettes configurable from UI
                    //Colors.White,
                    //Colors.LightGray,
                    //Colors.DarkGray,
                    //Colors.Black),
                    //new Color { R = 0xB8, G = 0xC2, B = 0x66 },
                    //new Color { R = 0x7B, G = 0x8A, B = 0x32 },
                    //new Color { R = 0x43, G = 0x59, B = 0x1D },
                    //new Color { R = 0x13, G = 0x2C, B = 0x13 }),
                    Colors.GhostWhite,
                    Colors.LightSlateGray,
                    Colors.DarkSlateBlue,
                    Colors.Black),
                new Timer(mmu),
                new Controller(mmu));

            Title = "GameboyEm";
            OpenCommand = new ActionCommand(Open);
            LoadStateCommand = new ActionCommand(LoadState);
            SaveStateCommand = new ActionCommand(SaveState);
            CloseCommand = new ActionCommand(Application.Current.Shutdown);
            PowerOnCommand = new ActionCommand(PowerOn);
            PowerOffCommand = new ActionCommand(PowerOff);
            ResetCommand = new ActionCommand(Reset);
            DebuggerCommand = new ActionCommand(Debugger);
        }
示例#2
0
        public void ProgramCounterIncrementation()
        {
            // Arrange
            var mmu     = new Mmu();
            var cpu     = new Cpu(mmu, new Registers());
            var gameboy = new GameBoy(cpu, mmu, new MockCartridge());

            gameboy.Cpu.Registers.PC.Value = 0x0000;

            // Act + assert
            gameboy.Cpu.Cycle();
            Assert.That(gameboy.Cpu.Registers.PC.Value == 0x0001);

            gameboy.Cpu.Cycle();
            Assert.That(gameboy.Cpu.Registers.PC.Value == 0x0002);

            gameboy.Cpu.Cycle();
            Assert.That(gameboy.Cpu.Registers.PC.Value == 0x0003);
        }
示例#3
0
        public void Op0xCB99_DoesSomethingUseful()
        {
            // Arrange
            var mmu     = new Mmu();
            var cpu     = new Cpu(mmu, new Registers());
            var gameboy = new GameBoy(cpu, mmu, new MockCartridge());

            gameboy.PowerUp();

            gameboy.Cpu.Registers.PC.Value = 0;
            // gameboy.Mmu.WriteByte(0x00, 0x00;
            // gameboy.Mmu.WriteByte(0x01, 0x00;

            // Act
            gameboy.Cpu.Cycle();

            // Assert
            // Assert.That(true);
        }
示例#4
0
        public void Op0x01_NNIsLoadedIntoRegisterBC()
        {
            // Arrange
            var mmu     = new Mmu();
            var cpu     = new Cpu(mmu, new Registers());
            var gameboy = new GameBoy(cpu, mmu, new MockCartridge());

            gameboy.PowerUp();

            const byte nn = 12;

            gameboy.Mmu.WriteByte(gameboy.Cpu.Registers.PC.Value, 0x01);
            gameboy.Mmu.WriteByte((ushort)(gameboy.Cpu.Registers.PC.Value + 1), nn);

            // Act
            gameboy.Cpu.Cycle();

            // Assert
            Assert.That(gameboy.Cpu.Registers.BC.Value == nn);
        }
示例#5
0
        public void Op0xAF_A0xFF_WipesA()
        {
            // Arrange
            var mmu     = new Mmu();
            var cpu     = new Cpu(mmu, new Registers());
            var gameboy = new GameBoy(cpu, mmu, new MockCartridge());

            gameboy.PowerUp();

            gameboy.Cpu.Registers.A.Value = 0xFF;

            gameboy.Cpu.Registers.PC.Value = 0x00;
            gameboy.Mmu.WriteByte(0x00, 0xAF);
            gameboy.Mmu.WriteByte(0x01, 0x00);

            // Act
            gameboy.Cpu.Cycle();

            // Assert
            Assert.That(gameboy.Cpu.Registers.A.Value == 0x00);
        }
示例#6
0
        public void Op0x5001_DisB()
        {
            // Arrange
            var mmu     = new Mmu();
            var cpu     = new Cpu(mmu, new Registers());
            var gameboy = new GameBoy(cpu, mmu, new MockCartridge());

            //gameboy.Memory.Init(0xFFFF);
            gameboy.Cpu.Registers.PC.Value = 0x00;
            gameboy.Cpu.Registers.B.Value  = 0xAA;

            gameboy.Mmu.WriteByte(0x00, 0x50);
            gameboy.Mmu.WriteByte(0x01, 0x01);

            // Act
            gameboy.Cpu.Cycle();

            // Assert
            Assert.That(gameboy.Cpu.Registers.D.Value == 0xAA);
            Assert.That(gameboy.Cpu.Registers.D.Value == gameboy.Cpu.Registers.B.Value);
        }
示例#7
0
        public void Op0x66_PointTo0xBBHIs0xBB()
        {
            // Arrange
            var mmu     = new Mmu();
            var cpu     = new Cpu(mmu, new Registers());
            var gameboy = new GameBoy(cpu, mmu, new MockCartridge());

            gameboy.PowerUp();

            gameboy.Cpu.Registers.PC.Value = 0x00;
            gameboy.Cpu.Registers.HL.Value = 0xFF00;

            gameboy.Mmu.WriteByte(0x00, 0x66);
            gameboy.Mmu.WriteByte(0x01, 0x00);
            gameboy.Mmu.WriteByte(0xFF00, 0xBB);

            // Act
            gameboy.Cpu.Cycle();

            // Assert
            Assert.That(gameboy.Cpu.Registers.H.Value == 0xBB);
        }
示例#8
0
文件: Program.cs 项目: szpght/moha
        public Benchmark()
        {
            const int memorySize = 32 * 1024 * 1024;
            var       mmu        = new Mmu(memorySize);
            var       decoder    = new InstructionDecoder();

            cpu1 = new Cpu <PhysicalMemoryAccessor, NoTracing>(mmu, decoder);
            cpu2 = new Cpu <PhysicalMemoryAccessor, NoTracing>(mmu, decoder);
            mmu._pageDirectory = memorySize - 4;

            var elf = ELFReader.Load <uint>("D:\\fibo");

            startAddress = elf.EntryPoint;
            var loadableSegments = elf.Segments.Where(s => s.Type == SegmentType.Load);

            foreach (var segment in loadableSegments)
            {
                var content = segment.GetMemoryContents();
                var address = segment.PhysicalAddress;
                mmu.CopyToPhysical(address, content);
            }
        }
示例#9
0
        public void Op0xCE_250Plus6CarryZero()
        {
            // Arrange
            var mmu     = new Mmu();
            var cpu     = new Cpu(mmu, new Registers());
            var gameboy = new GameBoy(cpu, mmu, new MockCartridge());

            gameboy.PowerUp();

            gameboy.Cpu.Registers.A.Value = 0xFA;

            gameboy.Cpu.Registers.PC.Value = 0x00;
            gameboy.Mmu.WriteByte(0x00, 0xCE);
            gameboy.Mmu.WriteByte(0x01, 0x06);

            // Act
            gameboy.Cpu.Cycle();

            // Assert
            Assert.That(gameboy.Cpu.Registers.A.Value == 0x00);
            Assert.That(gameboy.Cpu.Registers.F.CarryFlag == true);
            Assert.That(gameboy.Cpu.Registers.F.SubtractFlag == false);
            Assert.That(gameboy.Cpu.Registers.F.ZeroFlag == true);
        }
示例#10
0
        public void Op0x32_ASavedHLDecremented()
        {
            // Arrange
            var mmu     = new Mmu();
            var cpu     = new Cpu(mmu, new Registers());
            var gameboy = new GameBoy(cpu, mmu, new MockCartridge());

            gameboy.PowerUp();

            var originalHl = gameboy.Cpu.Registers.HL.Value;

            gameboy.Cpu.Registers.A.Value = 0x25;

            gameboy.Cpu.Registers.PC.Value = 0x00;
            gameboy.Mmu.WriteByte(0x00, 0x32);
            gameboy.Mmu.WriteByte(0x01, 0x00);

            // Act
            gameboy.Cpu.Cycle();

            // Assert
            Assert.That(gameboy.Mmu.ReadByte(originalHl) == gameboy.Cpu.Registers.A.Value);
            Assert.That(gameboy.Cpu.Registers.HL.Value == originalHl - 1);
        }
示例#11
0
        private void TestFile_(string fileName)
        {
            var lcd = new Lcd {
                Active = false
            };
            var serialBus   = new SerialBus();
            var ioAddresses = new IoAddresses(serialBus);
            var memoryMap   = new MemoryMap(ioAddresses);
            var registers   = new Registers();
            var memory      = new Mmu(memoryMap, registers);
            var cpu         = new Cpu(lcd, memory, new Opcodes(memory));

            ushort initialPc = 0;
            ushort finalPc   = 0;

            var maxCycleCount = 100000000;

            LinkedList <Expected?>?expecteds = null;

            if (BlarggTest.COMPARE_TO_BINJGB_)
            {
                var expectedTracePath =
                    "R:/Documents/CSharpWorkspace/FinCSharp/FinCSharpTests/tst/emulation/gb/blargg/" +
                    fileName +
                    ".txt";
                expecteds = new LinkedList <Expected?>();
                try {
                    using (var sr = new StreamReader(expectedTracePath)) {
                        string line;
                        while ((line = sr.ReadLine()) != null)
                        {
                            var words = line.Split(' ');

                            var expectedAHex = words[0].Substring(2);
                            var expectedA    = byte.Parse(expectedAHex, NumberStyles.HexNumber);

                            var expectedFText = words[1].Substring(2);
                            var expectedF     = 0;
                            if (expectedFText[0] != '-')
                            {
                                expectedF |= 1 << 7;
                            }
                            if (expectedFText[1] != '-')
                            {
                                expectedF |= 1 << 6;
                            }
                            if (expectedFText[2] != '-')
                            {
                                expectedF |= 1 << 5;
                            }
                            if (expectedFText[3] != '-')
                            {
                                expectedF |= 1 << 4;
                            }

                            var expectedAf = ByteMath.MergeBytes(expectedA, (byte)expectedF);

                            var expectedBcHex = words[2].Substring(3);
                            var expectedBc    = ushort.Parse(expectedBcHex,
                                                             NumberStyles.HexNumber);

                            var expectedDeHex = words[3].Substring(3);
                            var expectedDe    = ushort.Parse(expectedDeHex,
                                                             NumberStyles.HexNumber);

                            var expectedHlHex = words[4].Substring(3);
                            var expectedHl    = ushort.Parse(expectedHlHex,
                                                             NumberStyles.HexNumber);

                            var expectedPcHex = words[6].Substring(3);
                            //var expectedPcHex = line.Substring(47, 4);
                            var expectedPc = ushort.Parse(expectedPcHex,
                                                          NumberStyles.HexNumber);

                            var expectedCyclesText = line.Substring(57,
                                                                    line.IndexOf(
                                                                        ')',
                                                                        57) -
                                                                    57);
                            var expectedCycles = int.Parse(expectedCyclesText);

                            var expectedSclText = words[9].Substring(4);
                            var expectedScl     = int.Parse(expectedSclText);

                            var expectedPpuModeText = words[12].Substring(5);
                            var expectedPpuMode     = int.Parse(expectedPpuModeText);

                            expecteds.AddLast(new Expected(expectedAf,
                                                           expectedBc,
                                                           expectedDe,
                                                           expectedHl,
                                                           expectedPc,
                                                           expectedCycles,
                                                           expectedScl,
                                                           expectedPpuMode));
                        }
                    }
                } catch (Exception e) {
                    expecteds.Clear();
                    expecteds = null;
                }
            }

            var romPath =
                "R:/Documents/CSharpWorkspace/FinCSharp/FinCSharpTests/tst/emulation/gb/blargg/" +
                fileName +
                ".gb";

            var romFile = LocalFile.At(romPath);
            var romData = LocalFileUtil.ReadBytes(romFile);

            memoryMap.Rom = new Rom(romData);

            var output = "";

            serialBus.Bytes.Subscribe(b => { output += Convert.ToChar(b); });

            var outputPath =
                "R:/Documents/CSharpWorkspace/FinCSharp/FinCSharpTests/tst/emulation/gb/blargg/output_" +
                fileName +
                ".txt";

            using var writer = (BlarggTest.LOG_TRACE_)
                             ? new StreamWriter(outputPath)
                             : null;

            var pc = registers.Pc;

            initialPc = 0;
            finalPc   = 0;

            var shouldGetPpuMode =
                BlarggTest.LOG_TRACE_ || BlarggTest.COMPARE_TO_BINJGB_;

            var lcdc = ioAddresses.Lcdc;
            var ly   = ioAddresses.Ly;

            var instruction = 0;
            var cycles      = 0;
            //try {
            var enumerator = expecteds?.GetEnumerator();

            for (var i = 0; i < maxCycleCount; ++i)
            {
                var expected = enumerator?.Current;
                enumerator?.MoveNext();

                var ppuMode = shouldGetPpuMode ? cpu.PpuMode : 0;
                initialPc = pc.Value;

                if (BlarggTest.LOG_TRACE_)
                {
                    StringBuilder line = new StringBuilder();

                    line.AppendFormat("0x{0:x4}:  ", initialPc);
                    line.AppendFormat("{0:x2} |", memoryMap[initialPc]);
                    line.AppendFormat(" af={0:x4}", registers.Af.Value);
                    line.AppendFormat(" bc={0:x4}", registers.Bc.Value);
                    line.AppendFormat(" de={0:x4}", registers.De.Value);
                    line.AppendFormat(" hl={0:x4}", registers.Hl.Value);
                    line.AppendFormat(" sp={0:x4}", registers.Sp.Value);
                    line.AppendFormat(" pc={0:x4} |", registers.Pc.Value);

                    line.AppendFormat(" tot={0} |", cycles);

                    line.AppendFormat(" scl={0}", cpu.UpwardScanlineCycleCounter);
                    line.AppendFormat(" st={0}", cpu.PpuModeCycleCount);
                    line.AppendFormat(" cnt={0} |", cpu.ScanlineCycleCounter / 2);

                    line.AppendFormat(" lcdc={0:x2}", lcdc.Value);
                    line.AppendFormat(" ly={0:x2}", ly.Value);
                    line.AppendFormat(" ppu={0:x1} |", ppuMode);

                    line.AppendFormat(" div={0:x2}", ioAddresses.Div);
                    line.AppendFormat(" tima={0:x2}", ioAddresses.Tima);
                    line.AppendFormat(" tma={0:x2}", ioAddresses.Tma);
                    line.AppendFormat(" tac={0:x2}", ioAddresses.Tac);
                    writer.WriteLine(line.ToString());
                }

                if (expected != null &&
                    (expected.Pc != initialPc ||
                     expected.Cycles != cycles ||
                     expected.Af != registers.Af.Value ||
                     expected.Bc != registers.Bc.Value ||
                     expected.De != registers.De.Value ||
                     expected.Hl != registers.Hl.Value ||
                     expected.Scl != cpu.UpwardScanlineCycleCounter ||
                     expected.PpuMode != ppuMode))
                {
                    var errorBuilder = new StringBuilder();
                    errorBuilder.Append("Difference at instruction: " +
                                        instruction +
                                        "\n");
                    errorBuilder.AppendFormat("Af: {0:x4}/{1:x4}\n",
                                              expected.Af,
                                              registers.Af.Value);
                    errorBuilder.AppendFormat("Bc: {0:x4}/{1:x4}\n",
                                              expected.Bc,
                                              registers.Bc.Value);
                    errorBuilder.AppendFormat("De: {0:x4}/{1:x4}\n",
                                              expected.De,
                                              registers.De.Value);
                    errorBuilder.AppendFormat("Hl: {0:x4}/{1:x4}\n",
                                              expected.Hl,
                                              registers.Hl.Value);
                    errorBuilder.AppendFormat("Pc: {0:x4}/{1:x4}\n",
                                              expected.Pc,
                                              initialPc);
                    errorBuilder.AppendFormat("Cycles: {0}/{1}\n",
                                              expected.Cycles,
                                              cycles);
                    errorBuilder.AppendFormat("Scl: {0}/{1}\n",
                                              expected.Scl,
                                              cpu.UpwardScanlineCycleCounter);
                    errorBuilder.AppendFormat("Ppu Mode: {0}/{1}\n",
                                              expected.PpuMode,
                                              ppuMode);
                    Assert.Fail(errorBuilder.ToString());
                }

                cycles += cpu.ExecuteCycles(1);

                instruction++;
                finalPc = pc.Value;

                if (initialPc == finalPc && memory.HaltState != HaltState.HALTED)
                {
                    break;
                }
            }

            /*} catch (Exception e) {
             * output = cycles + ", " + registers.Pc.Value + ": " + output;
             * throw e;
             * }*/

            output = cycles + ", " + registers.Pc.Value + ": " + output;

            if (!output.Contains("Passed"))
            {
                Asserts.Fail(output);
            }
        }
示例#12
0
 public ReplayOpcodes(Mmu memory)
 {
     this.memory_ = memory;
     this.impl_   = new Opcodes(memory);
 }
示例#13
0
文件: Program.cs 项目: szpght/moha
        static void Main(string[] args)
        {
            const int memorySize = 32 * 1024 * 1024;
            var       mmu        = new Mmu(memorySize);
            var       decoder    = new InstructionDecoder();
            var       cpu        = new Cpu <PhysicalMemoryAccessor, Tracing>(mmu, decoder);

            if (false /*cpu is Cpu<VirtualMemoryAccessor>*/)
            {
                var(location, data) = TlbHelper.PrepareIdentityMap(memorySize);
                mmu.CopyToPhysical(location, data);
                mmu._pageDirectory = location;
            }
            else
            {
                mmu._pageDirectory = memorySize - 4;
            }

            var elf              = ELFReader.Load <uint>("D:\\fibo");
            var startAddress     = elf.EntryPoint;
            var loadableSegments = elf.Segments.Where(s => s.Type == SegmentType.Load);

            foreach (var segment in loadableSegments)
            {
                var content = segment.GetMemoryContents();
                var address = segment.PhysicalAddress;
                mmu.CopyToPhysical(address, content);
            }

            cpu.Execute((int)startAddress);
            var stoper = Stopwatch.StartNew();

            for (var i = 0; i < 10; ++i)
            {
                cpu.Execute((int)startAddress);
            }
            stoper.Stop();
            Console.WriteLine(stoper.ElapsedMilliseconds);
            Console.WriteLine(cpu.InstructionsExecuted);
            Console.WriteLine($"{(double)cpu.InstructionsExecuted / stoper.ElapsedMilliseconds / 1000} MIPS");
            cpu.Reset();


            stoper = Stopwatch.StartNew();
            for (var i = 0; i < 100; ++i)
            {
                cpu.Execute((int)startAddress);
            }
            stoper.Stop();
            Console.WriteLine(stoper.ElapsedMilliseconds);
            Console.WriteLine(cpu.InstructionsExecuted);
            Console.WriteLine($"{(double)cpu.InstructionsExecuted / stoper.ElapsedMilliseconds / 1000} MIPS");
            cpu.Reset();


            stoper = Stopwatch.StartNew();
            for (var i = 0; i < 100; ++i)
            {
                cpu.Execute((int)startAddress);
            }
            stoper.Stop();
            Console.WriteLine(stoper.ElapsedMilliseconds);
            Console.WriteLine(cpu.InstructionsExecuted);
            Console.WriteLine($"{(double)cpu.InstructionsExecuted / stoper.ElapsedMilliseconds / 1000} MIPS");
        }
示例#14
0
文件: MmuTests.cs 项目: szpght/moha
 public MmuTests()
 {
     _mmu = CreateMmu();
 }
示例#15
0
        public void TestReadInvalid()
        {
            var mmu = new Mmu(_bios);

            mmu.ReadByte(0xFFFF);
        }
示例#16
0
        public void TestWriteInvalid()
        {
            var mmu = new Mmu(_bios);

            mmu.WriteByte(0xFFFF, (byte)0xFF);
        }
示例#17
0
        public void TestWriteBiosFailsDuringBoot()
        {
            var mmu = new Mmu(_bios);

            mmu.WriteByte(0x00, 42);
        }
示例#18
0
 public void TestInvlidBiosLength()
 {
     var badBios = new byte[] { 1, 2, 3 };
     var mmu     = new Mmu(badBios);
 }