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(); }
/// <summary> /// Attempts to load a disk into the disk device based on diskMediaIndex /// </summary> protected void LoadDiskMedia() { if (this.GetType() == typeof(CPC464)) { CPC.CoreComm.ShowMessage("You are trying to load one of more disk images.\n\n Please select something other than CPC 464 emulation immediately and reboot the core"); return; } UPDDiskDevice.FDD_LoadDisk(diskImages[diskMediaIndex]); }
/// <summary> /// Attempts to load a disk into the disk device based on diskMediaIndex /// </summary> protected void LoadDiskMedia() { if (this.GetType() != typeof(ZX128Plus3)) { Spectrum.CoreComm.ShowMessage("You are trying to load one of more disk images.\n\n Please select ZX Spectrum +3 emulation immediately and reboot the core"); return; } UPDDiskDevice.FDD_LoadDisk(diskImages[diskMediaIndex]); }
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> /// Attempts to load a disk into the disk device based on diskMediaIndex /// </summary> protected void LoadDiskMedia() { if (this.GetType() != typeof(ZX128Plus3)) { Spectrum.CoreComm.ShowMessage("You are trying to load one of more disk images.\n\n Please select ZX Spectrum +3 emulation immediately and reboot the core"); return; } else { //Spectrum.CoreComm.ShowMessage("You are attempting to load a disk into the +3 disk drive.\n\nThis DOES NOT currently work properly but IS under active development."); } UPDDiskDevice.FDD_LoadDisk(diskImages[diskMediaIndex]); }
/// <summary> /// Reads a byte of data from a specified port address /// </summary> /// <param name="port"></param> /// <returns></returns> public override byte ReadPort(ushort port) { BitArray portBits = new BitArray(BitConverter.GetBytes(port)); byte portUpper = (byte)(port >> 8); byte portLower = (byte)(port & 0xff); int result = 0xff; if (DecodeINPort(port) == PortDevice.GateArray) { GateArray.ReadPort(port, ref result); } else if (DecodeINPort(port) == PortDevice.CRCT) { CRCT.ReadPort(port, ref result); } else if (DecodeINPort(port) == PortDevice.ROMSelect) { } else if (DecodeINPort(port) == PortDevice.Printer) { } else if (DecodeINPort(port) == PortDevice.PPI) { PPI.ReadPort(port, ref result); } else if (DecodeINPort(port) == PortDevice.Expansion) { if (!port.Bit(7)) { // FDC if (port.Bit(8) && !port.Bit(0)) { // FDC status register UPDDiskDevice.ReadStatus(ref result); } if (port.Bit(8) && port.Bit(0)) { // FDC data register UPDDiskDevice.ReadData(ref result); } } } return((byte)result); }
/// <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> /// Cycles through all the input callbacks /// This should be done once per frame /// </summary> public void PollInput() { Spectrum.InputCallbacks.Call(); lock (this) { // parse single keyboard matrix keys for (var i = 0; i < KeyboardDevice.KeyboardMatrix.Length; i++) { string key = KeyboardDevice.KeyboardMatrix[i]; bool prevState = KeyboardDevice.GetKeyStatus(key); bool currState = Spectrum._controller.IsPressed(key); if (currState != prevState) { KeyboardDevice.SetKeyStatus(key, currState); } } // non matrix keys foreach (string k in KeyboardDevice.NonMatrixKeys) { if (!k.StartsWith("Key")) { continue; } bool currState = Spectrum._controller.IsPressed(k); KeyboardDevice.SetKeyStatus(k, currState); } // J1 foreach (string j in JoystickCollection[0].ButtonCollection) { bool prevState = JoystickCollection[0].GetJoyInput(j); bool currState = Spectrum._controller.IsPressed(j); if (currState != prevState) { JoystickCollection[0].SetJoyInput(j, currState); } } // J2 foreach (string j in JoystickCollection[1].ButtonCollection) { bool prevState = JoystickCollection[1].GetJoyInput(j); bool currState = Spectrum._controller.IsPressed(j); if (currState != prevState) { JoystickCollection[1].SetJoyInput(j, currState); } } // J3 foreach (string j in JoystickCollection[2].ButtonCollection) { bool prevState = JoystickCollection[2].GetJoyInput(j); bool currState = Spectrum._controller.IsPressed(j); if (currState != prevState) { JoystickCollection[2].SetJoyInput(j, currState); } } } // Tape control if (Spectrum._controller.IsPressed(Play)) { if (!pressed_Play) { Spectrum.OSD_FireInputMessage(Play); TapeDevice.Play(); pressed_Play = true; } } else { pressed_Play = false; } if (Spectrum._controller.IsPressed(Stop)) { if (!pressed_Stop) { Spectrum.OSD_FireInputMessage(Stop); TapeDevice.Stop(); pressed_Stop = true; } } else { pressed_Stop = false; } if (Spectrum._controller.IsPressed(RTZ)) { if (!pressed_RTZ) { Spectrum.OSD_FireInputMessage(RTZ); TapeDevice.RTZ(); pressed_RTZ = true; } } else { pressed_RTZ = false; } if (Spectrum._controller.IsPressed(Record)) { } if (Spectrum._controller.IsPressed(NextTape)) { if (!pressed_NextTape) { Spectrum.OSD_FireInputMessage(NextTape); TapeMediaIndex++; pressed_NextTape = true; } } else { pressed_NextTape = false; } if (Spectrum._controller.IsPressed(PrevTape)) { if (!pressed_PrevTape) { Spectrum.OSD_FireInputMessage(PrevTape); TapeMediaIndex--; pressed_PrevTape = true; } } else { pressed_PrevTape = false; } if (Spectrum._controller.IsPressed(NextBlock)) { if (!pressed_NextBlock) { Spectrum.OSD_FireInputMessage(NextBlock); TapeDevice.SkipBlock(true); pressed_NextBlock = true; } } else { pressed_NextBlock = false; } if (Spectrum._controller.IsPressed(PrevBlock)) { if (!pressed_PrevBlock) { Spectrum.OSD_FireInputMessage(PrevBlock); TapeDevice.SkipBlock(false); pressed_PrevBlock = true; } } else { pressed_PrevBlock = false; } if (Spectrum._controller.IsPressed(TapeStatus)) { if (!pressed_TapeStatus) { //Spectrum.OSD_FireInputMessage(TapeStatus); Spectrum.OSD_ShowTapeStatus(); pressed_TapeStatus = true; } } else { pressed_TapeStatus = false; } if (Spectrum._controller.IsPressed(HardResetStr)) { if (!pressed_HardReset) { HardReset(); pressed_HardReset = true; } } else { pressed_HardReset = false; } if (Spectrum._controller.IsPressed(SoftResetStr)) { if (!pressed_SoftReset) { SoftReset(); pressed_SoftReset = true; } } else { pressed_SoftReset = false; } // disk control if (Spectrum._controller.IsPressed(NextDisk)) { if (!pressed_NextDisk) { Spectrum.OSD_FireInputMessage(NextDisk); DiskMediaIndex++; pressed_NextDisk = true; } } else { pressed_NextDisk = false; } if (Spectrum._controller.IsPressed(PrevDisk)) { if (!pressed_PrevDisk) { Spectrum.OSD_FireInputMessage(PrevDisk); DiskMediaIndex--; pressed_PrevDisk = true; } } else { pressed_PrevDisk = false; } if (Spectrum._controller.IsPressed(EjectDisk)) { if (!pressed_EjectDisk) { Spectrum.OSD_FireInputMessage(EjectDisk); if (UPDDiskDevice != null) { UPDDiskDevice.FDD_EjectDisk(); } } } else { pressed_EjectDisk = false; } if (Spectrum._controller.IsPressed(DiskStatus)) { if (!pressed_DiskStatus) { //Spectrum.OSD_FireInputMessage(TapeStatus); Spectrum.OSD_ShowDiskStatus(); pressed_DiskStatus = true; } } else { pressed_DiskStatus = false; } }
/// <summary> /// Writes a byte of data to a specified port address /// Because of the port decoding, multiple devices can be written to /// </summary> /// <param name="port"></param> /// <param name="value"></param> public override void WritePort(ushort port, byte value) { BitArray portBits = new BitArray(BitConverter.GetBytes(port)); BitArray dataBits = new BitArray(BitConverter.GetBytes(value)); byte portUpper = (byte)(port >> 8); byte portLower = (byte)(port & 0xff); var devs = DecodeOUTPort(port); foreach (var d in devs) { if (d == PortDevice.GateArray) { GateArray.WritePort(port, value); } else if (d == PortDevice.RAMManagement) { if (value.Bit(7) && value.Bit(6)) { RAMConfig = value & 0x07; // additional 64K bank index var b64 = value & 0x38; } } else if (d == PortDevice.CRCT) { CRCT.WritePort(port, value); } else if (d == PortDevice.ROMSelect) { UpperROMPosition = value; } else if (d == PortDevice.Printer) { } else if (d == PortDevice.PPI) { PPI.WritePort(port, value); } else if (d == PortDevice.Expansion) { if (!port.Bit(7)) { // FDC if (port.Bit(8) && !port.Bit(0) || port.Bit(8) && port.Bit(0)) { // FDC data register UPDDiskDevice.WriteData(value); } if ((!port.Bit(8) && !port.Bit(0)) || (!port.Bit(8) && port.Bit(0))) { // FDC motor UPDDiskDevice.Motor(value); } } } } return; }
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(); }