diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj
index 9ec852fc16..824b9f1642 100644
--- a/BizHawk.Emulation/BizHawk.Emulation.csproj
+++ b/BizHawk.Emulation/BizHawk.Emulation.csproj
@@ -112,6 +112,7 @@
+
diff --git a/BizHawk.Emulation/Consoles/GB/LibGambatte.cs b/BizHawk.Emulation/Consoles/GB/LibGambatte.cs
new file mode 100644
index 0000000000..4e461d0cc4
--- /dev/null
+++ b/BizHawk.Emulation/Consoles/GB/LibGambatte.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace BizHawk.Emulation.Consoles.GB
+{
+ ///
+ /// static bindings into libgambatte.dll
+ ///
+ public static class LibGambatte
+ {
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr gambatte_create();
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void gambatte_destroy(IntPtr core);
+
+ [Flags]
+ public enum LoadFlags : uint
+ {
+ /// Treat the ROM as not having CGB support regardless of what its header advertises
+ FORCE_DMG = 1,
+ /// Use GBA intial CPU register values when in CGB mode.
+ GBA_CGB = 2,
+ /// Use heuristics to detect and support some multicart MBCs disguised as MBC1.
+ MULTICART_COMPAT = 4
+ }
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int gambatte_load(IntPtr core, string filename, LoadFlags flags);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern long gambatte_runfor(IntPtr core, uint[] videobuf, int pitch, short[] soundbuf, ref uint samples);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void gambatte_reset(IntPtr core);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void gambatte_setdmgpalettecolor(IntPtr core, uint palnum, uint colornum, uint rgb32);
+
+ [Flags]
+ public enum Buttons
+ {
+ A = 0x01,
+ B = 0x02,
+ SELECT = 0x04,
+ START = 0x08,
+ RIGHT = 0x10,
+ LEFT = 0x20,
+ UP = 0x40,
+ DOWN = 0x80
+ }
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void gambatte_setinputgetter(IntPtr core, Func getinput);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void gambatte_setsavedir(IntPtr core, string sdir);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int gambatte_iscgb(IntPtr core);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int gambatte_isloaded(IntPtr core);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void gambatte_savesavedate(IntPtr core);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int gambatte_savestate(IntPtr core, uint[] videobuf, int pitch);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int gambatte_loadstate(IntPtr core);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int gambatte_savestate_file(IntPtr core, uint[] videobuf, int pitch, string filepath);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int gambatte_loadstate_file(IntPtr core, string filepath);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void gambatte_selectstate(IntPtr core, int n);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern int gambatte_currentstate(IntPtr core);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern string gambatte_romtitle(IntPtr core);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void gambatte_setgamegenie(IntPtr core, string codes);
+
+ [DllImport("libgambatte.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void gambatte_setgameshark(IntPtr core, string codes);
+
+ }
+}
diff --git a/libgambatte/libgambatte.vcxproj b/libgambatte/libgambatte.vcxproj
index 6faef05be9..b67d153081 100644
--- a/libgambatte/libgambatte.vcxproj
+++ b/libgambatte/libgambatte.vcxproj
@@ -79,6 +79,7 @@
+
@@ -112,6 +113,7 @@
+
diff --git a/libgambatte/libgambatte.vcxproj.filters b/libgambatte/libgambatte.vcxproj.filters
index ce8d3e1212..e303220cc5 100644
--- a/libgambatte/libgambatte.vcxproj.filters
+++ b/libgambatte/libgambatte.vcxproj.filters
@@ -99,6 +99,9 @@
Source Files
+
+ Source Files
+
@@ -218,5 +221,8 @@
Header Files
+
+ Header Files
+
\ No newline at end of file
diff --git a/libgambatte/src/cinterface.cpp b/libgambatte/src/cinterface.cpp
new file mode 100644
index 0000000000..8d851bb36d
--- /dev/null
+++ b/libgambatte/src/cinterface.cpp
@@ -0,0 +1,148 @@
+#include "cinterface.h"
+#include "gambatte.h"
+
+using namespace gambatte;
+
+
+__declspec(dllexport) void *gambatte_create()
+{
+ GB *g = new GB();
+ return (void *) g;
+}
+
+__declspec(dllexport) void gambatte_destroy(void *core)
+{
+ GB *g = (GB *) core;
+ delete g;
+}
+
+__declspec(dllexport) int gambatte_load(void *core, const char *filename, unsigned flags)
+{
+ GB *g = (GB *) core;
+ int ret = g->load(std::string(filename), flags);
+ return ret;
+}
+
+__declspec(dllexport) long gambatte_runfor(void *core, unsigned long *videobuf, int pitch, short *soundbuf, unsigned *samples)
+{
+ GB *g = (GB *) core;
+ unsigned sampv = *samples;
+ long ret = g->runFor(videobuf, pitch, (unsigned long *) soundbuf, sampv);
+ *samples = sampv;
+ return ret;
+}
+
+__declspec(dllexport) void gambatte_reset(void *core)
+{
+ GB *g = (GB *) core;
+ g->reset();
+}
+
+__declspec(dllexport) void gambatte_setdmgpalettecolor(void *core, unsigned palnum, unsigned colornum, unsigned rgb32)
+{
+ GB *g = (GB *) core;
+ g->setDmgPaletteColor(palnum, colornum, rgb32);
+}
+
+class CInputGetter: public InputGetter
+{
+public:
+
+ unsigned (*inputfunc)(void);
+ unsigned operator()()
+ {
+ return inputfunc ();
+ }
+};
+
+__declspec(dllexport) void gambatte_setinputgetter(void *core, unsigned (*getinput)(void))
+{
+ GB *g = (GB *) core;
+ CInputGetter *cig = new CInputGetter();
+ cig->inputfunc = getinput;
+ // how do i manage the lifetime of cig?
+ g->setInputGetter(cig);
+}
+
+__declspec(dllexport) void gambatte_setsavedir(void *core, const char *sdir)
+{
+ GB *g = (GB *) core;
+ g->setSaveDir(std::string(sdir));
+}
+
+__declspec(dllexport) int gambatte_iscgb(void *core)
+{
+ GB *g = (GB *) core;
+ return g->isCgb();
+}
+
+__declspec(dllexport) int gambatte_isloaded(void *core)
+{
+ GB *g = (GB *) core;
+ return g->isLoaded();
+}
+
+__declspec(dllexport) void gambatte_savesavedate(void *core)
+{
+ GB *g = (GB *) core;
+ g->saveSavedata();
+}
+
+__declspec(dllexport) int gambatte_savestate(void *core, const unsigned long *videobuf, int pitch)
+{
+ GB *g = (GB *) core;
+ return g->saveState(videobuf, pitch);
+}
+
+__declspec(dllexport) int gambatte_loadstate(void *core)
+{
+ GB *g = (GB *) core;
+ return g->loadState();
+}
+
+__declspec(dllexport) int gambatte_savestate_file(void *core, const unsigned long *videobuf, int pitch, const char *filepath)
+{
+ GB *g = (GB *) core;
+ return g->saveState(videobuf, pitch, std::string(filepath));
+}
+
+__declspec(dllexport) int gambatte_loadstate_file(void *core, const char *filepath)
+{
+ GB *g = (GB *) core;
+ return g->loadState(std::string(filepath));
+}
+
+__declspec(dllexport) void gambatte_selectstate(void *core, int n)
+{
+ GB *g = (GB *) core;
+ g->selectState(n);
+}
+
+__declspec(dllexport) int gambatte_currentstate(void *core)
+{
+ GB *g = (GB *) core;
+ return g->currentState();
+}
+
+static char horriblebuff[64];
+__declspec(dllexport) const char *gambatte_romtitle(void *core)
+{
+ GB *g = (GB *) core;
+ const char *s = g->romTitle().c_str();
+ std::strncpy(horriblebuff, s, 63);
+ horriblebuff[63] = 0;
+ return horriblebuff;
+}
+
+__declspec(dllexport) void gambatte_setgamegenie(void *core, const char *codes)
+{
+ GB *g = (GB *) core;
+ g->setGameGenie(std::string(codes));
+}
+
+__declspec(dllexport) void gambatte_setgameshark(void *core, const char *codes)
+{
+ GB *g = (GB *) core;
+ g->setGameShark(std::string(codes));
+}
+
diff --git a/libgambatte/src/cinterface.h b/libgambatte/src/cinterface.h
new file mode 100644
index 0000000000..82e4cc61d8
--- /dev/null
+++ b/libgambatte/src/cinterface.h
@@ -0,0 +1,48 @@
+#ifndef CINTERFACE_H
+#define CINTERFACE_H
+
+extern "C"
+{
+ __declspec(dllexport) void *gambatte_create();
+ __declspec(dllexport) void gambatte_destroy(void *core);
+
+ __declspec(dllexport) int gambatte_load(void *core, const char *filename, unsigned flags);
+
+ __declspec(dllexport) long gambatte_runfor(void *core, unsigned long *videobuf, int pitch, short *soundbuf, unsigned *samples);
+
+ __declspec(dllexport) void gambatte_reset(void *core);
+
+ __declspec(dllexport) void gambatte_setdmgpalettecolor(void *core, unsigned palnum, unsigned colornum, unsigned rgb32);
+
+ __declspec(dllexport) void gambatte_setinputgetter(void *core, unsigned (*getinput)(void));
+
+ __declspec(dllexport) void gambatte_setsavedir(void *core, const char *sdir);
+
+ __declspec(dllexport) int gambatte_iscgb(void *core);
+
+ __declspec(dllexport) int gambatte_isloaded(void *core);
+
+ __declspec(dllexport) void gambatte_savesavedate(void *core);
+
+ __declspec(dllexport) int gambatte_savestate(void *core, const unsigned long *videobuf, int pitch);
+
+ __declspec(dllexport) int gambatte_loadstate(void *core);
+
+ __declspec(dllexport) int gambatte_savestate_file(void *core, const unsigned long *videobuf, int pitch, const char *filepath);
+
+ __declspec(dllexport) int gambatte_loadstate_file(void *core, const char *filepath);
+
+ __declspec(dllexport) void gambatte_selectstate(void *core, int n);
+
+ __declspec(dllexport) int gambatte_currentstate(void *core);
+
+ __declspec(dllexport) const char *gambatte_romtitle(void *core);
+
+ __declspec(dllexport) void gambatte_setgamegenie(void *core, const char *codes);
+
+ __declspec(dllexport) void gambatte_setgameshark(void *core, const char *codes);
+}
+
+
+
+#endif