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