From fff3b623e8fdafd316a286a45400812ca8131582 Mon Sep 17 00:00:00 2001 From: saxxonpike Date: Fri, 16 Nov 2012 09:23:34 +0000 Subject: [PATCH] commodore64: more timer functionality added to VIA, memory domains added for VIA chips in 1541 drive --- .../Computers/Commodore64/1541.cs | 21 +++ .../Computers/Commodore64/C64.PeekPoke.cs | 28 +++- .../Computers/Commodore64/C64.cs | 2 + .../Computers/Commodore64/Cia.cs | 8 ++ .../Computers/Commodore64/DataPort.cs | 61 +++++++-- .../Computers/Commodore64/Input.cs | 6 +- .../Computers/Commodore64/Via.cs | 129 ++++++++++++++++-- 7 files changed, 228 insertions(+), 27 deletions(-) diff --git a/BizHawk.Emulation/Computers/Commodore64/1541.cs b/BizHawk.Emulation/Computers/Commodore64/1541.cs index eaac83a9d7..fa9d672ac1 100644 --- a/BizHawk.Emulation/Computers/Commodore64/1541.cs +++ b/BizHawk.Emulation/Computers/Commodore64/1541.cs @@ -73,6 +73,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 SetRPM(300.0); // attach VIA/CIA + via0.Connect(cia.ConnectSerialPort(1)); // set VIA values via0.Poke(0x0, 0x07); @@ -118,6 +119,16 @@ namespace BizHawk.Emulation.Computers.Commodore64 return 0xFF; } + public byte PeekVia0(int addr) + { + return via0.Peek(addr); + } + + public byte PeekVia1(int addr) + { + return via1.Peek(addr); + } + public void PerformCycle() { cpu.IRQ = via0.IRQ | via1.IRQ; @@ -143,6 +154,16 @@ namespace BizHawk.Emulation.Computers.Commodore64 } } + public void PokeVia0(int addr, byte val) + { + via0.Poke(addr, val); + } + + public void PokeVia1(int addr, byte val) + { + via1.Poke(addr, val); + } + public byte Read(ushort addr) { if (addr < 0x0800) diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs b/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs index c114799dcc..bc5af02466 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.PeekPoke.cs @@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Computers.Commodore64 public byte PeekColorRAM(int addr) { - return (byte)((mem.colorRam[addr & 0x3FF] & 0xF) | mem.busData); + return (byte)(mem.colorRam[addr & 0x3FF] & 0xF); } public byte PeekDiskDrive(int addr) @@ -49,6 +49,20 @@ namespace BizHawk.Emulation.Computers.Commodore64 return sid.regs[addr]; } + public byte PeekVia0(int addr) + { + if (diskDriveAttached) + return diskDrive.PeekVia0(addr); + return 0xFF; + } + + public byte PeekVia1(int addr) + { + if (diskDriveAttached) + return diskDrive.PeekVia1(addr); + return 0xFF; + } + public byte PeekVic(int addr) { return vic.regs[addr]; @@ -90,6 +104,18 @@ namespace BizHawk.Emulation.Computers.Commodore64 sid.Poke(addr, val); } + public void PokeVia0(int addr, byte val) + { + if (diskDriveAttached) + diskDrive.PokeVia0(addr, val); + } + + public void PokeVia1(int addr, byte val) + { + if (diskDriveAttached) + diskDrive.PokeVia1(addr, val); + } + public void PokeVic(int addr, byte val) { vic.Poke(addr, val); diff --git a/BizHawk.Emulation/Computers/Commodore64/C64.cs b/BizHawk.Emulation/Computers/Commodore64/C64.cs index 5ff3d25fce..f111256063 100644 --- a/BizHawk.Emulation/Computers/Commodore64/C64.cs +++ b/BizHawk.Emulation/Computers/Commodore64/C64.cs @@ -125,6 +125,8 @@ namespace BizHawk.Emulation.Computers.Commodore64 domains.Add(new MemoryDomain("VIC", 0x40, Endian.Little, new Func(PeekVic), new Action(PokeVic))); domains.Add(new MemoryDomain("CRAM", 0x400, Endian.Little, new Func(PeekColorRAM), new Action(PokeColorRAM))); domains.Add(new MemoryDomain("DISKRAM", 0x10000, Endian.Little, new Func(PeekDiskDrive), new Action(PokeDiskDrive))); + domains.Add(new MemoryDomain("DISKVIA0", 0x10, Endian.Little, new Func(PeekVia0), new Action(PokeVia0))); + domains.Add(new MemoryDomain("DISKVIA1", 0x10, Endian.Little, new Func(PeekVia1), new Action(PokeVia1))); memoryDomains = domains.AsReadOnly(); } diff --git a/BizHawk.Emulation/Computers/Commodore64/Cia.cs b/BizHawk.Emulation/Computers/Commodore64/Cia.cs index 1d804e8a82..37247ded48 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Cia.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Cia.cs @@ -342,6 +342,14 @@ namespace BizHawk.Emulation.Computers.Commodore64 return regs.ports[index].Connect(); } + public DataPortConnector ConnectSerialPort(int index) + { + DataPortConnector result = regs.ports[index].Connect(); + regs.ports[index].AttachInputConverter(result, new DataPortSerialInputConverter()); + regs.ports[index].AttachOutputConverter(result, new DataPortSerialOutputConverter()); + return result; + } + public void HardReset() { outputBitMask = new byte[] { 0x40, 0x80 }; diff --git a/BizHawk.Emulation/Computers/Commodore64/DataPort.cs b/BizHawk.Emulation/Computers/Commodore64/DataPort.cs index f94f3db324..d1d9f8e8b8 100644 --- a/BizHawk.Emulation/Computers/Commodore64/DataPort.cs +++ b/BizHawk.Emulation/Computers/Commodore64/DataPort.cs @@ -25,8 +25,8 @@ namespace BizHawk.Emulation.Computers.Commodore64 outputConverters[0] = new DataPortConverter(); outputConverters[1] = new DataPortConverter(); connectors = new DataPortConnector[2]; - connectors[0] = new DataPortConnector(ReadData0, ReadDirection0, ReadRemoteData0, WriteData0, WriteDirection0); - connectors[1] = new DataPortConnector(ReadData1, ReadDirection1, ReadRemoteData1, WriteData1, WriteDirection1); + connectors[0] = new DataPortConnector(ReadData0, ReadDirection0, ReadLatch0, ReadRemoteLatch0, WriteData0, WriteDirection0); + connectors[1] = new DataPortConnector(ReadData1, ReadDirection1, ReadLatch1, ReadRemoteLatch1, WriteData1, WriteDirection1); connected[0] = false; connected[1] = false; direction[0] = 0x00; @@ -168,12 +168,22 @@ namespace BizHawk.Emulation.Computers.Commodore64 return direction[1]; } - protected virtual byte ReadRemoteData0() + protected virtual byte ReadLatch0() + { + return latch[0]; + } + + protected virtual byte ReadLatch1() { return latch[1]; } - protected virtual byte ReadRemoteData1() + protected virtual byte ReadRemoteLatch0() + { + return latch[1]; + } + + protected virtual byte ReadRemoteLatch1() { return latch[0]; } @@ -213,24 +223,37 @@ namespace BizHawk.Emulation.Computers.Commodore64 { private Func ReadData; private Func ReadDirection; - private Func ReadRemoteData; + private Func ReadLatch; + private Func ReadRemoteLatch; private Action WriteData; private Action WriteDirection; + public DataPortConnector() + { + ReadData = ReadDataDummy; + ReadDirection = ReadDataDummy; + ReadLatch = ReadDataDummy; + ReadRemoteLatch = ReadDataDummy; + WriteData = WriteDataDummy; + WriteDirection = WriteDataDummy; + } + public DataPortConnector(DataPortConnector source) { ReadData = source.ReadData; ReadDirection = source.ReadDirection; - ReadRemoteData = source.ReadRemoteData; + ReadLatch = source.ReadLatch; + ReadRemoteLatch = source.ReadRemoteLatch; WriteData = source.WriteData; WriteDirection = source.WriteDirection; } - public DataPortConnector(Func newReadData, Func newReadDirection, Func newReadRemoteData, Action newWriteData, Action newWriteDirection) + public DataPortConnector(Func newReadData, Func newReadDirection, Func newReadLatch, Func newReadRemoteLatch, Action newWriteData, Action newWriteDirection) { ReadData = newReadData; ReadDirection = newReadDirection; - ReadRemoteData = newReadRemoteData; + ReadLatch = newReadLatch; + ReadRemoteLatch = newReadRemoteLatch; WriteData = newWriteData; WriteDirection = newWriteDirection; } @@ -259,18 +282,36 @@ namespace BizHawk.Emulation.Computers.Commodore64 } } + public byte Latch + { + get + { + return ReadLatch(); + } + } + public DataPortListener Listener() { return new DataPortListener(ReadData, ReadDirection); } - public byte RemoteData + private byte ReadDataDummy() + { + return 0x00; + } + + public byte RemoteLatch { get { - return ReadRemoteData(); + return ReadRemoteLatch(); } } + + private void WriteDataDummy(byte val) + { + return; + } } public class DataPortConverter diff --git a/BizHawk.Emulation/Computers/Commodore64/Input.cs b/BizHawk.Emulation/Computers/Commodore64/Input.cs index a7d8baa647..41c56cff53 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Input.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Input.cs @@ -65,8 +65,6 @@ namespace BizHawk.Emulation.Computers.Commodore64 result |= controller[keyboardMatrix[row, 5]] ? (byte)0x00 : (byte)0x20; result |= controller[keyboardMatrix[row, 6]] ? (byte)0x00 : (byte)0x40; result |= controller[keyboardMatrix[row, 7]] ? (byte)0x00 : (byte)0x80; - if (result != 0xFF) - row = row; return result; } @@ -106,14 +104,14 @@ namespace BizHawk.Emulation.Computers.Commodore64 public void WritePortA() { // keyboard matrix column select - keyboardColumnData = ports[0].RemoteData; + keyboardColumnData = ports[0].RemoteLatch; UpdatePortData(); } public void WritePortB() { // keyboard matrix row select - keyboardRowData = ports[1].RemoteData; + keyboardRowData = ports[1].RemoteLatch; UpdatePortData(); } } diff --git a/BizHawk.Emulation/Computers/Commodore64/Via.cs b/BizHawk.Emulation/Computers/Commodore64/Via.cs index b629b72aa0..59f5d2b4e9 100644 --- a/BizHawk.Emulation/Computers/Commodore64/Via.cs +++ b/BizHawk.Emulation/Computers/Commodore64/Via.cs @@ -30,23 +30,14 @@ namespace BizHawk.Emulation.Computers.Commodore64 public int[] TCONTROL = new int[2]; public int[] TL = new int[2]; - public DataPortBus[] ports; - private DataPortConnector[] connectors; public ViaRegs() { // power on state - 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; + connectors[0] = new DataPortConnector(); + connectors[1] = new DataPortConnector(); } public byte this[int addr] @@ -210,6 +201,36 @@ namespace BizHawk.Emulation.Computers.Commodore64 break; } } + + } + + public void Connect(DataPortConnector connector, int index) + { + connectors[index] = connector; + } + + public bool PB6 + { + get + { + return ((connectors[1].Latch & 0x40) != 0); + } + set + { + connectors[1].Data = (byte)((connectors[1].Latch & 0xBF) | (value ? 0x40 : 0x00)); + } + } + + public bool PB7 + { + get + { + return ((connectors[1].Latch & 0x80) != 0); + } + set + { + connectors[1].Data = (byte)((connectors[1].Latch & 0x7F) | (value ? 0x80 : 0x00)); + } } } @@ -239,6 +260,11 @@ namespace BizHawk.Emulation.Computers.Commodore64 HardReset(); } + public void Connect(DataPortConnector connector) + { + regs.Connect(connector, 1); + } + public void HardReset() { regs = new ViaRegs(); @@ -260,7 +286,8 @@ namespace BizHawk.Emulation.Computers.Commodore64 public void PerformCycle() { - // do stuff + Tick0(); + Tick1(); UpdateInterrupts(); } @@ -277,6 +304,18 @@ namespace BizHawk.Emulation.Computers.Commodore64 addr &= 0xF; switch (addr) { + case 0x4: + result = regs[0x4]; + regs.IT[0] = false; + break; + case 0x8: + result = (byte)(regs.TC[1] & 0xFF); + regs.IT[1] = false; + break; + case 0x9: + result = (byte)(regs.TC[1] >> 8); + regs.IT[1] = false; + break; case 0xD: // reading this clears it result = regs[addr]; @@ -290,6 +329,52 @@ namespace BizHawk.Emulation.Computers.Commodore64 return result; } + private void Tick0() + { + bool underflow = false; + + switch (regs.TCONTROL[0] & 0x1) + { + case 0: + if (regs.TC[0] > 0) + { + if (--regs.TC[0] <= 0) + { + regs.IT[0] = true; + underflow = true; + } + } + break; + case 1: + if (--regs.TC[0] <= 0) + { + regs.IT[0] = true; + regs.TC[0] = regs.TL[0]; + underflow = true; + } + break; + } + + if (underflow) + { + if ((regs.TCONTROL[0] & 0x2) != 0) + { + regs.PB7 = !regs.PB7; + } + } + } + + private void Tick1() + { + switch (regs.TCONTROL[1]) + { + case 0: + break; + case 1: + break; + } + } + private void UpdateInterrupts() { regs.IRQ = @@ -307,6 +392,26 @@ namespace BizHawk.Emulation.Computers.Commodore64 addr &= 0xF; switch (addr) { + case 0x4: // write low counter + regs[0x6] = val; + break; + case 0x5: // write high counter + regs[0x4] = regs[0x06]; + regs[0x5] = val; + regs[0x7] = val; + regs.IT[0] = false; + break; + case 0x7: + regs[0x7] = val; + regs.IT[0] = false; + break; + case 0x8: + regs.TL[1] = val; + break; + case 0x9: + regs.TC[1] = ((int)val << 8) | regs.TL[1]; + regs.IT[1] = false; + break; default: regs[addr] = val; break;