commodore64: replaced directional data port class with a more efficient one
This commit is contained in:
parent
a8957f1916
commit
b84ec59bb4
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -100,6 +100,8 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
cpu.ExecuteOne();
|
||||
}
|
||||
sid.PerformCycle();
|
||||
if (diskDriveAttached)
|
||||
diskDrive.PerformCycle();
|
||||
cia0.PerformCycle();
|
||||
cia1.PerformCycle();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue