diff --git a/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs b/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs
index ae7168156b..e0c33e2c34 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/GBA/LibMeteor.cs
@@ -77,5 +77,38 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
///
[DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void libmeteor_setmessagecallback(MessageCallback cb);
+
+ ///
+ /// combination of button flags used by the key callback
+ ///
+ [Flags]
+ public enum Buttons : ushort
+ {
+ BTN_A = 0x001,
+ BTN_B = 0x002,
+ BTN_SELECT = 0x004,
+ BTN_START = 0x008,
+ BTN_RIGHT = 0x010,
+ BTN_LEFT = 0x020,
+ BTN_UP = 0x040,
+ BTN_DOWN = 0x080,
+ BTN_R = 0x100,
+ BTN_L = 0x200
+ }
+
+ ///
+ /// core callback to get input state
+ ///
+ /// buttons pressed bitfield
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate Buttons InputCallback();
+
+ ///
+ /// set callback for whenever input is requested
+ ///
+ ///
+ [DllImport("libmeteor.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void libmeteor_setkeycallback(InputCallback callback);
+
}
}
diff --git a/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs b/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs
index fc5cfef4ac..43a75cb3c3 100644
--- a/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs
+++ b/BizHawk.Emulation/Consoles/Nintendo/GBA/Meteor.cs
@@ -31,12 +31,17 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
public void FrameAdvance(bool render, bool rendersound = true)
{
+ Controller.UpdateControls(Frame++);
+ IsLagFrame = true;
LibMeteor.libmeteor_frameadvance();
+ if (IsLagFrame)
+ LagCount++;
}
public int Frame
{
- get { return 0; }
+ get;
+ private set;
}
public int LagCount
@@ -47,7 +52,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
public bool IsLagFrame
{
- get { return false; }
+ get;
+ private set;
}
public string SystemId
@@ -77,8 +83,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
public void ResetFrameCounter()
{
+ Frame = 0;
+ LagCount = 0;
}
+ #region savestates
+
public void SaveStateText(System.IO.TextWriter writer)
{
}
@@ -104,6 +114,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
return ms.ToArray();
}
+ #endregion
+
public CoreInputComm CoreInputComm { get; set; }
CoreOutputComm _CoreOutputComm = new CoreOutputComm
@@ -126,6 +138,25 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
static GBA attachedcore;
LibMeteor.MessageCallback messagecallback;
+ LibMeteor.InputCallback inputcallback;
+
+ LibMeteor.Buttons GetInput()
+ {
+ IsLagFrame = false;
+ LibMeteor.Buttons ret = 0;
+ if (Controller["Up"]) ret |= LibMeteor.Buttons.BTN_UP;
+ if (Controller["Down"]) ret |= LibMeteor.Buttons.BTN_DOWN;
+ if (Controller["Left"]) ret |= LibMeteor.Buttons.BTN_LEFT;
+ if (Controller["Right"]) ret |= LibMeteor.Buttons.BTN_RIGHT;
+ if (Controller["Select"]) ret |= LibMeteor.Buttons.BTN_SELECT;
+ if (Controller["Start"]) ret |= LibMeteor.Buttons.BTN_START;
+ if (Controller["B"]) ret |= LibMeteor.Buttons.BTN_B;
+ if (Controller["A"]) ret |= LibMeteor.Buttons.BTN_A;
+ if (Controller["L"]) ret |= LibMeteor.Buttons.BTN_L;
+ if (Controller["R"]) ret |= LibMeteor.Buttons.BTN_R;
+ return ret;
+ }
+
void Init()
{
@@ -133,7 +164,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo.GBA
attachedcore.Dispose();
messagecallback = (str) => Console.Write(str.Replace("\n","\r\n"));
+ inputcallback = GetInput;
LibMeteor.libmeteor_setmessagecallback(messagecallback);
+ LibMeteor.libmeteor_setkeycallback(inputcallback);
LibMeteor.libmeteor_init();
videobuffer = new int[240 * 160];
diff --git a/BizHawk.MultiClient/output/dll/libmeteor.dll b/BizHawk.MultiClient/output/dll/libmeteor.dll
index bb3bdf477d..a6a52228bf 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 ff8957f675..712faed8f0 100644
--- a/libmeteor/cinterface.cpp
+++ b/libmeteor/cinterface.cpp
@@ -23,6 +23,19 @@ void print_bizhawk(std::string &msg)
messagecallback(msg.c_str());
}
+uint16_t (*keycallback)() = NULL;
+
+void keyupdate_bizhawk()
+{
+ if (keycallback)
+ AMeteor::_keypad.SetPadState(keycallback() ^ 0x3FF);
+}
+
+EXPORT void libmeteor_setkeycallback(uint16_t (*callback)())
+{
+ keycallback = callback;
+}
+
EXPORT void libmeteor_reset()
{
AMeteor::Reset(AMeteor::UNIT_ALL ^ AMeteor::UNIT_MEMORY_BIOS);
@@ -96,7 +109,7 @@ EXPORT void libmeteor_init()
EXPORT void libmeteor_frameadvance()
{
- AMeteor::_keypad.SetPadState(0x3ff);
+ //AMeteor::_keypad.SetPadState(0x3ff);
AMeteor::Run(10000000);
}
diff --git a/libmeteor/source/debug.hpp b/libmeteor/source/debug.hpp
index 3e77a7e181..a3324ee7d9 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 keyupdate_bizhawk();
#if 0
#define met_abort(str) \
diff --git a/libmeteor/source/io.cpp b/libmeteor/source/io.cpp
index c0cd244ab1..c9cbffc25a 100644
--- a/libmeteor/source/io.cpp
+++ b/libmeteor/source/io.cpp
@@ -99,6 +99,8 @@ namespace AMeteor
// TODO implement unreadable or write-only io
uint8_t Io::Read8 (uint32_t add)
{
+ if ((add & 0xFFE) == KEYINPUT)
+ keyupdate_bizhawk();
//debug ("IO Read8 at " << IOS_ADD << add << " of " << IOS_ADD << (int)*(uint8_t*)(m_iomem + (add & 0xFFF)));
if ((add & 0xFF0) == 0x100)
switch (add & 0xF)
@@ -114,6 +116,8 @@ namespace AMeteor
uint16_t Io::Read16 (uint32_t add)
{
+ if ((add & 0xFFE) == KEYINPUT)
+ keyupdate_bizhawk();
//debug ("IO Read16 at " << IOS_ADD << add << " of " << IOS_ADD << *(uint16_t*)(m_iomem + (add & 0xFFF)));
// special case, reading timers
if ((add & 0xFF0) == 0x100)
@@ -129,6 +133,8 @@ namespace AMeteor
uint32_t Io::Read32 (uint32_t add)
{
+ if ((add & 0xFFC) == KEYINPUT)
+ keyupdate_bizhawk();
//debug ("IO Read32 at " << IOS_ADD << add << " of " << IOS_ADD << *(uint32_t*)(m_iomem + (add & 0xFFF)));
// special case, reading timers
if ((add & 0xFF0) == 0x100)