Пример #1
0
        public void MachineStopsAtFirstInstructionBreakpointAndStepsFurther()
        {
            // --- Arrange
            var spectrum      = new SpectrumAdvancedTestMachine();
            var debugProvider = new TestDebugInfoProvider();

            spectrum.SetDebugInfoProvider(debugProvider);

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x3E, 0x10,       // LD A,$10
                0x87,             // ADD A,A
                0x47,             // LD B,A
                0x4F,             // LD C,A
            });
            debugProvider.Breakpoints.Add(0x8000, MinimumBreakpointInfo.EmptyBreakpointInfo);
            debugProvider.Breakpoints.Add(0x8002, MinimumBreakpointInfo.EmptyBreakpointInfo);
            var regs = spectrum.Cpu.Registers;

            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger));

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger));

            // --- Assert
            regs.A.ShouldBe((byte)0x10);
            regs.B.ShouldBe((byte)0x00);
            regs.C.ShouldBe((byte)0x00);
            regs.PC.ShouldBe((ushort)0x8002);
        }
Пример #2
0
        public void StepOverWorksWithRst()
        {
            // --- Arrange
            var spectrum      = new SpectrumAdvancedTestMachine();
            var debugProvider = new TestDebugInfoProvider();

            spectrum.SetDebugInfoProvider(debugProvider);

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0xF3,       // DI
                0x16, 0x06, // LD D,6
                0xFF,       // RST $38
                0x7A,       // LD A,D
                0x76        // HALT
            });
            var regs = spectrum.Cpu.Registers;

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger, DebugStepMode.StepOver));
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger, DebugStepMode.StepOver));
            var pc1 = regs.PC;

            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger, DebugStepMode.StepOver));
            var pc2 = regs.PC;

            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger, DebugStepMode.StepOver));

            // --- Assert
            regs.D.ShouldBe((byte)0x06);
            pc1.ShouldBe((ushort)0x8003);
            pc2.ShouldBe((ushort)0x8004);
            regs.PC.ShouldBe((ushort)0x8005);
        }
Пример #3
0
        public void StepIntoStopsAtNextInstruction()
        {
            // --- Arrange
            var pars          = new ScreenConfiguration();
            var pixels        = new TestPixelRenderer(pars);
            var spectrum      = new SpectrumAdvancedTestMachine(pars, pixels);
            var debugProvider = new TestDebugInfoProvider();

            spectrum.SetDebugInfoProvider(debugProvider);

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x3E, 0x10,       // LD A,$10
                0x87,             // ADD A,A
                0x47,             // LD B,A
                0x4F,             // LD C,A
            });
            var regs = spectrum.Cpu.Registers;

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger, DebugStepMode.StepInto));

            // --- Assert
            regs.A.ShouldBe((byte)0x10);
            regs.B.ShouldBe((byte)0x00);
            regs.C.ShouldBe((byte)0x00);
            regs.PC.ShouldBe((ushort)0x8002);
        }
Пример #4
0
        public void DisabledInterruptIsNotRaised()
        {
            // --- Arrange
            var spectrum = new SpectrumAdvancedTestMachine();

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0xED, 0x56,       // IM 1
                0xF3,             // DI
                0x3E, 0x05,       // LD A,$05
                0xD3, 0xFE,       // OUT ($FE),A
                0x01, 0x00, 0x0A, // LD BC,$0A00
                0x0B,             // DECLB: DEC BC
                0x78,             // LD A,B
                0xB1,             // OR C
                0x20, 0xFB,       // JR NZ,DECLB
                0x76              // HALT
            });

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.UntilHalt));

            // --- Assert
            var regs = spectrum.Cpu.Registers;

            regs.PC.ShouldBe((ushort)0x800F);

            spectrum.Cpu.Tacts.ShouldBeGreaterThanOrEqualTo(66599L);
        }
        public void MachineWorksWithNoDebugCondition()
        {
            // --- Arrange
            var spectrum = new SpectrumAdvancedTestMachine();

            spectrum.DebugExpressionContext = new SpectrumEvaluationContext(spectrum);
            var debugProvider = new TestDebugInfoProvider();

            spectrum.SetDebugInfoProvider(debugProvider);

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x3E, 0x10,       // LD A,$10
                0x87,             // ADD A,A
                0x47,             // LD B,A
                0x4F,             // LD C,A
            });

            var bp = CreateBreakpoint(null, null);

            debugProvider.Breakpoints.Add(0x8000, bp);
            debugProvider.Breakpoints.Add(0x8007, MinimumBreakpointInfo.EmptyBreakpointInfo);
            var regs = spectrum.Cpu.Registers;

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger));

            // --- Assert
            regs.A.ShouldBe((byte)0x00);
            regs.B.ShouldBe((byte)0x00);
            regs.C.ShouldBe((byte)0x00);
            regs.PC.ShouldBe((ushort)0x8000);
        }
        public void RegisterCWorksWithTrueCondition()
        {
            // --- Arrange
            var spectrum = new SpectrumAdvancedTestMachine();

            spectrum.DebugExpressionContext = new SpectrumEvaluationContext(spectrum);
            var debugProvider = new TestDebugInfoProvider();

            spectrum.SetDebugInfoProvider(debugProvider);

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x06, 0x80,       // LD B,$80
                0x0E, 0x00,       // LD C,$00
                0x0C,             // INC C
                0x10, 0xFD,       // DJNZ -3
                0x76,             // HALT
            });

            var bp = CreateBreakpoint(null, "C == 4");

            debugProvider.Breakpoints.Add(0x8004, bp);
            debugProvider.Breakpoints.Add(0x8007, MinimumBreakpointInfo.EmptyBreakpointInfo);
            var regs = spectrum.Cpu.Registers;

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger));

            // --- Assert
            regs.C.ShouldBe((byte)0x04);
            regs.B.ShouldBe((byte)0x7C);
            regs.PC.ShouldBe((ushort)0x8004);
        }
Пример #7
0
        public void Flag5WorksWithFalseCondition()
        {
            // --- Arrange
            var spectrum = new SpectrumAdvancedTestMachine();

            spectrum.DebugExpressionContext = new SpectrumEvaluationContext(spectrum);
            var debugProvider = new TestDebugInfoProvider();

            spectrum.SetDebugInfoProvider(debugProvider);

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x3E, 0x04,       // LD A,$04
                0xB7,             // OR A
                0x47,             // LD B,A
                0x76,             // HALT
            });

            var bp = CreateBreakpoint(null, "`5");

            debugProvider.Breakpoints.Add(0x8003, bp);
            debugProvider.Breakpoints.Add(0x8004, MinimumBreakpointInfo.EmptyBreakpointInfo);
            var regs = spectrum.Cpu.Registers;

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger));

            // --- Assert
            regs.PC.ShouldBe((ushort)0x8004);
        }
Пример #8
0
        public void NoKempstonDeviceWorks()
        {
            // --- Arrange
            var spectrum = new SpectrumAdvancedTestMachine();
            var provider = spectrum.KempstonProvider as KempstonTestProvider;

            // ReSharper disable once PossibleNullReferenceException
            provider.Reset();
            provider.IsPresent = false;

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x01, 0x1F, 0x00, // LD BC,001FH
                0xED, 0x78,       // IN A,(C)
                0x76              // HALT
            });

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.UntilHalt));

            // --- Assert
            var regs = spectrum.Cpu.Registers;

            regs.A.ShouldBe((byte)0xFF);
        }
Пример #9
0
        public void MachineStopsAtMultipleBreakpoints()
        {
            // --- Arrange
            var pars          = new ScreenConfiguration();
            var pixels        = new TestPixelRenderer(pars);
            var spectrum      = new SpectrumAdvancedTestMachine(pars, pixels);
            var debugProvider = new TestDebugInfoProvider();

            spectrum.SetDebugInfoProvider(debugProvider);

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x3E, 0x10,       // LD A,$10
                0x87,             // ADD A,A
                0x47,             // LD B,A
                0x4F,             // LD C,A
            });
            debugProvider.Breakpoints.Add(0x8003, MinimumBreakpointInfo.EmptyBreakpointInfo);
            debugProvider.Breakpoints.Add(0x8004, MinimumBreakpointInfo.EmptyBreakpointInfo);
            var regs = spectrum.Cpu.Registers;

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger));
            var pc1 = regs.PC;

            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger));

            // --- Assert
            regs.A.ShouldBe((byte)0x20);
            regs.B.ShouldBe((byte)0x20);
            regs.C.ShouldBe((byte)0x00);
            pc1.ShouldBe((ushort)0x8003);
            regs.PC.ShouldBe((ushort)0x8004);
        }
Пример #10
0
        public void StopsAtTerminationPointWhenRequested()
        {
            // --- Arrange
            var spectrum      = new SpectrumAdvancedTestMachine();
            var debugProvider = new TestDebugInfoProvider();

            spectrum.SetDebugInfoProvider(debugProvider);

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x3E, 0x10,       // LD A,$10
                0x87,             // ADD A,A
                0x47,             // LD B,A
                0x4F,             // LD C,A
                0x76              // HALT
            });
            var regs = spectrum.Cpu.Registers;

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None,
                                  new ExecuteCycleOptions(EmulationMode.UntilExecutionPoint, terminationPoint: 0x8003));

            // --- Assert
            regs.A.ShouldBe((byte)0x20);
            regs.B.ShouldBe((byte)0x00);
            regs.C.ShouldBe((byte)0x00);
            regs.PC.ShouldBe((ushort)0x8003);
        }
Пример #11
0
        public void PortWithIssue3UlaAndHighTimingWorks()
        {
            // --- Arrange
            var spectrum = new SpectrumAdvancedTestMachine();

            spectrum.InitCode(new byte[]
            {
                0x3E, 0x18,             // LD A,$18
                0xF6, 0xF8,             // OR A,$F8
                0xD3, 0xFE,             // OUT ($FE),A
                0x3E, 0x08,             // LD A,$08
                0xF6, 0xE8,             // OR A,$E8
                0xD3, 0xFE,             // OUT ($FE),A
                0x06, 0x08,             // LD B,8
                0xDD, 0x21, 0x00, 0x00, // LD IX,0
                0x10, 0xFA,             // DJNZ $-4
                0xDB, 0xFE,             // IN A,($FE)
                0x76                    // HALT
            });

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.UntilHalt));

            // --- Assert
            spectrum.Cpu.Registers.A.ShouldBe((byte)0xBF);
        }
        public void RegisterHl2WorksWithFalseCondition()
        {
            // --- Arrange
            var spectrum = new SpectrumAdvancedTestMachine();

            spectrum.DebugExpressionContext = new SpectrumEvaluationContext(spectrum);
            var debugProvider = new TestDebugInfoProvider();

            spectrum.SetDebugInfoProvider(debugProvider);

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x06, 0x80,       // LD B,$80
                0x21, 0x00, 0x40, // LD HL,$4000
                0x23,             // INC HL
                0xD9,             // EXX
                0xD9,             // EXX
                0x10, 0xFB,       // DJNZ -5
                0x76,             // HALT
            });

            var bp = CreateBreakpoint(null, "HL' == 0x6003");

            debugProvider.Breakpoints.Add(0x8007, bp);
            debugProvider.Breakpoints.Add(0x800A, MinimumBreakpointInfo.EmptyBreakpointInfo);
            var regs = spectrum.Cpu.Registers;

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger));

            // --- Assert
            regs.PC.ShouldBe((ushort)0x800A);
            regs.B.ShouldBe((byte)0x00);
        }
Пример #13
0
        public void KempstonDeviceWithKeyPressWorks(bool left, bool right, bool up, bool down, bool fire, int expected)
        {
            // --- Arrange
            var spectrum = new SpectrumAdvancedTestMachine();
            var provider = spectrum.KempstonProvider as KempstonTestProvider;

            // ReSharper disable once PossibleNullReferenceException
            provider.Reset();
            provider.IsPresent    = true;
            provider.LeftPressed  = left;
            provider.RightPressed = right;
            provider.DownPressed  = down;
            provider.UpPressed    = up;
            provider.FirePressed  = fire;

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x01, 0x1F, 0x00, // LD BC,001FH
                0xED, 0x78,       // IN A,(C)
                0x76              // HALT
            });

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.UntilHalt));

            // --- Assert
            var regs = spectrum.Cpu.Registers;

            regs.A.ShouldBe((byte)expected);
        }
Пример #14
0
        public void EnabledInterruptIsRaised()
        {
            // --- Arrange
            var spectrum = new SpectrumAdvancedTestMachine();

            // --- We render the screen while the interrupt is enabled
            spectrum.InitCode(new byte[]
            {
                0xED, 0x56,       // IM 1
                0xFB,             // EI
                0x3E, 0x05,       // LD A,$05
                0xD3, 0xFE,       // OUT ($FE),A
                0x01, 0x00, 0x0A, // LD BC,$0A00
                0x0B,             // DECLB: DEC BC
                0x78,             // LD A,B
                0xB1,             // OR C
                0x20, 0xFB,       // JR NZ,DECLB
                0x76              // HALT
            });

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.UntilHalt));

            // --- Assert
            var regs = spectrum.Cpu.Registers;

            regs.PC.ShouldBe((ushort)0x800F);

            // --- The instructions above take 66599 tacts while reaching the HALT operation
            // --- However, an interrupt is generated, and because of IM 1, the RST 38 is
            // --- invoked. It checks to keyboard status in 1034 tacts.
            // --- When HALT is reached, the CPU tact count is 67633.
            spectrum.Cpu.Tacts.ShouldBeGreaterThanOrEqualTo(67553L);
        }
Пример #15
0
        public void ExecutionCyleWorksWithCancellation()
        {
            // --- Arrange
            var pixels   = new TestPixelRenderer(SpectrumModels.ZxSpectrum48Pal.Screen);
            var spectrum = new SpectrumAdvancedTestMachine(pixels);

            // === The same as RenderingScreenWithPatternWorks1 test case, but waits
            // === while the full frame is rendered and a new frame is started.

            // --- We render the screen with pixels with color index
            // --- of 0x09 and 0x0A in a chequered pattern
            spectrum.InitCode(new byte[]
            {
                0xF3,             // DI
                0x3E, 0x05,       // LD A,$05
                0xD3, 0xFE,       // OUT ($FE),A
                0x01, 0x75, 0x0A, // LD BC,$0A75
                0x0B,             // DECLB: DEC BC
                0x78,             // LD A,B
                0xB1,             // OR C
                0x20, 0xFB,       // JR NZ,DECLB
                0xFB,             // EI
                0x76              // HALT
            });

            for (var addr = 0x4000; addr < 0x5800; addr++)
            {
                spectrum.WriteSpectrumMemory((ushort)addr, (byte)((addr & 0x0100) == 0 ? 0x55 : 0xAA));
            }
            for (var addr = 0x5800; addr < 0x5B00; addr++)
            {
                spectrum.WriteSpectrumMemory((ushort)addr, 0x51);
            }
            var counter          = spectrum.Clock.GetCounter();
            var cancellationTime = counter + spectrum.Clock.GetFrequency() / 100000; // 0.01ms

            var startTime          = spectrum.Clock.GetCounter();
            var cancellationSource = new CancellationTokenSource();

            // --- Act
            // === We wait up to two frames
            Task.WaitAll(
                Task.Run(() => spectrum.ExecuteCycle(cancellationSource.Token, new ExecuteCycleOptions(EmulationMode.UntilFrameEnds)),
                         cancellationSource.Token),
                Task.Run(() =>
            {
                spectrum.Clock.WaitUntil(cancellationTime, cancellationSource.Token);
                cancellationSource.Cancel();
            }, cancellationSource.Token));

            // === Display some extra information about the duration of the frame execution
            var duration = (spectrum.Clock.GetCounter() - startTime)
                           / (double)spectrum.Clock.GetFrequency();

            Console.WriteLine("Frame execution time: {0} second", duration);

            // --- Assert
            // === Only a part of the frame's tact time is used
            spectrum.Cpu.Tacts.ShouldBeLessThanOrEqualTo(spectrum.ScreenDevice.ScreenConfiguration.ScreenRenderingFrameTactCount + 1);
        }
Пример #16
0
        public void SettingBorderValueChangesBorderArea1()
        {
            // --- Arrange
            var pars     = new ScreenConfiguration();
            var pixels   = new TestPixelRenderer(pars);
            var spectrum = new SpectrumAdvancedTestMachine(pars, pixels);

            // --- Because we execute 3675 CPU tacts, rendering reaches
            // --- the first 104 pixels of the first border row
            spectrum.InitCode(new byte[]
            {
                0xF3,             // DI
                0x3E, 0x05,       // LD A,$05
                0xD3, 0xFE,       // OUT ($FE),A
                0x01, 0x8C, 0x00, // LD BC,$008C
                0x0B,             // DECLB: DEC BC
                0x78,             // LD A,B
                0xB1,             // OR C
                0x20, 0xFB,       // JR NZ,DECLB
                0x76              // HALT
            });

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.UntilHalt));

            // --- Assert
            var regs = spectrum.Cpu.Registers;

            regs.PC.ShouldBe((ushort)0x800D);
            spectrum.Cpu.Tacts.ShouldBe(3671L);
            pixels.IsFrameReady.ShouldBeFalse();

            // --- The left 104 pixels of the first border row should be set to 0x05
            pixels.SetPixelMemory(spectrum.ScreenDevice.GetPixelBuffer());
            for (var column = 0; column < 96; column++)
            {
                pixels[0, column].ShouldBe((byte)0x05);
            }

            // --- The remaining pixels of the first border row should be intact (0xFF)
            for (var column = 96; column < spectrum.ScreenDevice.ScreenConfiguration.ScreenWidth; column++)
            {
                pixels[0, column].ShouldBe((byte)0x00);
            }

            // --- All the other screen bytes should be intact (0xFF)
            for (var row = 1; row < spectrum.ScreenDevice.ScreenConfiguration.ScreenLines; row++)
            {
                for (var column = 0; column < spectrum.ScreenDevice.ScreenConfiguration.ScreenWidth; column++)
                {
                    pixels[row, column].ShouldBe((byte)0x00);
                }
            }
        }
Пример #17
0
        public void UlaFrameTactCountIsCalculatedProperlyForSpectrum48Ntsc()
        {
            // --- Arrange
            var screenConfig = SpectrumModels.ZxSpectrum48Ntsc.Screen;
            var pixels       = new TestPixelRenderer(screenConfig);
            var spectrum     = new SpectrumAdvancedTestMachine(pixels, screenConfig);

            // --- Act
            var ulaFrameTactCount = spectrum.ScreenDevice.ScreenConfiguration.ScreenRenderingFrameTactCount;

            // --- Assert
            ulaFrameTactCount.ShouldBe(59136);
        }
Пример #18
0
        public void RefreshRateIsCalculatedProperlyForSpectrum48Ntsc()
        {
            // --- Arrange
            var screenConfig = SpectrumModels.ZxSpectrum48Ntsc.Screen;
            var pixels       = new TestPixelRenderer(screenConfig);
            var spectrum     = new SpectrumAdvancedTestMachine(pixels, screenConfig);

            // --- Act
            var freq = Math.Round(spectrum.ScreenDevice.RefreshRate, 2);

            // --- Assert
            freq.ShouldBe(59.19m);
        }
Пример #19
0
        public void FlashToggleRateIsCalculatedProperlyForSpectrum48Ntsc()
        {
            // --- Arrange
            var screenConfig = SpectrumModels.ZxSpectrum48Ntsc.Screen;
            var pixels       = new TestPixelRenderer(screenConfig);
            var spectrum     = new SpectrumAdvancedTestMachine(pixels, screenConfig);

            // --- Act
            var rate = spectrum.ScreenDevice.FlashToggleFrames;

            // --- Assert
            rate.ShouldBe(30);
        }
Пример #20
0
        private static void InitMachineOutCWithNops(int tactToReach, byte port, SpectrumAdvancedTestMachine spectrum)
        {
            var code = new List <byte>
            {
                0xF3 // DI ; (4)
            };
            var usedTacts = 4;
            var remainder = tactToReach % 4;

            switch (remainder)
            {
            case 0:
                code.Add(0x03);     // INC BC (6)
                usedTacts += 6;
                break;

            case 1:
                code.Add(0x3E);     // LD A,0 (7)
                code.Add(0x00);
                usedTacts += 7;
                break;

            case 2:
                break;

            case 3:
                code.Add(0xED);     // LD A,I (9)
                code.Add(0x57);
                usedTacts += 9;
                break;
            }

            usedTacts += 26;
            var extraNops = (tactToReach - usedTacts) / 4;

            for (var i = 0; i < extraNops; i++)
            {
                code.Add(0x00); // NOP
            }

            // --- Now we add the instruction for contention
            code.Add(0x06); // LD B,port ; (7)
            code.Add(port);
            code.Add(0x0E); // LD C,port ; (7)
            code.Add(port);
            code.Add(0xED); // OUT (C),A ; (12)
            code.Add(0x79);
            code.Add(0x76); // HALT

            spectrum.InitCode(code);
        }
Пример #21
0
        public void SettingBorderValueChangesBorderArea2()
        {
            // --- Arrange
            var pixels   = new TestPixelRenderer(SpectrumModels.ZxSpectrum48Pal.Screen);
            var spectrum = new SpectrumAdvancedTestMachine(pixels);

            // --- Because we execute 14335 CPU tacts, rendering reaches
            // --- all top border rows, save the last invisible pixels of the last top border row
            spectrum.InitCode(new byte[]
            {
                0xF3,             // DI
                0x3E, 0x05,       // LD A,$05
                0xD3, 0xFE,       // OUT ($FE),A
                0x01, 0x26, 0x02, // LD BC,$0226
                0x0B,             // DECLB: DEC BC
                0x78,             // LD A,B
                0xB1,             // OR C
                0x20, 0xFB,       // JR NZ,DECLB
                0x76              // HALT
            });

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.UntilHalt));

            // --- Assert
            var regs = spectrum.Cpu.Registers;

            regs.PC.ShouldBe((ushort)0x800D);
            spectrum.Cpu.Tacts.ShouldBe(14331L);
            pixels.IsFrameReady.ShouldBeFalse();

            // --- The top 48 border rows should be set to 0x05
            pixels.SetPixelMemory(spectrum.ScreenDevice.GetPixelBuffer());
            for (var row = 0; row < 48; row++)
            {
                for (var column = 0; column < spectrum.ScreenDevice.ScreenConfiguration.ScreenWidth; column++)
                {
                    pixels[row, column].ShouldBe((byte)0x05);
                }
            }

            // --- All the other screen bytes should be intact (0xFF)
            for (var row = 48; row < spectrum.ScreenDevice.ScreenConfiguration.ScreenLines; row++)
            {
                for (var column = 0; column < spectrum.ScreenDevice.ScreenConfiguration.ScreenWidth; column++)
                {
                    pixels[row, column].ShouldBe((byte)0x00);
                }
            }
        }
Пример #22
0
        private static void InitMachineReadWithNops(int tactToReach, SpectrumAdvancedTestMachine spectrum)
        {
            var code = new List <byte>
            {
                0xF3 // DI ; (4)
            };
            var usedTacts = 4;
            var remainder = tactToReach % 4;

            switch (remainder)
            {
            case 0:
                break;

            case 1:
                code.Add(0xED);     // LD A,I (9)
                code.Add(0x57);
                usedTacts += 9;
                break;

            case 2:
                code.Add(0x03);     // INC BC (6)
                usedTacts += 6;
                break;

            default:
                code.Add(0x3E);     // LD A,0 (7)
                code.Add(0x00);
                usedTacts += 7;
                break;
            }

            usedTacts += 20;
            var extraNops = (tactToReach - usedTacts) / 4;

            for (var i = 0; i < extraNops; i++)
            {
                code.Add(0x00); // NOP
            }

            // --- Now we add the instruction for contention
            code.Add(0x3E); // LD A,#FF ; (7)
            code.Add(0xFF);
            code.Add(0x3A); // LD A,(#4100) ; (13)
            code.Add(0x00);
            code.Add(0x41);
            code.Add(0x76); // HALT

            spectrum.InitCode(code);
        }
Пример #23
0
        public void InterruptDeviceResetWorksAsExpected()
        {
            // --- Arrange
            var vm   = new SpectrumAdvancedTestMachine();
            var idev = new InterruptDevice(TEST_INT_TACT);

            idev.OnAttachedToVm(vm);

            // --- Act
            idev.Reset();

            // --- Assert
            idev.InterruptRaised.ShouldBeFalse();
            idev.InterruptRevoked.ShouldBeFalse();
        }
Пример #24
0
        public void InterruptIsRaisedWithinAllowedRange()
        {
            for (var tact = TEST_INT_TACT; tact <= TEST_INT_TACT + InterruptDevice.LONGEST_OP_TACTS; tact++)
            {
                // --- Arrange
                var vm   = new SpectrumAdvancedTestMachine();
                var idev = new InterruptDevice(TEST_INT_TACT);
                idev.OnAttachedToVm(vm);

                // --- Act/Assert
                idev.CheckForInterrupt(tact);
                idev.InterruptRaised.ShouldBeTrue();
                idev.InterruptRevoked.ShouldBeFalse();
                idev.FrameCount.ShouldBe(1);
                (vm.Cpu.StateFlags & Z80StateFlags.Int).ShouldBe(Z80StateFlags.Int);
            }
        }
Пример #25
0
        public void InterruptNotRaisedTooEarly()
        {
            // --- Arrange
            var vm   = new SpectrumAdvancedTestMachine();
            var idev = new InterruptDevice(TEST_INT_TACT);

            idev.OnAttachedToVm(vm);

            // --- Act/Assert
            for (var tact = 0; tact < TEST_INT_TACT; tact++)
            {
                idev.CheckForInterrupt(tact);
                idev.InterruptRaised.ShouldBeFalse();
                idev.InterruptRevoked.ShouldBeFalse();
                idev.FrameCount.ShouldBe(0);
                (vm.Cpu.StateFlags & Z80StateFlags.Int).ShouldBe(Z80StateFlags.None);
            }
        }
Пример #26
0
        public void NoInCContentionValueOnPort0XffIsAppliedWhenLeftDisplayEdgeIsReached(int deviation, int expected)
        {
            // --- Arrange
            var screenConfig = new ScreenConfiguration(SpectrumModels.ZxSpectrum48Pal.Screen);
            var pixels       = new TestPixelRenderer(SpectrumModels.ZxSpectrum48Pal.Screen);
            var spectrum     = new SpectrumAdvancedTestMachine(pixels);

            var tactToReach = screenConfig.FirstDisplayLine * screenConfig.ScreenLineTime
                              + screenConfig.FirstPixelTactInLine - 12 + deviation;

            InitMachineInCWithNops(tactToReach, 0xff, spectrum);

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.UntilHalt));

            // --- Assert
            spectrum.Cpu.Tacts.ShouldBe(expected + tactToReach + 4); // +4 for HALT
        }
Пример #27
0
        public void NoReadContentionValueIsAppliedWhileFirstDisplayLineIsReached()
        {
            // --- Arrange
            const int EXPECTED_CONTENTION = 0;
            var       screenConfig        = new ScreenConfiguration(SpectrumModels.ZxSpectrum48Pal.Screen);
            var       pixels   = new TestPixelRenderer(SpectrumModels.ZxSpectrum48Pal.Screen);
            var       spectrum = new SpectrumAdvancedTestMachine(pixels);

            var tactToReach = screenConfig.FirstDisplayLine * screenConfig.ScreenLineTime;

            InitMachineReadWithNops(tactToReach, spectrum);

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.UntilHalt));

            // --- Assert
            spectrum.Cpu.Tacts.ShouldBe(EXPECTED_CONTENTION + tactToReach + 4); // +4 for HALT
        }
        public void CycleWorksWithGreaterThanOrEqualHitCondition5()
        {
            // --- Arrange
            var spectrum = new SpectrumAdvancedTestMachine();

            spectrum.DebugExpressionContext = new SpectrumEvaluationContext(spectrum);
            var debugProvider = new TestDebugInfoProvider();

            spectrum.SetDebugInfoProvider(debugProvider);

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x06, 0x80,       // LD B,$80
                0x3E, 0x00,       // LD A,$00
                0x3C,             // INC A
                0x10, 0xFD,       // DJNZ -3
                0x76,             // HALT
            });

            var bp = CreateBreakpoint(">=127", null);

            debugProvider.Breakpoints.Add(0x8004, bp);
            debugProvider.Breakpoints.Add(0x8007, MinimumBreakpointInfo.EmptyBreakpointInfo);
            var regs = spectrum.Cpu.Registers;

            // --- Act/Assert (Run 1)
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger));
            regs.A.ShouldBe((byte)0x7E);
            regs.B.ShouldBe((byte)0x02);
            regs.PC.ShouldBe((ushort)0x8004);

            // --- Act/Assert (Run 2)
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger));
            regs.A.ShouldBe((byte)0x7F);
            regs.B.ShouldBe((byte)0x01);
            regs.PC.ShouldBe((ushort)0x8004);

            // --- Act/Assert (Run 3)
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger));
            regs.A.ShouldBe((byte)0x80);
            regs.B.ShouldBe((byte)0x00);
            regs.PC.ShouldBe((ushort)0x8007);
        }
Пример #29
0
        public void StepOverWorksWithCallPFalse()
        {
            // --- Arrange
            var pars          = new ScreenConfiguration();
            var pixels        = new TestPixelRenderer(pars);
            var spectrum      = new SpectrumAdvancedTestMachine(pars, pixels);
            var debugProvider = new TestDebugInfoProvider();

            spectrum.SetDebugInfoProvider(debugProvider);

            // --- We render the screen while the interrupt is disabled
            spectrum.InitCode(new byte[]
            {
                0x3E, 0x90,       // LD A,$90
                0xB7,             // OR A
                0xF4, 0x09, 0x80, // CALL P,$8009
                0x47,             // LD B,A
                0x4F,             // LD C,A
                0x76,             // HALT
                0x3E, 0x20,       // LD a,$20
                0x57,             // LD D,A
                0xC9              // RET
            });
            var regs = spectrum.Cpu.Registers;

            // --- Act
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger, DebugStepMode.StepOver));
            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger, DebugStepMode.StepOver));
            var pc1 = regs.PC;

            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger, DebugStepMode.StepOver));
            var pc2 = regs.PC;

            spectrum.ExecuteCycle(CancellationToken.None, new ExecuteCycleOptions(EmulationMode.Debugger, DebugStepMode.StepOver));

            // --- Assert
            regs.A.ShouldBe((byte)0x90);
            regs.B.ShouldBe((byte)0x90);
            regs.C.ShouldBe((byte)0x00);
            regs.D.ShouldBe((byte)0x00);
            pc1.ShouldBe((ushort)0x8003);
            pc2.ShouldBe((ushort)0x8006);
            regs.PC.ShouldBe((ushort)0x8007);
        }
Пример #30
0
        public void InterruptIsNotRereaised()
        {
            // --- Arrange
            var vm   = new SpectrumAdvancedTestMachine();
            var idev = new InterruptDevice(TEST_INT_TACT);

            idev.OnAttachedToVm(vm);
            idev.CheckForInterrupt(TEST_INT_TACT);

            // --- Act
            vm.Cpu.StateFlags &= Z80StateFlags.InvInt;
            idev.CheckForInterrupt(TEST_INT_TACT + 1);

            // --- Assert
            idev.InterruptRaised.ShouldBeTrue();
            idev.InterruptRevoked.ShouldBeFalse();
            (vm.Cpu.StateFlags & Z80StateFlags.Int).ShouldBe(Z80StateFlags.None);
            idev.FrameCount.ShouldBe(1);
        }