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()
{