Essgee.Unity/Assets/Plugins/Essgee/Emulation/Peripherals/Intel8255.cs
2025-01-02 17:55:16 +08:00

102 lines
2.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Essgee.Exceptions;
using Essgee.Utilities;
namespace Essgee.Emulation.Peripherals
{
public class Intel8255 : IPeripheral
{
[StateRequired]
public byte PortAInput { get; set; }
[StateRequired]
public byte PortBInput { get; set; }
[StateRequired]
public byte PortCInput { get; set; }
[StateRequired]
public byte PortAOutput { get; set; }
[StateRequired]
public byte PortBOutput { get; set; }
[StateRequired]
public byte PortCOutput { get; set; }
[StateRequired]
byte configByte, setResetControlByte;
int operatingModeGroupA => ((configByte >> 5) & 0x03);
bool isPortAInput => ((configByte & 0x10) == 0x10);
bool isPortCUInput => ((configByte & 0x08) == 0x08);
int operatingModeGroupB => ((configByte >> 2) & 0x01);
bool isPortBInput => ((configByte & 0x02) == 0x02);
bool isPortCLInput => ((configByte & 0x01) == 0x01);
int bitToChange => ((setResetControlByte >> 1) & 0x07);
bool isSetBitOperation => ((setResetControlByte & 0x01) == 0x01);
public Intel8255() { }
public void Startup()
{
//
}
public void Shutdown()
{
//
}
public void Reset()
{
PortAInput = PortAOutput = 0x00;
PortBInput = PortBOutput = 0x00;
PortCInput = PortCOutput = 0x00;
WritePort(0x03, 0x9B);
}
public byte ReadPort(byte port)
{
switch (port & 0x03)
{
case 0x00: return (isPortAInput ? PortAInput : PortAOutput);
case 0x01: return (isPortBInput ? PortBInput : PortBOutput);
case 0x02: return (byte)(((isPortCUInput ? PortCInput : PortCOutput) & 0xF0) | (isPortCLInput ? PortCInput : PortCOutput) & 0x0F);
case 0x03: return 0xFF; /* Cannot read control port */
default: throw new EmulationException(string.Format("i8255: Unsupported read from port 0x{0:X2}", port));
}
}
public void WritePort(byte port, byte value)
{
switch (port & 0x03)
{
case 0x00: PortAOutput = value; break;
case 0x01: PortBOutput = value; break;
case 0x02: PortCOutput = value; break;
case 0x03:
/* Control port */
if ((value & 0x80) == 0x80)
{
configByte = value;
}
else
{
setResetControlByte = value;
byte mask = (byte)(1 << bitToChange);
if (isSetBitOperation) PortCOutput |= mask;
else PortCOutput &= (byte)~mask;
}
break;
default: throw new EmulationException(string.Format("i8255: Unsupported write to port 0x{0:X2}, value 0x{1:X2}", port, value));
}
}
}
}