public void SyncState(Serializer ser) { ser.BeginSection("ZXMachine"); ser.Sync("FrameCompleted", ref FrameCompleted); ser.Sync("OverFlow", ref OverFlow); ser.Sync("FrameCount", ref FrameCount); ser.Sync("_frameCycles", ref _frameCycles); ser.Sync("inputRead", ref inputRead); ser.Sync("LastFrameStartCPUTick", ref LastFrameStartCPUTick); ser.Sync("LastULAOutByte", ref LastULAOutByte); ser.Sync("ROM0", ref ROM0, false); ser.Sync("ROM1", ref ROM1, false); ser.Sync("ROM2", ref ROM2, false); ser.Sync("ROM3", ref ROM3, false); ser.Sync("RAM0", ref RAM0, false); ser.Sync("RAM1", ref RAM1, false); ser.Sync("RAM2", ref RAM2, false); ser.Sync("RAM3", ref RAM3, false); ser.Sync("RAM4", ref RAM4, false); ser.Sync("RAM5", ref RAM5, false); ser.Sync("RAM6", ref RAM6, false); ser.Sync("RAM7", ref RAM7, false); ser.Sync("ROMPaged", ref ROMPaged); ser.Sync("SHADOWPaged", ref SHADOWPaged); ser.Sync("RAMPaged", ref RAMPaged); ser.Sync("PagingDisabled", ref PagingDisabled); ser.Sync("SpecialPagingMode", ref SpecialPagingMode); ser.Sync("PagingConfiguration", ref PagingConfiguration); ser.Sync("ROMhigh", ref ROMhigh); ser.Sync("ROMlow", ref ROMlow); KeyboardDevice.SyncState(ser); BuzzerDevice.SyncState(ser); TapeBuzzer.SyncState(ser); ULADevice.SyncState(ser); if (AYDevice != null) { AYDevice.SyncState(ser); ((AYChip)AYDevice as AYChip).PanningConfiguration = Spectrum.Settings.AYPanConfig; } if (UPDDiskDevice != null) { UPDDiskDevice.SyncState(ser); } ser.Sync("tapeMediaIndex", ref tapeMediaIndex); TapeMediaIndex = tapeMediaIndex; ser.Sync("diskMediaIndex", ref diskMediaIndex); DiskMediaIndex = diskMediaIndex; TapeDevice.SyncState(ser); ser.EndSection(); }
public void SyncState(Serializer ser) { ser.BeginSection("CPCMachine"); ser.Sync("FrameCompleted", ref FrameCompleted); ser.Sync("OverFlow", ref OverFlow); ser.Sync("FrameCount", ref FrameCount); ser.Sync("_frameCycles", ref _frameCycles); ser.Sync("inputRead", ref inputRead); ser.Sync("LastFrameStartCPUTick", ref LastFrameStartCPUTick); ser.Sync("ROMLower", ref ROMLower, false); ser.Sync("ROM0", ref ROM0, false); ser.Sync("ROM7", ref ROM7, false); ser.Sync("RAM0", ref RAM0, false); ser.Sync("RAM1", ref RAM1, false); ser.Sync("RAM2", ref RAM2, false); ser.Sync("RAM3", ref RAM3, false); ser.Sync("RAM4", ref RAM4, false); ser.Sync("RAM5", ref RAM5, false); ser.Sync("RAM6", ref RAM6, false); ser.Sync("RAM7", ref RAM7, false); ser.Sync("UpperROMPosition", ref UpperROMPosition); ser.Sync("UpperROMPaged", ref UpperROMPaged); ser.Sync("LowerROMPaged", ref LowerROMPaged); ser.Sync("RAMConfig", ref RAMConfig); ser.Sync("RAM64KBank", ref RAM64KBank); CRCT.SyncState(ser); //CRT.SyncState(ser); GateArray.SyncState(ser); KeyboardDevice.SyncState(ser); TapeBuzzer.SyncState(ser); AYDevice.SyncState(ser); ser.Sync("tapeMediaIndex", ref tapeMediaIndex); if (ser.IsReader) { TapeMediaIndex = tapeMediaIndex; } TapeDevice.SyncState(ser); ser.Sync("diskMediaIndex", ref diskMediaIndex); if (ser.IsReader) { DiskMediaIndex = diskMediaIndex; } if (UPDDiskDevice != null) { UPDDiskDevice.SyncState(ser); } ser.EndSection(); }
public void SyncState(Serializer ser) { ser.BeginSection("CPCMachine"); ser.Sync(nameof(FrameCompleted), ref FrameCompleted); ser.Sync(nameof(OverFlow), ref OverFlow); ser.Sync(nameof(FrameCount), ref FrameCount); ser.Sync(nameof(_frameCycles), ref _frameCycles); ser.Sync(nameof(inputRead), ref inputRead); ser.Sync(nameof(LastFrameStartCPUTick), ref LastFrameStartCPUTick); ser.Sync(nameof(ROMLower), ref ROMLower, false); ser.Sync(nameof(ROM0), ref ROM0, false); ser.Sync(nameof(ROM7), ref ROM7, false); ser.Sync(nameof(RAM0), ref RAM0, false); ser.Sync(nameof(RAM1), ref RAM1, false); ser.Sync(nameof(RAM2), ref RAM2, false); ser.Sync(nameof(RAM3), ref RAM3, false); ser.Sync(nameof(RAM4), ref RAM4, false); ser.Sync(nameof(RAM5), ref RAM5, false); ser.Sync(nameof(RAM6), ref RAM6, false); ser.Sync(nameof(RAM7), ref RAM7, false); ser.Sync(nameof(UpperROMPosition), ref UpperROMPosition); ser.Sync(nameof(UpperROMPaged), ref UpperROMPaged); ser.Sync(nameof(LowerROMPaged), ref LowerROMPaged); ser.Sync(nameof(RAMConfig), ref RAMConfig); ser.Sync(nameof(RAM64KBank), ref RAM64KBank); CRCT.SyncState(ser); //CRT.SyncState(ser); GateArray.SyncState(ser); KeyboardDevice.SyncState(ser); TapeBuzzer.SyncState(ser); AYDevice.SyncState(ser); ser.Sync(nameof(tapeMediaIndex), ref tapeMediaIndex); if (ser.IsReader) { TapeMediaIndex = tapeMediaIndex; } TapeDevice.SyncState(ser); ser.Sync(nameof(diskMediaIndex), ref diskMediaIndex); if (ser.IsReader) { DiskMediaIndex = diskMediaIndex; } if (UPDDiskDevice != null) { UPDDiskDevice.SyncState(ser); } ser.EndSection(); }
/// <summary> /// Reads a byte of data from a specified port address /// </summary> public override byte ReadPort(ushort port) { bool deviceAddressed = true; int result = 0xFF; // check AY if (AYDevice.ReadPort(port, ref result)) { return((byte)result); } byte lowByte = (byte)(port & 0xff); // Kempston joystick input takes priority over all keyboard input // if this is detected just return the kempston byte if (lowByte == 0x1f) { if (LocateUniqueJoystick(JoystickType.Kempston) != null) { InputRead = true; return((byte)((KempstonJoystick)LocateUniqueJoystick(JoystickType.Kempston) as KempstonJoystick).JoyLine); } InputRead = true; } else if (UPDDiskDevice.ReadPort(port, ref result)) { return((byte)result); } else { if (KeyboardDevice.ReadPort(port, ref result)) { // not a lagframe InputRead = true; // process tape INs TapeDevice.ReadPort(port, ref result); } else { deviceAddressed = false; } } if (!deviceAddressed) { // If this is an unused port the floating memory bus should be returned ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result, port); } return((byte)result); }
/// <summary> /// Soft reset of the emulated machine /// </summary> public virtual void SoftReset() { //ULADevice.ResetInterrupt(); ROMPaged = 0; SpecialPagingMode = false; RAMPaged = 0; CPU.RegPC = 0; Spectrum.SetCpuRegister("SP", 0xFFFF); Spectrum.SetCpuRegister("IY", 0xFFFF); Spectrum.SetCpuRegister("IX", 0xFFFF); Spectrum.SetCpuRegister("AF", 0xFFFF); Spectrum.SetCpuRegister("BC", 0xFFFF); Spectrum.SetCpuRegister("DE", 0xFFFF); Spectrum.SetCpuRegister("HL", 0xFFFF); Spectrum.SetCpuRegister("SP", 0xFFFF); Spectrum.SetCpuRegister("Shadow AF", 0xFFFF); Spectrum.SetCpuRegister("Shadow BC", 0xFFFF); Spectrum.SetCpuRegister("Shadow DE", 0xFFFF); Spectrum.SetCpuRegister("Shadow HL", 0xFFFF); CPU.Regs[CPU.I] = 0; CPU.Regs[CPU.R] = 0; TapeDevice.Reset(); if (AYDevice != null) { AYDevice.Reset(); } byte[][] rams = new byte[][] { RAM0, RAM1, RAM2, RAM3, RAM4, RAM5, RAM6, RAM7 }; foreach (var r in rams) { for (int i = 0; i < r.Length; i++) { r[i] = 0x00; } } }
/// <summary> /// Writes a byte of data to a specified port address /// </summary> /// <param name="port"></param> /// <param name="value"></param> public override void WritePort(ushort port, byte value) { // process IO contention ContendPortAddress(port); // get a BitArray of the port BitArray portBits = new BitArray(BitConverter.GetBytes(port)); // get a BitArray of the value byte BitArray bits = new BitArray(new byte[] { value }); // Check whether the low bit is reset bool lowBitReset = !portBits[0]; // (port & 0x01) == 0; AYDevice.WritePort(port, value); UPDDiskDevice.WritePort(port, value); // port 0x7ffd - hardware should only respond when bits 1 & 15 are reset and bit 14 is set if (port == 0x7ffd) { if (!PagingDisabled) { // bits 0, 1, 2 select the RAM page var rp = value & 0x07; if (rp < 8) { RAMPaged = rp; } // bit 3 controls shadow screen SHADOWPaged = bits[3]; // Bit 5 set signifies that paging is disabled until next reboot PagingDisabled = bits[5]; // portbit 4 is the LOW BIT of the ROM selection ROMlow = bits[4]; } } // port 0x1ffd - hardware should only respond when bits 1, 13, 14 & 15 are reset and bit 12 is set if (port == 0x1ffd) { if (!PagingDisabled) { if (!bits[0]) { // special paging is not enabled - get the ROMpage high byte ROMhigh = bits[2]; // set the special paging mode flag SpecialPagingMode = false; } else { // special paging is enabled // this is decided based on combinations of bits 1 & 2 // Config 0 = Bit1-0 Bit2-0 // Config 1 = Bit1-1 Bit2-0 // Config 2 = Bit1-0 Bit2-1 // Config 3 = Bit1-1 Bit2-1 BitArray confHalfNibble = new BitArray(2); confHalfNibble[0] = bits[1]; confHalfNibble[1] = bits[2]; // set special paging configuration PagingConfiguration = ZXSpectrum.GetIntFromBitArray(confHalfNibble); // set the special paging mode flag SpecialPagingMode = true; } } // bit 4 is the printer port strobe PrinterPortStrobe = bits[4]; } // Only even addresses address the ULA if (lowBitReset) { // store the last OUT byte LastULAOutByte = value; /* * Bit 7 6 5 4 3 2 1 0 +-------------------------------+ | | | | E | M | Border | +-------------------------------+ */ // Border - LSB 3 bits hold the border colour if (ULADevice.borderColour != (value & BORDER_BIT)) { ULADevice.UpdateScreenBuffer(CurrentFrameCycle); } ULADevice.borderColour = value & BORDER_BIT; // Buzzer BuzzerDevice.ProcessPulseValue((value & EAR_BIT) != 0); // Tape TapeDevice.WritePort(port, value); // Tape //TapeDevice.ProcessMicBit((value & MIC_BIT) != 0); } LastULAOutByte = value; }
/// <summary> /// Reads a byte of data from a specified port address /// </summary> /// <param name="port"></param> /// <returns></returns> public override byte ReadPort(ushort port) { bool deviceAddressed = true; // process IO contention ContendPortAddress(port); int result = 0xFF; // check AY if (AYDevice.ReadPort(port, ref result)) { return((byte)result); } // Kempston joystick input takes priority over all other input // if this is detected just return the kempston byte if ((port & 0xe0) == 0 || (port & 0x20) == 0) { if (LocateUniqueJoystick(JoystickType.Kempston) != null) { return((byte)((KempstonJoystick)LocateUniqueJoystick(JoystickType.Kempston) as KempstonJoystick).JoyLine); } InputRead = true; } else if (UPDDiskDevice.ReadPort(port, ref result)) { return((byte)result); } else { if (KeyboardDevice.ReadPort(port, ref result)) { // not a lagframe InputRead = true; // process tape INs TapeDevice.ReadPort(port, ref result); } else { deviceAddressed = false; } } if (!deviceAddressed) { // If this is an unused port the floating memory bus should be returned // Floating bus is read on the previous cycle long _tStates = CurrentFrameCycle - 1; // if we are on the top or bottom border return 0xff if ((_tStates < ULADevice.contentionStartPeriod) || (_tStates > ULADevice.contentionEndPeriod)) { result = 0xff; } else { if (ULADevice.floatingBusTable[_tStates] < 0) { result = 0xff; } else { result = ReadBus((ushort)ULADevice.floatingBusTable[_tStates]); } } } return((byte)result); }
/// <summary> /// Executes a single frame /// </summary> public virtual void ExecuteFrame(bool render, bool renderSound) { ULADevice.FrameEnd = false; ULADevice.ULACycleCounter = CurrentFrameCycle; InputRead = false; _render = render; _renderSound = renderSound; FrameCompleted = false; if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded) { TapeDevice.StartFrame(); } if (_renderSound) { if (AYDevice != null) { AYDevice.StartFrame(); } } PollInput(); for (;;) { // run the CPU Monitor cycle CPUMon.ExecuteCycle(); // cycle the tape device if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded) { TapeDevice.TapeCycle(); } // has frame end been reached? if (ULADevice.FrameEnd) { break; } } OverFlow = (int)CurrentFrameCycle - ULADevice.FrameLength; // we have reached the end of a frame LastFrameStartCPUTick = CPU.TotalExecutedCycles - OverFlow; ULADevice.LastTState = 0; if (AYDevice != null) { AYDevice.EndFrame(); } FrameCount++; if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded) { TapeDevice.EndFrame(); } FrameCompleted = true; // is this a lag frame? Spectrum.IsLagFrame = !InputRead; // FDC debug if (UPDDiskDevice != null && UPDDiskDevice.writeDebug) { // only write UPD log every second if (FrameCount % 10 == 0) { System.IO.File.AppendAllLines(UPDDiskDevice.outputfile, UPDDiskDevice.dLog); UPDDiskDevice.dLog = new System.Collections.Generic.List <string>(); //System.IO.File.WriteAllText(UPDDiskDevice.outputfile, UPDDiskDevice.outputString); } } }
/// <summary> /// Executes a single frame /// </summary> public virtual void ExecuteFrame(bool render, bool renderSound) { GateArray.FrameEnd = false; CRCT.lineCounter = 0; InputRead = false; _render = render; _renderSound = renderSound; FrameCompleted = false; if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded) { TapeDevice.StartFrame(); } if (_renderSound) { AYDevice.StartFrame(); } PollInput(); //CRT.SetupVideo(); //CRT.ScanlineCounter = 0; while (!GateArray.FrameEnd) { GateArray.ClockCycle(); // cycle the tape device if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded) { TapeDevice.TapeCycle(); } } // we have reached the end of a frame LastFrameStartCPUTick = CPU.TotalExecutedCycles; // - OverFlow; if (AYDevice != null) { AYDevice.EndFrame(); } FrameCount++; if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded) { TapeDevice.EndFrame(); } FrameCompleted = true; // is this a lag frame? CPC.IsLagFrame = !InputRead; // FDC debug if (UPDDiskDevice != null && UPDDiskDevice.writeDebug) { // only write UPD log every second if (FrameCount % 10 == 0) { System.IO.File.AppendAllLines(UPDDiskDevice.outputfile, UPDDiskDevice.dLog); UPDDiskDevice.dLog = new System.Collections.Generic.List <string>(); //System.IO.File.WriteAllText(UPDDiskDevice.outputfile, UPDDiskDevice.outputString); } } GateArray.FrameClock = 0; }
/// <summary> /// Executes a single frame /// </summary> public virtual void ExecuteFrame(bool render, bool renderSound) { InputRead = false; _render = render; _renderSound = renderSound; FrameCompleted = false; TapeDevice.StartFrame(); if (_renderSound) { BuzzerDevice.StartFrame(); TapeBuzzer.StartFrame(); if (AYDevice != null) { AYDevice.StartFrame(); } } PollInput(); while (CurrentFrameCycle < ULADevice.FrameLength) { // check for interrupt ULADevice.CheckForInterrupt(CurrentFrameCycle); // run a single CPU instruction CPU.ExecuteOne(); // cycle the tape device TapeDevice.TapeCycle(); } // we have reached the end of a frame LastFrameStartCPUTick = CPU.TotalExecutedCycles - OverFlow; // paint the buffer if needed if (ULADevice.needsPaint && _render) { ULADevice.UpdateScreenBuffer(ULADevice.FrameLength); } if (_renderSound) { BuzzerDevice.EndFrame(); TapeBuzzer.EndFrame(); } if (AYDevice != null) { AYDevice.EndFrame(); } FrameCount++; // setup for next frame ULADevice.ResetInterrupt(); TapeDevice.EndFrame(); FrameCompleted = true; // is this a lag frame? Spectrum.IsLagFrame = !InputRead; }
/// <summary> /// Reads a byte of data from a specified port address /// </summary> /// <param name="port"></param> /// <returns></returns> public override byte ReadPort(ushort port) { bool deviceAddressed = true; // process IO contention ContendPortAddress(port); int result = 0xFF; // check AY if (AYDevice.ReadPort(port, ref result)) { return((byte)result); } // Kempston joystick input takes priority over all other input // if this is detected just return the kempston byte if ((port & 0xe0) == 0 || (port & 0x20) == 0) { if (LocateUniqueJoystick(JoystickType.Kempston) != null) { return((byte)((KempstonJoystick)LocateUniqueJoystick(JoystickType.Kempston) as KempstonJoystick).JoyLine); } InputRead = true; } else { if (KeyboardDevice.ReadPort(port, ref result)) { // not a lagframe InputRead = true; // process tape INs TapeDevice.ReadPort(port, ref result); } else { deviceAddressed = false; } } if (!deviceAddressed) { // If this is an unused port the floating memory bus should be returned // Floating bus is read on the previous cycle long _tStates = CurrentFrameCycle - 1; // if we are on the top or bottom border return 0xff if ((_tStates < ULADevice.contentionStartPeriod) || (_tStates > ULADevice.contentionEndPeriod)) { result = 0xff; } else { if (ULADevice.floatingBusTable[_tStates] < 0) { result = 0xff; } else { result = ReadBus((ushort)ULADevice.floatingBusTable[_tStates]); } } } /* * // Check whether the low bit is reset * // Technically the ULA should respond to every even I/O address * bool lowBitReset = (port & 0x0001) == 0; * * // Kempston joystick input takes priority over all other input * // if this is detected just return the kempston byte * if ((port & 0xe0) == 0 || (port & 0x20) == 0) * { * if (LocateUniqueJoystick(JoystickType.Kempston) != null) * return (byte)((KempstonJoystick)LocateUniqueJoystick(JoystickType.Kempston) as KempstonJoystick).JoyLine; * * InputRead = true; * } * else if (lowBitReset) * { * // Even I/O address so get input from keyboard * KeyboardDevice.ReadPort(port, ref result); * * TapeDevice.MonitorRead(); * * // not a lagframe * InputRead = true; * * // tape loading monitor cycle * //TapeDevice.MonitorRead(); * * // process tape INs * TapeDevice.ReadPort(port, ref result); * } * else * { * // devices other than the ULA will respond here * // (e.g. the AY sound chip in a 128k spectrum * * // AY register activate - on +3/2a both FFFD and BFFD active AY * if ((port & 0xc002) == 0xc000) * { * result = (int)AYDevice.PortRead(); * } * else if ((port & 0xc002) == 0x8000) * { * result = (int)AYDevice.PortRead(); * } * * // Kempston Mouse * * /* * else if ((port & 0xF002) == 0x2000) //Is bit 12 set and bits 13,14,15 and 1 reset? * { * //result = udpDrive.DiskStatusRead(); * * // disk drive is not yet implemented - return a max status byte for the menu to load * result = 255; * } * else if ((port & 0xF002) == 0x3000) * { * //result = udpDrive.DiskReadByte(); * result = 0; * } * * else if ((port & 0xF002) == 0x0) * { * if (PagingDisabled) * result = 0x1; * else * result = 0xff; * } *//* * * // if unused port the floating memory bus should be returned (still todo) * } */ return((byte)result); }
/// <summary> /// Writes a byte of data to a specified port address /// </summary> public override void WritePort(ushort port, byte value) { // get a BitArray of the port BitArray portBits = new BitArray(BitConverter.GetBytes(port)); // get a BitArray of the value byte BitArray bits = new BitArray(new byte[] { value }); // handle AY port writes AYDevice.WritePort(port, value); // memory paging // this is controlled by writes to port 0x7ffd // but it is only partially decoded so it actually responds to any port with bits 1 and 15 reset if (portBits[1] == false && portBits[15] == false) { Last7ffd = value; // if paging is disabled then all writes to this port are ignored until the next reboot if (!PagingDisabled) { // Bits 0, 1, 2 select the RAM page var rp = value & 0x07; if (RAMPaged != rp && rp < 8) { RAMPaged = rp; } // bit 3 controls shadow screen if (SHADOWPaged != bits[3]) { SHADOWPaged = bits[3]; } // ROM page if (bits[4]) { // 48k basic rom ROMPaged = 1; } else { // 128k editor and menu system ROMPaged = 0; } // Bit 5 set signifies that paging is disabled until next reboot PagingDisabled = bits[5]; } else { // no changes to paging } } if (port == 0x1ffd) { } // Check whether the low bit is reset // Technically the ULA should respond to every even I/O address bool lowBitReset = !portBits[0]; // (port & 0x01) == 0; // Only even addresses address the ULA if (lowBitReset) { LastFe = value; // store the last OUT byte LastULAOutByte = value; /* * Bit 7 6 5 4 3 2 1 0 +-------------------------------+ | | | | E | M | Border | +-------------------------------+ */ // Border - LSB 3 bits hold the border colour if (ULADevice.BorderColor != (value & BORDER_BIT)) { //ULADevice.RenderScreen((int)CurrentFrameCycle); ULADevice.BorderColor = value & BORDER_BIT; } // Buzzer BuzzerDevice.ProcessPulseValue((value & EAR_BIT) != 0, _renderSound); TapeDevice.WritePort(port, value); // Tape //TapeDevice.ProcessMicBit((value & MIC_BIT) != 0); } }
/// <summary> /// Reads a byte of data from a specified port address /// </summary> public override byte ReadPort(ushort port) { bool deviceAddressed = true; int result = 0xFF; // ports 0x3ffd & 0x7ffd // traditionally thought to be write-only if (port == 0x3ffd || port == 0x7ffd) { // https://faqwiki.zxnet.co.uk/wiki/ZX_Spectrum_128 // HAL bugs // Reads from port 0x7ffd cause a crash, as the 128's HAL10H8 chip does not distinguish between reads and writes to this port, // resulting in a floating data bus being used to set the paging registers. // -asni (2018-06-08) - need this to pass the final portread tests from fusetest.tap // get the floating bus value ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result, port); // use this to set the paging registers WritePort(port, (byte)result); // return the floating bus value return((byte)result); } // check AY if (AYDevice.ReadPort(port, ref result)) { return((byte)result); } byte lowByte = (byte)(port & 0xff); // Kempston joystick input takes priority over keyboard input // if this is detected just return the kempston byte if (lowByte == 0x1f) { if (LocateUniqueJoystick(JoystickType.Kempston) != null) { return((byte)((KempstonJoystick)LocateUniqueJoystick(JoystickType.Kempston) as KempstonJoystick).JoyLine); } InputRead = true; } else { if (KeyboardDevice.ReadPort(port, ref result)) { // not a lagframe InputRead = true; // process tape INs TapeDevice.ReadPort(port, ref result); } else { deviceAddressed = false; } } if (!deviceAddressed) { // If this is an unused port the floating memory bus should be returned ULADevice.ReadFloatingBus((int)CurrentFrameCycle, ref result, port); } return((byte)result); }
public void SyncState(Serializer ser) { ser.BeginSection("ZXMachine"); ser.Sync(nameof(FrameCompleted), ref FrameCompleted); ser.Sync(nameof(OverFlow), ref OverFlow); ser.Sync(nameof(FrameCount), ref FrameCount); ser.Sync(nameof(_frameCycles), ref _frameCycles); ser.Sync(nameof(inputRead), ref inputRead); ser.Sync(nameof(LastFrameStartCPUTick), ref LastFrameStartCPUTick); ser.Sync(nameof(LastULAOutByte), ref LastULAOutByte); ser.Sync(nameof(ROM0), ref ROM0, false); ser.Sync(nameof(ROM1), ref ROM1, false); ser.Sync(nameof(ROM2), ref ROM2, false); ser.Sync(nameof(ROM3), ref ROM3, false); ser.Sync(nameof(RAM0), ref RAM0, false); ser.Sync(nameof(RAM1), ref RAM1, false); ser.Sync(nameof(RAM2), ref RAM2, false); ser.Sync(nameof(RAM3), ref RAM3, false); ser.Sync(nameof(RAM4), ref RAM4, false); ser.Sync(nameof(RAM5), ref RAM5, false); ser.Sync(nameof(RAM6), ref RAM6, false); ser.Sync(nameof(RAM7), ref RAM7, false); ser.Sync(nameof(ROMPaged), ref ROMPaged); ser.Sync(nameof(SHADOWPaged), ref SHADOWPaged); ser.Sync(nameof(RAMPaged), ref RAMPaged); ser.Sync(nameof(PagingDisabled), ref PagingDisabled); ser.Sync(nameof(SpecialPagingMode), ref SpecialPagingMode); ser.Sync(nameof(PagingConfiguration), ref PagingConfiguration); ser.Sync(nameof(ROMhigh), ref ROMhigh); ser.Sync(nameof(ROMlow), ref ROMlow); ser.Sync(nameof(LastContendedReadByte), ref LastContendedReadByte); KeyboardDevice.SyncState(ser); BuzzerDevice.SyncState(ser); TapeBuzzer.SyncState(ser); ULADevice.SyncState(ser); CPUMon.SyncState(ser); if (AYDevice != null) { AYDevice.SyncState(ser); ((AY38912)AYDevice).PanningConfiguration = Spectrum.Settings.AYPanConfig; } ser.Sync(nameof(tapeMediaIndex), ref tapeMediaIndex); if (ser.IsReader) { IsLoadState = true; TapeMediaIndex = tapeMediaIndex; IsLoadState = false; } TapeDevice.SyncState(ser); ser.Sync(nameof(diskMediaIndex), ref diskMediaIndex); if (ser.IsReader) { IsLoadState = true; DiskMediaIndex = diskMediaIndex; IsLoadState = false; } UPDDiskDevice?.SyncState(ser); ser.EndSection(); }
/// <summary> /// Executes a single frame /// </summary> public virtual void ExecuteFrame(bool render, bool renderSound) { InputRead = false; _render = render; _renderSound = renderSound; FrameCompleted = false; if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded) { TapeDevice.StartFrame(); } if (_renderSound) { //BuzzerDevice.StartFrame(); //TapeBuzzer.StartFrame(); if (AYDevice != null) { AYDevice.StartFrame(); } } PollInput(); while (CurrentFrameCycle < ULADevice.FrameLength) { // check for interrupt ULADevice.CheckForInterrupt(CurrentFrameCycle); // run a single CPU instruction CPU.ExecuteOne(); // cycle the tape device if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded) { TapeDevice.TapeCycle(); } } // we have reached the end of a frame LastFrameStartCPUTick = CPU.TotalExecutedCycles - OverFlow; // paint the buffer if needed if (ULADevice.needsPaint && _render) { ULADevice.UpdateScreenBuffer(ULADevice.FrameLength); } if (_renderSound) { //BuzzerDevice.EndFrame(); //TapeBuzzer.EndFrame(); } if (AYDevice != null) { AYDevice.EndFrame(); } FrameCount++; // setup for next frame ULADevice.ResetInterrupt(); if (UPDDiskDevice == null || !UPDDiskDevice.FDD_IsDiskLoaded) { TapeDevice.EndFrame(); } FrameCompleted = true; // is this a lag frame? Spectrum.IsLagFrame = !InputRead; // FDC debug if (UPDDiskDevice != null && UPDDiskDevice.writeDebug) { // only write UPD log every second if (FrameCount % 10 == 0) { System.IO.File.WriteAllText(UPDDiskDevice.outputfile, UPDDiskDevice.outputString); } } }