clean things up and make gpgx fully (?) multi-instance correct

This commit is contained in:
nattthebear 2017-05-28 13:46:08 -04:00
parent 7d0330bb9e
commit 7f2e06b0b5
9 changed files with 226 additions and 147 deletions

View File

@ -7,9 +7,10 @@ using System.Linq;
using System.Text; using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using BizHawk.Client.Common; using BizHawk.Client.Common;
using BizHawk.Emulation.Cores.Consoles.Sega.gpgx;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Consoles.Sega.gpgx64;
using BizHawk.Common;
namespace BizHawk.Client.EmuHawk namespace BizHawk.Client.EmuHawk
{ {
@ -18,7 +19,8 @@ namespace BizHawk.Client.EmuHawk
[RequiredService] [RequiredService]
private GPGX Emu { get; set; } private GPGX Emu { get; set; }
private LibGPGX.VDPView View = new LibGPGX.VDPView(); private GPGX.VDPView View;
int palindex = 0; int palindex = 0;
protected override System.Drawing.Point ScrollToControl(System.Windows.Forms.Control activeControl) protected override System.Drawing.Point ScrollToControl(System.Windows.Forms.Control activeControl)
@ -81,7 +83,7 @@ namespace BizHawk.Client.EmuHawk
bv.Refresh(); bv.Refresh();
} }
unsafe void DrawPalettes(int *pal) unsafe void DrawPalettes(int* pal)
{ {
var lockdata = bmpViewPal.bmp.LockBits(new Rectangle(0, 0, 16, 4), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); var lockdata = bmpViewPal.bmp.LockBits(new Rectangle(0, 0, 16, 4), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
int pitch = lockdata.Stride / sizeof(int); int pitch = lockdata.Stride / sizeof(int);
@ -121,23 +123,24 @@ namespace BizHawk.Client.EmuHawk
public void NewUpdate(ToolFormUpdateType type) { } public void NewUpdate(ToolFormUpdateType type) { }
public void UpdateValues() public unsafe void UpdateValues()
{ {
if (Emu == null) if (Emu == null)
return; return;
Emu.UpdateVDPViewContext(View);
unsafe using ((View = Emu.UpdateVDPViewContext()).EnterExit())
{ {
int* pal = (int*)View.ColorCache; int* pal = (int*)View.ColorCache;
//for (int i = 0; i < 0x40; i++) //for (int i = 0; i < 0x40; i++)
// pal[i] |= unchecked((int)0xff000000); // pal[i] |= unchecked((int)0xff000000);
DrawPalettes(pal); DrawPalettes(pal);
DrawTiles(); DrawTiles();
ushort *VRAMNT = (ushort*)View.VRAM; ushort* VRAMNT = (ushort*)View.VRAM;
byte *tiles = (byte*)View.PatternCache; byte* tiles = (byte*)View.PatternCache;
DrawNameTable(View.NTA, VRAMNT, tiles, pal, bmpViewNTA); DrawNameTable(View.NTA, VRAMNT, tiles, pal, bmpViewNTA);
DrawNameTable(View.NTB, VRAMNT, tiles, pal, bmpViewNTB); DrawNameTable(View.NTB, VRAMNT, tiles, pal, bmpViewNTB);
DrawNameTable(View.NTW, VRAMNT, tiles, pal, bmpViewNTW); DrawNameTable(View.NTW, VRAMNT, tiles, pal, bmpViewNTW);
View = null;
} }
} }

View File

@ -10,7 +10,8 @@ namespace BizHawk.Emulation.Common
public Func<long, byte> Peek public Func<long, byte> Peek
{ {
get { return _peek; } set { _peek = value; } get { return _peek; }
set { _peek = value; }
} }
public Action<long, byte> Poke public Action<long, byte> Poke
@ -228,4 +229,53 @@ namespace BizHawk.Emulation.Common
WordSize = 2; WordSize = 2;
} }
} }
public unsafe class MemoryDomainIntPtrSwap16Monitor : MemoryDomain
{
public IntPtr Data { get; set; }
private readonly IMonitor _monitor;
public override byte PeekByte(long addr)
{
if ((ulong)addr < (ulong)Size)
{
using (_monitor.EnterExit())
{
return ((byte*)Data)[addr ^ 1];
}
}
throw new ArgumentOutOfRangeException(nameof(addr));
}
public override void PokeByte(long addr, byte val)
{
if (Writable)
{
if ((ulong)addr < (ulong)Size)
{
using (_monitor.EnterExit())
{
((byte*)Data)[addr ^ 1] = val;
}
}
else
{
throw new ArgumentOutOfRangeException(nameof(addr));
}
}
}
public MemoryDomainIntPtrSwap16Monitor(string name, Endian endian, IntPtr data, long size, bool writable,
IMonitor monitor)
{
Name = name;
EndianType = endian;
Data = data;
Size = size;
Writable = writable;
WordSize = 2;
_monitor = monitor;
}
}
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64 namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
{ {
@ -11,6 +12,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
private IMemoryDomains MemoryDomains; private IMemoryDomains MemoryDomains;
private unsafe void SetMemoryDomains() private unsafe void SetMemoryDomains()
{
using (_elf.EnterExit())
{ {
var mm = new List<MemoryDomain>(); var mm = new List<MemoryDomain>();
for (int i = LibGPGX.MIN_MEM_DOMAIN; i <= LibGPGX.MAX_MEM_DOMAIN; i++) for (int i = LibGPGX.MIN_MEM_DOMAIN; i <= LibGPGX.MAX_MEM_DOMAIN; i++)
@ -26,13 +29,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
// vram pokes need to go through hook which invalidates cached tiles // vram pokes need to go through hook which invalidates cached tiles
byte* p = (byte*)area; byte* p = (byte*)area;
mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Unknown, mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Unknown,
delegate(long addr) delegate (long addr)
{ {
if (addr < 0 || addr >= 65536) if (addr < 0 || addr >= 65536)
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
using (_elf.EnterExit())
return p[addr ^ 1]; return p[addr ^ 1];
}, },
delegate(long addr, byte val) delegate (long addr, byte val)
{ {
if (addr < 0 || addr >= 65536) if (addr < 0 || addr >= 65536)
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
@ -40,11 +44,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
}, },
wordSize: 2)); wordSize: 2));
} }
else else
{ {
// TODO: are the Z80 domains really Swap16 in the core? Check this // TODO: are the Z80 domains really Swap16 in the core? Check this
mm.Add(new MemoryDomainIntPtrSwap16(name, MemoryDomain.Endian.Big, area, size, name != "MD CART" && name != "CD BOOT ROM")); mm.Add(new MemoryDomainIntPtrSwap16Monitor(name, MemoryDomain.Endian.Big, area, size, name != "MD CART" && name != "CD BOOT ROM", _elf));
} }
} }
var m68Bus = new MemoryDomainDelegate("M68K BUS", 0x1000000, MemoryDomain.Endian.Big, var m68Bus = new MemoryDomainDelegate("M68K BUS", 0x1000000, MemoryDomain.Endian.Big,
@ -65,6 +68,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
mm.Add(m68Bus); mm.Add(m68Bus);
if (IsMegaCD)
{
var s68Bus = new MemoryDomainDelegate("S68K BUS", 0x1000000, MemoryDomain.Endian.Big, var s68Bus = new MemoryDomainDelegate("S68K BUS", 0x1000000, MemoryDomain.Endian.Big,
delegate (long addr) delegate (long addr)
{ {
@ -81,8 +86,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
Core.gpgx_write_s68k_bus(a, val); Core.gpgx_write_s68k_bus(a, val);
}, 2); }, 2);
if (IsMegaCD)
{
mm.Add(s68Bus); mm.Add(s68Bus);
} }
@ -92,4 +96,5 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(MemoryDomains); (ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(MemoryDomains);
} }
} }
}
} }

View File

@ -4,6 +4,7 @@ using System.IO;
using BizHawk.Common.BufferExtensions; using BizHawk.Common.BufferExtensions;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64 namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
{ {
@ -17,6 +18,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
return new byte[0]; return new byte[0];
byte[] ret = new byte[size]; byte[] ret = new byte[size];
using (_elf.EnterExit())
Marshal.Copy(area, ret, 0, size); Marshal.Copy(area, ret, 0, size);
return ret; return ret;
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64 namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
{ {
@ -50,6 +51,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
Core.gpgx_get_audio(ref nsamp, ref src); Core.gpgx_get_audio(ref nsamp, ref src);
if (src != IntPtr.Zero) if (src != IntPtr.Zero)
{ {
using (_elf.EnterExit())
Marshal.Copy(src, samples, 0, nsamp * 2); Marshal.Copy(src, samples, 0, nsamp * 2);
} }
} }

View File

@ -62,9 +62,5 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
ms.Close(); ms.Close();
return ms.ToArray(); return ms.ToArray();
} }
private void InitStateBuffers()
{
}
} }
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64 namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
{ {
@ -47,6 +48,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
return; return;
} }
using (_elf.EnterExit())
{
int gppitch, gpwidth, gpheight; int gppitch, gpwidth, gpheight;
IntPtr src = IntPtr.Zero; IntPtr src = IntPtr.Zero;
@ -75,13 +78,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
for (int i = 0; i < xpad; i++) for (int i = 0; i < xpad; i++)
*pdst++ = unchecked((int)0xff000000); *pdst++ = unchecked((int)0xff000000);
for (int i = 0; i < gpwidth; i++) for (int i = 0; i < gpwidth; i++)
*pdst++ = *psrc++;; *pdst++ = *psrc++; ;
for (int i = 0; i < xpad2; i++) for (int i = 0; i < xpad2; i++)
*pdst++ = unchecked((int)0xff000000); *pdst++ = unchecked((int)0xff000000);
psrc += rinc; psrc += rinc;
} }
} }
} }
}
} }
} }

View File

@ -5,6 +5,7 @@ using System.Runtime.InteropServices;
using BizHawk.Common.BizInvoke; using BizHawk.Common.BizInvoke;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Waterbox; using BizHawk.Emulation.Cores.Waterbox;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64 namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
{ {
@ -40,8 +41,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?"); throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?");
} }
try
{
_elf = new PeRunner(new PeRunnerOptions _elf = new PeRunner(new PeRunnerOptions
{ {
Path = comm.CoreFileProvider.DllPath(), Path = comm.CoreFileProvider.DllPath(),
@ -52,11 +51,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
SpecialHeapSizeKB = 64 SpecialHeapSizeKB = 64
}); });
if (_elf.ShouldMonitor)
Core = BizInvoker.GetInvoker<LibGPGX>(_elf, _elf); Core = BizInvoker.GetInvoker<LibGPGX>(_elf, _elf);
else using (_elf.EnterExit())
Core = BizInvoker.GetInvoker<LibGPGX>(_elf); {
_syncSettings = (GPGXSyncSettings)syncSettings ?? new GPGXSyncSettings(); _syncSettings = (GPGXSyncSettings)syncSettings ?? new GPGXSyncSettings();
_settings = (GPGXSettings)settings ?? new GPGXSettings(); _settings = (GPGXSettings)settings ?? new GPGXSettings();
@ -110,7 +107,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
break; break;
} }
if (!Core.gpgx_init(romextension, LoadCallback, _syncSettings.UseSixButton, system_a, system_b, _syncSettings.Region, _settings.GetNativeSettings())) if (!Core.gpgx_init(romextension, LoadCallback, _syncSettings.UseSixButton, system_a, system_b, _syncSettings.Region, _settings.GetNativeSettings()))
throw new Exception("gpgx_init() failed"); throw new Exception("gpgx_init() failed");
@ -131,10 +127,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
_elf.Seal(); _elf.Seal();
Core.gpgx_set_cdd_callback(cd_callback_handle); Core.gpgx_set_cdd_callback(cd_callback_handle);
// compute state size
InitStateBuffers();
SetControllerDefinition(); SetControllerDefinition();
// pull the default video size from the core // pull the default video size from the core
@ -160,11 +152,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
Tracer = new GPGXTraceBuffer(this, MemoryDomains, this); Tracer = new GPGXTraceBuffer(this, MemoryDomains, this);
(ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer); (ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer);
} }
catch
{
Dispose();
throw;
}
} }
private LibGPGX Core; private LibGPGX Core;
@ -382,10 +369,46 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
public bool IsMegaCD { get { return CD != null; } } public bool IsMegaCD { get { return CD != null; } }
public void UpdateVDPViewContext(LibGPGX.VDPView view) public class VDPView : IMonitor
{ {
Core.gpgx_get_vdp_view(view); private readonly IMonitor _m;
public VDPView(LibGPGX.VDPView v, IMonitor m)
{
_m = m;
VRAM = v.VRAM;
PatternCache = v.PatternCache;
ColorCache = v.ColorCache;
NTA = v.NTA;
NTB = v.NTB;
NTW = v.NTW;
}
public IntPtr VRAM;
public IntPtr PatternCache;
public IntPtr ColorCache;
public LibGPGX.VDPNameTable NTA;
public LibGPGX.VDPNameTable NTB;
public LibGPGX.VDPNameTable NTW;
public void Enter()
{
_m.Enter();
}
public void Exit()
{
_m.Exit();
}
}
public VDPView UpdateVDPViewContext()
{
var v = new LibGPGX.VDPView();
Core.gpgx_get_vdp_view(v);
Core.gpgx_flush_vram(); // fully regenerate internal caches as needed Core.gpgx_flush_vram(); // fully regenerate internal caches as needed
return new VDPView(v, _elf);
} }
public DisplayType Region { get; private set; } public DisplayType Region { get; private set; }

View File

@ -15,9 +15,9 @@ namespace BizHawk.Emulation.Cores.Waterbox
public abstract class Swappable : IMonitor, IDisposable public abstract class Swappable : IMonitor, IDisposable
{ {
/// <summary> /// <summary>
/// start address, or 0 if we don't need to be swapped /// start address
/// </summary> /// </summary>
private ulong _lockkey = 0; private ulong _lockkey;
/// <summary> /// <summary>
/// the the relevant lockinfo for this core /// the the relevant lockinfo for this core
@ -42,16 +42,10 @@ namespace BizHawk.Emulation.Cores.Waterbox
protected void Initialize(ulong lockkey) protected void Initialize(ulong lockkey)
{ {
_lockkey = lockkey; _lockkey = lockkey;
if (lockkey != 0) if (lockkey == 0)
{ throw new NullReferenceException();
_currentLockInfo = LockInfos.GetOrAdd(_lockkey, new LockInfo { Sync = new object() }); _currentLockInfo = LockInfos.GetOrAdd(_lockkey, new LockInfo { Sync = new object() });
} }
}
/// <summary>
/// true if the IMonitor should be used for native calls
/// </summary>
public bool ShouldMonitor { get { return _lockkey != 0; } }
// any Swappable is assumed to conflict with any other Swappable at the same base address, // any Swappable is assumed to conflict with any other Swappable at the same base address,
// but not any other starting address. so don't put them too close together! // but not any other starting address. so don't put them too close together!