/// <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);
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        /// <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);
        }