gba: handle libmeteor aborts. Final Fantasy 5 (J) now crashes instead of drifting off into the sunset

This commit is contained in:
goyuken 2012-11-20 15:52:36 +00:00
parent 00469301e5
commit 83f74f1290
5 changed files with 42 additions and 37 deletions

View File

@ -68,8 +68,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
/// core callback to print meaningful (or meaningless) log messages /// core callback to print meaningful (or meaningless) log messages
/// </summary> /// </summary>
/// <param name="msg">message to be printed</param> /// <param name="msg">message to be printed</param>
/// <param name="abort">true if emulation should be aborted</param>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void MessageCallback(string msg); public delegate void MessageCallback(string msg, bool abort);
/// <summary> /// <summary>
/// set callback for log messages. this can (and should) be called first /// set callback for log messages. this can (and should) be called first

View File

@ -40,33 +40,19 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
LagCount++; 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; Frame = 0;
private set; LagCount = 0;
} }
public int LagCount #region saveram
{
get;
set;
}
public bool IsLagFrame
{
get;
private set;
}
public string SystemId
{
get { return "GBA"; }
}
public bool DeterministicEmulation
{
get { return true; }
}
public byte[] ReadSaveRam() public byte[] ReadSaveRam()
{ {
@ -83,11 +69,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
public bool SaveRamModified { get { return false; } set { } } public bool SaveRamModified { get { return false; } set { } }
public void ResetFrameCounter() #endregion
{
Frame = 0;
LagCount = 0;
}
#region savestates #region savestates
@ -138,12 +120,16 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
get { return null; } get { return null; }
} }
/// <summary>like libsnes, the library is single-instance</summary>
static GBA attachedcore; static GBA attachedcore;
/// <summary>hold pointer to message callback so it won't get GCed</summary>
LibMeteor.MessageCallback messagecallback; LibMeteor.MessageCallback messagecallback;
/// <summary>hold pointer to input callback so it won't get GCed</summary>
LibMeteor.InputCallback inputcallback; LibMeteor.InputCallback inputcallback;
LibMeteor.Buttons GetInput() LibMeteor.Buttons GetInput()
{ {
// libmeteor bitflips everything itself, so 0 == off, 1 == on
IsLagFrame = false; IsLagFrame = false;
LibMeteor.Buttons ret = 0; LibMeteor.Buttons ret = 0;
if (Controller["Up"]) ret |= LibMeteor.Buttons.BTN_UP; if (Controller["Up"]) ret |= LibMeteor.Buttons.BTN_UP;
@ -159,13 +145,20 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
return ret; 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() void Init()
{ {
if (attachedcore != null) if (attachedcore != null)
attachedcore.Dispose(); attachedcore.Dispose();
messagecallback = (str) => Console.Write(str.Replace("\n","\r\n")); messagecallback = PrintMessage;
inputcallback = GetInput; inputcallback = GetInput;
LibMeteor.libmeteor_setmessagecallback(messagecallback); LibMeteor.libmeteor_setmessagecallback(messagecallback);
LibMeteor.libmeteor_setkeycallback(inputcallback); LibMeteor.libmeteor_setkeycallback(inputcallback);
@ -192,6 +185,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
disposed = true; disposed = true;
videohandle.Free(); videohandle.Free();
soundhandle.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(); uint nbytes = LibMeteor.libmeteor_emptysound();
samples = soundbuffer; samples = soundbuffer;
nsamp = (int)(nbytes / 4); nsamp = (int)(nbytes / 4);
} }
public void DiscardSamples() public void DiscardSamples()

View File

@ -4,9 +4,9 @@
#define EXPORT extern "C" __declspec(dllexport) #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; messagecallback = callback;
print_bizhawk("libmeteor message stream operational."); 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) void print_bizhawk(const char *msg)
{ {
if (messagecallback) if (messagecallback)
messagecallback(msg); messagecallback(msg, 0);
} }
void print_bizhawk(std::string &msg) void print_bizhawk(std::string &msg)
{ {
if (messagecallback) 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; uint16_t (*keycallback)() = NULL;

View File

@ -28,6 +28,7 @@
// from cinterface.cpp // from cinterface.cpp
void print_bizhawk(const char *msg); void print_bizhawk(const char *msg);
void print_bizhawk(std::string &msg); void print_bizhawk(std::string &msg);
void abort_bizhawk(const char *msg);
void keyupdate_bizhawk(); void keyupdate_bizhawk();
#if 0 #if 0
@ -52,7 +53,7 @@ void keyupdate_bizhawk();
<< IOS_ADD << ::AMeteor::_cpu.Reg(15) << "\n[r15] = " << IOS_ADD \ << IOS_ADD << ::AMeteor::_cpu.Reg(15) << "\n[r15] = " << IOS_ADD \
<< ::AMeteor::_memory.Read32(::AMeteor::_cpu.Reg(15)) \ << ::AMeteor::_memory.Read32(::AMeteor::_cpu.Reg(15)) \
<< "\nFlag T : " << ::AMeteor::_cpu.ICpsr().thumb << std::endl; \ << "\nFlag T : " << ::AMeteor::_cpu.ICpsr().thumb << std::endl; \
print_bizhawk(_zisrny.str().c_str()); \ abort_bizhawk(_zisrny.str().c_str()); \
} }
#else #else