diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 99f23f3401..6c21f9741d 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -228,6 +228,7 @@ + diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6522.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6522.cs new file mode 100644 index 0000000000..81bd05e946 --- /dev/null +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Chip6522.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS +{ + public static class Chip6522 + { + public static Via Create(Func readPrA, Func readPrB) + { + return new Via(readPrA, readPrB); + } + + public static Via Create(Func readClock, Func readData, Func readAtn, int driveNumber) + { + return new Via(readClock, readData, readAtn, driveNumber); + } + } +} diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.Registers.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.Registers.cs index 84119b3062..2db8c5d966 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.Registers.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.Registers.cs @@ -124,9 +124,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS _t1L = (_t1L & 0xFF) | ((val & 0xFF) << 8); _ifr &= 0xBF; _t1C = _t1L; + _t1CLoaded = true; + _t1Delayed = 1; break; case 0x7: _t1L = (_t1L & 0xFF) | ((val & 0xFF) << 8); + _ifr &= 0xBF; break; case 0x8: _t2L = (_t2L & 0xFF00) | (val & 0xFF); @@ -134,7 +137,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS case 0x9: _t2L = (_t2L & 0xFF) | ((val & 0xFF) << 8); _ifr &= 0xDF; - _t2C = _t2L; + if (_acrT2Control == ACR_T2_CONTROL_TIMED) + { + _t2C = _t2L; + _t2CLoaded = true; + } + _t2Delayed = 1; break; case 0xA: _ifr &= 0xFB; diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.cs index 5110e3eb94..ad60babc6b 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/MOS/Via.cs @@ -122,6 +122,17 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS [SaveState.SaveWithName("PB6")] private bool _pb6; + [SaveState.SaveWithName("InterruptNextClock")] + private int _interruptNextClock; + [SaveState.SaveWithName("T1Loaded")] + private bool _t1CLoaded; + [SaveState.SaveWithName("T2Loaded")] + private bool _t2CLoaded; + [SaveState.SaveWithName("T1Delayed")] + private int _t1Delayed; + [SaveState.SaveWithName("T2Delayed")] + private int _t2Delayed; + public Via() { _port = new DisconnectedPort(); @@ -183,10 +194,17 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS _resetCb2NextClock = false; _handshakeCa2NextClock = false; _handshakeCb2NextClock = false; + _interruptNextClock = 0; + _t1CLoaded = false; + _t2CLoaded = false; } public void ExecutePhase() { + // Process delayed interrupts + _ifr |= _interruptNextClock; + _interruptNextClock = 0; + // Process 'pulse' and 'handshake' outputs on CA2 and CB2 if (_resetCa2NextClock) @@ -215,48 +233,70 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS // Count timers - _t1C--; - if (_t1C < 0) + if (_t1Delayed > 0) { - switch (_acrT1Control) + _t1Delayed--; + } + else + { + _t1C--; + if (_t1C < 0) { - case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS: - _t1C = _t1L; - break; - case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS_AND_OUTPUT_ON_PB7: - _t1C = _t1L; - _prb ^= 0x80; - break; - default: - _t1C = 0xFFFF; - break; + if (_t1CLoaded) + { + _interruptNextClock |= 0x40; + _t1CLoaded = false; + } + switch (_acrT1Control) + { + case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS: + _t1C = _t1L; + _t1CLoaded = true; + break; + case ACR_T1_CONTROL_CONTINUOUS_INTERRUPTS_AND_OUTPUT_ON_PB7: + _t1C = _t1L; + _prb ^= 0x80; + _t1CLoaded = true; + break; + } + _t1C &= 0xFFFF; } - _ifr |= 0x40; } - switch (_acrT2Control) + if (_t2Delayed > 0) { - case ACR_T2_CONTROL_TIMED: - _t2C--; - if (_t2C < 0) - { - _ifr |= 0x20; - _t2C = 0xFFFF; - } - break; - case ACR_T2_CONTROL_COUNT_ON_PB6: - _pb6L = _pb6; - _pb6 = (_port.ReadExternalPrb() & 0x40) != 0; - if (!_pb6 && _pb6L) - { + _t2Delayed--; + } + else + { + switch (_acrT2Control) + { + case ACR_T2_CONTROL_TIMED: _t2C--; if (_t2C < 0) { - _ifr |= 0x20; - _t2C = 0xFFFF; + if (_t2CLoaded) + { + _interruptNextClock |= 0x20; + _t2CLoaded = false; + } + _t2C = _t2L; } - } - break; + break; + case ACR_T2_CONTROL_COUNT_ON_PB6: + _pb6L = _pb6; + _pb6 = (_port.ReadExternalPrb() & 0x40) != 0; + if (!_pb6 && _pb6L) + { + _t2C--; + if (_t2C < 0) + { + _ifr |= 0x20; + _t2C = 0xFFFF; + } + } + break; + } } // Process CA2 diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs index c69b185509..82bba29bf1 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs @@ -71,8 +71,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial }; _ram = new int[0x800]; - Via0 = new Via(ViaReadClock, ViaReadData, ViaReadAtn, 8); - Via1 = new Via(ReadVia1PrA, ReadVia1PrB); + Via0 = Chip6522.Create(ViaReadClock, ViaReadData, ViaReadAtn, 8); + Via1 = Chip6522.Create(ReadVia1PrA, ReadVia1PrB); _cpuClockNum = clockNum; _driveCpuClockNum = clockDen*1000000; // 1mhz diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPortDevice.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPortDevice.cs index bee7d35688..1894373725 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPortDevice.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/SerialPortDevice.cs @@ -9,11 +9,11 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial public abstract class SerialPortDevice { [SaveState.DoNotSave] - public Func ReadMasterAtn; + public Func ReadMasterAtn = () => true; [SaveState.DoNotSave] - public Func ReadMasterClk; + public Func ReadMasterClk = () => true; [SaveState.DoNotSave] - public Func ReadMasterData; + public Func ReadMasterData = () => true; public virtual void ExecutePhase() {