/// <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> /// 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> /// 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> /// 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); }