238 lines
9.6 KiB
C#
238 lines
9.6 KiB
C#
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";
|
|
|
|
/// <summary>
|
|
/// setup extra mappers. should be done before anything else
|
|
/// </summary>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern void qn_setup_mappers();
|
|
/// <summary>
|
|
/// create a new quicknes context
|
|
/// </summary>
|
|
/// <returns>NULL on failure</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_new();
|
|
/// <summary>
|
|
/// destroy a quicknes context
|
|
/// </summary>
|
|
/// <param name="e">context previously returned from qn_new()</param>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern void qn_delete(IntPtr e);
|
|
/// <summary>
|
|
/// load an ines file
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="data">file</param>
|
|
/// <param name="length">length of file</param>
|
|
/// <returns></returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_loadines(IntPtr e, byte[] data, int length);
|
|
/// <summary>
|
|
/// set audio sample rate
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="rate">hz</param>
|
|
/// <returns>string error</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_set_sample_rate(IntPtr e, int rate);
|
|
/// <summary>
|
|
/// emulate a single frame
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="pad1">pad 1 input</param>
|
|
/// <param name="pad2">pad 2 input</param>
|
|
/// <returns>string error</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_emulate_frame(IntPtr e, int pad1, int pad2);
|
|
/// <summary>
|
|
/// blit to rgb32
|
|
/// </summary>
|
|
/// <param name="e">Context</param>
|
|
/// <param name="dest">rgb32 256x240 packed</param>
|
|
/// <param name="colors">rgb32 colors, 512 of them</param>
|
|
[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);
|
|
/// <summary>
|
|
/// get quicknes's default palette
|
|
/// </summary>
|
|
/// <returns>1536 bytes suitable for qn_blit</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_get_default_colors();
|
|
/// <summary>
|
|
/// get number of times joypad was read in most recent frame
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <returns>0 means lag</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern int qn_get_joypad_read_count(IntPtr e);
|
|
/// <summary>
|
|
/// get audio info for most recent frame
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="sample_count">number of samples actually created</param>
|
|
/// <param name="chan_count">1 for mono, 2 for stereo</param>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern void qn_get_audio_info(IntPtr e, ref int sample_count, ref int chan_count);
|
|
/// <summary>
|
|
/// get audio for most recent frame. must not be called more than once per frame!
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="dest">sample buffer</param>
|
|
/// <param name="max_samples">length to read into sample buffer</param>
|
|
/// <returns>length actually read</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern int qn_read_audio(IntPtr e, short[] dest, int max_samples);
|
|
/// <summary>
|
|
/// reset the console
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="hard">true for powercycle, false for reset button</param>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern void qn_reset(IntPtr e, bool hard);
|
|
/// <summary>
|
|
/// get the required byte size of a savestate
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="size">size is returned</param>
|
|
/// <returns>string error</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_state_size(IntPtr e, ref int size);
|
|
/// <summary>
|
|
/// save state to buffer
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="dest">buffer</param>
|
|
/// <param name="size">length of buffer</param>
|
|
/// <returns>string error</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_state_save(IntPtr e, byte[] dest, int size);
|
|
/// <summary>
|
|
/// load state from buffer
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="src">buffer</param>
|
|
/// <param name="size">length of buffer</param>
|
|
/// <returns>string error</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_state_load(IntPtr e, byte[] src, int size);
|
|
/// <summary>
|
|
/// query battery ram state
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <returns>true if battery backup sram exists</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern bool qn_has_battery_ram(IntPtr e);
|
|
/// <summary>
|
|
/// query battery ram size
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="size">size is returned</param>
|
|
/// <returns>string error</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_battery_ram_size(IntPtr e, ref int size);
|
|
/// <summary>
|
|
/// save battery ram to buffer
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="dest">buffer</param>
|
|
/// <param name="size">size</param>
|
|
/// <returns>string error</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_battery_ram_save(IntPtr e, byte[] dest, int size);
|
|
/// <summary>
|
|
/// load battery ram from buffer
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="src">buffer</param>
|
|
/// <param name="size">size</param>
|
|
/// <returns>string error</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_battery_ram_load(IntPtr e, byte[] src, int size);
|
|
/// <summary>
|
|
/// clear battery ram
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <returns>string error</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_battery_ram_clear(IntPtr e);
|
|
/// <summary>
|
|
/// set sprite limit; does not affect emulation
|
|
/// </summary>
|
|
/// <param name="e">context</param>
|
|
/// <param name="n">0 to hide, 8 for normal, 64 for all</param>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern void qn_set_sprite_limit(IntPtr e, int n);
|
|
/// <summary>
|
|
/// get memory area for debugging
|
|
/// </summary>
|
|
/// <param name="e">Context</param>
|
|
/// <param name="which"></param>
|
|
/// <param name="data"></param>
|
|
/// <param name="size"></param>
|
|
/// <param name="writable"></param>
|
|
/// <param name="name"></param>
|
|
/// <returns></returns>
|
|
[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);
|
|
/// <summary>
|
|
/// peek the system bus
|
|
/// </summary>
|
|
/// <param name="e">Context</param>
|
|
/// <param name="addr">0000:ffff, but non-ram/rom addresses won't work</param>
|
|
/// <returns></returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern byte qn_peek_prgbus(IntPtr e, int addr);
|
|
/// <summary>
|
|
/// poke the system bus
|
|
/// </summary>
|
|
/// <param name="e">Context</param>
|
|
/// <param name="addr">0000:ffff, but non-ram/rom addresses won't work</param>
|
|
/// <param name="val"></param>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern void qn_poke_prgbus(IntPtr e, int addr, byte val);
|
|
/// <summary>
|
|
/// get internal registers
|
|
/// </summary>
|
|
/// <param name="e">Context</param>
|
|
/// <param name="dest">a, x, y, sp, pc, p</param>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern void qn_get_cpuregs(IntPtr e, [Out] int[] dest);
|
|
/// <summary>
|
|
/// get the mapper that's loaded
|
|
/// </summary>
|
|
/// <param name="e">Context</param>
|
|
/// <param name="number">recieves mapper number</param>
|
|
/// <returns>mapper name</returns>
|
|
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
|
|
public static extern IntPtr qn_get_mapper(IntPtr e, ref int number);
|
|
|
|
/// <summary>
|
|
/// handle "string error" as returned by some quicknes functions
|
|
/// </summary>
|
|
/// <param name="p"></param>
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|