Lua: fix for joypad.set not working when called from outside a registerbegin callback

This commit is contained in:
nitsuja 2009-08-22 07:39:15 +00:00
parent c20c88bdbc
commit 54193cc623
1 changed files with 37 additions and 25 deletions

View File

@ -49,7 +49,7 @@ struct LuaContextInfo {
bool panic; // if set to true, tells the script to terminate as soon as it can do so safely (used because directly calling lua_close() or luaL_error() is unsafe in some contexts)
bool ranExit; // used to prevent a registered exit callback from ever getting called more than once
bool guiFuncsNeedDeferring; // true whenever GUI drawing would be cleared by the next emulation update before it would be visible, and thus needs to be deferred until after the next emulation update
int numDeferredGUIFuncs; // number of deferred function calls accumulated, used to impose an arbitrary limit to avoid running out of memory
int numDeferredFuncs; // number of deferred function calls accumulated, used to impose an arbitrary limit to avoid running out of memory
bool ranFrameAdvance; // false if gens.frameadvance() hasn't been called yet
int transparencyModifier; // values less than 255 will scale down the opacity of whatever the GUI renders, values greater than 255 will increase the opacity of anything transparent the GUI renders
SpeedMode speedMode; // determines how gens.frameadvance() acts
@ -635,11 +635,19 @@ DEFINE_LUA_FUNCTION(emu_persistglobalvariables, "variabletable")
}
static const char* deferredGUIIDString = "lazygui";
static const char* deferredJoySetIDString = "lazyjoy";
#define MAX_DEFERRED_COUNT 16384
// store the most recent C function call from Lua (and all its arguments)
// for later evaluation
void DeferFunctionCall(lua_State* L, const char* idstring)
{
LuaContextInfo& info = GetCurrentInfo();
if(info.numDeferredFuncs < MAX_DEFERRED_COUNT)
info.numDeferredFuncs++;
else
return; // too many deferred functions on the same frame, silently discard the rest
// there might be a cleaner way of doing this using lua_pushcclosure and lua_getref
int num = lua_gettop(L);
@ -694,17 +702,20 @@ void CallDeferredFunctions(lua_State* L, const char* idstring)
}
// clear the list of deferred functions
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, idstring);
LuaContextInfo& info = GetCurrentInfo();
info.numDeferredGUIFuncs = 0;
if(numCalls > 0)
{
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, idstring);
LuaContextInfo& info = GetCurrentInfo();
info.numDeferredFuncs -= numCalls;
if(info.numDeferredFuncs < 0)
info.numDeferredFuncs = 0;
}
// clean the stack
lua_settop(L, 0);
}
#define MAX_DEFERRED_COUNT 16384
bool DeferGUIFuncIfNeeded(lua_State* L)
{
LuaContextInfo& info = GetCurrentInfo();
@ -716,17 +727,8 @@ bool DeferGUIFuncIfNeeded(lua_State* L)
}
if(info.guiFuncsNeedDeferring)
{
if(info.numDeferredGUIFuncs < MAX_DEFERRED_COUNT)
{
// defer whatever function called this one until later
DeferFunctionCall(L, deferredGUIIDString);
info.numDeferredGUIFuncs++;
}
else
{
// too many deferred functions on the same frame
// silently discard the rest
}
// defer whatever function called this one until later
DeferFunctionCall(L, deferredGUIIDString);
return true;
}
@ -1923,6 +1925,7 @@ DEFINE_LUA_FUNCTION(state_load, "location[,option]")
//joypad lib
static const char *button_mappings[] = {
// G E W X Y A B S T U D L R F
"debug","R","L","X","Y","A","B","start","select","up","down","left","right","lid"
};
@ -1947,11 +1950,18 @@ DEFINE_LUA_FUNCTION(joy_set, "buttonTable")
if(movieMode == MOVIEMODE_PLAY) // don't allow tampering with a playing movie's input
return 0; // (although it might be useful sometimes...)
if(!NDS_isProcessingUserInput())
{
// defer this function until when we are processing input
DeferFunctionCall(L, deferredJoySetIDString);
return 0;
}
int index = 1;
(void)joy_getArgControllerNum(L, index);
luaL_checktype(L, index, LUA_TTABLE);
UserButtons buttons = NDS_isProcessingUserInput() ? NDS_getProcessingUserInput().buttons : NDS_getRawUserInput().buttons;
UserButtons& buttons = NDS_getProcessingUserInput().buttons;
for(int i = 0; i < sizeof(button_mappings)/sizeof(*button_mappings); i++)
{
@ -1965,11 +1975,6 @@ DEFINE_LUA_FUNCTION(joy_set, "buttonTable")
lua_pop(L,1);
}
if(NDS_isProcessingUserInput())
NDS_getProcessingUserInput().buttons = buttons;
else
NDS_setPad(buttons.R, buttons.L, buttons.D, buttons.U, buttons.T, buttons.S, buttons.B, buttons.A, buttons.Y, buttons.X, buttons.W, buttons.E, buttons.G, buttons.F);
return 0;
}
@ -3782,7 +3787,7 @@ void ResetInfo(LuaContextInfo& info)
info.stopWorrying = false;
info.panic = false;
info.ranExit = false;
info.numDeferredGUIFuncs = 0;
info.numDeferredFuncs = 0;
info.ranFrameAdvance = false;
info.transparencyModifier = 255;
info.speedMode = SPEEDMODE_NORMAL;
@ -3858,6 +3863,8 @@ void RunLuaScriptFile(int uid, const char* filenameCStr)
// deferred evaluation table
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, deferredGUIIDString);
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, deferredJoySetIDString);
info.started = true;
RefreshScriptStartedStatus();
@ -4373,6 +4380,11 @@ void CallRegisteredLuaFunctions(LuaCallID calltype)
info.guiFuncsNeedDeferring = false;
if(calltype == LUACALL_AFTEREMULATIONGUI)
CallDeferredFunctions(L, deferredGUIIDString);
if(calltype == LUACALL_BEFOREEMULATION)
{
assert(NDS_isProcessingUserInput());
CallDeferredFunctions(L, deferredJoySetIDString);
}
lua_settop(L, 0);
lua_getfield(L, LUA_REGISTRYINDEX, idstring);