132 lines
3.8 KiB
C#
132 lines
3.8 KiB
C#
using BizHawk.Common;
|
|
|
|
namespace BizHawk.Emulation.Cores.Sega.Genesis
|
|
{
|
|
partial class Genesis
|
|
{
|
|
bool SegaCD = false;
|
|
|
|
class IOPort
|
|
{
|
|
public byte Data;
|
|
public byte Control;
|
|
public byte TxData;
|
|
public byte RxData;
|
|
public byte SCtrl;
|
|
// TODO- a reference to connected device? That gets into the issue of configuring different types of controllers. :|
|
|
|
|
public bool TH { get { return (Data & 0x40) != 0; } }
|
|
}
|
|
|
|
IOPort[] IOPorts = new IOPort[]
|
|
{
|
|
new IOPort { Data = 0x7F, TxData = 0xFF, RxData = 0xFF, SCtrl = 0xFF },
|
|
new IOPort { Data = 0x7F, TxData = 0xFF, RxData = 0xFF, SCtrl = 0xFF },
|
|
new IOPort { Data = 0x7F, TxData = 0xFF, RxData = 0xFF, SCtrl = 0xFF }
|
|
};
|
|
|
|
byte ReadIO(int offset)
|
|
{
|
|
offset >>= 1;
|
|
offset &= 0x0F;
|
|
if (offset > 1)
|
|
Log.Note("CPU", "^^^ IO Read {0}: 00", offset);
|
|
switch (offset)
|
|
{
|
|
case 0: // version
|
|
byte value = (byte)(SegaCD ? 0x00 : 0x20);
|
|
switch ((char)RomData[0x01F0])
|
|
{
|
|
case 'J': value |= 0x00; break;
|
|
case 'U': value |= 0x80; break;
|
|
case 'E': value |= 0xC0; break;
|
|
case 'A': value |= 0xC0; break;
|
|
case '4': value |= 0x80; break;
|
|
default: value |= 0x80; break;
|
|
}
|
|
//value |= 1; // US
|
|
Log.Note("CPU", "^^^ IO Read 0: {0:X2}", value);
|
|
return value;
|
|
case 1: // Port A
|
|
lagged = false;
|
|
ReadController(ref IOPorts[0].Data);
|
|
Log.Note("CPU", "^^^ IO Read 1: {0:X2}", IOPorts[0].Data);
|
|
return IOPorts[0].Data;
|
|
case 2: return 0xFF;
|
|
case 3: return 0xFF;
|
|
|
|
case 0x04: return IOPorts[0].Control;
|
|
case 0x05: return IOPorts[1].Control;
|
|
case 0x06: return IOPorts[2].Control;
|
|
|
|
case 0x07: return IOPorts[0].TxData;
|
|
case 0x08: return IOPorts[0].RxData;
|
|
case 0x09: return IOPorts[0].SCtrl;
|
|
|
|
case 0x0A: return IOPorts[1].TxData;
|
|
case 0x0B: return IOPorts[1].RxData;
|
|
case 0x0C: return IOPorts[1].SCtrl;
|
|
|
|
case 0x0D: return IOPorts[2].TxData;
|
|
case 0x0E: return IOPorts[2].RxData;
|
|
case 0x0F: return IOPorts[2].SCtrl;
|
|
}
|
|
Log.Note("CPU", "^^^ IO Read {0}: {1:X2}", offset, 0xFF);
|
|
return 0xFF;
|
|
}
|
|
|
|
void WriteIO(int offset, int value)
|
|
{
|
|
offset >>= 1;
|
|
offset &= 0x0F;
|
|
|
|
switch (offset)
|
|
{
|
|
case 0x00: break;
|
|
|
|
case 0x01: IOPorts[0].Data = (byte)value; break;
|
|
case 0x02: IOPorts[1].Data = (byte)value; break;
|
|
case 0x03: IOPorts[2].Data = (byte)value; break;
|
|
|
|
case 0x04: IOPorts[0].Control = (byte)value; break;
|
|
case 0x05: IOPorts[1].Control = (byte)value; break;
|
|
case 0x06: IOPorts[2].Control = (byte)value; break;
|
|
|
|
case 0x07: IOPorts[0].TxData = (byte)value; break;
|
|
case 0x08: IOPorts[0].RxData = (byte)value; break;
|
|
case 0x09: IOPorts[0].SCtrl = (byte)value; break;
|
|
|
|
case 0x0A: IOPorts[1].TxData = (byte)value; break;
|
|
case 0x0B: IOPorts[1].RxData = (byte)value; break;
|
|
case 0x0C: IOPorts[1].SCtrl = (byte)value; break;
|
|
|
|
case 0x0D: IOPorts[2].TxData = (byte)value; break;
|
|
case 0x0E: IOPorts[2].RxData = (byte)value; break;
|
|
case 0x0F: IOPorts[2].SCtrl = (byte)value; break;
|
|
}
|
|
}
|
|
|
|
void ReadController(ref byte data)
|
|
{
|
|
InputCallbacks.Call();
|
|
data &= 0xC0;
|
|
if ((data & 0x40) != 0) // TH high
|
|
{
|
|
if (Controller["P1 Up"] == false) data |= 0x01;
|
|
if (Controller["P1 Down"] == false) data |= 0x02;
|
|
if (Controller["P1 Left"] == false) data |= 0x04;
|
|
if (Controller["P1 Right"] == false) data |= 0x08;
|
|
if (Controller["P1 B"] == false) data |= 0x10;
|
|
if (Controller["P1 C"] == false) data |= 0x20;
|
|
}
|
|
else
|
|
{ // TH low
|
|
if (Controller["P1 Up"] == false) data |= 0x01;
|
|
if (Controller["P1 Down"] == false) data |= 0x02;
|
|
if (Controller["P1 A"] == false) data |= 0x10;
|
|
if (Controller["P1 Start"] == false) data |= 0x20;
|
|
}
|
|
|
|
}
|
|
}
|
|
} |