controls work and stuff now
This commit is contained in:
parent
a818710589
commit
a6cbd85930
|
@ -364,6 +364,10 @@ namespace BizHawk.Client.Common
|
|||
{
|
||||
return "|.|"; // TODO
|
||||
}
|
||||
else if (_controlType == "GPGX Genesis Controller")
|
||||
{
|
||||
return "|.|"; // TODO
|
||||
}
|
||||
|
||||
var input = new StringBuilder("|");
|
||||
|
||||
|
|
|
@ -542,6 +542,11 @@ namespace BizHawk.Client.Common
|
|||
// TODO
|
||||
return;
|
||||
}
|
||||
else if (ControlType == "GPGX Genesis Controller")
|
||||
{
|
||||
// TODO
|
||||
return;
|
||||
}
|
||||
|
||||
MnemonicChecker c = new MnemonicChecker(mnemonic);
|
||||
|
||||
|
|
|
@ -3221,7 +3221,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
case "GEN":
|
||||
{
|
||||
//nextEmulator = new Genesis(nextComm, game, rom.RomData);
|
||||
nextEmulator = new BizHawk.Emulation.Cores.Consoles.Sega.gpgx.GPGX(nextComm, rom.RomData, "GEN");
|
||||
nextEmulator = new BizHawk.Emulation.Cores.Consoles.Sega.gpgx.GPGX(nextComm, rom.RomData, "GEN", true, Emulation.Cores.Consoles.Sega.gpgx.GPGX.ControlType.Normal);
|
||||
break;
|
||||
}
|
||||
case "TI83":
|
||||
|
|
|
@ -409,6 +409,7 @@
|
|||
<Compile Include="Consoles\Sega\Genesis\Input.cs" />
|
||||
<Compile Include="Consoles\Sega\Genesis\Native68000\Musashi.cs" />
|
||||
<Compile Include="Consoles\Sega\gpgx\GPGX.cs" />
|
||||
<Compile Include="Consoles\Sega\gpgx\GPGXControlConverter.cs" />
|
||||
<Compile Include="Consoles\Sega\gpgx\LibGPGX.cs" />
|
||||
<Compile Include="Consoles\Sega\Saturn\FilePiping.cs" />
|
||||
<Compile Include="Consoles\Sega\Saturn\LibYabause.cs" />
|
||||
|
|
|
@ -21,8 +21,25 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
LibGPGX.load_archive_cb LoadCallback = null;
|
||||
|
||||
public GPGX(CoreComm NextComm, byte[] romfile, string romextension)
|
||||
LibGPGX.InputData input = new LibGPGX.InputData();
|
||||
|
||||
// still working out what all the possibilities are here
|
||||
public enum ControlType
|
||||
{
|
||||
None,
|
||||
OnePlayer,
|
||||
Normal,
|
||||
Xea1p,
|
||||
Activator,
|
||||
Teamplayer,
|
||||
Wayplay
|
||||
};
|
||||
|
||||
public GPGX(CoreComm NextComm, byte[] romfile, string romextension, bool sixbutton, ControlType controls)
|
||||
{
|
||||
// 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
|
||||
|
||||
try
|
||||
{
|
||||
CoreComm = NextComm;
|
||||
|
@ -39,8 +56,54 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
this.romfile = romfile;
|
||||
|
||||
if (!LibGPGX.gpgx_init(romextension, LoadCallback))
|
||||
LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;
|
||||
LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE;
|
||||
|
||||
switch (controls)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
if (!LibGPGX.gpgx_init(romextension, LoadCallback, sixbutton, system_a, system_b))
|
||||
throw new Exception("gpgx_init() failed");
|
||||
|
||||
{
|
||||
int fpsnum = 60;
|
||||
int fpsden = 1;
|
||||
LibGPGX.gpgx_get_fps(ref fpsnum, ref fpsden);
|
||||
CoreComm.VsyncNum = fpsnum;
|
||||
CoreComm.VsyncDen = fpsden;
|
||||
}
|
||||
|
||||
savebuff = new byte[LibGPGX.gpgx_state_size()];
|
||||
savebuff2 = new byte[savebuff.Length + 13];
|
||||
|
||||
SetControllerDefinition();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -97,18 +160,45 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
#region controller
|
||||
|
||||
public ControllerDefinition ControllerDefinition { get { return NullEmulator.NullController; } }
|
||||
GPGXControlConverter ControlConverter;
|
||||
|
||||
public ControllerDefinition ControllerDefinition { get; private set; }
|
||||
public IController Controller { get; set; }
|
||||
|
||||
void SetControllerDefinition()
|
||||
{
|
||||
if (!LibGPGX.gpgx_get_control(input))
|
||||
throw new Exception("gpgx_get_control() failed");
|
||||
|
||||
ControlConverter = new GPGXControlConverter(input);
|
||||
|
||||
ControllerDefinition = ControlConverter.ControllerDef;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: use render and rendersound
|
||||
public void FrameAdvance(bool render, bool rendersound = true)
|
||||
{
|
||||
// do we really have to get each time? nothing has changed
|
||||
if (!LibGPGX.gpgx_get_control(input))
|
||||
throw new Exception("gpgx_get_control() failed!");
|
||||
|
||||
ControlConverter.Convert(Controller, input);
|
||||
|
||||
if (!LibGPGX.gpgx_put_control(input))
|
||||
throw new Exception("gpgx_put_control() failed!");
|
||||
|
||||
IsLagFrame = true;
|
||||
Frame++;
|
||||
LibGPGX.gpgx_advance();
|
||||
update_video();
|
||||
update_audio();
|
||||
|
||||
IsLagFrame = false; // TODO
|
||||
if (IsLagFrame)
|
||||
LagCount++;
|
||||
}
|
||||
|
||||
public int Frame { get; private set; }
|
||||
|
@ -161,6 +251,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
#region savestates
|
||||
|
||||
private byte[] savebuff;
|
||||
private byte[] savebuff2;
|
||||
|
||||
public void SaveStateText(System.IO.TextWriter writer)
|
||||
{
|
||||
}
|
||||
|
@ -171,15 +264,39 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
|
||||
public void SaveStateBinary(System.IO.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);
|
||||
}
|
||||
|
||||
public void LoadStateBinary(System.IO.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();
|
||||
}
|
||||
|
||||
public byte[] SaveStateBinary()
|
||||
{
|
||||
return new byte[0];
|
||||
var ms = new System.IO.MemoryStream(savebuff2, true);
|
||||
var bw = new System.IO.BinaryWriter(ms);
|
||||
SaveStateBinary(bw);
|
||||
bw.Flush();
|
||||
ms.Close();
|
||||
return savebuff2;
|
||||
}
|
||||
|
||||
public bool BinarySaveStatesPreferred { get { return true; } }
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
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("B", LibGPGX.INPUT_KEYS.INPUT_B),
|
||||
new CName("C", LibGPGX.INPUT_KEYS.INPUT_C),
|
||||
new CName("A", LibGPGX.INPUT_KEYS.INPUT_A),
|
||||
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("B", LibGPGX.INPUT_KEYS.INPUT_B),
|
||||
new CName("C", LibGPGX.INPUT_KEYS.INPUT_C),
|
||||
new CName("A", LibGPGX.INPUT_KEYS.INPUT_A),
|
||||
new CName("Start", LibGPGX.INPUT_KEYS.INPUT_START),
|
||||
new CName("Z", LibGPGX.INPUT_KEYS.INPUT_Z),
|
||||
new CName("Y", LibGPGX.INPUT_KEYS.INPUT_Y),
|
||||
new CName("X", LibGPGX.INPUT_KEYS.INPUT_X),
|
||||
new CName("Mode", LibGPGX.INPUT_KEYS.INPUT_MODE),
|
||||
};
|
||||
|
||||
static CName[] Mouse =
|
||||
{
|
||||
new CName("Left", LibGPGX.INPUT_KEYS.INPUT_MOUSE_LEFT),
|
||||
new CName("Center", LibGPGX.INPUT_KEYS.INPUT_MOUSE_CENTER),
|
||||
new CName("Right", LibGPGX.INPUT_KEYS.INPUT_MOUSE_RIGHT),
|
||||
};
|
||||
|
||||
static ControllerDefinition.FloatRange FullShort = new ControllerDefinition.FloatRange(-32767, 0, 32767);
|
||||
|
||||
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} X", player);
|
||||
string NY = string.Format("P{0} Y", player);
|
||||
ControllerDef.FloatControls.Add(NX);
|
||||
ControllerDef.FloatControls.Add(NY);
|
||||
ControllerDef.FloatRanges.Add(FullShort);
|
||||
ControllerDef.FloatRanges.Add(FullShort);
|
||||
Converts.Add(delegate()
|
||||
{
|
||||
target.analog[idx,0] = (short)source.GetFloat(NX);
|
||||
target.analog[idx,1] = (short)source.GetFloat(NY);
|
||||
});
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -21,7 +21,177 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
public static extern void gpgx_advance();
|
||||
|
||||
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool gpgx_init(string feromextension, load_archive_cb feload_archive_cb);
|
||||
public static extern bool gpgx_init(string feromextension, load_archive_cb feload_archive_cb, bool sixbutton, INPUT_SYSTEM system_a, INPUT_SYSTEM system_b);
|
||||
|
||||
[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_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(IntPtr dest, int bytes);
|
||||
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern bool gpgx_put_control(IntPtr src, int bytes);
|
||||
|
||||
public static bool gpgx_get_control(InputData dest)
|
||||
{
|
||||
int bytes = Marshal.SizeOf(typeof(InputData));
|
||||
IntPtr p = Marshal.AllocHGlobal(bytes);
|
||||
|
||||
bool succeed = gpgx_get_control(p, bytes);
|
||||
if (succeed)
|
||||
Marshal.PtrToStructure(p, dest);
|
||||
Marshal.FreeHGlobal(p);
|
||||
return succeed;
|
||||
}
|
||||
|
||||
public static bool gpgx_put_control(InputData src)
|
||||
{
|
||||
int bytes = Marshal.SizeOf(typeof(InputData));
|
||||
IntPtr p = Marshal.AllocHGlobal(bytes);
|
||||
|
||||
Marshal.StructureToPtr(src, p, false);
|
||||
|
||||
bool succeed = gpgx_put_control(p, bytes);
|
||||
Marshal.FreeHGlobal(p);
|
||||
return succeed;
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
/// <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_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,
|
||||
};
|
||||
|
||||
[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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,6 +76,45 @@ GPGX_EX void gpgx_get_audio(int *n, void **buffer)
|
|||
*buffer = soundbuffer;
|
||||
}
|
||||
|
||||
// this is most certainly wrong for interlacing
|
||||
GPGX_EX void gpgx_get_fps(int *num, int *den)
|
||||
{
|
||||
if (vdp_pal)
|
||||
{
|
||||
if (num)
|
||||
*num = 53203424;
|
||||
if (den)
|
||||
*den = 3420 * 313;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num)
|
||||
*num = 53693175;
|
||||
if (den)
|
||||
*den = 3420 * 262;
|
||||
}
|
||||
}
|
||||
|
||||
GPGX_EX int gpgx_state_size(void)
|
||||
{
|
||||
return STATE_SIZE;
|
||||
}
|
||||
|
||||
GPGX_EX int gpgx_state_save(void *dest, int size)
|
||||
{
|
||||
if (size != STATE_SIZE)
|
||||
return 0;
|
||||
|
||||
return !!state_save((unsigned char*) dest);
|
||||
}
|
||||
|
||||
GPGX_EX int gpgx_state_load(void *src, int size)
|
||||
{
|
||||
if (size != STATE_SIZE)
|
||||
return 0;
|
||||
|
||||
return !!state_load((unsigned char *) src);
|
||||
}
|
||||
|
||||
void osd_input_update(void)
|
||||
{
|
||||
|
@ -94,6 +133,21 @@ int load_archive(char *filename, unsigned char *buffer, int maxsize, char *exten
|
|||
return load_archive_cb(filename, buffer, maxsize);
|
||||
}
|
||||
|
||||
GPGX_EX int gpgx_get_control(t_input *dest, int bytes)
|
||||
{
|
||||
if (bytes != sizeof(t_input))
|
||||
return 0;
|
||||
memcpy(dest, &input, sizeof(t_input));
|
||||
return 1;
|
||||
}
|
||||
|
||||
GPGX_EX int gpgx_put_control(t_input *src, int bytes)
|
||||
{
|
||||
if (bytes != sizeof(t_input))
|
||||
return 0;
|
||||
memcpy(&input, src, sizeof(t_input));
|
||||
}
|
||||
|
||||
GPGX_EX void gpgx_advance(void)
|
||||
{
|
||||
if (system_hw == SYSTEM_MCD)
|
||||
|
@ -113,7 +167,7 @@ GPGX_EX void gpgx_advance(void)
|
|||
}
|
||||
|
||||
|
||||
GPGX_EX int gpgx_init(const char *feromextension, int (*feload_archive_cb)(const char *filename, unsigned char *buffer, int maxsize))
|
||||
GPGX_EX int gpgx_init(const char *feromextension, int (*feload_archive_cb)(const char *filename, unsigned char *buffer, int maxsize), int sixbutton, char system_a, char system_b)
|
||||
{
|
||||
memset(&bitmap, 0, sizeof(bitmap));
|
||||
memset(bitmap_data_, 0, sizeof(bitmap_data_));
|
||||
|
@ -160,6 +214,23 @@ GPGX_EX int gpgx_init(const char *feromextension, int (*feload_archive_cb)(const
|
|||
config.ntsc = 0;
|
||||
config.render= 0;
|
||||
|
||||
// set overall input system type
|
||||
// usual is MD GAMEPAD or NONE
|
||||
// TEAMPLAYER, WAYPLAY, ACTIVATOR, XEA1P, MOUSE need to be specified
|
||||
// everything else is auto or master system only
|
||||
// XEA1P is port 1 only
|
||||
// WAYPLAY is both ports at same time only
|
||||
input.system[0] = system_a;
|
||||
input.system[1] = system_b;
|
||||
|
||||
// apparently, the only part of config.input used is the padtype identifier,
|
||||
// and that's used only for choosing pad type when system_md
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_INPUTS; i++)
|
||||
config.input[i].padtype = sixbutton ? DEVICE_PAD6B : DEVICE_PAD3B;
|
||||
}
|
||||
|
||||
if (!load_rom("PRIMARY_ROM"))
|
||||
return 0;
|
||||
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue