Support latch notifications on SNES

This patch is so large since it adds support for passing arguments to
the Lua callback, even if SNES doesn't use those.
This commit is contained in:
Ilari Liusvaara 2013-10-27 14:41:28 +02:00
parent 4f3df85a46
commit 1d2df8ebea
7 changed files with 70 additions and 0 deletions

View file

@ -2,6 +2,8 @@
#define _interface__callbacks__hpp__included__
#include <cstdint>
#include <string>
#include <list>
#include "library/framebuffer.hpp"
/**
@ -21,6 +23,10 @@ public:
* Returns the actual input value used.
*/
virtual int16_t set_input(unsigned port, unsigned index, unsigned control, int16_t value) = 0;
/**
* Notifies about latch. Only called on some systems.
*/
virtual void notify_latch(std::list<std::string>& l) = 0;
/**
* Tick the RTC timer.
*/

View file

@ -86,6 +86,13 @@ public:
T val;
_store_tag(T& a, T v) : addr(a), val(v) {}
};
//Auxillary type for vararg-tag.
struct vararg_tag
{
std::list<std::string> args;
vararg_tag(std::list<std::string>& _args) : args(_args) {}
int pushargs(lua_state& L);
};
//Auxillary type for numeric-tag.
template<typename T> struct _numeric_tag
@ -173,6 +180,12 @@ private:
tag.addr = NULL;
}
template<typename... T> void _callback(int argc, vararg_tag tag, T... args)
{
int e = tag.pushargs(*this);
_callback(argc + e, args...);
}
template<typename... T> void _callback(int argc, nil_tag tag, T... args)
{
pushnil();

View file

@ -32,6 +32,7 @@ void lua_callback_keyhook(const std::string& key, keyboard_key& p) throw();
void lua_callback_do_unsafe_rewind(const std::vector<char>& save, uint64_t secs, uint64_t ssecs, movie& mov, void* u);
bool lua_callback_do_button(uint32_t port, uint32_t controller, uint32_t index, const char* type);
void lua_callback_movie_lost(const char* what);
void lua_callback_do_latch(std::list<std::string>& args);
#define LUA_TIMED_HOOK_IDLE 0
#define LUA_TIMED_HOOK_TIMER 1

View file

@ -419,6 +419,7 @@ uint64_t audio_irq_time;
uint64_t controller_irq_time;
uint64_t frame_irq_time;
struct lsnes_callbacks : public emucore_callbacks
{
public:
@ -444,6 +445,11 @@ public:
return movb.get_movie().next_input(port, index, control);
}
void notify_latch(std::list<std::string>& args)
{
lua_callback_do_latch(args);
}
void timer_tick(uint32_t increment, uint32_t per_second)
{
our_movie.rtc_subsecond += increment;
@ -493,6 +499,17 @@ public:
namespace
{
function_ptr_command<const std::string&> test4(lsnes_cmd, "test4", "test", "test",
[](const std::string& args) throw(std::bad_alloc, std::runtime_error) {
std::list<std::string> _args;
std::string args2 = args;
while(args2 != "") {
std::string sym;
extract_token(args2, sym, " \t");
_args.push_back(sym);
}
lua_callback_do_latch(_args);
});
function_ptr_command<> count_rerecords(lsnes_cmd, "count-rerecords", "Count rerecords",
"Syntax: count-rerecords\nCounts rerecords.\n",
[]() throw(std::bad_alloc, std::runtime_error) {

View file

@ -348,6 +348,12 @@ namespace
return ecore_callbacks->get_randomseed();
}
void notifyLatched()
{
std::list<std::string> dummy;
ecore_callbacks->notify_latch(dummy);
}
void videoRefresh(const uint32_t* data, bool hires, bool interlace, bool overscan);
void audioSample(int16_t l_sample, int16_t r_sample)

View file

@ -340,3 +340,24 @@ std::string try_print_userdata(lua_state& L, int index)
return i.print(L, index);
return "no data available";
}
int lua_state::vararg_tag::pushargs(lua_state& L)
{
int e = 0;
for(auto i : args) {
if(i == "")
L.pushnil();
else if(i == "true")
L.pushboolean(true);
else if(i == "false")
L.pushboolean(false);
else if(regex_match("[+-]?(|0|[1-9][0-9]*)(.[0-9]+)?([eE][+-]?(0|[1-9][0-9]*))?", i))
L.pushnumber(strtod(i.c_str(), NULL));
else if(i[0] == ':')
L.pushlstring(i.substr(1));
else
L.pushlstring(i);
e++;
}
return e;
}

View file

@ -271,6 +271,7 @@ namespace
DEFINE_CB(pre_rewind);
DEFINE_CB(post_rewind);
DEFINE_CB(set_rewind);
DEFINE_CB(latch);
}
void lua_callback_do_paint(struct lua_render_context* ctx, bool non_synthetic) throw()
@ -503,6 +504,11 @@ void lua_callback_movie_lost(const char* what)
run_callback(on_movie_lost, std::string(what));
}
void lua_callback_do_latch(std::list<std::string>& args)
{
run_callback(on_latch, lua_state::vararg_tag(args));
}
bool lua_requests_repaint = false;
bool lua_requests_subframe_paint = false;