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)
{
return cia0.regs[addr];
return cia0.Peek(addr);
}
public byte PeekCia1(int addr)
{
return cia1.regs[addr];
return cia1.Peek(addr);
}
public byte PeekColorRAM(int addr)

View File

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

View File

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

View File

@ -40,6 +40,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
public int TODREADLATCHHR; // tod read latch (internal)
public int TODSEC; // time of day seconds
public DataPortBus[] ports;
private DataPortConnector[] connectors;
private ChipSignals signal;
public CiaRegs(ChipSignals newSignal)
@ -53,6 +56,17 @@ namespace BizHawk.Emulation.Computers.Commodore64
T[1] = TLATCH[1];
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]
@ -65,6 +79,18 @@ namespace BizHawk.Emulation.Computers.Commodore64
addr &= 0x0F;
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:
result = (T[0] & 0xFF);
break;
@ -134,6 +160,18 @@ namespace BizHawk.Emulation.Computers.Commodore64
addr &= 0x0F;
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:
T[0] &= 0xFF00;
T[0] |= val;
@ -204,8 +242,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
public int intMask;
public bool lastCNT;
public byte[] outputBitMask;
public DirectionalDataPort[] ports;
public CiaRegs regs;
private CiaRegs regs;
public ChipSignals signal;
public bool thisCNT;
public int todCounter;
@ -271,6 +308,11 @@ namespace BizHawk.Emulation.Computers.Commodore64
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)
{
int lo;
@ -293,10 +335,14 @@ namespace BizHawk.Emulation.Computers.Commodore64
return result;
}
public DataPortConnector ConnectPort(int index)
{
return regs.ports[index].Connect();
}
public void HardReset()
{
outputBitMask = new byte[] { 0x40, 0x80 };
ports = new DirectionalDataPort[2];
regs = new CiaRegs(signal);
underflow = new bool[2];
todCounter = todFrequency;
@ -305,19 +351,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
public byte Peek(int addr)
{
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()
@ -342,19 +376,19 @@ namespace BizHawk.Emulation.Computers.Commodore64
if (regs.OUTMODE[i])
{
// clear bit if set
ports[1].Data &= (byte)~outputBitMask[i];
regs[0x01] &= (byte)~outputBitMask[i];
}
if (underflow[i])
{
if (regs.OUTMODE[i])
{
// toggle bit
ports[1].Data ^= outputBitMask[i];
regs[0x01] ^= outputBitMask[i];
}
else
{
// 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)
{
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;
break;
}
regs[addr] = val;
}
public byte Read(ushort addr)
@ -392,14 +409,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
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:
regs.TODREADLATCH = false;
return (byte)regs.TODREADLATCH10;
@ -484,18 +493,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
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;
case 0x04:
regs.TLATCH[0] &= 0xFF00;
regs.TLATCH[0] |= val;

View File

@ -5,52 +5,192 @@ using System.Text;
namespace BizHawk.Emulation.Computers.Commodore64
{
public class DirectionalDataPort
public class DataPortBus
{
protected byte _data;
protected byte _remoteData;
public byte Direction;
public Action<byte> WritePort;
private DataPortConnector[] connectors;
private bool[] connected = new bool[2];
private byte[] direction = new byte[2];
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;
_data = initData;
Direction = initDirection;
WritePort = WritePortDummy;
WritePort(_data);
connectors = new DataPortConnector[2];
connectors[0] = new DataPortConnector(ReadData0, ReadDirection0, WriteData0, WriteDirection0);
connectors[1] = new DataPortConnector(ReadData1, ReadDirection1, WriteData1, WriteDirection1);
connected[0] = false;
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
{
get
{
byte result = _remoteData;
result &= (byte)~Direction;
result |= (byte)(_data & Direction);
return result;
return ReadData();
}
set
{
_data = value;
WritePort(_data);
WriteData(value);
}
}
public byte RemoteData
public byte Direction
{
get
{
return _remoteData;
return ReadDirection();
}
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[] keyboardLatch = new byte[8];
private byte keyboardRowData = 0xFF;
private DirectionalDataPort[] ports;
private DataPortConnector[] ports;
public Input(DirectionalDataPort[] newPorts)
public Input(DataPortConnector[] newPorts)
{
ports = newPorts;
// attach input to a CIA I/O port
ports[0].WritePort = WritePortA;
ports[1].WritePort = WritePortB;
// set full output
ports[0].Direction = 0xFF;
ports[1].Direction = 0xFF;
}
private byte GetJoystickBits(int index)
@ -97,8 +97,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
}
port1result &= joystickLatch[0];
ports[0].RemoteData = port0result;
ports[1].RemoteData = port1result;
ports[0].Data = port0result;
ports[1].Data = port1result;
}
public void WritePortA(byte data)

View File

@ -62,12 +62,13 @@ namespace BizHawk.Emulation.Computers.Commodore64
// registers
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 writeTrigger = true;
// ports
public DataPortConnector cpuPort;
public DataPortBus cpuPortBus = new DataPortBus();
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);
@ -96,9 +97,10 @@ namespace BizHawk.Emulation.Computers.Commodore64
sid = newSid;
cia0 = newCia0;
cia1 = newCia1;
cia1.ports[0] = cia1PortA;
cia1.ports[1] = cia1PortB;
cia1PortA.WritePort = UpdateVicOffset;
cpuPort = cpuPortBus.Connect();
cpuPortBus.AttachWriteHook(UpdateLayout);
cia1.AttachWriteHook(0, UpdateVicOffset);
HardReset();
}
@ -185,13 +187,16 @@ namespace BizHawk.Emulation.Computers.Commodore64
public void HardReset()
{
layout = new MemoryLayout();
ram = new byte[0x10000];
colorRam = new byte[0x1000];
WipeMemory();
cpuPort = new DirectionalDataPort(0x37, 0x2F, 0x00);
layout = new MemoryLayout();
UpdateLayout();
UpdateVicOffset(cia1PortA.Data);
cpuPort.Direction = 0x2F;
cpuPort.Data = 0x37;
UpdateVicOffset();
}
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:
vicCharEnabled = false;
@ -550,7 +555,6 @@ namespace BizHawk.Emulation.Computers.Commodore64
else if (addr == 0x0001)
{
cpuPort.Data = val;
UpdateLayout();
}
else
{