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)