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:
beirich 2012-08-26 14:39:06 +00:00
parent 2f73408029
commit 8ad3e72ffa
7 changed files with 175 additions and 20 deletions

View File

@ -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" />

View File

@ -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;

View File

@ -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); } }
}
}

View File

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

View File

@ -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

View File

@ -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.