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