public void Spectrum48NtscVmCreationWorks() { // --- Act var sm = SpectrumVmFactory.CreateSpectrum48Ntsc(); // --- Assert sm.ModelKey.ShouldBe(SpectrumModels.ZX_SPECTRUM_48); sm.EditionKey.ShouldBe(SpectrumModels.NTSC); sm.Cpu.ShouldNotBeNull(); sm.Roms.ShouldNotBeNull(); sm.RomCount.ShouldBe(1); sm.PagingInfo.ShouldNotBeNull(); sm.RamBanks.ShouldNotBeNull(); sm.RamBankCount.ShouldBe(0); sm.Keyboard.ShouldNotBeNull(); sm.ScreenConfiguration.ShouldNotBeNull(); sm.ScreenConfiguration.ScreenRenderingFrameTactCount.ShouldBe(59136); sm.ScreenBitmap.ShouldNotBeNull(); sm.ScreenRenderingStatus.ShouldNotBeNull(); sm.BeeperConfiguration.ShouldNotBeNull(); sm.BeeperSamples.ShouldNotBeNull(); sm.SoundConfiguration.ShouldBeNull(); sm.AudioSamples.ShouldNotBeNull(); sm.Breakpoints.ShouldNotBeNull(); sm.MachineState.ShouldBe(VmState.None); sm.ExecutionCompletionReason.ShouldBe(ExecutionCompletionReason.None); sm.IsFirstStart.ShouldBeFalse(); sm.IsFirstPause.ShouldBeFalse(); }
public async Task ResetOperationTrackingWorks() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); sm.Breakpoints.AddBreakpoint(0x11CB); sm.StartDebug(); await sm.CompletionTask; var pcBefore = sm.Cpu.PC; sm.ExecutionCompletionReason.ShouldBe(ExecutionCompletionReason.BreakpointReached); sm.MachineState.ShouldBe(VmState.Paused); // --- Act sm.Cpu.ResetOperationTracking(); sm.Breakpoints.ClearAllBreakpoints(); sm.Breakpoints.AddBreakpoint(0x11CE); sm.StartDebug(); await sm.CompletionTask; var pcAfter = sm.Cpu.PC; // --- Assert pcBefore.ShouldBe((ushort)0x11CB); pcAfter.ShouldBe((ushort)0x11CE); sm.Cpu.OperationTrackingState.TouchedAny(0x0000, 0x11CA).ShouldBeFalse(); sm.Cpu.OperationTrackingState[0x11CB].ShouldBeTrue(); sm.Cpu.OperationTrackingState[0x11CC].ShouldBeTrue(); sm.Cpu.OperationTrackingState[0x11CD].ShouldBeTrue(); sm.Cpu.OperationTrackingState.TouchedAny(0x11CE, 0xFFFF).ShouldBeFalse(); }
public async Task InterruptExecutingIsInvoked() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); sm.CachedVmStateFolder = STATE_FOLDER; await sm.StartAndRunToMain(true); var counter = 0; // --- Act sm.Cpu.InterruptExecuting += (s, e) => { counter++; }; var entryAddress = sm.InjectCode(@" .org #8000 ld a,2 out (#fe),a halt halt halt ret "); sm.CallCode(entryAddress); await sm.CompletionTask; // --- Assert counter.ShouldBe(4); }
public async Task InjectCodeWorksWithSpectrum48() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); sm.CachedVmStateFolder = STATE_FOLDER; await sm.StartAndRunToMain(true); // --- Act var entryAddress = sm.InjectCode(@" .org #8000 ld a,2 out (#fe),a halt halt ret "); sm.CallCode(entryAddress); await sm.CompletionTask; // --- Assert sm.Cpu.A.ShouldBe((byte)2); foreach (var item in sm.ScreenBitmap[0]) { item.ShouldBe((byte)0x02); } }
public async Task PortWrittenIsInvoked() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); sm.CachedVmStateFolder = STATE_FOLDER; await sm.StartAndRunToMain(true); var events = new List <AddressAndDataEventArgs>(); // --- Act var entryAddress = sm.InjectCode(@" .org #8000 ld a,5 ld bc,#7FFE out (c),a ld a,#24 out (#FE),a ret "); sm.Cpu.PortWritten += (s, e) => { events.Add(e); }; sm.CallCode(entryAddress); await sm.CompletionTask; // --- Assert var sampleIndex = events.Count - 2; // -2 for the 2 read operation events[sampleIndex].Address.ShouldBe((ushort)0x7FFE); events[sampleIndex].Data.ShouldBe((byte)0x05); events[sampleIndex + 1].Address.ShouldBe((ushort)0x24FE); events[sampleIndex + 1].Data.ShouldBe((byte)0x24); }
public async Task StartWorksAfterPause() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); sm.Start(); await sm.Pause(); var stateBefore = sm.MachineState; var eventCounter = 0; var goesToRunning = false; sm.VmStateChanged += (s, e) => { eventCounter++; if (eventCounter == 1) { goesToRunning = e.OldState == VmState.Paused && e.NewState == VmState.Running; } }; // --- Act sm.Start(); var stateAfter = sm.MachineState; // --- Assert stateBefore.ShouldBe(VmState.Paused); stateAfter.ShouldBe(VmState.Running); sm.IsFirstStart.ShouldBeFalse(); goesToRunning.ShouldBeTrue(); }
public async Task MemoryReadIsInvoked() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); sm.CachedVmStateFolder = STATE_FOLDER; await sm.StartAndRunToMain(true); var events = new List <AddressAndDataEventArgs>(); // --- Act var entryAddress = sm.InjectCode(@" .org #8000 ld hl,#4000 ld (hl),#AA ld a,(hl) inc hl ld (hl),#55 ld a,(#4001) ret "); sm.Cpu.MemoryRead += (s, e) => { events.Add(e); }; sm.CallCode(entryAddress); await sm.CompletionTask; // --- Assert var sampleIndex = events.Count - 2 - 2; // -2 for RET, -2 for the two memory reads events[sampleIndex].Address.ShouldBe((ushort)0x4000); events[sampleIndex].Data.ShouldBe((byte)0xAA); events[sampleIndex + 1].Address.ShouldBe((ushort)0x4001); events[sampleIndex + 1].Data.ShouldBe((byte)0x55); }
public async Task StopAfterStartWorks() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); sm.Start(); var stateBefore = sm.MachineState; var eventCounter = 0; var goesToStopping = false; var goesToStopped = false; sm.VmStateChanged += (s, e) => { eventCounter++; if (eventCounter == 1) { goesToStopping = e.OldState == VmState.Running && e.NewState == VmState.Stopping; } else if (eventCounter == 2) { goesToStopped = e.OldState == VmState.Stopping && e.NewState == VmState.Stopped; } }; // --- Act await sm.Stop(); var stateAfter = sm.MachineState; // --- Assert stateBefore.ShouldBe(VmState.Running); stateAfter.ShouldBe(VmState.Stopped); goesToStopping.ShouldBeTrue(); goesToStopped.ShouldBeTrue(); }
public async Task SpectrumP3EIn48ModeStartAndRunToMainWorksWithExistingStateFile() { // --- Arrange const string STATE_FILE = SpectrumVmStateFileManagerBase.SPECTRUM_P3_STARTUP_48; var filename = Path.Combine(STATE_FOLDER, STATE_FILE); if (File.Exists(filename)) { File.Delete(filename); } var sm = SpectrumVmFactory.CreateSpectrumP3E(); sm.CachedVmStateFolder = STATE_FOLDER; await sm.StartAndRunToMain(true); var creationTimeBefore = new FileInfo(filename).CreationTime; await sm.Stop(); // --- Act await sm.StartAndRunToMain(true); // --- Assert var creationTimeAfter = new FileInfo(filename).CreationTime; sm.MachineState.ShouldBe(VmState.Paused); sm.Cpu.PC.ShouldBe(SpectrumVmStateFileManagerBase.SP48_MAIN_EXEC_ADDR); File.Exists(filename).ShouldBeTrue(); creationTimeBefore.ShouldBe(creationTimeAfter); }
public void CreateSpectrum48NtscTurboWorks() { // --- Act var sm = SpectrumVmFactory.CreateSpectrum48NtscTurbo(); // --- Assert sm.ShouldNotBeNull(); sm.ModelKey.ShouldBe(SpectrumModels.ZX_SPECTRUM_48); sm.EditionKey.ShouldBe(SpectrumModels.NTSC_2_X); }
public void CreateSpectrumP3EWorks() { // --- Act var sm = SpectrumVmFactory.CreateSpectrumP3E(); // --- Assert sm.ShouldNotBeNull(); sm.ModelKey.ShouldBe(SpectrumModels.ZX_SPECTRUM_P3_E); sm.EditionKey.ShouldBe(SpectrumModels.PAL); }
static async Task Main(string[] args) { Console.WriteLine("Creating ZX Spectrum 48K"); var sm = SpectrumVmFactory.CreateSpectrum48Pal(); Console.WriteLine("Running to breakpoint 0x0001"); sm.Breakpoints.AddBreakpoint(0x0001); sm.StartDebug(); await sm.CompletionTask; Console.WriteLine($"Paused at breakpoint 0x{sm.Cpu.PC:X4}"); }
public async Task SoundSamplesCreatedForSpectrum128() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum128(); // --- Act sm.RunUntilFrameCompletion(); await sm.CompletionTask; // --- Assert sm.AudioSamples.Count.ShouldBeGreaterThanOrEqualTo(sm.SoundConfiguration.SamplesPerFrame); sm.AudioSamples.Count.ShouldBeLessThanOrEqualTo(sm.SoundConfiguration.SamplesPerFrame + 1); }
public async Task AddressTrackingWorks1() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); // --- Act sm.Breakpoints.AddBreakpoint(0x0001); sm.StartDebug(); await sm.CompletionTask; // --- Assert sm.Cpu.OperationTrackingState[0x0000].ShouldBeTrue(); sm.Cpu.OperationTrackingState.TouchedAny(0x0001, 0xFFFF).ShouldBeFalse(); }
public async Task FirstSoundFrameShouldBeSilent() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); // --- Act sm.RunUntilFrameCompletion(); await sm.CompletionTask; // --- Assert for (var i = 0; i < sm.BeeperSamples.Count; i++) { sm.BeeperSamples[i].ShouldBe(0.0f); } }
public async Task PauseKeepsNonStartedState() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); // --- Act var stateBefore = sm.MachineState; await sm.Pause(); var stateAfter = sm.MachineState; // --- Assert stateBefore.ShouldBe(VmState.None); stateAfter.ShouldBe(VmState.None); }
public async Task MachineStopsAfterTimeout() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); var stateBefore = sm.MachineState; // --- Act sm.TimeoutInMs = 10; sm.Start(); await sm.CompletionTask; var stateAfter = sm.MachineState; // --- Assert stateBefore.ShouldBe(VmState.None); sm.ExecutionCompletionReason.ShouldBe(ExecutionCompletionReason.Timeout); stateAfter.ShouldBe(VmState.Paused); }
public async Task MachineRaisesFrameCompletedEvents() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); // --- Act sm.TimeoutInMs = 200; var counter = 0; sm.VmFrameCompleted += (s, e) => { counter++; }; sm.Start(); await sm.CompletionTask; // --- Assert counter.ShouldBeGreaterThanOrEqualTo(9); counter.ShouldBeLessThanOrEqualTo(11); }
public async Task StopKeepsStoppedState() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); sm.Start(); await sm.Stop(); // --- Act var stateBefore = sm.MachineState; await sm.Stop(); var stateAfter = sm.MachineState; // --- Assert stateBefore.ShouldBe(VmState.Stopped); stateAfter.ShouldBe(VmState.Stopped); }
public async Task StartDebugWorks() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); var stateBefore = sm.MachineState; // --- Act sm.Breakpoints.AddBreakpoint(0x0001); sm.StartDebug(); await sm.CompletionTask; var stateAfter = sm.MachineState; // --- Assert stateBefore.ShouldBe(VmState.None); stateAfter.ShouldBe(VmState.Paused); sm.RunsInDebugMode.ShouldBeTrue(); sm.Cpu.PC.ShouldBe((ushort)0x0001); sm.ExecutionCompletionReason.ShouldBe(ExecutionCompletionReason.BreakpointReached); }
public async Task Spectrum128In48ModeStartAndRunToMainWorksWithNoStateFile() { // --- Arrange const string STATE_FILE = SpectrumVmStateFileManagerBase.SPECTRUM_128_STARTUP_48; var filename = Path.Combine(STATE_FOLDER, STATE_FILE); if (File.Exists(filename)) { File.Delete(filename); } var sm = SpectrumVmFactory.CreateSpectrum128(); sm.CachedVmStateFolder = STATE_FOLDER; // --- Act await sm.StartAndRunToMain(true); // --- Assert sm.MachineState.ShouldBe(VmState.Paused); sm.Cpu.PC.ShouldBe(SpectrumVmStateFileManagerBase.SP48_MAIN_EXEC_ADDR); File.Exists(filename).ShouldBeTrue(); }
public async Task SpectrumP3EStartAndRunToMainWorksWithNoStateFile() { // --- Arrange const string STATE_FILE = SpectrumVmStateFileManagerBase.SPECTRUM_P3_STARTUP_P3; var filename = Path.Combine(STATE_FOLDER, STATE_FILE); if (File.Exists(filename)) { File.Delete(filename); } var sm = SpectrumVmFactory.CreateSpectrumP3E(); sm.CachedVmStateFolder = STATE_FOLDER; // --- Act await sm.StartAndRunToMain(); // --- Assert sm.MachineState.ShouldBe(VmState.Paused); sm.Cpu.PC.ShouldBe(SpectrumVmStateFileManagerBase.SPP3_RETURN_TO_EDITOR); File.Exists(filename).ShouldBeTrue(); }
public async Task RunningSpectrumP3EDoesNotAllowStratAndRunToMain() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrumP3E(); sm.CachedVmStateFolder = STATE_FOLDER; sm.Start(); // --- Act/Assert try { await sm.StartAndRunToMain(true); } catch (InvalidOperationException) { return; } finally { await sm.Stop(); } Assert.Fail("Expected InvalidOperationException"); }
public void TestInitialize() { SpectrumVmFactory.Reset(); SpectrumVmFactory.RegisterDefaultProviders(); }
public async Task OperationExecutedIsInvoked() { // --- Arrange var sm = SpectrumVmFactory.CreateSpectrum48Pal(); sm.CachedVmStateFolder = STATE_FOLDER; await sm.StartAndRunToMain(true); var events = new List <Z80InstructionExecutionEventArgs>(); // --- Act var entryAddress = sm.InjectCode(@" .org #8000 di; 8000: No prefix bit 3,a; 8001: CB prefix ld a,(ix+2); 8003: DD prefix ld a,(iy+6); 8006: FD prefix bit 2,(ix+2); 8009: DD CB prefixes bit 2,(iy+6); 800D: FD CB prefixes in d,(c); 8011: ED prefix ret "); sm.Cpu.OperationExecuted += (s, e) => { events.Add(e); }; sm.CallCode(entryAddress); await sm.CompletionTask; // --- Assert var sampleIndex = events.Count - 1 - 7; // -1 for the RET operation, -7 for the 7 operations var op = events[sampleIndex]; op.PcBefore.ShouldBe((ushort)0x8000); op.Instruction.SequenceEqual(new byte[] { 0xF3 }).ShouldBeTrue(); op.OpCode.ShouldBe((byte)0xF3); op.PcAfter.ShouldBe((ushort)0x8001); op = events[sampleIndex + 1]; op.PcBefore.ShouldBe((ushort)0x8001); op.Instruction.SequenceEqual(new byte[] { 0xCB, 0x5F }).ShouldBeTrue(); op.OpCode.ShouldBe((byte)0x5F); op.PcAfter.ShouldBe((ushort)0x8003); op = events[sampleIndex + 2]; op.PcBefore.ShouldBe((ushort)0x8003); op.Instruction.SequenceEqual(new byte[] { 0xDD, 0x7E, 0x02 }).ShouldBeTrue(); op.OpCode.ShouldBe((byte)0x7E); op.PcAfter.ShouldBe((ushort)0x8006); op = events[sampleIndex + 3]; op.PcBefore.ShouldBe((ushort)0x8006); op.Instruction.SequenceEqual(new byte[] { 0xFD, 0x7E, 0x06 }).ShouldBeTrue(); op.OpCode.ShouldBe((byte)0x7E); op.PcAfter.ShouldBe((ushort)0x8009); op = events[sampleIndex + 4]; op.PcBefore.ShouldBe((ushort)0x8009); op.Instruction.SequenceEqual(new byte[] { 0xDD, 0xCB, 0x56, 0x02 }).ShouldBeTrue(); op.OpCode.ShouldBe((byte)0x56); op.PcAfter.ShouldBe((ushort)0x800D); op = events[sampleIndex + 5]; op.PcBefore.ShouldBe((ushort)0x800D); op.Instruction.SequenceEqual(new byte[] { 0xFD, 0xCB, 0x56, 0x06 }).ShouldBeTrue(); op.OpCode.ShouldBe((byte)0x56); op.PcAfter.ShouldBe((ushort)0x8011); op = events[sampleIndex + 6]; op.PcBefore.ShouldBe((ushort)0x8011); op.Instruction.SequenceEqual(new byte[] { 0xED, 0x50 }).ShouldBeTrue(); op.OpCode.ShouldBe((byte)0x50); op.PcAfter.ShouldBe((ushort)0x8013); }