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);
}
}
}
}