From b84ec59bb46a53cc882ebd2d9f05caf7dd9daa70 Mon Sep 17 00:00:00 2001 From: saxxonpike Date: Wed, 14 Nov 2012 07:12:04 +0000 Subject: [PATCH] commodore64: replaced directional data port class with a more efficient one --- .../Computers/Commodore64/C64.PeekPoke.cs | 4 +- .../Computers/Commodore64/C64.core.cs | 17 +- .../Computers/Commodore64/C64.cs | 2 + .../Computers/Commodore64/Cia.cs | 111 ++++++----- .../Computers/Commodore64/DataPort.cs | 182 ++++++++++++++++-- .../Computers/Commodore64/Input.cs | 14 +- .../Computers/Commodore64/MemBus.cs | 30 +-- 7 files changed, 249 insertions(+), 111 deletions(-) diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs b/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs index 0a46592896..1b2287d4f1 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs @@ -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) diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.core.cs b/BizHawk.Emulation/Computers/Commodore64/C64.core.cs index 5efc2d8c1e..9fd2955e6c 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.core.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.core.cs @@ -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 mediaAttached = new List(); @@ -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() diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.cs b/BizHawk.Emulation/Computers/Commodore64/C64.cs index e6753d4801..1c4619dd7d 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.cs @@ -100,6 +100,8 @@ namespace BizHawk.Emulation.Computers.Commodore64 cpu.ExecuteOne(); } sid.PerformCycle(); + if (diskDriveAttached) + diskDrive.PerformCycle(); cia0.PerformCycle(); cia1.PerformCycle(); } diff --git a/BizHawk.Emulation/Computers/Commodore64/Cia.cs b/BizHawk.Emulation/Computers/Commodore64/Cia.cs index bcc65ba18a..b390ed6e3d 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Cia.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Cia.cs @@ -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; diff --git a/BizHawk.Emulation/Computers/Commodore64/DataPort.cs b/BizHawk.Emulation/Computers/Commodore64/DataPort.cs index 79d203fe36..5f95699bbd 100644 --- a/BizHawk.Emulation/Computers/Commodore64/DataPort.cs +++ b/BizHawk.Emulation/Computers/Commodore64/DataPort.cs @@ -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 WritePort; + private DataPortConnector[] connectors; + private bool[] connected = new bool[2]; + private byte[] direction = new byte[2]; + private byte[] latch = new byte[2]; + private List writeHooks = new List(); - 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 ReadData; + private Func ReadDirection; + private Action WriteData; + private Action WriteDirection; + + public DataPortConnector(Func newReadData, Func newReadDirection, Action newWriteData, Action 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 ReadData; + private Func ReadDirection; + + public DataPortListener(Func newReadData, Func newReadDirection) + { + ReadData = newReadData; + ReadDirection = newReadDirection; + } + + public byte Data + { + get + { + return ReadData(); + } + } + + public byte Direction + { + get + { + return ReadDirection(); + } } } } diff --git a/BizHawk.Emulation/Computers/Commodore64/Input.cs b/BizHawk.Emulation/Computers/Commodore64/Input.cs index 6a16ca43c4..d1b7453b10 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Input.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Input.cs @@ -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) diff --git a/BizHawk.Emulation/Computers/Commodore64/MemBus.cs b/BizHawk.Emulation/Computers/Commodore64/MemBus.cs index 39f57327bf..de5f7c4949 100644 --- a/BizHawk.Emulation/Computers/Commodore64/MemBus.cs +++ b/BizHawk.Emulation/Computers/Commodore64/MemBus.cs @@ -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 {