Allow easy swapping of active 68000 core the C# core, or Musashi... As we are likely to be swapping between versions rapidly for some period of time.
This commit is contained in:
parent
2f73408029
commit
8ad3e72ffa
|
@ -290,6 +290,7 @@
|
|||
<Compile Include="CPUs\MOS 6502\Disassembler.cs" />
|
||||
<Compile Include="CPUs\MOS 6502\Execute.cs" />
|
||||
<Compile Include="CPUs\MOS 6502\MOS6502.cs" />
|
||||
<Compile Include="CPUs\Native68000\Musashi.cs" />
|
||||
<Compile Include="CPUs\x86\Disassembler.cs" />
|
||||
<Compile Include="CPUs\x86\Execute.cs" />
|
||||
<Compile Include="CPUs\x86\Timing.cs" />
|
||||
|
|
|
@ -96,6 +96,8 @@ namespace BizHawk.Emulation.CPUs.M68000
|
|||
public Action<int, short> WriteWord;
|
||||
public Action<int, int> WriteLong;
|
||||
|
||||
public Action<int> IrqCallback;
|
||||
|
||||
// Initialization
|
||||
|
||||
public MC68000()
|
||||
|
@ -141,6 +143,7 @@ namespace BizHawk.Emulation.CPUs.M68000
|
|||
PC = ReadLong((24 + Interrupt) * 4); // Jump to interrupt vector
|
||||
InterruptMaskLevel = Interrupt; // Set interrupt mask to level currently being entered
|
||||
Interrupt = 0; // "ack" interrupt. Note: this is wrong.
|
||||
IrqCallback(InterruptMaskLevel); // Invoke the "Interrupt accepted" callback handler
|
||||
}
|
||||
|
||||
int prevCycles = PendingCycles;
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Native68000
|
||||
{
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
delegate int VdpCallback(int i);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
delegate uint ReadCallback(uint a);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
delegate void WriteCallback(uint a, uint v);
|
||||
|
||||
public class Musashi
|
||||
{
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void RegisterVdpCallback(IntPtr callback);
|
||||
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void RegisterRead8(IntPtr callback);
|
||||
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void RegisterRead16(IntPtr callback);
|
||||
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void RegisterRead32(IntPtr callback);
|
||||
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void RegisterWrite8(IntPtr callback);
|
||||
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void RegisterWrite16(IntPtr callback);
|
||||
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void RegisterWrite32(IntPtr callback);
|
||||
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void Init();
|
||||
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void Reset();
|
||||
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void SetIRQ(int level);
|
||||
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int Execute(int cycles);
|
||||
|
||||
[DllImport("MusashiDLL.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern int QueryCpuState(int regcode);
|
||||
|
||||
public static int D0 { get { return QueryCpuState(0); } }
|
||||
public static int D1 { get { return QueryCpuState(1); } }
|
||||
public static int D2 { get { return QueryCpuState(2); } }
|
||||
public static int D3 { get { return QueryCpuState(3); } }
|
||||
public static int D4 { get { return QueryCpuState(4); } }
|
||||
public static int D5 { get { return QueryCpuState(5); } }
|
||||
public static int D6 { get { return QueryCpuState(6); } }
|
||||
public static int D7 { get { return QueryCpuState(7); } }
|
||||
|
||||
public static int A0 { get { return QueryCpuState(8); } }
|
||||
public static int A1 { get { return QueryCpuState(9); } }
|
||||
public static int A2 { get { return QueryCpuState(10); } }
|
||||
public static int A3 { get { return QueryCpuState(11); } }
|
||||
public static int A4 { get { return QueryCpuState(12); } }
|
||||
public static int A5 { get { return QueryCpuState(13); } }
|
||||
public static int A6 { get { return QueryCpuState(14); } }
|
||||
public static int A7 { get { return QueryCpuState(15); } }
|
||||
|
||||
public static int PC { get { return QueryCpuState(16); } }
|
||||
public static int SR { get { return QueryCpuState(17); } }
|
||||
public static int SP { get { return QueryCpuState(18); } }
|
||||
}
|
||||
}
|
|
@ -14,6 +14,8 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
|
||||
byte[] PriorityBuffer = new byte[320];
|
||||
|
||||
static readonly byte[] PalXlatTable = { 0, 0, 36, 36, 73, 73, 109, 109, 145, 145, 182, 182, 219, 219, 255, 255 };
|
||||
|
||||
// TODO, should provide startup register values.
|
||||
public void RenderLine()
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
bool ControlWordPending;
|
||||
ushort VdpDataAddr;
|
||||
byte VdpDataCode;
|
||||
|
||||
|
||||
const int CommandVramRead = 0;
|
||||
const int CommandVramWrite = 1;
|
||||
const int CommandCramWrite = 3;
|
||||
|
@ -45,8 +45,14 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
const int CommandVsramWrite = 5;
|
||||
const int CommandCramRead = 7;
|
||||
|
||||
static readonly byte[] PalXlatTable = { 0, 0, 36, 36, 73, 73, 109, 109, 145, 145, 182, 182, 219, 219, 255, 255 };
|
||||
|
||||
public ushort VdpStatusWord = 0x3400;
|
||||
public const int StatusVerticalInterruptPending = 0x80;
|
||||
public const int StatusSpriteOverflow = 0x40;
|
||||
public const int StatusSpriteCollision = 0x20;
|
||||
public const int StatusOddFrame = 0x10;
|
||||
public const int StatusVerticalBlanking = 0x08;
|
||||
public const int StatusHorizBlanking = 0x04;
|
||||
|
||||
public ushort ReadVdp(int addr)
|
||||
{
|
||||
switch (addr)
|
||||
|
@ -58,7 +64,8 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
case 6:
|
||||
return ReadVdpControl();
|
||||
default:
|
||||
throw new Exception("HV Counter read....");
|
||||
//throw new Exception("HV Counter read....");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,10 +142,8 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
|
||||
public ushort ReadVdpControl()
|
||||
{
|
||||
ushort value = 0x3400; // fixed bits per genvdp.txt TODO test on everdrive, I guess.
|
||||
value |= 0x0200; // Fifo empty
|
||||
//Log.Note("VDP", "VDP: Control Read {0:X4}", value);
|
||||
return value;
|
||||
VdpStatusWord |= 0x0200; // Fifo empty
|
||||
return VdpStatusWord;
|
||||
}
|
||||
|
||||
public void WriteVdpData(ushort data)
|
||||
|
@ -210,7 +215,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
{
|
||||
case 0x00: // Mode Set Register 1
|
||||
Registers[register] = data;
|
||||
//Log.Note("VDP", "HINT enabled: " + HInterruptsEnabled);
|
||||
Log.Error("VDP", "HINT enabled: " + HInterruptsEnabled);
|
||||
break;
|
||||
|
||||
case 0x01: // Mode Set Register 2
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
using System;
|
||||
#define MUSASHI
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BizHawk.Emulation.CPUs.M68000;
|
||||
using BizHawk.Emulation.CPUs.Z80;
|
||||
using BizHawk.Emulation.Sound;
|
||||
using Native68000;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Emulation.Consoles.Sega
|
||||
{
|
||||
|
@ -58,6 +62,16 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
// 320 are active display, the remaining 160 are horizontal blanking.
|
||||
// A total of 3420 mclks per line, but 2560 mclks are active display and 860 mclks are blanking.
|
||||
|
||||
#if MUSASHI
|
||||
VdpCallback _vdp;
|
||||
ReadCallback read8;
|
||||
ReadCallback read16;
|
||||
ReadCallback read32;
|
||||
WriteCallback write8;
|
||||
WriteCallback write16;
|
||||
WriteCallback write32;
|
||||
#endif
|
||||
|
||||
public Genesis(GameInfo game, byte[] rom)
|
||||
{
|
||||
CoreOutputComm = new CoreOutputComm();
|
||||
|
@ -75,6 +89,27 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
MainCPU.WriteByte = WriteByte;
|
||||
MainCPU.WriteWord = WriteWord;
|
||||
MainCPU.WriteLong = WriteLong;
|
||||
MainCPU.IrqCallback = InterruptCallback;
|
||||
|
||||
// ---------------------- musashi -----------------------
|
||||
#if MUSASHI
|
||||
_vdp = vdpcallback;
|
||||
read8 = Read8;
|
||||
read16 = Read16;
|
||||
read32 = Read32;
|
||||
write8 = Write8;
|
||||
write16 = Write16;
|
||||
write32 = Write32;
|
||||
|
||||
Musashi.RegisterVdpCallback(Marshal.GetFunctionPointerForDelegate(_vdp));
|
||||
Musashi.RegisterRead8(Marshal.GetFunctionPointerForDelegate(read8));
|
||||
Musashi.RegisterRead16(Marshal.GetFunctionPointerForDelegate(read16));
|
||||
Musashi.RegisterRead32(Marshal.GetFunctionPointerForDelegate(read32));
|
||||
Musashi.RegisterWrite8(Marshal.GetFunctionPointerForDelegate(write8));
|
||||
Musashi.RegisterWrite16(Marshal.GetFunctionPointerForDelegate(write16));
|
||||
Musashi.RegisterWrite32(Marshal.GetFunctionPointerForDelegate(write32));
|
||||
#endif
|
||||
// ---------------------- musashi -----------------------
|
||||
|
||||
SoundCPU.ReadMemory = ReadMemoryZ80;
|
||||
SoundCPU.WriteMemory = WriteMemoryZ80;
|
||||
|
@ -87,14 +122,19 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
RomData[i] = rom[i];
|
||||
|
||||
SetupMemoryDomains();
|
||||
MainCPU.Reset();
|
||||
}
|
||||
#if MUSASHI
|
||||
Musashi.Init();
|
||||
Musashi.Reset();
|
||||
#else
|
||||
MainCPU.Reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void FrameAdvance(bool render)
|
||||
{
|
||||
lagged = true;
|
||||
|
||||
Frame++;
|
||||
Controller.UpdateControls(Frame++);
|
||||
PSG.BeginFrame(SoundCPU.TotalExecutedCycles);
|
||||
YM2612.BeginFrame(SoundCPU.TotalExecutedCycles);
|
||||
for (VDP.ScanLine = 0; VDP.ScanLine < 262; VDP.ScanLine++)
|
||||
|
@ -104,22 +144,23 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
if (VDP.ScanLine < 224)
|
||||
VDP.RenderLine();
|
||||
|
||||
MainCPU.ExecuteCycles(487); // 488??
|
||||
Exec68k(487);
|
||||
if (Z80Runnable)
|
||||
{
|
||||
//Console.WriteLine("running z80");
|
||||
SoundCPU.ExecuteCycles(228);
|
||||
SoundCPU.Interrupt = false;
|
||||
} else {
|
||||
SoundCPU.TotalExecutedCycles += 228; // I emulate the YM2612 synced to Z80 clock, for better or worse. Keep the timer going even if Z80 isn't running.
|
||||
}
|
||||
|
||||
if (VDP.ScanLine == 224)
|
||||
if (VDP.ScanLine == 224)
|
||||
{
|
||||
MainCPU.ExecuteCycles(16);// stupid crap to sync with genesis plus for log testing
|
||||
VDP.VdpStatusWord |= GenVDP.StatusVerticalInterruptPending;
|
||||
VDP.VdpStatusWord |= GenVDP.StatusVerticalBlanking;
|
||||
Exec68k(16); // this is stupidly wrong.
|
||||
// End-frame stuff
|
||||
if (VDP.VInterruptEnabled)
|
||||
MainCPU.Interrupt = 6;
|
||||
if (VDP.VInterruptEnabled)
|
||||
Set68kIrq(6);
|
||||
|
||||
if (Z80Runnable)
|
||||
SoundCPU.Interrupt = true;
|
||||
|
@ -128,7 +169,8 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
PSG.EndFrame(SoundCPU.TotalExecutedCycles);
|
||||
YM2612.EndFrame(SoundCPU.TotalExecutedCycles);
|
||||
|
||||
Controller.UpdateControls(Frame++);
|
||||
unchecked { VDP.VdpStatusWord &= (ushort)~GenVDP.StatusVerticalBlanking; }
|
||||
|
||||
if (lagged)
|
||||
{
|
||||
_lagcount++;
|
||||
|
@ -138,6 +180,35 @@ namespace BizHawk.Emulation.Consoles.Sega
|
|||
islag = false;
|
||||
}
|
||||
|
||||
void Exec68k(int cycles)
|
||||
{
|
||||
#if MUSASHI
|
||||
Musashi.Execute(cycles);
|
||||
#else
|
||||
MainCPU.ExecuteCycles(cycles);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Set68kIrq(int irq)
|
||||
{
|
||||
#if MUSASHI
|
||||
Musashi.SetIRQ(irq);
|
||||
#else
|
||||
MainCPU.Interrupt = irq;
|
||||
#endif
|
||||
}
|
||||
|
||||
int vdpcallback(int level) // Musashi handler
|
||||
{
|
||||
InterruptCallback(level);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void InterruptCallback(int level)
|
||||
{
|
||||
unchecked { VDP.VdpStatusWord &= (ushort)~GenVDP.StatusVerticalInterruptPending; }
|
||||
}
|
||||
|
||||
public CoreInputComm CoreInputComm { get; set; }
|
||||
public CoreOutputComm CoreOutputComm { get; private set; }
|
||||
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue