diff --git a/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs b/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs index e0c33e2c34..0b75031d9d 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs @@ -68,8 +68,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA /// core callback to print meaningful (or meaningless) log messages /// /// message to be printed + /// true if emulation should be aborted [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void MessageCallback(string msg); + public delegate void MessageCallback(string msg, bool abort); /// /// set callback for log messages. this can (and should) be called first diff --git a/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs b/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs index 482eaa2f51..b804db5dc8 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs @@ -40,33 +40,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA LagCount++; } - public int Frame + public int Frame { get; private set; } + public int LagCount { get; set; } + public bool IsLagFrame { get; private set; } + public string SystemId { get { return "GBA"; } } + public bool DeterministicEmulation { get { return true; } } + + public void ResetFrameCounter() { - get; - private set; + Frame = 0; + LagCount = 0; } - public int LagCount - { - get; - set; - } - - public bool IsLagFrame - { - get; - private set; - } - - public string SystemId - { - get { return "GBA"; } - } - - public bool DeterministicEmulation - { - get { return true; } - } + #region saveram public byte[] ReadSaveRam() { @@ -83,11 +69,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA public bool SaveRamModified { get { return false; } set { } } - public void ResetFrameCounter() - { - Frame = 0; - LagCount = 0; - } + #endregion #region savestates @@ -138,12 +120,16 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA get { return null; } } + /// like libsnes, the library is single-instance static GBA attachedcore; + /// hold pointer to message callback so it won't get GCed LibMeteor.MessageCallback messagecallback; + /// hold pointer to input callback so it won't get GCed LibMeteor.InputCallback inputcallback; LibMeteor.Buttons GetInput() { + // libmeteor bitflips everything itself, so 0 == off, 1 == on IsLagFrame = false; LibMeteor.Buttons ret = 0; if (Controller["Up"]) ret |= LibMeteor.Buttons.BTN_UP; @@ -159,13 +145,20 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA return ret; } + void PrintMessage(string msg, bool abort) + { + if (!abort) + Console.Write(msg.Replace("\n", "\r\n")); + else + throw new Exception("libmeteor abort:\n " + msg); + } void Init() { if (attachedcore != null) attachedcore.Dispose(); - messagecallback = (str) => Console.Write(str.Replace("\n","\r\n")); + messagecallback = PrintMessage; inputcallback = GetInput; LibMeteor.libmeteor_setmessagecallback(messagecallback); LibMeteor.libmeteor_setkeycallback(inputcallback); @@ -192,6 +185,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA disposed = true; videohandle.Free(); soundhandle.Free(); + // guarantee crash if it gets accessed + LibMeteor.libmeteor_setbuffers(IntPtr.Zero, 240 * 160 * 4, IntPtr.Zero, 4); + messagecallback = null; + inputcallback = null; + LibMeteor.libmeteor_setmessagecallback(messagecallback); + LibMeteor.libmeteor_setkeycallback(inputcallback); } } @@ -225,7 +224,6 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA uint nbytes = LibMeteor.libmeteor_emptysound(); samples = soundbuffer; nsamp = (int)(nbytes / 4); - } public void DiscardSamples() diff --git a/BizHawk.MultiClient/output/dll/libmeteor.dll b/BizHawk.MultiClient/output/dll/libmeteor.dll index a6a52228bf..5335be733a 100644 Binary files a/BizHawk.MultiClient/output/dll/libmeteor.dll and b/BizHawk.MultiClient/output/dll/libmeteor.dll differ diff --git a/libmeteor/cinterface.cpp b/libmeteor/cinterface.cpp index 712faed8f0..0856955f39 100644 --- a/libmeteor/cinterface.cpp +++ b/libmeteor/cinterface.cpp @@ -4,9 +4,9 @@ #define EXPORT extern "C" __declspec(dllexport) -void (*messagecallback)(const char *msg) = NULL; +void (*messagecallback)(const char *msg, int abort) = NULL; -EXPORT void libmeteor_setmessagecallback(void (*callback)(const char *msg)) +EXPORT void libmeteor_setmessagecallback(void (*callback)(const char *msg, int abort)) { messagecallback = callback; print_bizhawk("libmeteor message stream operational."); @@ -15,12 +15,17 @@ EXPORT void libmeteor_setmessagecallback(void (*callback)(const char *msg)) void print_bizhawk(const char *msg) { if (messagecallback) - messagecallback(msg); + messagecallback(msg, 0); } void print_bizhawk(std::string &msg) { if (messagecallback) - messagecallback(msg.c_str()); + messagecallback(msg.c_str(), 0); +} +void abort_bizhawk(const char *msg) +{ + if (messagecallback) + messagecallback(msg, 1); } uint16_t (*keycallback)() = NULL; diff --git a/libmeteor/source/debug.hpp b/libmeteor/source/debug.hpp index a3324ee7d9..7c2c5236ae 100644 --- a/libmeteor/source/debug.hpp +++ b/libmeteor/source/debug.hpp @@ -28,6 +28,7 @@ // from cinterface.cpp void print_bizhawk(const char *msg); void print_bizhawk(std::string &msg); +void abort_bizhawk(const char *msg); void keyupdate_bizhawk(); #if 0 @@ -52,7 +53,7 @@ void keyupdate_bizhawk(); << IOS_ADD << ::AMeteor::_cpu.Reg(15) << "\n[r15] = " << IOS_ADD \ << ::AMeteor::_memory.Read32(::AMeteor::_cpu.Reg(15)) \ << "\nFlag T : " << ::AMeteor::_cpu.ICpsr().thumb << std::endl; \ - print_bizhawk(_zisrny.str().c_str()); \ + abort_bizhawk(_zisrny.str().c_str()); \ } #else