remove the 32bit gpgx, and refactor things to only use the 64 bit version. keep 64bit stuff in a gpgx64 folder to avoid git auto-rename detection shenanigans

This commit is contained in:
adelikat 2017-07-09 09:21:03 -05:00
parent 7156d9c7c8
commit 9a5ae16c7d
39 changed files with 25 additions and 2399 deletions

View File

@ -21,7 +21,7 @@ using BizHawk.Emulation.Cores.Sony.PSP;
using BizHawk.Emulation.Cores.Sony.PSX;
using BizHawk.Emulation.DiscSystem;
using GPGX64 = BizHawk.Emulation.Cores.Consoles.Sega.gpgx64;
using GPGX64 = BizHawk.Emulation.Cores.Consoles.Sega.gpgx;
using BizHawk.Emulation.Cores.Consoles.Sega.Saturn;
namespace BizHawk.Client.Common
@ -504,17 +504,8 @@ namespace BizHawk.Client.Common
switch (game.System)
{
case "GEN":
if (Environment.Is64BitProcess)
{
var genesis = new GPGX64.GPGX(nextComm, null, disc, GetCoreSettings<GPGX64.GPGX>(), GetCoreSyncSettings<GPGX64.GPGX>());
nextEmulator = genesis;
}
else
{
var genesis = new GPGX(nextComm, null, disc, GetCoreSettings<GPGX>(), GetCoreSyncSettings<GPGX>());
nextEmulator = genesis;
}
var genesis = new GPGX(nextComm, null, disc, GetCoreSettings<GPGX>(), GetCoreSyncSettings<GPGX>());
nextEmulator = genesis;
break;
case "SAT":
//nextEmulator = new Yabause(nextComm, disc, GetCoreSyncSettings<Yabause>());
@ -911,17 +902,7 @@ namespace BizHawk.Client.Common
nextEmulator.CoreComm.RomStatusDetails = "PSX etc.";
break;
case "GEN":
// discard "Genplus-gx64", auto-added due to implementing IEmulator // HUH?
// core = CoreInventory.Instance["GEN", "Genplus-gx"];
if (Environment.Is64BitProcess)
{
core = CoreInventory.Instance["GEN", "Genplus-gx64"];
}
else
{
core = CoreInventory.Instance["GEN", "Genplus-gx"];
}
core = CoreInventory.Instance["GEN", "Genplus-gx"];
break;
}

View File

@ -320,7 +320,7 @@ namespace BizHawk.Client.Common.MovieConversionExtensions
movie.HeaderEntries.Add("IsSGMode", "1");
}
if (Global.Emulator is GPGX && (Global.Emulator as GPGX).IsSegaCD)
if (Global.Emulator is GPGX && (Global.Emulator as GPGX).IsMegaCD)
{
movie.HeaderEntries.Add("IsSegaCDMode", "1");
}

View File

@ -9,7 +9,7 @@ using System.Windows.Forms;
using BizHawk.Client.Common;
using System.Drawing.Imaging;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Consoles.Sega.gpgx64;
using BizHawk.Emulation.Cores.Consoles.Sega.gpgx;
using BizHawk.Common;
namespace BizHawk.Client.EmuHawk

View File

@ -1036,49 +1036,6 @@
<Compile Include="Consoles\Sega\gpgx64\GPGX.ISoundProvider.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GenDbgHlp.cs" />
<Compile Include="Consoles\Sega\gpgx\GPGX.cs" />
<Compile Include="Consoles\Sega\gpgx\GPGX.ICodeDataLogger.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.IDebuggable.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.IDisassembler.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.IDriveLight.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.IEmulator.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.IInputPollable.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.IMemoryDomains.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.ISaveRam.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.ISettable.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.ISoundProvider.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.IStatable.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.ITraceable.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGX.IVideoProvider.cs">
<DependentUpon>GPGX.cs</DependentUpon>
</Compile>
<Compile Include="Consoles\Sega\gpgx\GPGXControlConverter.cs" />
<Compile Include="Consoles\Sega\gpgx\LibGPGX.cs" />
<Compile Include="Consoles\Sega\gpgx64\GenDbgHlp.cs" />
<Compile Include="Consoles\Sega\gpgx64\GPGX.cs" />
<Compile Include="Consoles\Sega\gpgx64\GPGX.ICodeDataLogger.cs">

View File

@ -70,7 +70,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive
_exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_EU", true), "cd.eu");
_exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_US", true), "cd.us");
_exe.AddReadonlyFile(comm.CoreFileProvider.GetFirmware("GEN", "CD_BIOS_JP", true), "cd.jp");
_exe.AddReadonlyFile(gpgx64.GPGX.GetCDData(cd), "toc");
_exe.AddReadonlyFile(gpgx.GPGX.GetCDData(cd), "toc");
_cd = cd;
_cdReader = new DiscSectorReader(_cd);
_cdcallback = CDRead;

View File

@ -1,53 +0,0 @@
using System;
using System.IO;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : ICodeDataLogger
{
public void SetCDL(ICodeDataLog cdl)
{
CDL = cdl;
if (cdl == null) LibGPGX.gpgx_set_cd_callback(null);
else LibGPGX.gpgx_set_cd_callback(CDCallback);
}
public void NewCDL(ICodeDataLog cdl)
{
cdl["MD CART"] = new byte[MemoryDomains["MD CART"].Size];
cdl["68K RAM"] = new byte[MemoryDomains["68K RAM"].Size];
cdl["Z80 RAM"] = new byte[MemoryDomains["Z80 RAM"].Size];
if (MemoryDomains.Has("SRAM"))
cdl["SRAM"] = new byte[MemoryDomains["SRAM"].Size];
cdl.SubType = "GEN";
cdl.SubVer = 0;
}
// TODO: we have Disassembling now
// not supported
public void DisassembleCDL(Stream s, ICodeDataLog cdl) { }
private ICodeDataLog CDL;
private void CDCallbackProc(int addr, LibGPGX.CDLog_AddrType addrtype, LibGPGX.CDLog_Flags flags)
{
//TODO - hard reset makes CDL go nuts.
if (CDL == null) return;
if (!CDL.Active) return;
string key;
switch (addrtype)
{
case LibGPGX.CDLog_AddrType.MDCART: key = "MD CART"; break;
case LibGPGX.CDLog_AddrType.RAM68k: key = "68K RAM"; break;
case LibGPGX.CDLog_AddrType.RAMZ80: key = "Z80 RAM"; break;
case LibGPGX.CDLog_AddrType.SRAM: key = "SRAM"; break;
default: throw new InvalidOperationException("Lagrangian earwax incident");
}
CDL[key][addr] |= (byte)flags;
}
}
}

View File

@ -1,83 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IDebuggable
{
public IDictionary<string, RegisterValue> GetCpuFlagsAndRegisters()
{
LibGPGX.RegisterInfo[] regs = new LibGPGX.RegisterInfo[LibGPGX.gpgx_getmaxnumregs()];
int n = LibGPGX.gpgx_getregs(regs);
if (n > regs.Length)
throw new InvalidOperationException("A buffer overrun has occured!");
var ret = new Dictionary<string, RegisterValue>();
for (int i = 0; i < n; i++)
{
// el hacko
string name = Marshal.PtrToStringAnsi(regs[i].Name);
byte size = 32;
if (name.Contains("68K SR") || name.StartsWith("Z80"))
size = 16;
ret[name] = new RegisterValue((ulong)regs[i].Value, size);
}
return ret;
}
[FeatureNotImplemented]
public void SetCpuRegister(string register, int value)
{
throw new NotImplementedException();
}
public IMemoryCallbackSystem MemoryCallbacks
{
get { return _memoryCallbacks; }
}
public bool CanStep(StepType type) { return false; }
[FeatureNotImplemented]
public void Step(StepType type) { throw new NotImplementedException(); }
[FeatureNotImplemented]
public int TotalExecutedCycles
{
get { throw new NotImplementedException(); }
}
private readonly MemoryCallbackSystem _memoryCallbacks = new MemoryCallbackSystem();
private LibGPGX.mem_cb ExecCallback;
private LibGPGX.mem_cb ReadCallback;
private LibGPGX.mem_cb WriteCallback;
private LibGPGX.CDCallback CDCallback;
private void InitMemCallbacks()
{
ExecCallback = new LibGPGX.mem_cb(a => MemoryCallbacks.CallExecutes(a));
ReadCallback = new LibGPGX.mem_cb(a => MemoryCallbacks.CallReads(a));
WriteCallback = new LibGPGX.mem_cb(a => MemoryCallbacks.CallWrites(a));
_memoryCallbacks.ActiveChanged += RefreshMemCallbacks;
}
private void RefreshMemCallbacks()
{
LibGPGX.gpgx_set_mem_callback(
MemoryCallbacks.HasReads ? ReadCallback : null,
MemoryCallbacks.HasWrites ? WriteCallback : null,
MemoryCallbacks.HasExecutes ? ExecCallback : null);
}
private void KillMemCallbacks()
{
LibGPGX.gpgx_set_mem_callback(null, null, null);
}
}
}

View File

@ -1,46 +0,0 @@
using System.Collections.Generic;
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Components.M68000;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IDisassemblable
{
public string Cpu
{
get
{
return "M68000";
}
set
{
}
}
public string PCRegisterName
{
get { return "M68K PC"; }
}
public IEnumerable<string> AvailableCpus
{
get { yield return "M68000"; }
}
public string Disassemble(MemoryDomain m, uint addr,out int length)
{
const uint mask = 0xFFFFFF;
_disassemblerInstance.ReadWord = (a) => (short)m.PeekUshort(a & mask, m.EndianType == MemoryDomain.Endian.Big);
_disassemblerInstance.ReadByte = (a) => (sbyte)m.PeekByte(a & mask);
_disassemblerInstance.ReadLong = (a) => (int)m.PeekUint(a & mask, m.EndianType == MemoryDomain.Endian.Big);
var info = _disassemblerInstance.Disassemble((int)addr);
length = info.Length;
return string.Format("{0:X4} {1,-7} {2}", info.RawBytes.Substring(0, 4), info.Mnemonic, info.Args);
}
// TODO: refactor MC6800's disassembler to be a static call
private MC68000 _disassemblerInstance = new MC68000();
}
}

View File

@ -1,12 +0,0 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IDriveLight
{
public bool DriveLightEnabled { get; private set; }
public bool DriveLightOn { get; private set; }
private bool _drivelight;
}
}

View File

@ -1,90 +0,0 @@
using System;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IEmulator
{
public IEmulatorServiceProvider ServiceProvider { get; private set; }
public ControllerDefinition ControllerDefinition { get; private set; }
// TODO: use render and rendersound
public void FrameAdvance(IController controller, bool render, bool rendersound = true)
{
if (controller.IsPressed("Reset"))
LibGPGX.gpgx_reset(false);
if (controller.IsPressed("Power"))
LibGPGX.gpgx_reset(true);
// do we really have to get each time? nothing has changed
if (!LibGPGX.gpgx_get_control(input, inputsize))
throw new Exception("gpgx_get_control() failed!");
ControlConverter.ScreenWidth = vwidth;
ControlConverter.ScreenHeight = vheight;
ControlConverter.Convert(controller, input);
if (!LibGPGX.gpgx_put_control(input, inputsize))
throw new Exception("gpgx_put_control() failed!");
IsLagFrame = true;
Frame++;
_drivelight = false;
if (Tracer.Enabled)
LibGPGX.gpgx_set_trace_callback(_tracecb);
else
LibGPGX.gpgx_set_trace_callback(null);
LibGPGX.gpgx_advance();
UpdateVideo();
update_audio();
if (IsLagFrame)
LagCount++;
if (CD != null)
DriveLightOn = _drivelight;
}
public int Frame { get; private set; }
public string SystemId
{
get { return "GEN"; }
}
public bool DeterministicEmulation
{
get { return true; }
}
public void ResetCounters()
{
Frame = 0;
IsLagFrame = false;
LagCount = 0;
}
public CoreComm CoreComm { get; private set; }
public void Dispose()
{
if (!disposed)
{
if (AttachedCore != this)
throw new Exception();
if (SaveRamModified)
_disposedSaveRam = CloneSaveRam();
KillMemCallbacks();
if (CD != null)
{
CD.Dispose();
}
AttachedCore = null;
disposed = true;
}
}
}
}

View File

@ -1,23 +0,0 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IInputPollable
{
public int LagCount { get; set; }
public bool IsLagFrame { get; set; }
public IInputCallbackSystem InputCallbacks { get { return _inputCallbacks; } }
private LibGPGX.input_cb InputCallback = null;
private readonly InputCallbackSystem _inputCallbacks = new InputCallbackSystem();
private void input_callback()
{
InputCallbacks.Call();
IsLagFrame = false;
}
}
}

View File

@ -1,101 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX
{
private IMemoryDomains MemoryDomains;
private unsafe void SetMemoryDomains()
{
var mm = new List<MemoryDomain>();
for (int i = LibGPGX.MIN_MEM_DOMAIN; i <= LibGPGX.MAX_MEM_DOMAIN; i++)
{
IntPtr area = IntPtr.Zero;
int size = 0;
IntPtr pname = LibGPGX.gpgx_get_memdom(i, ref area, ref size);
if (area == IntPtr.Zero || pname == IntPtr.Zero || size == 0)
continue;
string name = Marshal.PtrToStringAnsi(pname);
if (name == "VRAM")
{
// vram pokes need to go through hook which invalidates cached tiles
byte* p = (byte*)area;
mm.Add(new MemoryDomainDelegate(name, size, MemoryDomain.Endian.Unknown,
delegate (long addr)
{
if (addr < 0 || addr >= 65536)
throw new ArgumentOutOfRangeException();
return p[addr ^ 1];
},
delegate (long addr, byte val)
{
if (addr < 0 || addr >= 65536)
throw new ArgumentOutOfRangeException();
LibGPGX.gpgx_poke_vram(((int)addr) ^ 1, val);
},
wordSize: 2));
}
else
{
// TODO: are the Z80 domains really Swap16 in the core? Check this
//var byteSize = name.Contains("Z80") ? 1 : 2;
mm.Add(new MemoryDomainIntPtrSwap16(name, MemoryDomain.Endian.Big, area, size, name != "MD CART" && name != "CD BOOT ROM"));
}
}
//it's gross for this not to be the full 32bits.
//Uhh I mean, I guess the bus is physically smaller.. but the cpu's view of it is larger...
//So... I guess no matter what we do, some badness will propagate. This is probably least bad.
//Anyway, the disassembler, for instance, must have been masked down to size, since code can run from FFxxxxxxxx...
var m68Bus = new MemoryDomainDelegate("M68K BUS", 0x1000000, MemoryDomain.Endian.Big,
delegate (long addr)
{
var a = (uint)addr;
if (a >= 0x1000000)
throw new ArgumentOutOfRangeException();
return LibGPGX.gpgx_peek_m68k_bus(a);
},
delegate (long addr, byte val)
{
var a = (uint)addr;
if (a >= 0x1000000)
throw new ArgumentOutOfRangeException();
LibGPGX.gpgx_write_m68k_bus(a, val);
}, 2);
mm.Add(m68Bus);
var s68Bus = new MemoryDomainDelegate("S68K BUS", 0x1000000, MemoryDomain.Endian.Big,
delegate (long addr)
{
var a = (uint)addr;
if (a >= 0x1000000)
throw new ArgumentOutOfRangeException();
return LibGPGX.gpgx_peek_s68k_bus(a);
},
delegate (long addr, byte val)
{
var a = (uint)addr;
if (a >= 0x1000000)
throw new ArgumentOutOfRangeException();
LibGPGX.gpgx_write_s68k_bus(a, val);
}, 2);
if (IsSegaCD)
{
mm.Add(s68Bus);
}
MemoryDomains = new MemoryDomainList(mm);
MemoryDomains.SystemBus = m68Bus;
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(MemoryDomains);
}
}
}

View File

@ -1,79 +0,0 @@
using System;
using System.IO;
using BizHawk.Common.BufferExtensions;
using BizHawk.Emulation.Common;
using System.Runtime.InteropServices;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : ISaveRam
{
public byte[] CloneSaveRam()
{
if (disposed)
{
if (_disposedSaveRam != null)
{
return (byte[])_disposedSaveRam.Clone();
}
return new byte[0];
}
else
{
int size = 0;
IntPtr area = IntPtr.Zero;
LibGPGX.gpgx_get_sram(ref area, ref size);
if (size <= 0 || area == IntPtr.Zero)
return new byte[0];
LibGPGX.gpgx_sram_prepread();
byte[] ret = new byte[size];
Marshal.Copy(area, ret, 0, size);
return ret;
}
}
public void StoreSaveRam(byte[] data)
{
if (disposed)
{
throw new ObjectDisposedException(typeof(GPGX).ToString());
}
else
{
int size = 0;
IntPtr area = IntPtr.Zero;
LibGPGX.gpgx_get_sram(ref area, ref size);
if (size <= 0 || area == IntPtr.Zero)
return;
if (size != data.Length)
throw new Exception("Unexpected saveram size");
Marshal.Copy(data, 0, area, size);
LibGPGX.gpgx_sram_commitwrite();
}
}
public bool SaveRamModified
{
get
{
if (disposed)
{
return _disposedSaveRam != null;
}
else
{
int size = 0;
IntPtr area = IntPtr.Zero;
LibGPGX.gpgx_get_sram(ref area, ref size);
return size > 0 && area != IntPtr.Zero;
}
}
}
private byte[] _disposedSaveRam = null;
}
}

View File

@ -1,278 +0,0 @@
using System;
using System.ComponentModel;
using System.Globalization;
using BizHawk.Common;
using BizHawk.Emulation.Common;
using Newtonsoft.Json;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : ISettable<GPGX.GPGXSettings, GPGX.GPGXSyncSettings>
{
public GPGXSettings GetSettings()
{
return _settings.Clone();
}
public GPGXSyncSettings GetSyncSettings()
{
return _syncSettings.Clone();
}
public bool PutSettings(GPGXSettings o)
{
bool ret = GPGXSettings.NeedsReboot(_settings, o);
_settings = o;
LibGPGX.gpgx_set_draw_mask(_settings.GetDrawMask());
return ret;
}
public bool PutSyncSettings(GPGXSyncSettings o)
{
bool ret = GPGXSyncSettings.NeedsReboot(_syncSettings, o);
_syncSettings = o;
return ret;
}
private class UintToHexConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
else
{
return base.CanConvertFrom(context, sourceType);
}
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
{
return true;
}
else
{
return base.CanConvertTo(context, destinationType);
}
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string) && value.GetType() == typeof(uint))
{
return string.Format("0x{0:x8}", value);
}
else
{
return base.ConvertTo(context, culture, value, destinationType);
}
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value.GetType() == typeof(string))
{
string input = (string)value;
if (input.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
{
input = input.Substring(2);
}
return uint.Parse(input, NumberStyles.HexNumber, culture);
}
else
{
return base.ConvertFrom(context, culture, value);
}
}
}
private GPGXSyncSettings _syncSettings;
private GPGXSettings _settings;
public class GPGXSettings
{
[DeepEqualsIgnore]
[JsonIgnore]
private bool _DrawBGA;
[DisplayName("Background Layer A")]
[Description("True to draw BG layer A")]
[DefaultValue(true)]
public bool DrawBGA { get { return _DrawBGA; } set { _DrawBGA = value; } }
[DeepEqualsIgnore]
[JsonIgnore]
private bool _DrawBGB;
[DisplayName("Background Layer B")]
[Description("True to draw BG layer B")]
[DefaultValue(true)]
public bool DrawBGB { get { return _DrawBGB; } set { _DrawBGB = value; } }
[DeepEqualsIgnore]
[JsonIgnore]
private bool _DrawBGW;
[DisplayName("Background Layer W")]
[Description("True to draw BG layer W")]
[DefaultValue(true)]
public bool DrawBGW { get { return _DrawBGW; } set { _DrawBGW = value; } }
[DeepEqualsIgnore]
[JsonIgnore]
private bool _DrawObj;
[DisplayName("Sprite Layer")]
[Description("True to draw sprite layer")]
[DefaultValue(true)]
public bool DrawObj { get { return _DrawObj; } set { _DrawObj = value; } }
[DeepEqualsIgnore]
[JsonIgnore]
private bool _PadScreen320;
[DeepEqualsIgnore]
[JsonIgnore]
private bool _AlwaysDoubleSize;
[DisplayName("Pad screen to 320")]
[Description("Set to True to pad the screen out to be 320 when in 256 wide video modes")]
[DefaultValue(false)]
public bool PadScreen320 { get { return _PadScreen320; } set { _PadScreen320 = value; } }
[DisplayName("Always double-size")]
[Description("Set to True to convert the video to high-resolution mode even when it's low resolution so that the window doesn't change size between game modes")]
[DefaultValue(false)]
public bool AlwaysDoubleSize { get { return _AlwaysDoubleSize; } set { _AlwaysDoubleSize = value; } }
[DisplayName("Audio Filter")]
[DefaultValue(LibGPGX.InitSettings.FilterType.LowPass)]
public LibGPGX.InitSettings.FilterType Filter { get; set; }
[DisplayName("Low Pass Range")]
[Description("Only active when filter type is lowpass")]
[DefaultValue((ushort)39321)]
public ushort LowPassRange { get; set; }
[DisplayName("Three band low cutoff")]
[Description("Only active when filter type is three band")]
[DefaultValue((short)880)]
public short LowFreq { get; set; }
[DisplayName("Three band high cutoff")]
[Description("Only active when filter type is three band")]
[DefaultValue((short)5000)]
public short HighFreq { get; set; }
[DisplayName("Three band low gain")]
[Description("Only active when filter type is three band")]
[DefaultValue((short)1)]
public short LowGain { get; set; }
[DisplayName("Three band mid gain")]
[Description("Only active when filter type is three band")]
[DefaultValue((short)1)]
public short MidGain { get; set; }
[DisplayName("Three band high gain")]
[Description("Only active when filter type is three band")]
[DefaultValue((short)1)]
public short HighGain { get; set; }
[DeepEqualsIgnore]
[JsonIgnore]
private bool _Backdrop;
[DisplayName("Use custom backdrop color")]
[Description("Filler when layers are off")]
[DefaultValue((bool)false)]
public bool Backdrop { get { return _Backdrop; } set { _Backdrop = value; } }
[DisplayName("Custom backdrop color")]
[Description("Magic pink by default. Requires core reboot")]
[TypeConverter(typeof(UintToHexConverter))]
[DefaultValue((uint)0xffff00ff)]
public uint BackdropColor { get; set; }
public GPGXSettings()
{
SettingsUtil.SetDefaultValues(this);
}
public GPGXSettings Clone()
{
return (GPGXSettings)MemberwiseClone();
}
public LibGPGX.DrawMask GetDrawMask()
{
LibGPGX.DrawMask ret = 0;
if (DrawBGA) ret |= LibGPGX.DrawMask.BGA;
if (DrawBGB) ret |= LibGPGX.DrawMask.BGB;
if (DrawBGW) ret |= LibGPGX.DrawMask.BGW;
if (DrawObj) ret |= LibGPGX.DrawMask.Obj;
if (Backdrop) ret |= LibGPGX.DrawMask.Backdrop;
return ret;
}
public static bool NeedsReboot(GPGXSettings x, GPGXSettings y)
{
return !DeepEquality.DeepEquals(x, y);
}
public LibGPGX.InitSettings GetNativeSettings()
{
return new LibGPGX.InitSettings
{
Filter = Filter,
LowPassRange = LowPassRange,
LowFreq = LowFreq,
HighFreq = HighFreq,
LowGain = LowGain,
MidGain = MidGain,
HighGain = HighGain,
BackdropColor = BackdropColor
};
}
}
public class GPGXSyncSettings
{
[DisplayName("Use Six Button Controllers")]
[Description("Controls the type of any attached normal controllers; six button controllers are used if true, otherwise three button controllers. Some games don't work correctly with six button controllers. Not relevant if other controller types are connected.")]
[DefaultValue(true)]
public bool UseSixButton { get; set; }
[DisplayName("Control Type")]
[Description("Sets the type of controls that are plugged into the console. Some games will automatically load with a different control type.")]
[DefaultValue(ControlType.Normal)]
public ControlType ControlType { get; set; }
[DisplayName("Autodetect Region")]
[Description("Sets the region of the emulated console. Many games can run on multiple regions and will behave differently on different ones. Some games may require a particular region.")]
[DefaultValue(LibGPGX.Region.Autodetect)]
public LibGPGX.Region Region { get; set; }
public GPGXSyncSettings()
{
SettingsUtil.SetDefaultValues(this);
}
public GPGXSyncSettings Clone()
{
return (GPGXSyncSettings)MemberwiseClone();
}
public static bool NeedsReboot(GPGXSyncSettings x, GPGXSyncSettings y)
{
return !DeepEquality.DeepEquals(x, y);
}
}
}
}

View File

@ -1,57 +0,0 @@
using System;
using BizHawk.Emulation.Common;
using System.Runtime.InteropServices;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : ISoundProvider
{
private short[] samples = new short[4096];
private int nsamp = 0;
public bool CanProvideAsync
{
get { return false; }
}
public void GetSamplesSync(out short[] samples, out int nsamp)
{
nsamp = this.nsamp;
samples = this.samples;
this.nsamp = 0;
}
public void DiscardSamples()
{
this.nsamp = 0;
}
public void SetSyncMode(SyncSoundMode mode)
{
if (mode == SyncSoundMode.Async)
{
throw new NotSupportedException("Async mode is not supported.");
}
}
public SyncSoundMode SyncMode
{
get { return SyncSoundMode.Sync; }
}
public void GetSamplesAsync(short[] samples)
{
throw new InvalidOperationException("Async mode is not supported.");
}
private void update_audio()
{
IntPtr src = IntPtr.Zero;
LibGPGX.gpgx_get_audio(ref nsamp, ref src);
if (src != IntPtr.Zero)
{
Marshal.Copy(src, samples, 0, nsamp * 2);
}
}
}
}

View File

@ -1,79 +0,0 @@
using System;
using System.IO;
using BizHawk.Common.BufferExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IStatable
{
public bool BinarySaveStatesPreferred
{
get { return true; }
}
public void SaveStateText(TextWriter writer)
{
var temp = SaveStateBinary();
temp.SaveAsHexFast(writer);
// write extra copy of stuff we don't use
writer.WriteLine("Frame {0}", Frame);
}
public void LoadStateText(TextReader reader)
{
string hex = reader.ReadLine();
byte[] state = new byte[hex.Length / 2];
state.ReadFromHexFast(hex);
LoadStateBinary(new BinaryReader(new MemoryStream(state)));
}
public byte[] SaveStateBinary()
{
var ms = new MemoryStream(_savebuff2, true);
var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
ms.Close();
return _savebuff2;
}
public void LoadStateBinary(BinaryReader reader)
{
int newlen = reader.ReadInt32();
if (newlen != _savebuff.Length)
{
throw new Exception("Unexpected state size");
}
reader.Read(_savebuff, 0, _savebuff.Length);
if (!LibGPGX.gpgx_state_load(_savebuff, _savebuff.Length))
{
throw new Exception("gpgx_state_load() returned false");
}
// other variables
Frame = reader.ReadInt32();
LagCount = reader.ReadInt32();
IsLagFrame = reader.ReadBoolean();
UpdateVideo();
}
public void SaveStateBinary(BinaryWriter writer)
{
if (!LibGPGX.gpgx_state_save(_savebuff, _savebuff.Length))
throw new Exception("gpgx_state_save() returned false");
writer.Write(_savebuff.Length);
writer.Write(_savebuff);
// other variables
writer.Write(Frame);
writer.Write(LagCount);
writer.Write(IsLagFrame);
}
private byte[] _savebuff;
private byte[] _savebuff2;
}
}

View File

@ -1,68 +0,0 @@
using BizHawk.Emulation.Common;
using System;
using System.Collections.Generic;
using System.Text;
using BizHawk.Common.NumberExtensions;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX
{
public TraceBuffer Tracer { get; private set; }
private LibGPGX.trace_cb _tracecb;
private const string TraceHeader = "M68K: PC, machine code, mnemonic, operands, registers (D0-D7, A0-A7, SR, USP), flags (XNZVC)";
private void MakeTrace()
{
var regs = GetCpuFlagsAndRegisters();
uint pc = (uint)regs["M68K PC"].Value;
var length = 0;
var disasm = Disassemble(MemoryDomains.SystemBus, pc, out length).PadRight(40);
var traceInfo = new TraceInfo
{
Disassembly = string.Format("{0:X6}: {1}", pc, disasm)
};
var sb = new StringBuilder();
foreach (var r in regs)
{
if (r.Key.StartsWith("M68K")) // drop Z80 regs until it has its own debugger/tracer
{
if (r.Key != "M68K SP" && r.Key != "M68K ISP" && // copies of a7
r.Key != "M68K PC" && // already present in every line start
r.Key != "M68K IR") // copy of last opcode, already shown in raw bytes
{
sb.Append(
string.Format("{0}:{1} ",
r.Key.Replace("M68K", "").Trim(),
r.Value.Value.ToHexString(r.Value.BitSize / 4)));
}
}
}
var sr = regs["M68K SR"].Value;
sb.Append(
string.Format("{0}{1}{2}{3}{4}",
(sr & 16) > 0 ? "X" : "x",
(sr & 8) > 0 ? "N" : "n",
(sr & 4) > 0 ? "Z" : "z",
(sr & 2) > 0 ? "V" : "v",
(sr & 1) > 0 ? "C" : "c"));
traceInfo.RegisterInfo = sb.ToString().Trim();
Tracer.Put(traceInfo);
}
private void ConnectTracer()
{
Tracer = new TraceBuffer { Header = TraceHeader };
(ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer);
_tracecb = new LibGPGX.trace_cb(MakeTrace);
}
}
}

View File

@ -1,123 +0,0 @@
using System;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IVideoProvider
{
public int[] GetVideoBuffer() { return vidbuff; }
public int VirtualWidth { get { return 320; } }
public int VirtualHeight { get { return 224; } }
public int BufferWidth { get { return vwidth; } }
public int BufferHeight { get { return vheight; } }
public int BackgroundColor { get { return unchecked((int)0xff000000); } }
public int VsyncNumerator { get; }
public int VsyncDenominator { get; }
private int[] vidbuff = new int[0];
private int vwidth;
private int vheight;
private void UpdateVideoInitial()
{
// hack: you should call update_video() here, but that gives you 256x192 on frame 0
// and we know that we only use GPGX to emulate genesis games that will always be 320x224 immediately afterwards
// so instead, just assume a 320x224 size now; if that happens to be wrong, it'll be fixed soon enough.
vwidth = 320;
vheight = 224;
vidbuff = new int[vwidth * vheight];
for (int i = 0; i < vidbuff.Length; i++)
vidbuff[i] = unchecked((int)0xff000000);
}
private unsafe void UpdateVideo()
{
int gppitch, gpwidth, gpheight;
IntPtr src = IntPtr.Zero;
LibGPGX.gpgx_get_video(out gpwidth, out gpheight, out gppitch, ref src);
//in case we're receiving high vertical resolution video, we shall double the horizontal resolution to keep the same proportions
//(concept pioneered for snes)
bool dotDouble = (gpheight == 448); //todo: pal?
bool lineDouble = false;
vwidth = gpwidth;
vheight = gpheight;
if (_settings.AlwaysDoubleSize)
{
dotDouble = true;
if (gpheight == 224 || gpheight == 240)
{
lineDouble = true;
vheight *= 2;
}
}
if (_settings.PadScreen320 && vwidth == 256)
vwidth = 320;
int xpad = (vwidth - gpwidth) / 2;
int xpad2 = vwidth - gpwidth - xpad;
if (dotDouble) vwidth *= 2;
if (vidbuff.Length < vwidth * vheight)
vidbuff = new int[vwidth * vheight];
int xskip = 1;
if (dotDouble)
xskip = 2;
int lines = lineDouble ? 2: 1;
for (int D = 0; D < xskip; D++)
{
int rinc = (gppitch / 4) - gpwidth;
fixed (int* pdst_ = &vidbuff[0])
{
int* pdst = pdst_ + D;
int* psrc = (int*)src;
for (int j = 0; j < gpheight; j++)
{
int* ppsrc = psrc;
for (int L = 0; L < lines; L++)
{
int* pppsrc = ppsrc;
for (int i = 0; i < xpad; i++)
{
*pdst = unchecked((int)0xff000000);
pdst += xskip;
}
for (int i = 0; i < gpwidth; i++)
{
*pdst = *pppsrc++;// | unchecked((int)0xff000000);
pdst += xskip;
}
for (int i = 0; i < xpad2; i++)
{
*pdst = unchecked((int)0xff000000);
pdst += xskip;
}
psrc = pppsrc;
}
psrc += rinc;
}
}
}
}
}
}

View File

@ -1,377 +0,0 @@
using System;
using System.Runtime.InteropServices;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
[CoreAttributes(
"Genplus-gx",
"",
isPorted: true,
isReleased: true,
portedVersion: "r874",
portedUrl: "https://code.google.com/p/genplus-gx/",
singleInstance: true)]
public partial class GPGX : IEmulator, IVideoProvider, ISaveRam, IStatable, IRegionable,
IInputPollable, IDebuggable, IDriveLight, ICodeDataLogger, IDisassemblable
{
[CoreConstructor("GEN")]
public GPGX(CoreComm comm, byte[] file, object settings, object syncSettings)
: this(comm, file, null, settings, syncSettings)
{
}
public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object settings, object syncSettings)
{
ServiceProvider = new BasicServiceProvider(this);
// this can influence some things internally
string romextension = "GEN";
// three or six button?
// http://www.sega-16.com/forum/showthread.php?4398-Forgotten-Worlds-giving-you-GAME-OVER-immediately-Fix-inside&highlight=forgotten%20worlds
//hack, don't use
if (rom != null && rom.Length > 32 * 1024 * 1024)
{
throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?");
}
try
{
_syncSettings = (GPGXSyncSettings)syncSettings ?? new GPGXSyncSettings();
_settings = (GPGXSettings)settings ?? new GPGXSettings();
CoreComm = comm;
if (AttachedCore != null)
{
AttachedCore.Dispose();
AttachedCore = null;
}
AttachedCore = this;
LoadCallback = new LibGPGX.load_archive_cb(load_archive);
this.romfile = rom;
this.CD = CD;
this.DiscSectorReader = new DiscSystem.DiscSectorReader(CD);
LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;
LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;
switch (_syncSettings.ControlType)
{
case ControlType.None:
default:
break;
case ControlType.Activator:
system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR;
break;
case ControlType.Normal:
system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
break;
case ControlType.OnePlayer:
system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
break;
case ControlType.Xea1p:
system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P;
break;
case ControlType.Teamplayer:
system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER;
break;
case ControlType.Wayplay:
system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY;
break;
case ControlType.Mouse:
system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD;
// seems like mouse in port 1 would be supported, but not both at the same time
system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE;
break;
}
if (!LibGPGX.gpgx_init(romextension, LoadCallback, _syncSettings.UseSixButton, system_a, system_b, _syncSettings.Region, _settings.GetNativeSettings()))
throw new Exception("gpgx_init() failed");
{
int fpsnum = 60;
int fpsden = 1;
LibGPGX.gpgx_get_fps(ref fpsnum, ref fpsden);
VsyncNumerator = fpsnum;
VsyncDenominator = fpsden;
Region = VsyncNumerator / VsyncDenominator > 55 ? DisplayType.NTSC : DisplayType.PAL;
}
// compute state size
{
byte[] tmp = new byte[LibGPGX.gpgx_state_max_size()];
int size = LibGPGX.gpgx_state_size(tmp, tmp.Length);
if (size <= 0)
throw new Exception("Couldn't Determine GPGX internal state size!");
_savebuff = new byte[size];
_savebuff2 = new byte[_savebuff.Length + 13];
Console.WriteLine("GPGX Internal State Size: {0}", size);
}
SetControllerDefinition();
// pull the default video size from the core
UpdateVideoInitial();
SetMemoryDomains();
InputCallback = new LibGPGX.input_cb(input_callback);
LibGPGX.gpgx_set_input_callback(InputCallback);
if (CD != null)
DriveLightEnabled = true;
// process the non-init settings now
PutSettings(_settings);
//TODO - this hits performance, we need to make it controllable
CDCallback = new LibGPGX.CDCallback(CDCallbackProc);
InitMemCallbacks();
KillMemCallbacks();
ConnectTracer();
}
catch
{
Dispose();
throw;
}
}
static GPGX AttachedCore = null;
DiscSystem.Disc CD;
DiscSystem.DiscSectorReader DiscSectorReader;
byte[] romfile;
bool disposed = false;
LibGPGX.load_archive_cb LoadCallback = null;
LibGPGX.InputData input = new LibGPGX.InputData();
public enum ControlType
{
None,
OnePlayer,
Normal,
Xea1p,
Activator,
Teamplayer,
Wayplay,
Mouse
};
/// <summary>
/// core callback for file loading
/// </summary>
/// <param name="filename">string identifying file to be loaded</param>
/// <param name="buffer">buffer to load file to</param>
/// <param name="maxsize">maximum length buffer can hold</param>
/// <returns>actual size loaded, or 0 on failure</returns>
int load_archive(string filename, IntPtr buffer, int maxsize)
{
byte[] srcdata = null;
if (buffer == IntPtr.Zero)
{
Console.WriteLine("Couldn't satisfy firmware request {0} because buffer == NULL", filename);
return 0;
}
if (filename == "PRIMARY_ROM")
{
if (romfile == null)
{
Console.WriteLine("Couldn't satisfy firmware request PRIMARY_ROM because none was provided.");
return 0;
}
srcdata = romfile;
}
else if (filename == "PRIMARY_CD" || filename == "SECONDARY_CD")
{
if (filename == "PRIMARY_CD" && romfile != null)
{
Console.WriteLine("Declined to satisfy firmware request PRIMARY_CD because PRIMARY_ROM was provided.");
return 0;
}
else
{
if (CD == null)
{
Console.WriteLine("Couldn't satisfy firmware request {0} because none was provided.", filename);
return 0;
}
srcdata = GetCDData();
if (srcdata.Length != maxsize)
{
Console.WriteLine("Couldn't satisfy firmware request {0} because of struct size.", filename);
return 0;
}
}
}
else
{
// use fromtend firmware interface
string firmwareID = null;
switch (filename)
{
case "CD_BIOS_EU": firmwareID = "CD_BIOS_EU"; break;
case "CD_BIOS_JP": firmwareID = "CD_BIOS_JP"; break;
case "CD_BIOS_US": firmwareID = "CD_BIOS_US"; break;
default:
break;
}
if (firmwareID != null)
{
// this path will be the most common PEBKAC error, so be a bit more vocal about the problem
srcdata = CoreComm.CoreFileProvider.GetFirmware("GEN", firmwareID, false, "GPGX firmwares are usually required.");
if (srcdata == null)
{
Console.WriteLine("Frontend couldn't satisfy firmware request GEN:{0}", firmwareID);
return 0;
}
}
else
{
Console.WriteLine("Unrecognized firmware request {0}", filename);
return 0;
}
}
if (srcdata != null)
{
if (srcdata.Length > maxsize)
{
Console.WriteLine("Couldn't satisfy firmware request {0} because {1} > {2}", filename, srcdata.Length, maxsize);
return 0;
}
else
{
Marshal.Copy(srcdata, 0, buffer, srcdata.Length);
Console.WriteLine("Firmware request {0} satisfied at size {1}", filename, srcdata.Length);
return srcdata.Length;
}
}
else
{
throw new Exception();
//Console.WriteLine("Couldn't satisfy firmware request {0} for unknown reasons", filename);
//return 0;
}
}
void CDRead(int lba, IntPtr dest, bool audio)
{
if (audio)
{
byte[] data = new byte[2352];
if (lba < CD.Session1.LeadoutLBA)
{
DiscSectorReader.ReadLBA_2352(lba, data, 0);
}
else
{
// audio seems to read slightly past the end of disks; probably innoculous
// just send back 0s.
// Console.WriteLine("!!{0} >= {1}", lba, CD.LBACount);
}
Marshal.Copy(data, 0, dest, 2352);
}
else
{
byte[] data = new byte[2048];
DiscSectorReader.ReadLBA_2048(lba, data, 0);
Marshal.Copy(data, 0, dest, 2048);
_drivelight = true;
}
}
LibGPGX.cd_read_cb cd_callback_handle;
unsafe byte[] GetCDData()
{
LibGPGX.CDData ret = new LibGPGX.CDData();
int size = Marshal.SizeOf(ret);
ret.readcallback = cd_callback_handle = new LibGPGX.cd_read_cb(CDRead);
var ses = CD.Session1;
int ntrack = ses.InformationTrackCount;
// bet you a dollar this is all wrong
//zero 07-jul-2015 - throws a dollar in the pile, since he probably messed it up worse
for (int i = 0; i < LibGPGX.CD_MAX_TRACKS; i++)
{
if (i < ntrack)
{
ret.tracks[i].start = ses.Tracks[i + 1].LBA;
ret.tracks[i].end = ses.Tracks[i + 2].LBA;
if (i == ntrack - 1)
{
ret.end = ret.tracks[i].end;
ret.last = ntrack;
}
}
else
{
ret.tracks[i].start = 0;
ret.tracks[i].end = 0;
}
}
byte[] retdata = new byte[size];
fixed (byte* p = &retdata[0])
{
Marshal.StructureToPtr(ret, (IntPtr)p, false);
}
return retdata;
}
/// <summary>
/// size of native input struct
/// </summary>
int inputsize;
GPGXControlConverter ControlConverter;
private void SetControllerDefinition()
{
inputsize = Marshal.SizeOf(typeof(LibGPGX.InputData));
if (!LibGPGX.gpgx_get_control(input, inputsize))
throw new Exception("gpgx_get_control() failed");
ControlConverter = new GPGXControlConverter(input);
ControllerDefinition = ControlConverter.ControllerDef;
}
public LibGPGX.INPUT_DEVICE[] GetDevices()
{
return (LibGPGX.INPUT_DEVICE[])input.dev.Clone();
}
public bool IsSegaCD { get { return CD != null; } }
public void UpdateVDPViewContext(LibGPGX.VDPView view)
{
LibGPGX.gpgx_get_vdp_view(view);
LibGPGX.gpgx_flush_vram(); // fully regenerate internal caches as needed
}
public DisplayType Region { get; private set; }
}
}

View File

@ -1,266 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public class GPGXControlConverter
{
// this isn't all done
struct CName
{
public string Name;
public LibGPGX.INPUT_KEYS Key;
public CName(string Name, LibGPGX.INPUT_KEYS Key)
{
this.Name = Name;
this.Key = Key;
}
}
static CName[] Genesis3 =
{
new CName("Up", LibGPGX.INPUT_KEYS.INPUT_UP),
new CName("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN),
new CName("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT),
new CName("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT),
new CName("A", LibGPGX.INPUT_KEYS.INPUT_A),
new CName("B", LibGPGX.INPUT_KEYS.INPUT_B),
new CName("C", LibGPGX.INPUT_KEYS.INPUT_C),
new CName("Start", LibGPGX.INPUT_KEYS.INPUT_START),
};
static CName[] Genesis6 =
{
new CName("Up", LibGPGX.INPUT_KEYS.INPUT_UP),
new CName("Down", LibGPGX.INPUT_KEYS.INPUT_DOWN),
new CName("Left", LibGPGX.INPUT_KEYS.INPUT_LEFT),
new CName("Right", LibGPGX.INPUT_KEYS.INPUT_RIGHT),
new CName("A", LibGPGX.INPUT_KEYS.INPUT_A),
new CName("B", LibGPGX.INPUT_KEYS.INPUT_B),
new CName("C", LibGPGX.INPUT_KEYS.INPUT_C),
new CName("Start", LibGPGX.INPUT_KEYS.INPUT_START),
new CName("X", LibGPGX.INPUT_KEYS.INPUT_X),
new CName("Y", LibGPGX.INPUT_KEYS.INPUT_Y),
new CName("Z", LibGPGX.INPUT_KEYS.INPUT_Z),
new CName("Mode", LibGPGX.INPUT_KEYS.INPUT_MODE),
};
static CName[] Mouse =
{
new CName("Mouse Left", LibGPGX.INPUT_KEYS.INPUT_MOUSE_LEFT),
new CName("Mouse Center", LibGPGX.INPUT_KEYS.INPUT_MOUSE_CENTER),
new CName("Mouse Right", LibGPGX.INPUT_KEYS.INPUT_MOUSE_RIGHT),
new CName("Mouse Start", LibGPGX.INPUT_KEYS.INPUT_MOUSE_START),
};
static CName[] Lightgun =
{
new CName("Lightgun Trigger", LibGPGX.INPUT_KEYS.INPUT_MENACER_TRIGGER),
new CName("Lightgun Start", LibGPGX.INPUT_KEYS.INPUT_MENACER_START),
new CName("Lightgun B", LibGPGX.INPUT_KEYS.INPUT_MENACER_B),
new CName("Lightgun C", LibGPGX.INPUT_KEYS.INPUT_MENACER_C)
};
static CName[] Activator =
{
new CName("1L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_1L),
new CName("1U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_1U),
new CName("2L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_2L),
new CName("2U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_2U),
new CName("3L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_3L),
new CName("3U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_3U),
new CName("4L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_4L),
new CName("4U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_4U),
new CName("5L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_5L),
new CName("5U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_5U),
new CName("6L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_6L),
new CName("6U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_6U),
new CName("7L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_7L),
new CName("7U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_7U),
new CName("8L", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_8L),
new CName("8U", LibGPGX.INPUT_KEYS.INPUT_ACTIVATOR_8U),
};
static CName[] XEA1P =
{
new CName("XE A", LibGPGX.INPUT_KEYS.INPUT_XE_A),
new CName("XE B", LibGPGX.INPUT_KEYS.INPUT_XE_B),
new CName("XE C", LibGPGX.INPUT_KEYS.INPUT_XE_C),
new CName("XE D", LibGPGX.INPUT_KEYS.INPUT_XE_D),
new CName("XE Start", LibGPGX.INPUT_KEYS.INPUT_XE_START),
new CName("XE Select", LibGPGX.INPUT_KEYS.INPUT_XE_SELECT),
new CName("XE E1", LibGPGX.INPUT_KEYS.INPUT_XE_E1),
new CName("XE E2", LibGPGX.INPUT_KEYS.INPUT_XE_E2),
};
static ControllerDefinition.FloatRange MouseRange = new ControllerDefinition.FloatRange(-256, 0, 255);
// lightgun needs to be transformed to match the current screen resolution
static ControllerDefinition.FloatRange LightgunRange = new ControllerDefinition.FloatRange(0, 5000, 10000);
static ControllerDefinition.FloatRange XEA1PRange = new ControllerDefinition.FloatRange(-128, 0, 127);
LibGPGX.InputData target = null;
IController source = null;
List<Action> Converts = new List<Action>();
public ControllerDefinition ControllerDef { get; private set; }
void AddToController(int idx, int player, IEnumerable<CName> Buttons)
{
foreach (var Button in Buttons)
{
string Name = string.Format("P{0} {1}", player, Button.Name);
ControllerDef.BoolButtons.Add(Name);
var ButtonFlag = Button.Key;
Converts.Add(delegate()
{
if (source.IsPressed(Name))
target.pad[idx] |= ButtonFlag;
});
}
}
void DoMouseAnalog(int idx, int player)
{
string NX = string.Format("P{0} Mouse X", player);
string NY = string.Format("P{0} Mouse Y", player);
ControllerDef.FloatControls.Add(NX);
ControllerDef.FloatControls.Add(NY);
ControllerDef.FloatRanges.Add(MouseRange);
ControllerDef.FloatRanges.Add(MouseRange);
Converts.Add(delegate()
{
target.analog[(2 * idx) + 0] = (short)source.GetFloat(NX);
target.analog[(2 * idx) + 1] = (short)source.GetFloat(NY);
});
}
void DoLightgunAnalog(int idx, int player)
{
string NX = string.Format("P{0} Lightgun X", player);
string NY = string.Format("P{0} Lightgun Y", player);
ControllerDef.FloatControls.Add(NX);
ControllerDef.FloatControls.Add(NY);
ControllerDef.FloatRanges.Add(LightgunRange);
ControllerDef.FloatRanges.Add(LightgunRange);
Converts.Add(delegate()
{
target.analog[(2 * idx) + 0] = (short)(source.GetFloat(NX) / 10000.0f * (ScreenWidth - 1));
target.analog[(2 * idx) + 1] = (short)(source.GetFloat(NY) / 10000.0f * (ScreenHeight - 1));
});
}
void DoXEA1PAnalog(int idx, int player)
{
string NX = string.Format("P{0} Stick X", player);
string NY = string.Format("P{0} Stick Y", player);
string NZ = string.Format("P{0} Stick Z", player);
ControllerDef.FloatControls.Add(NX);
ControllerDef.FloatControls.Add(NY);
ControllerDef.FloatControls.Add(NZ);
ControllerDef.FloatRanges.Add(XEA1PRange);
ControllerDef.FloatRanges.Add(XEA1PRange);
ControllerDef.FloatRanges.Add(XEA1PRange);
Converts.Add(delegate()
{
target.analog[(2 * idx) + 0] = (short)(source.GetFloat(NX));
target.analog[(2 * idx) + 1] = (short)(source.GetFloat(NY));
// +2 is correct in how gpgx internally does this
target.analog[(2 * idx) + 2] = (short)(source.GetFloat(NZ));
});
}
public GPGXControlConverter(LibGPGX.InputData input)
{
Console.WriteLine("Genesis Controller report:");
foreach (var e in input.system)
Console.WriteLine("S:{0}", e);
foreach (var e in input.dev)
Console.WriteLine("D:{0}", e);
int player = 1;
ControllerDef = new ControllerDefinition();
ControllerDef.BoolButtons.Add("Power");
ControllerDef.BoolButtons.Add("Reset");
for (int i = 0; i < LibGPGX.MAX_DEVICES; i++)
{
switch (input.dev[i])
{
case LibGPGX.INPUT_DEVICE.DEVICE_PAD3B:
AddToController(i, player, Genesis3);
player++;
break;
case LibGPGX.INPUT_DEVICE.DEVICE_PAD6B:
AddToController(i, player, Genesis6);
player++;
break;
case LibGPGX.INPUT_DEVICE.DEVICE_MOUSE:
AddToController(i, player, Mouse);
DoMouseAnalog(i, player);
player++;
break;
case LibGPGX.INPUT_DEVICE.DEVICE_NONE:
break;
case LibGPGX.INPUT_DEVICE.DEVICE_LIGHTGUN:
// supports menacers and justifiers
AddToController(i, player, Lightgun);
DoLightgunAnalog(i, player);
player++;
break;
case LibGPGX.INPUT_DEVICE.DEVICE_PAD2B:
case LibGPGX.INPUT_DEVICE.DEVICE_PADDLE:
case LibGPGX.INPUT_DEVICE.DEVICE_SPORTSPAD:
case LibGPGX.INPUT_DEVICE.DEVICE_TEREBI:
throw new Exception("Master System only device? Something went wrong.");
case LibGPGX.INPUT_DEVICE.DEVICE_ACTIVATOR:
AddToController(i, player, Activator);
player++;
break;
case LibGPGX.INPUT_DEVICE.DEVICE_XE_A1P:
AddToController(i, player, XEA1P);
DoXEA1PAnalog(i, player);
player++;
break;
case LibGPGX.INPUT_DEVICE.DEVICE_PICO:
// PICO isn't finished on the unmanaged side either
throw new Exception("Sega PICO not implemented yet!");
default:
throw new Exception("Unknown Genesis control device! Something went wrong.");
}
}
ControllerDef.Name = "GPGX Genesis Controller";
}
public void Convert(IController source, LibGPGX.InputData target)
{
this.source = source;
this.target = target;
target.ClearAllBools();
foreach (var f in Converts)
f();
this.source = null;
this.target = null;
}
/// <summary>
/// must be set for proper lightgun operation
/// </summary>
public int ScreenWidth { get; set; }
/// <summary>
/// must be set for proper lightgun operation
/// </summary>
public int ScreenHeight { get; set; }
}
}

View File

@ -1,214 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
/*
* how to use:
* 0) get https://code.google.com/p/pdbparse/
* 1) set modulename to the name of the dll file.
* 2) set symbolname to the name of a file that you produced by executing the following command:
* pdb_print_gvars.py [module pdb file] 0x00000000 > [output file]
* 3) set start to an address (relative to the beginning of the dll) to start scanning
* 4) set length to the byte length of the scan area
* 5) instantiate a GenDbWind, and use it to control the scanner while you manipulate the dll into various configurations.
*
* ideas for modification:
* 1) unhardcode config parameters and allow modifying them through the interface
* 2) read section sizes and positions from the dll itself instead of the start\length params
* 3) support an ignore list of symbols
*/
public class GenDbgHlp : IDisposable
{
private static class Win32
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
}
// config
const string modulename = "libgenplusgx.dll";
const string symbolname = @"D:\encodes\bizhawksrc\genplus-gx\libretro\msvc\Debug\vars.txt";
const int start = 0x0c7d8000 - 0x0c540000;
const int length = 0x01082000;
bool disposed = false;
public void Dispose()
{
if (!disposed)
{
Win32.FreeLibrary(DllBase);
DllBase = IntPtr.Zero;
disposed = true;
}
}
IntPtr DllBase;
List<Symbol> SymbolsByAddr = new List<Symbol>();
Dictionary<string, Symbol> SymbolsByName = new Dictionary<string, Symbol>();
byte[][] data = new byte[10][];
public void SaveState(int statenum)
{
if (disposed) throw new ObjectDisposedException(this.GetType().ToString());
if (data[statenum] == null)
data[statenum] = new byte[length];
Marshal.Copy(DllBase + start, data[statenum], 0, length);
Console.WriteLine("State {0} saved", statenum);
}
unsafe public void Cmp(int statex, int statey)
{
if (disposed) throw new ObjectDisposedException(this.GetType().ToString());
List<Tuple<int, int>> bads = new List<Tuple<int, int>>();
byte[] x = data[statex];
byte[] y = data[statey];
if (x == null || y == null)
{
Console.WriteLine("Missing State!");
return;
}
bool inrange = false;
int startsec = 0;
fixed (byte* p0 = &x[0])
fixed (byte* p1 = &y[0])
{
for (int i = 0; i < length; i++)
{
if (!inrange)
{
if (p0[i] != p1[i])
{
startsec = i;
inrange = true;
}
}
else
{
if (p0[i] == p1[i])
{
bads.Add(new Tuple<int, int>(startsec, i));
inrange = false;
}
}
}
}
if (inrange)
bads.Add(new Tuple<int, int>(startsec, length));
for (int i = 0; i < bads.Count; i++)
{
IntPtr addr = (IntPtr)(bads[i].Item1 + start);
int len = bads[i].Item2 - bads[i].Item1;
var ss = Find(addr, len);
Console.WriteLine("0x{0:X8}[0x{1}]", (int)addr, len);
foreach (var sym in ss)
Console.WriteLine(sym);
Console.WriteLine();
}
if (bads.Count == 0)
Console.WriteLine("Clean!");
}
public GenDbgHlp()
{
using (StreamReader sr = new StreamReader(symbolname))
{
string line;
while ((line = sr.ReadLine()) != null)
{
Symbol sym = Symbol.FromString(line);
SymbolsByAddr.Add(sym);
SymbolsByName.Add(sym.name, sym);
}
SymbolsByAddr.Sort();
}
DllBase = Win32.LoadLibrary(modulename);
if (DllBase == IntPtr.Zero)
throw new Exception();
}
public List<Symbol> Find(IntPtr addr, int length)
{
if (disposed) throw new ObjectDisposedException(this.GetType().ToString());
Symbol min = new Symbol { addr = addr };
Symbol max = new Symbol { addr = addr + length };
int minidx = SymbolsByAddr.BinarySearch(min);
if (minidx < 0)
{
minidx = ~minidx;
// inexact matches return the first larger value, so find the next smallset one
if (minidx > 0)
minidx--;
}
int maxidx = SymbolsByAddr.BinarySearch(max);
if (maxidx < 0)
{
maxidx = ~maxidx;
if (maxidx > 0)
maxidx--;
}
return SymbolsByAddr.GetRange(minidx, maxidx - minidx + 1);
}
public struct Symbol : IComparable<Symbol>
{
public IntPtr addr;
public string section;
public string name;
public static Symbol FromString(string s)
{
string[] ss = s.Split(',');
if (ss.Length != 4)
throw new Exception();
if (!ss[1].StartsWith("0x"))
throw new Exception();
Symbol ret = new Symbol
{
addr = (IntPtr)int.Parse(ss[1].Substring(2), System.Globalization.NumberStyles.AllowHexSpecifier),
section = ss[3],
name = ss[0]
};
return ret;
}
public int CompareTo(Symbol other)
{
return (int)this.addr - (int)other.addr;
}
public override string ToString()
{
return string.Format("0x{0:X8} {1} ({2})", (int)addr, name, section);
}
}
}
}

View File

@ -1,363 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public static class LibGPGX
{
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_get_video(out int w, out int h, out int pitch, ref IntPtr buffer);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_get_audio(ref int n, ref IntPtr buffer);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int load_archive_cb(string filename, IntPtr buffer, int maxsize);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_advance();
public enum Region : int
{
Autodetect = 0,
USA = 1,
Europe = 2,
Japan_NTSC = 3,
Japan_PAL = 4
}
[StructLayout(LayoutKind.Sequential)]
public class InitSettings
{
public enum FilterType : byte
{
None = 0,
LowPass = 1,
ThreeBand = 2
}
public FilterType Filter;
public ushort LowPassRange;
public short LowFreq;
public short HighFreq;
public short LowGain;
public short MidGain;
public short HighGain;
public uint BackdropColor;
}
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gpgx_init(string feromextension, load_archive_cb feload_archive_cb, bool sixbutton, INPUT_SYSTEM system_a, INPUT_SYSTEM system_b, Region region, [In]InitSettings settings);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_get_fps(ref int num, ref int den);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gpgx_state_max_size();
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gpgx_state_size(byte[] dest, int size);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gpgx_state_save(byte[] dest, int size);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gpgx_state_load(byte[] src, int size);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gpgx_get_control([Out]InputData dest, int bytes);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gpgx_put_control([In]InputData src, int bytes);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_get_sram(ref IntPtr area, ref int size);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_clear_sram();
public const int MIN_MEM_DOMAIN = 0;
public const int MAX_MEM_DOMAIN = 13;
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
// apparently, if you use built in string marshalling, the interop will assume that
// the unmanaged char pointer was allocated in hglobal and try to free it that way
public static extern IntPtr gpgx_get_memdom(int which, ref IntPtr area, ref int size);
// call this before reading sram returned by gpgx_get_sram()
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_sram_prepread();
// call this after writing sram returned by gpgx_get_sram()
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_sram_commitwrite();
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_reset(bool hard);
public const int MAX_DEVICES = 8;
public enum INPUT_SYSTEM : byte
{
SYSTEM_NONE = 0, // unconnected port
SYSTEM_MD_GAMEPAD = 1, // single 3-buttons or 6-buttons Control Pad
SYSTEM_MOUSE = 2, // Sega Mouse
SYSTEM_MENACER = 3, // Sega Menacer -- port B only
SYSTEM_JUSTIFIER = 4, // Konami Justifiers -- port B only
SYSTEM_XE_A1P = 5, // XE-A1P analog controller -- port A only
SYSTEM_ACTIVATOR = 6, // Sega Activator
SYSTEM_MS_GAMEPAD = 7, // single 2-buttons Control Pad -- Master System
SYSTEM_LIGHTPHASER = 8, // Sega Light Phaser -- Master System
SYSTEM_PADDLE = 9, // Sega Paddle Control -- Master System
SYSTEM_SPORTSPAD = 10, // Sega Sports Pad -- Master System
SYSTEM_TEAMPLAYER = 11, // Multi Tap -- Sega TeamPlayer
SYSTEM_WAYPLAY = 12, // Multi Tap -- EA 4-Way Play -- use both ports
};
public enum INPUT_DEVICE : byte
{
DEVICE_NONE = 0xff, // unconnected device = fixed ID for Team Player)
DEVICE_PAD3B = 0x00, // 3-buttons Control Pad = fixed ID for Team Player)
DEVICE_PAD6B = 0x01, // 6-buttons Control Pad = fixed ID for Team Player)
DEVICE_PAD2B = 0x02, // 2-buttons Control Pad
DEVICE_MOUSE = 0x03, // Sega Mouse
DEVICE_LIGHTGUN = 0x04, // Sega Light Phaser, Menacer or Konami Justifiers
DEVICE_PADDLE = 0x05, // Sega Paddle Control
DEVICE_SPORTSPAD = 0x06,// Sega Sports Pad
DEVICE_PICO = 0x07, // PICO tablet
DEVICE_TEREBI = 0x08, // Terebi Oekaki tablet
DEVICE_XE_A1P = 0x09, // XE-A1P analog controller
DEVICE_ACTIVATOR = 0x0a,// Activator
};
public enum CDLog_AddrType
{
MDCART, RAM68k, RAMZ80, SRAM,
};
[Flags]
public enum CDLog_Flags
{
Exec68k = 0x01,
Data68k = 0x04,
ExecZ80First = 0x08,
ExecZ80Operand = 0x10,
DataZ80 = 0x20,
DMASource = 0x40,
};
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void input_cb();
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_set_input_callback(input_cb cb);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void mem_cb(uint addr);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_set_mem_callback(mem_cb read, mem_cb write, mem_cb exec);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void trace_cb();
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_set_trace_callback(trace_cb cb);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CDCallback(int addr, CDLog_AddrType addrtype, CDLog_Flags flags);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_set_cd_callback(CDCallback cd);
/// <summary>
/// not every flag is valid for every device!
/// </summary>
[Flags]
public enum INPUT_KEYS : ushort
{
/* Default Input bitmasks */
INPUT_MODE = 0x0800,
INPUT_X = 0x0400,
INPUT_Y = 0x0200,
INPUT_Z = 0x0100,
INPUT_START = 0x0080,
INPUT_A = 0x0040,
INPUT_C = 0x0020,
INPUT_B = 0x0010,
INPUT_RIGHT = 0x0008,
INPUT_LEFT = 0x0004,
INPUT_DOWN = 0x0002,
INPUT_UP = 0x0001,
/* Master System specific bitmasks */
INPUT_BUTTON2 = 0x0020,
INPUT_BUTTON1 = 0x0010,
/* Mega Mouse specific bitmask */
INPUT_MOUSE_START = 0x0080,
INPUT_MOUSE_CENTER = 0x0040,
INPUT_MOUSE_RIGHT = 0x0020,
INPUT_MOUSE_LEFT = 0x0010,
/* Pico hardware specific bitmask */
INPUT_PICO_PEN = 0x0080,
INPUT_PICO_RED = 0x0010,
/* XE-1AP specific bitmask */
INPUT_XE_E1 = 0x0800,
INPUT_XE_E2 = 0x0400,
INPUT_XE_START = 0x0200,
INPUT_XE_SELECT = 0x0100,
INPUT_XE_A = 0x0080,
INPUT_XE_B = 0x0040,
INPUT_XE_C = 0x0020,
INPUT_XE_D = 0x0010,
/* Activator specific bitmasks */
INPUT_ACTIVATOR_8U = 0x8000,
INPUT_ACTIVATOR_8L = 0x4000,
INPUT_ACTIVATOR_7U = 0x2000,
INPUT_ACTIVATOR_7L = 0x1000,
INPUT_ACTIVATOR_6U = 0x0800,
INPUT_ACTIVATOR_6L = 0x0400,
INPUT_ACTIVATOR_5U = 0x0200,
INPUT_ACTIVATOR_5L = 0x0100,
INPUT_ACTIVATOR_4U = 0x0080,
INPUT_ACTIVATOR_4L = 0x0040,
INPUT_ACTIVATOR_3U = 0x0020,
INPUT_ACTIVATOR_3L = 0x0010,
INPUT_ACTIVATOR_2U = 0x0008,
INPUT_ACTIVATOR_2L = 0x0004,
INPUT_ACTIVATOR_1U = 0x0002,
INPUT_ACTIVATOR_1L = 0x0001,
/* Menacer */
INPUT_MENACER_TRIGGER = 0x0040,
INPUT_MENACER_START = 0x0080,
INPUT_MENACER_B = 0x0020,
INPUT_MENACER_C = 0x0010
};
[StructLayout(LayoutKind.Sequential)]
public class InputData
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public readonly INPUT_SYSTEM[] system = new INPUT_SYSTEM[2];
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DEVICES)]
public readonly INPUT_DEVICE[] dev = new INPUT_DEVICE[MAX_DEVICES];
/// <summary>
/// digital inputs
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DEVICES)]
public readonly INPUT_KEYS[] pad = new INPUT_KEYS[MAX_DEVICES];
/// <summary>
/// analog (x/y)
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DEVICES * 2)]
public readonly short[] analog = new short[MAX_DEVICES * 2];
/// <summary>
/// gun horizontal offset
/// </summary>
public int x_offset;
/// <summary>
/// gun vertical offset
/// </summary>
public int y_offset;
public void ClearAllBools()
{
for (int i = 0; i < pad.Length; i++)
pad[i] = 0;
}
}
public const int CD_MAX_TRACKS = 100;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void cd_read_cb(int lba, IntPtr dest, bool audio);
[StructLayout(LayoutKind.Sequential)]
public struct CDTrack
{
public int start;
public int end;
}
[StructLayout(LayoutKind.Sequential)]
public class CDData
{
public int end;
public int last;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = CD_MAX_TRACKS)]
public readonly CDTrack[] tracks = new CDTrack[CD_MAX_TRACKS];
public cd_read_cb readcallback;
}
[StructLayout(LayoutKind.Sequential)]
public struct VDPNameTable
{
public int Width; // in cells
public int Height; // in cells
public int Baseaddr;
}
[StructLayout(LayoutKind.Sequential)]
public class VDPView
{
public IntPtr VRAM;
public IntPtr PatternCache;
public IntPtr ColorCache;
public VDPNameTable NTA;
public VDPNameTable NTB;
public VDPNameTable NTW;
}
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_get_vdp_view([Out] VDPView view);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_poke_vram(int addr, byte value);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_flush_vram();
[StructLayout(LayoutKind.Sequential)]
public struct RegisterInfo
{
public int Value;
public IntPtr Name;
}
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gpgx_getmaxnumregs();
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gpgx_getregs([Out] RegisterInfo[] regs);
[Flags]
public enum DrawMask : int
{
BGA = 1,
BGB = 2,
BGW = 4,
Obj = 8,
Backdrop = 16
}
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_set_draw_mask(DrawMask mask);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_write_m68k_bus(uint addr, byte data);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void gpgx_write_s68k_bus(uint addr, byte data);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern byte gpgx_peek_m68k_bus(uint addr);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern byte gpgx_peek_s68k_bus(uint addr);
}
}

View File

@ -3,7 +3,7 @@ using System.IO;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : ICodeDataLogger
{

View File

@ -4,7 +4,7 @@ using System.Runtime.InteropServices;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IDebuggable
{

View File

@ -2,7 +2,7 @@
using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Components.M68000;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IDisassemblable
{

View File

@ -1,6 +1,6 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IDriveLight
{

View File

@ -1,7 +1,7 @@
using System;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IEmulator, ISoundProvider
{

View File

@ -1,6 +1,6 @@
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IInputPollable
{

View File

@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
using BizHawk.Emulation.Common;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX
{

View File

@ -6,7 +6,7 @@ using BizHawk.Emulation.Common;
using System.Runtime.InteropServices;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : ISaveRam
{

View File

@ -5,7 +5,7 @@ using BizHawk.Emulation.Common;
using Newtonsoft.Json;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : ISettable<GPGX.GPGXSettings, GPGX.GPGXSyncSettings>
{

View File

@ -3,7 +3,7 @@ using BizHawk.Emulation.Common;
using System.Runtime.InteropServices;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : ISoundProvider
{

View File

@ -4,7 +4,7 @@ using System.IO;
using BizHawk.Common.BufferExtensions;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IStatable
{

View File

@ -5,7 +5,7 @@ using System.Text;
using BizHawk.Common.NumberExtensions;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX
{

View File

@ -2,7 +2,7 @@
using BizHawk.Emulation.Common;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public partial class GPGX : IVideoProvider
{

View File

@ -8,10 +8,10 @@ using BizHawk.Emulation.Cores.Waterbox;
using BizHawk.Common;
using BizHawk.Emulation.DiscSystem;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
[CoreAttributes(
"Genplus-gx64",
"Genplus-gx",
"",
isPorted: true,
isReleased: true,

View File

@ -6,7 +6,7 @@ using System.Text;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public class GPGXControlConverter
{

View File

@ -5,7 +5,7 @@ using System.Text;
using System.Runtime.InteropServices;
using System.IO;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
/*
* how to use:

View File

@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
using BizHawk.Common.BizInvoke;
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
{
public abstract class LibGPGX
{