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(ref int w, ref int h, ref 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 } [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); [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 }; [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); /// /// not every flag is valid for every device! /// [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, }; [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]; /// /// digital inputs /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DEVICES)] public readonly INPUT_KEYS[] pad = new INPUT_KEYS[MAX_DEVICES]; /// /// analog (x/y) /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DEVICES * 2)] public readonly short[] analog = new short[MAX_DEVICES * 2]; /// /// gun horizontal offset /// public int x_offset; /// /// gun vertical offset /// 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 } [DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void gpgx_set_draw_mask(DrawMask mask); } }