diff --git a/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.Interop.cs b/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.Interop.cs
index 9eb6e1eddf..1e6cbd3716 100644
--- a/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.Interop.cs
+++ b/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.Interop.cs
@@ -41,6 +41,18 @@ namespace BizHawk.Emulation.Cores.Components.vr6502
[DllImport(lib, CallingConvention = cc)]
public static extern byte vrEmu6502InstCycle(ref VrEmu6502State state);
+ ///
+ /// Pointer to the NMI pin
+ ///
+ [DllImport(lib, CallingConvention = cc)]
+ public static extern IntPtr vrEmu6502Nmi(ref VrEmu6502State state);
+
+ ///
+ /// Pointer to the INT pin
+ ///
+ [DllImport(lib, CallingConvention = cc)]
+ public static extern IntPtr vrEmu6502Int(ref VrEmu6502State state);
+
[DllImport(lib, CallingConvention = cc)]
public static extern IntPtr vrEmu6502OpcodeToMnemonicStr(ref VrEmu6502State state, byte opcode);
diff --git a/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.Structures.cs b/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.Structures.cs
index 4a13abb5eb..37a93e5706 100644
--- a/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.Structures.cs
+++ b/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.Structures.cs
@@ -37,8 +37,7 @@ namespace BizHawk.Emulation.Cores.Components.vr6502
public IntPtr opcodes;
public IntPtr mnemonicNames;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
- public VrEmu6502AddrMode[] addrModes;
+ public IntPtr addrModes;
}
public enum VrEmu6502Model
diff --git a/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.cs b/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.cs
index 13a01d0ab8..67f238c8cd 100644
--- a/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.cs
+++ b/src/BizHawk.Emulation.Cores/CPUs/65x02/vr6502.cs
@@ -3,6 +3,7 @@ using BizHawk.Common.NumberExtensions;
using BizHawk.Emulation.Common;
using System.Collections.Generic;
using System.Runtime.InteropServices;
+using static BizHawk.Emulation.Cores.Components.vr6502.vr6502;
namespace BizHawk.Emulation.Cores.Components.vr6502
{
@@ -49,9 +50,32 @@ namespace BizHawk.Emulation.Cores.Components.vr6502
public delegate byte VrEmu6502MemRead(ushort addr, bool isDbg);
public delegate void VrEmu6502MemWrite(ushort addr, byte val);
- public void SetNMI() => _6502s.nmiPin = VrEmu6502Interrupt.IntLow;
+ public void SetNMI() => WriteNMI(VrEmu6502Interrupt.IntRequested);
+ public void SetIRQ() => WriteInt(VrEmu6502Interrupt.IntRequested);
- public bool SetIRQ() => _6502s.intPin == VrEmu6502Interrupt.IntLow;
+ private void WriteNMI(VrEmu6502Interrupt state)
+ {
+ IntPtr nmiPtr = VrEmu6502Interop.vrEmu6502Nmi(ref _6502s);
+ Marshal.WriteInt32(nmiPtr, (int)state);
+ }
+
+ private VrEmu6502Interrupt ReadNMI()
+ {
+ IntPtr nmiPtr = VrEmu6502Interop.vrEmu6502Nmi(ref _6502s);
+ return (VrEmu6502Interrupt)Marshal.ReadInt32(nmiPtr);
+ }
+
+ private void WriteInt(VrEmu6502Interrupt state)
+ {
+ IntPtr intPtr = VrEmu6502Interop.vrEmu6502Int(ref _6502s);
+ Marshal.WriteInt32(intPtr, (int)state);
+ }
+
+ private VrEmu6502Interrupt ReadInt()
+ {
+ IntPtr intPtr = VrEmu6502Interop.vrEmu6502Int(ref _6502s);
+ return (VrEmu6502Interrupt)Marshal.ReadInt32(intPtr);
+ }
public bool RDY;
@@ -61,8 +85,8 @@ namespace BizHawk.Emulation.Cores.Components.vr6502
}
public void ExecuteTick()
- {
- if (RDY)
+ {
+ if (!RDY)
{
VrEmu6502Interop.vrEmu6502Tick(ref _6502s);
}
@@ -72,9 +96,9 @@ namespace BizHawk.Emulation.Cores.Components.vr6502
public byte ExecuteInstruction()
{
- int cycles = 0;
+ int cycles = 0;
- if (RDY)
+ if (!RDY)
{
cycles = VrEmu6502Interop.vrEmu6502InstCycle(ref _6502s);
}
@@ -118,10 +142,8 @@ namespace BizHawk.Emulation.Cores.Components.vr6502
ser.Sync(nameof(RDY), ref RDY);
ser.SyncEnum(nameof(_6502s.Model), ref _6502s.Model);
- // ReadFn not serializable
- // WriteFn not serializable
- ser.SyncEnum(nameof(_6502s.intPin), ref _6502s.intPin);
- ser.SyncEnum(nameof(_6502s.nmiPin), ref _6502s.nmiPin);
+ //ser.SyncEnum(nameof(_6502s.intPin), ref _6502s.intPin);
+ //ser.SyncEnum(nameof(_6502s.nmiPin), ref _6502s.nmiPin);
ser.Sync(nameof(_6502s.step), ref _6502s.step);
ser.Sync(nameof(_6502s.currentOpcode), ref _6502s.currentOpcode);
ser.Sync(nameof(_6502s.currentOpcodeAddr), ref _6502s.currentOpcodeAddr);
@@ -136,9 +158,26 @@ namespace BizHawk.Emulation.Cores.Components.vr6502
ser.Sync(nameof(_6502s.zpBase), ref _6502s.zpBase);
ser.Sync(nameof(_6502s.spBase), ref _6502s.spBase);
ser.Sync(nameof(_6502s.tmpAddr), ref _6502s.tmpAddr);
- // Opcodes????
- // MnemonicNames??
- // AddrModes??
+
+ VrEmu6502Interrupt nmiP = new VrEmu6502Interrupt();
+ VrEmu6502Interrupt intP = new VrEmu6502Interrupt();
+
+ if (ser.IsReader)
+ {
+ // loading state
+ ser.SyncEnum(nameof(nmiP), ref nmiP);
+ ser.SyncEnum(nameof(intP), ref intP);
+ WriteNMI(nmiP);
+ WriteInt(intP);
+ }
+ else
+ {
+ // saving state
+ nmiP = ReadNMI();
+ intP = ReadInt();
+ ser.SyncEnum(nameof(nmiP), ref nmiP);
+ ser.SyncEnum(nameof(intP), ref intP);
+ }
ser.Sync(nameof(TotalExecutedCycles), ref TotalExecutedCycles);
ser.EndSection();
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs
index 791da927e2..760414bcac 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/ASIC.cs
@@ -91,7 +91,50 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
private int _vramStartAddress;
///
- /// ASIC is clocked at the same rate as the CPU
+ /// Runs 'ticks' clock cycles of the ASIC
+ ///
+ public void Clock(int ticks)
+ {
+ int dmaCycles = 0;
+ int lcdCycles = 0;
+
+ // sequencer
+ for (int i = 0; i < ticks; i++)
+ {
+ _seqCounter++;
+
+ if (_seqCounter == 7)
+ {
+ _seqCounter = 0;
+ lcdCycles++;
+ }
+ else
+ {
+ dmaCycles++;
+ }
+ }
+
+ // DMA
+ CheckDMA();
+ if (_dmaInProgress)
+ {
+ DoDMA(dmaCycles);
+ }
+
+ // interrupts
+ CheckInterrupt(ticks);
+
+ // video
+
+
+ // audio
+ AudioClock();
+
+ _sv.FrameClock += ticks;
+ }
+
+ ///
+ /// Runs a single clock cycle of the ASIC
///
public void Clock()
{
@@ -104,14 +147,14 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
// 4: DMA byte transfer to VRAM (if DMA is active) / CPU RDY line false (if DMA is active)
// 5: DMA byte transfer to VRAM (if DMA is active) / CPU RDY line false (if DMA is active)
- CheckDMA();
+
// so DMA can transfer 5 bytes to VRAM every 6 clocks, the 6th clock being the 1/2 byte transfer to the LCD
switch (_seqCounter)
{
case 0:
// there is no DMA on this cycle so CPU can run freely
- _sv._cpu.RDY = true;
+ //_sv._cpu.RDY = true;
bool lineEnd = _byteCounter == CLOCK_WIDTH - 1;
bool fieldEnd = _lineCounter == LINE_HEIGHT - 1 && lineEnd && _field == 0;
@@ -213,14 +256,14 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
///
/// Interrupt management
///
- private void CheckInterrupt()
+ private void CheckInterrupt(int ticks = 0)
{
- _nmiTimer++;
+ _nmiTimer += ticks;
// The NMI occurs every 65536 clock cycles (61.04Hz) regardless of the rate that the LCD refreshes
- if (_nmiTimer == 0x10000 && _regs[R_SYSTEM_CONTROL].Bit(0))
+ if (_nmiTimer >= 0x10000 && _regs[R_SYSTEM_CONTROL].Bit(0))
{
- _nmiTimer = 0;
+ _nmiTimer %= 0x10000;
//_sv._cpu.NMI = true;
_sv._cpu.SetNMI();
}
@@ -235,31 +278,34 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
_intTimer = 0;
}
- if (_intTimerEnabled)
+ for (int i = 0; i < ticks; i++)
{
- if (_regs[R_IRQ_TIMER] == 0)
+ if (_intTimerEnabled)
{
- if (_regs[R_SYSTEM_CONTROL].Bit(1))
+ if (_regs[R_IRQ_TIMER] == 0)
{
- // raise IRQ
- // this handles IRQ after timer countdown AND instant IRQ when timer is set to 0
- _intFlag = true;
- _intTimerEnabled = false;
+ if (_regs[R_SYSTEM_CONTROL].Bit(1))
+ {
+ // raise IRQ
+ // this handles IRQ after timer countdown AND instant IRQ when timer is set to 0
+ _intFlag = true;
+ _intTimerEnabled = false;
- // set IRQ Timer expired bit
- _regs[R_IRQ_STATUS] = (byte) (_regs[R_IRQ_STATUS] | 2);
+ // set IRQ Timer expired bit
+ _regs[R_IRQ_STATUS] = (byte) (_regs[R_IRQ_STATUS] | 2);
+ }
}
- }
- else
- {
- // timer should be counting down clocked by the prescaler
- if (_intTimer++ == IntPrescaler)
+ else
{
- // prescaler clock
- _intTimer = 0;
+ // timer should be counting down clocked by the prescaler
+ if (_intTimer++ == IntPrescaler)
+ {
+ // prescaler clock
+ _intTimer = 0;
- // decrement timer
- _regs[R_IRQ_TIMER]--;
+ // decrement timer
+ _regs[R_IRQ_TIMER]--;
+ }
}
}
}
@@ -291,9 +337,9 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
///
/// Perform a DMA transfer
///
- private void DoDMA()
+ private void DoDMA(int dmaCycles = 1)
{
- if (_dmaInProgress)
+ for (int i = 0; i > dmaCycles; i++)
{
_dmaCounter++;
@@ -302,9 +348,10 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
// wraparound or length reached
_dmaCounter = 0;
_dmaInProgress = false;
+ break;
}
else
- {
+ {
ushort source = (ushort) (_regs[R_DMA_SOURCE_HIGH] << 8 | _regs[R_DMA_SOURCE_LOW]);
ushort dest = (ushort) (_regs[R_DMA_DEST_HIGH] << 8 | _regs[R_DMA_DEST_LOW]);
diff --git a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.IEmulator.cs b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.IEmulator.cs
index b68af17047..bc2c37f204 100644
--- a/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.IEmulator.cs
+++ b/src/BizHawk.Emulation.Cores/Consoles/Watara/SuperVision/SuperVision.IEmulator.cs
@@ -59,16 +59,16 @@ namespace BizHawk.Emulation.Cores.Consoles.SuperVision
PollInput();
- _asic.FrameStart = true;
+ //_asic.FrameStart = true;
while (_frameClock < _cpuClocksPerFrame)
{
- _asic.Clock();
+ int ticks = _cpu.ExecuteInstruction();
+ _asic.Clock(ticks);
//_cpu.ExecuteOne();
- _cpu.ExecuteTick();
}
- _frameClock = 0;
+ _frameClock %= (int)_cpuClocksPerFrame;
_frame++;
if (_isLag)