using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES { public static class LibQuickNES { public const string dllname = "libquicknes.dll"; /// /// setup extra mappers. should be done before anything else /// [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern void qn_setup_mappers(); /// /// create a new quicknes context /// /// NULL on failure [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_new(); /// /// destroy a quicknes context /// /// context previously returned from qn_new() [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern void qn_delete(IntPtr e); /// /// load an ines file /// /// context /// file /// length of file /// [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_loadines(IntPtr e, byte[] data, int length); /// /// set audio sample rate /// /// context /// hz /// string error [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_set_sample_rate(IntPtr e, int rate); /// /// emulate a single frame /// /// context /// pad 1 input /// pad 2 input /// string error [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_emulate_frame(IntPtr e, int pad1, int pad2); /// /// blit to rgb32 /// /// Context /// rgb32 256x240 packed /// rgb32 colors, 512 of them [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern void qn_blit(IntPtr e, int[] dest, int[] colors, int cropleft, int croptop, int cropright, int cropbottom); /// /// get quicknes's default palette /// /// 1536 bytes suitable for qn_blit [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_get_default_colors(); /// /// get number of times joypad was read in most recent frame /// /// context /// 0 means lag [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern int qn_get_joypad_read_count(IntPtr e); /// /// get audio info for most recent frame /// /// context /// number of samples actually created /// 1 for mono, 2 for stereo [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern void qn_get_audio_info(IntPtr e, ref int sample_count, ref int chan_count); /// /// get audio for most recent frame. must not be called more than once per frame! /// /// context /// sample buffer /// length to read into sample buffer /// length actually read [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern int qn_read_audio(IntPtr e, short[] dest, int max_samples); /// /// reset the console /// /// context /// true for powercycle, false for reset button [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern void qn_reset(IntPtr e, bool hard); /// /// get the required byte size of a savestate /// /// context /// size is returned /// string error [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_state_size(IntPtr e, ref int size); /// /// save state to buffer /// /// context /// buffer /// length of buffer /// string error [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_state_save(IntPtr e, byte[] dest, int size); /// /// load state from buffer /// /// context /// buffer /// length of buffer /// string error [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_state_load(IntPtr e, byte[] src, int size); /// /// query battery ram state /// /// context /// true if battery backup sram exists [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern bool qn_has_battery_ram(IntPtr e); /// /// query battery ram size /// /// context /// size is returned /// string error [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_battery_ram_size(IntPtr e, ref int size); /// /// save battery ram to buffer /// /// context /// buffer /// size /// string error [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_battery_ram_save(IntPtr e, byte[] dest, int size); /// /// load battery ram from buffer /// /// context /// buffer /// size /// string error [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_battery_ram_load(IntPtr e, byte[] src, int size); /// /// clear battery ram /// /// context /// string error [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_battery_ram_clear(IntPtr e); /// /// set sprite limit; does not affect emulation /// /// context /// 0 to hide, 8 for normal, 64 for all [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern void qn_set_sprite_limit(IntPtr e, int n); /// /// get memory area for debugging /// /// Context /// /// /// /// /// /// [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern bool qn_get_memory_area(IntPtr e, int which, ref IntPtr data, ref int size, ref bool writable, ref IntPtr name); /// /// peek the system bus /// /// Context /// 0000:ffff, but non-ram/rom addresses won't work /// [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern byte qn_peek_prgbus(IntPtr e, int addr); /// /// poke the system bus /// /// Context /// 0000:ffff, but non-ram/rom addresses won't work /// [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern void qn_poke_prgbus(IntPtr e, int addr, byte val); /// /// get internal registers /// /// Context /// a, x, y, sp, pc, p [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern void qn_get_cpuregs(IntPtr e, [Out] int[] dest); /// /// get the mapper that's loaded /// /// Context /// recieves mapper number /// mapper name [DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr qn_get_mapper(IntPtr e, ref int number); /// /// handle "string error" as returned by some quicknes functions /// /// public static void ThrowStringError(IntPtr p) { if (p == IntPtr.Zero) return; string s = Marshal.PtrToStringAnsi(p); if (s == "Unsupported mapper" || s == "Not an iNES file") // Not worth making a new exception for the iNES error, they ultimately are the same problem { throw new Emulation.Common.UnsupportedMapperException("Quicknes unsupported mapper"); } else { throw new InvalidOperationException("LibQuickNES error: " + s); } } } }