commodore64: replaced directional data port class with a more efficient one

This commit is contained in:
saxxonpike 2012-11-14 07:12:04 +00:00
parent a8957f1916
commit b84ec59bb4
7 changed files with 249 additions and 111 deletions

View File

@ -9,12 +9,12 @@ namespace BizHawk.Emulation.Computers.Commodore64
{ {
public byte PeekCia0(int addr) public byte PeekCia0(int addr)
{ {
return cia0.regs[addr]; return cia0.Peek(addr);
} }
public byte PeekCia1(int addr) public byte PeekCia1(int addr)
{ {
return cia1.regs[addr]; return cia1.Peek(addr);
} }
public byte PeekColorRAM(int addr) public byte PeekColorRAM(int addr)

View File

@ -19,8 +19,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
public Input input; public Input input;
// source // source
public Cartridge cart; public Cartridge cart = null;
public Drive1541 diskDrive; public Drive1541 diskDrive = null;
public bool diskDriveAttached = false;
public string extension; public string extension;
public byte[] inputFile; public byte[] inputFile;
public List<IMedia> mediaAttached = new List<IMedia>(); public List<IMedia> mediaAttached = new List<IMedia>();
@ -44,11 +45,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
// initialize cia timers // initialize cia timers
cia0 = new Cia(signal, Region.NTSC); cia0 = new Cia(signal, Region.NTSC);
cia0.ports[0] = new DirectionalDataPort(0x00, 0x00, 0xFF);
cia0.ports[1] = new DirectionalDataPort(0x00, 0x00, 0xFF);
cia1 = new Cia(signal, Region.NTSC); cia1 = new Cia(signal, Region.NTSC);
cia1.ports[0] = new DirectionalDataPort(0x00, 0x00, 0xFF);
cia1.ports[1] = new DirectionalDataPort(0x00, 0x00, 0xFF);
// initialize vic // initialize vic
signal = new ChipSignals(); signal = new ChipSignals();
@ -70,7 +67,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
cpu.PC = (ushort)(ReadMemory(0xFFFC) + (ReadMemory(0xFFFD) << 8)); cpu.PC = (ushort)(ReadMemory(0xFFFC) + (ReadMemory(0xFFFD) << 8));
// initailize input // initailize input
input = new Input(cia0.ports); input = new Input( new DataPortConnector[] { cia0.ConnectPort(0), cia0.ConnectPort(1) } );
// initialize media // initialize media
switch (extension.ToUpper()) switch (extension.ToUpper())
@ -94,12 +91,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
cart = newCart; cart = newCart;
mediaAttached.Add(cart); mediaAttached.Add(cart);
} }
else
{
cart = null;
}
break; break;
} }
diskDriveAttached = (diskDrive != null);
} }
public void PollInput() public void PollInput()

View File

@ -100,6 +100,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
cpu.ExecuteOne(); cpu.ExecuteOne();
} }
sid.PerformCycle(); sid.PerformCycle();
if (diskDriveAttached)
diskDrive.PerformCycle();
cia0.PerformCycle(); cia0.PerformCycle();
cia1.PerformCycle(); cia1.PerformCycle();
} }

View File

@ -40,6 +40,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
public int TODREADLATCHHR; // tod read latch (internal) public int TODREADLATCHHR; // tod read latch (internal)
public int TODSEC; // time of day seconds public int TODSEC; // time of day seconds
public DataPortBus[] ports;
private DataPortConnector[] connectors;
private ChipSignals signal; private ChipSignals signal;
public CiaRegs(ChipSignals newSignal) public CiaRegs(ChipSignals newSignal)
@ -53,6 +56,17 @@ namespace BizHawk.Emulation.Computers.Commodore64
T[1] = TLATCH[1]; T[1] = TLATCH[1];
this[0x0B] = 0x01; this[0x0B] = 0x01;
ports = new DataPortBus[2];
ports[0] = new DataPortBus();
ports[1] = new DataPortBus();
connectors = new DataPortConnector[2];
connectors[0] = ports[0].Connect();
connectors[1] = ports[1].Connect();
connectors[0].Data = 0xFF;
connectors[1].Data = 0xFF;
connectors[0].Direction = 0xFF;
connectors[1].Direction = 0xFF;
} }
public byte this[int addr] public byte this[int addr]
@ -65,6 +79,18 @@ namespace BizHawk.Emulation.Computers.Commodore64
addr &= 0x0F; addr &= 0x0F;
switch (addr) switch (addr)
{ {
case 0x00:
result = connectors[0].Data;
break;
case 0x01:
result = connectors[1].Data;
break;
case 0x02:
result = connectors[0].Direction;
break;
case 0x03:
result = connectors[1].Direction;
break;
case 0x04: case 0x04:
result = (T[0] & 0xFF); result = (T[0] & 0xFF);
break; break;
@ -134,6 +160,18 @@ namespace BizHawk.Emulation.Computers.Commodore64
addr &= 0x0F; addr &= 0x0F;
switch (addr) switch (addr)
{ {
case 0x00:
connectors[0].Data = val;
break;
case 0x01:
connectors[1].Data = val;
break;
case 0x02:
connectors[0].Direction = val;
break;
case 0x03:
connectors[1].Direction = val;
break;
case 0x04: case 0x04:
T[0] &= 0xFF00; T[0] &= 0xFF00;
T[0] |= val; T[0] |= val;
@ -204,8 +242,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
public int intMask; public int intMask;
public bool lastCNT; public bool lastCNT;
public byte[] outputBitMask; public byte[] outputBitMask;
public DirectionalDataPort[] ports; private CiaRegs regs;
public CiaRegs regs;
public ChipSignals signal; public ChipSignals signal;
public bool thisCNT; public bool thisCNT;
public int todCounter; public int todCounter;
@ -271,6 +308,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
regs.TODPM = ampm; regs.TODPM = ampm;
} }
public void AttachWriteHook(int index, Action act)
{
regs.ports[index].AttachWriteHook(act);
}
private int BCDAdd(int i, int j, out bool overflow) private int BCDAdd(int i, int j, out bool overflow)
{ {
int lo; int lo;
@ -293,10 +335,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
return result; return result;
} }
public DataPortConnector ConnectPort(int index)
{
return regs.ports[index].Connect();
}
public void HardReset() public void HardReset()
{ {
outputBitMask = new byte[] { 0x40, 0x80 }; outputBitMask = new byte[] { 0x40, 0x80 };
ports = new DirectionalDataPort[2];
regs = new CiaRegs(signal); regs = new CiaRegs(signal);
underflow = new bool[2]; underflow = new bool[2];
todCounter = todFrequency; todCounter = todFrequency;
@ -305,20 +351,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
public byte Peek(int addr) public byte Peek(int addr)
{ {
addr &= 0xF; addr &= 0xF;
switch (addr)
{
case 0x00:
return ports[0].Data;
case 0x01:
return ports[1].Data;
case 0x02:
return ports[0].Direction;
case 0x03:
return ports[1].Direction;
default:
return regs[addr]; return regs[addr];
} }
}
public void PerformCycle() public void PerformCycle()
{ {
@ -342,19 +376,19 @@ namespace BizHawk.Emulation.Computers.Commodore64
if (regs.OUTMODE[i]) if (regs.OUTMODE[i])
{ {
// clear bit if set // clear bit if set
ports[1].Data &= (byte)~outputBitMask[i]; regs[0x01] &= (byte)~outputBitMask[i];
} }
if (underflow[i]) if (underflow[i])
{ {
if (regs.OUTMODE[i]) if (regs.OUTMODE[i])
{ {
// toggle bit // toggle bit
ports[1].Data ^= outputBitMask[i]; regs[0x01] ^= outputBitMask[i];
} }
else else
{ {
// set for a cycle // set for a cycle
ports[1].Data |= outputBitMask[i]; regs[0x01] |= outputBitMask[i];
} }
} }
} }
@ -365,24 +399,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
public void Poke(int addr, byte val) public void Poke(int addr, byte val)
{ {
addr &= 0xF; addr &= 0xF;
switch (addr)
{
case 0x00:
ports[0].Data = val;
break;
case 0x01:
ports[1].Data = val;
break;
case 0x02:
ports[0].Direction = val;
break;
case 0x03:
ports[1].Direction = val;
break;
default:
regs[addr] = val; regs[addr] = val;
break;
}
} }
public byte Read(ushort addr) public byte Read(ushort addr)
@ -392,14 +409,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
switch (addr) switch (addr)
{ {
case 0x00:
return ports[0].Data;
case 0x01:
return ports[1].Data;
case 0x02:
return ports[0].Direction;
case 0x03:
return ports[1].Direction;
case 0x08: case 0x08:
regs.TODREADLATCH = false; regs.TODREADLATCH = false;
return (byte)regs.TODREADLATCH10; return (byte)regs.TODREADLATCH10;
@ -484,18 +493,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
addr &= 0xF; addr &= 0xF;
switch (addr) switch (addr)
{ {
case 0x00:
ports[0].Data = val;
break;
case 0x01:
ports[1].Data = val;
break;
case 0x02:
ports[0].Direction = val;
break;
case 0x03:
ports[1].Direction = val;
break;
case 0x04: case 0x04:
regs.TLATCH[0] &= 0xFF00; regs.TLATCH[0] &= 0xFF00;
regs.TLATCH[0] |= val; regs.TLATCH[0] |= val;

View File

@ -5,52 +5,192 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64 namespace BizHawk.Emulation.Computers.Commodore64
{ {
public class DirectionalDataPort public class DataPortBus
{ {
protected byte _data; private DataPortConnector[] connectors;
protected byte _remoteData; private bool[] connected = new bool[2];
public byte Direction; private byte[] direction = new byte[2];
public Action<byte> WritePort; private byte[] latch = new byte[2];
private List<Action> writeHooks = new List<Action>();
public DirectionalDataPort(byte initData, byte initDirection, byte initRemoteData) public DataPortBus()
{ {
_remoteData = initRemoteData; connectors = new DataPortConnector[2];
_data = initData; connectors[0] = new DataPortConnector(ReadData0, ReadDirection0, WriteData0, WriteDirection0);
Direction = initDirection; connectors[1] = new DataPortConnector(ReadData1, ReadDirection1, WriteData1, WriteDirection1);
WritePort = WritePortDummy; connected[0] = false;
WritePort(_data); connected[1] = false;
direction[0] = 0x00;
direction[1] = 0x00;
latch[0] = 0x00;
latch[1] = 0x00;
}
public void AttachWriteHook(Action act)
{
writeHooks.Add(act);
}
public DataPortConnector Connect()
{
if (!connected[0])
{
connected[0] = true;
direction[0] = 0xFF;
return connectors[0];
}
else if (!connected[1])
{
connected[1] = true;
direction[1] = 0xFF;
return connectors[1];
}
throw new Exception("Two connections to this bus have already been established..");
}
public void Disconnect(DataPortConnector connector)
{
if (connector.Equals(connectors[0]))
{
connected[0] = false;
latch[0] = 0;
direction[0] = 0;
}
else if (connector.Equals(connectors[1]))
{
connected[1] = false;
latch[1] = 0;
direction[1] = 0;
}
}
private byte ReadData0()
{
if (connected[1])
return (byte)((~direction[0] & latch[1]) | (direction[0] & latch[0]));
else
return latch[0];
}
private byte ReadData1()
{
if (connected[0])
return (byte)((~direction[1] & latch[0]) | (direction[1] & latch[1]));
else
return latch[1];
}
private byte ReadDirection0()
{
return direction[0];
}
private byte ReadDirection1()
{
return direction[1];
}
private void WriteData0(byte val)
{
latch[0] &= (byte)~direction[0];
latch[0] |= (byte)(val & direction[0]);
foreach (Action hook in writeHooks)
hook();
}
private void WriteData1(byte val)
{
latch[1] &= (byte)~direction[1];
latch[1] |= (byte)(val & direction[1]);
foreach (Action hook in writeHooks)
hook();
}
private void WriteDirection0(byte val)
{
direction[0] = val;
foreach (Action hook in writeHooks)
hook();
}
private void WriteDirection1(byte val)
{
direction[1] = val;
foreach (Action hook in writeHooks)
hook();
}
}
public class DataPortConnector
{
private Func<byte> ReadData;
private Func<byte> ReadDirection;
private Action<byte> WriteData;
private Action<byte> WriteDirection;
public DataPortConnector(Func<byte> newReadData, Func<byte> newReadDirection, Action<byte> newWriteData, Action<byte> newWriteDirection)
{
ReadData = newReadData;
ReadDirection = newReadDirection;
WriteData = newWriteData;
WriteDirection = newWriteDirection;
} }
public byte Data public byte Data
{ {
get get
{ {
byte result = _remoteData; return ReadData();
result &= (byte)~Direction;
result |= (byte)(_data & Direction);
return result;
} }
set set
{ {
_data = value; WriteData(value);
WritePort(_data);
} }
} }
public byte RemoteData public byte Direction
{ {
get get
{ {
return _remoteData; return ReadDirection();
} }
set set
{ {
_remoteData = value; WriteDirection(value);
} }
} }
private void WritePortDummy(byte val) public DataPortListener Listener()
{ {
return new DataPortListener(ReadData, ReadDirection);
}
}
public class DataPortListener
{
private Func<byte> ReadData;
private Func<byte> ReadDirection;
public DataPortListener(Func<byte> newReadData, Func<byte> newReadDirection)
{
ReadData = newReadData;
ReadDirection = newReadDirection;
}
public byte Data
{
get
{
return ReadData();
}
}
public byte Direction
{
get
{
return ReadDirection();
}
} }
} }
} }

View File

@ -32,15 +32,15 @@ namespace BizHawk.Emulation.Computers.Commodore64
private byte keyboardColumnData = 0xFF; private byte keyboardColumnData = 0xFF;
private byte[] keyboardLatch = new byte[8]; private byte[] keyboardLatch = new byte[8];
private byte keyboardRowData = 0xFF; private byte keyboardRowData = 0xFF;
private DirectionalDataPort[] ports; private DataPortConnector[] ports;
public Input(DirectionalDataPort[] newPorts) public Input(DataPortConnector[] newPorts)
{ {
ports = newPorts; ports = newPorts;
// attach input to a CIA I/O port // set full output
ports[0].WritePort = WritePortA; ports[0].Direction = 0xFF;
ports[1].WritePort = WritePortB; ports[1].Direction = 0xFF;
} }
private byte GetJoystickBits(int index) private byte GetJoystickBits(int index)
@ -97,8 +97,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
} }
port1result &= joystickLatch[0]; port1result &= joystickLatch[0];
ports[0].RemoteData = port0result; ports[0].Data = port0result;
ports[1].RemoteData = port1result; ports[1].Data = port1result;
} }
public void WritePortA(byte data) public void WritePortA(byte data)

View File

@ -62,12 +62,13 @@ namespace BizHawk.Emulation.Computers.Commodore64
// registers // registers
public byte busData; public byte busData;
public DirectionalDataPort cia1PortA = new DirectionalDataPort(0x7F, 0x00, 0xFF);
public DirectionalDataPort cia1PortB = new DirectionalDataPort(0xFF, 0x00, 0xFF);
public DirectionalDataPort cpuPort;
public bool readTrigger = true; public bool readTrigger = true;
public bool writeTrigger = true; public bool writeTrigger = true;
// ports
public DataPortConnector cpuPort;
public DataPortBus cpuPortBus = new DataPortBus();
void HandleFirmwareError(string file) void HandleFirmwareError(string file)
{ {
System.Windows.Forms.MessageBox.Show("the C64 core is referencing a firmware file which could not be found. Please make sure it's in your configured C64 firmwares folder. The referenced filename is: " + file); System.Windows.Forms.MessageBox.Show("the C64 core is referencing a firmware file which could not be found. Please make sure it's in your configured C64 firmwares folder. The referenced filename is: " + file);
@ -96,9 +97,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
sid = newSid; sid = newSid;
cia0 = newCia0; cia0 = newCia0;
cia1 = newCia1; cia1 = newCia1;
cia1.ports[0] = cia1PortA;
cia1.ports[1] = cia1PortB; cpuPort = cpuPortBus.Connect();
cia1PortA.WritePort = UpdateVicOffset; cpuPortBus.AttachWriteHook(UpdateLayout);
cia1.AttachWriteHook(0, UpdateVicOffset);
HardReset(); HardReset();
} }
@ -185,13 +187,16 @@ namespace BizHawk.Emulation.Computers.Commodore64
public void HardReset() public void HardReset()
{ {
layout = new MemoryLayout();
ram = new byte[0x10000]; ram = new byte[0x10000];
colorRam = new byte[0x1000]; colorRam = new byte[0x1000];
WipeMemory(); WipeMemory();
cpuPort = new DirectionalDataPort(0x37, 0x2F, 0x00);
layout = new MemoryLayout(); cpuPort.Direction = 0x2F;
UpdateLayout(); cpuPort.Data = 0x37;
UpdateVicOffset(cia1PortA.Data);
UpdateVicOffset();
} }
public byte Peek(ushort addr) public byte Peek(ushort addr)
@ -489,9 +494,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
} }
} }
private void UpdateVicOffset(byte val) private void UpdateVicOffset()
{ {
switch (cia1PortA.Data & 0x03) switch (cia1.Peek(0x00) & 0x03)
{ {
case 0: case 0:
vicCharEnabled = false; vicCharEnabled = false;
@ -550,7 +555,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
else if (addr == 0x0001) else if (addr == 0x0001)
{ {
cpuPort.Data = val; cpuPort.Data = val;
UpdateLayout();
} }
else else
{ {