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