/// <summary> /// Reads a byte of data from a specified port address /// </summary> 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) { } return((byte)result); }
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> /// Called every CPU cycle /// In reality the GA is clocked at 16Mhz (4 times the frequency of the CPU) /// Therefore this method has to take care of: /// 4 GA cycles /// 1 CRCT cycle every 4 calls /// 1 PSG cycle every 4 calls /// 1 CPU cycle (uncontended) /// </summary> public void ClockCycle() { // gatearray uses 4-phase clock to supply clocks to other devices switch (ClockCounter) { case 0: CRCT.ClockCycle(); WaitLine = false; break; case 1: WaitLine = true; // detect new scanline and upcoming new frame on next render cycle //FrameDetector(); break; case 2: // video fetch WaitLine = true; //FetchByte(1); break; case 3: // video fetch and render WaitLine = true; //FetchByte(2); GACharacterCycle(); //PixelGenerator(); break; } if (!HSYNC && CRCT.HSYNC) { HSYNC = true; } // run the interrupt generator routine InterruptGenerator(); if (!CRCT.HSYNC) { HSYNC = false; } // conditional CPU cycle DoConditionalCPUCycle(); AdvanceClock(); }
/// <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 /// Because of the port decoding, multiple devices can be written to /// </summary> 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) { // not present in the unexpanded CPC464 } else if (d == PortDevice.CRCT) { CRCT.WritePort(port, value); } else if (d == PortDevice.ROMSelect) { } else if (d == PortDevice.Printer) { } else if (d == PortDevice.PPI) { PPI.WritePort(port, value); } else if (d == PortDevice.Expansion) { } } return; }
/// <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; }