mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-09 15:49:25 +01:00
fixed a bug where events scheduled for the same time run in backwards order
simplified CoreTiming::AddEventToQueue fixed emu.frameadvance and implemented emu.wait fixed Lua script termination brought over some luaconf customizations to fix issue 2245 in a better way and deal with certain other scripting problems git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5383 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
766818baa8
commit
b31042cb10
15
Externals/Lua/luaconf.h
vendored
15
Externals/Lua/luaconf.h
vendored
@ -93,9 +93,9 @@
|
||||
#define LUA_CDIR "!\\"
|
||||
#define LUA_PATH_DEFAULT \
|
||||
".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \
|
||||
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua"
|
||||
LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" "?;" "?.lua"
|
||||
#define LUA_CPATH_DEFAULT \
|
||||
".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
|
||||
".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" "?;" "?.dll"
|
||||
|
||||
#else
|
||||
#define LUA_ROOT "/usr/local/"
|
||||
@ -211,7 +211,7 @@
|
||||
@* of a function in debug information.
|
||||
** CHANGE it if you want a different size.
|
||||
*/
|
||||
#define LUA_IDSIZE 60
|
||||
#define LUA_IDSIZE 48
|
||||
|
||||
|
||||
/*
|
||||
@ -303,7 +303,7 @@
|
||||
** mean larger pauses which mean slower collection.) You can also change
|
||||
** this value dynamically.
|
||||
*/
|
||||
#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */
|
||||
#define LUAI_GCPAUSE 150 /* 200% (wait memory to double before next GC) */
|
||||
|
||||
|
||||
/*
|
||||
@ -314,7 +314,7 @@
|
||||
** infinity, where each step performs a full collection.) You can also
|
||||
** change this value dynamically.
|
||||
*/
|
||||
#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
|
||||
#define LUAI_GCMUL 150 /* GC runs 'twice the speed' of memory allocation */
|
||||
|
||||
|
||||
|
||||
@ -378,6 +378,9 @@
|
||||
** a bit, but may be quite useful when debugging C code that interfaces
|
||||
** with Lua. A useful redefinition is to use assert.h.
|
||||
*/
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
#define LUA_USE_APICHECK
|
||||
#endif
|
||||
#if defined(LUA_USE_APICHECK)
|
||||
#include <assert.h>
|
||||
#define luai_apicheck(L,o) { (void)L; assert(o); }
|
||||
@ -562,7 +565,7 @@
|
||||
(defined(__i386) || defined (_M_IX86) || defined(__i386__))
|
||||
|
||||
/* On a Microsoft compiler, use assembler */
|
||||
#if defined(_MSC_VER)
|
||||
#if 0 /*defined(_MSC_VER)*/ /* disabled because it handles some integers very incorrectly and the other case works perfectly fine with current MSVC compilers */
|
||||
|
||||
#define lua_number2int(i,d) __asm fld d __asm fistp i
|
||||
#define lua_number2integer(i,n) lua_number2int(i, n)
|
||||
|
@ -49,6 +49,7 @@ typedef LinkedListItem<BaseEvent> Event;
|
||||
// STATE_TO_SAVE (how?)
|
||||
Event *first;
|
||||
Event *tsFirst;
|
||||
Event *tsLast;
|
||||
|
||||
// event pools
|
||||
Event *eventPool = 0;
|
||||
@ -213,9 +214,13 @@ void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata
|
||||
Event *ne = GetNewTsEvent();
|
||||
ne->time = globalTimer + cyclesIntoFuture;
|
||||
ne->type = event_type;
|
||||
ne->next = tsFirst;
|
||||
ne->next = 0;
|
||||
ne->userdata = userdata;
|
||||
tsFirst = ne;
|
||||
if(!tsFirst)
|
||||
tsFirst = ne;
|
||||
if(tsLast)
|
||||
tsLast->next = ne;
|
||||
tsLast = ne;
|
||||
externalEventSection.Leave();
|
||||
}
|
||||
|
||||
@ -243,44 +248,21 @@ void ClearPendingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
void AddEventToQueue(Event *ne)
|
||||
void AddEventToQueue(Event* ne)
|
||||
{
|
||||
// Damn, this logic got complicated. Must be an easier way.
|
||||
if (!first)
|
||||
Event* prev = NULL;
|
||||
Event** pNext = &first;
|
||||
for(;;)
|
||||
{
|
||||
first = ne;
|
||||
ne->next = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Event *ptr = first;
|
||||
Event *prev = 0;
|
||||
if (ptr->time > ne->time)
|
||||
Event*& next = *pNext;
|
||||
if(!next || ne->time < next->time)
|
||||
{
|
||||
ne->next = first;
|
||||
first = ne;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = first;
|
||||
ptr = first->next;
|
||||
|
||||
while (ptr)
|
||||
{
|
||||
if (ptr->time <= ne->time)
|
||||
{
|
||||
prev = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
//OK, ptr points to the item AFTER our new item. Let's insert
|
||||
ne->next = prev->next;
|
||||
prev->next = ne;
|
||||
// Done!
|
||||
ne->next = next;
|
||||
next = ne;
|
||||
break;
|
||||
}
|
||||
prev = next;
|
||||
pNext = &prev->next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,6 +347,7 @@ void Advance()
|
||||
AddEventToQueue(tsFirst);
|
||||
tsFirst = next;
|
||||
}
|
||||
tsLast = NULL;
|
||||
|
||||
// Move free events to threadsafe pool
|
||||
while(allocatedTsEvents > 0 && eventPool)
|
||||
@ -378,8 +361,8 @@ void Advance()
|
||||
externalEventSection.Leave();
|
||||
|
||||
int cyclesExecuted = slicelength - downcount;
|
||||
|
||||
globalTimer += cyclesExecuted;
|
||||
downcount = slicelength;
|
||||
|
||||
while (first)
|
||||
{
|
||||
@ -387,10 +370,10 @@ void Advance()
|
||||
{
|
||||
// LOG(GEKKO, "[Scheduler] %s (%lld, %lld) ",
|
||||
// first->name ? first->name : "?", (u64)globalTimer, (u64)first->time);
|
||||
event_types[first->type].callback(first->userdata, (int)(globalTimer - first->time));
|
||||
Event *next = first->next;
|
||||
FreeEvent(first);
|
||||
first = next;
|
||||
Event* evt = first;
|
||||
first = first->next;
|
||||
event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time));
|
||||
FreeEvent(evt);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -30,7 +30,8 @@
|
||||
#include "PluginManager.h"
|
||||
#include "HW/Memmap.h"
|
||||
#include "Host.h"
|
||||
|
||||
#include "PowerPC/PowerPC.h"
|
||||
#include "CoreTiming.h"
|
||||
|
||||
extern "C" {
|
||||
#include "lua.h"
|
||||
@ -1107,20 +1108,11 @@ DEFINE_LUA_FUNCTION(bitbit, "whichbit")
|
||||
// (e.g. a savestate could possibly get loaded before emu.wait() returns)
|
||||
DEFINE_LUA_FUNCTION(emulua_wait, "")
|
||||
{
|
||||
/*LuaContextInfo& info = GetCurrentInfo();
|
||||
//LuaContextInfo& info = GetCurrentInfo();
|
||||
|
||||
switch(info.speedMode)
|
||||
{
|
||||
default:
|
||||
case SPEEDMODE_NORMAL:
|
||||
Step_emulua_MainLoop(true, false);
|
||||
break;
|
||||
case SPEEDMODE_NOTHROTTLE:
|
||||
case SPEEDMODE_TURBO:
|
||||
case SPEEDMODE_MAXIMUM:
|
||||
Step_emulua_MainLoop(Core::GetState() == Core::CORE_PAUSE, false);
|
||||
break;
|
||||
}*/
|
||||
// we're only calling this to run user events. (a windows-only example of what that means is the canonical Peek/Translate/Dispatch loop)
|
||||
// hopefully this won't actually advance the emulation state in any non-user-input-driven way when called in this context...
|
||||
CoreTiming::Advance();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1176,6 +1168,7 @@ void LuaRescueHook(lua_State* L, lua_Debug *dbg)
|
||||
{
|
||||
//lua_sethook(L, NULL, 0, 0);
|
||||
assert(L->errfunc || L->errorJmp);
|
||||
luaL_error(L, info.panic ? info.panicMessage : "terminated by user");
|
||||
}
|
||||
|
||||
info.panic = false;
|
||||
@ -1213,7 +1206,7 @@ void printfToOutput(const char* fmt, ...)
|
||||
|
||||
bool FailVerifyAtFrameBoundary(lua_State* L, const char* funcName, int unstartedSeverity=2, int inframeSeverity=2)
|
||||
{
|
||||
if (!Core::isRunning())
|
||||
if (!Core::isRunning() || Core::GetState() == Core::CORE_STOPPING)
|
||||
{
|
||||
static const char* msg = "cannot call %s() when emulation has not started.";
|
||||
switch(unstartedSeverity)
|
||||
@ -1361,25 +1354,36 @@ DEFINE_LUA_FUNCTION(emulua_speedmode, "mode")
|
||||
}*/
|
||||
|
||||
|
||||
// I didn't make it clear enough what this function needs to do, so I'll spell it out this time:
|
||||
// 1: This function needs to cause emulation to run for 1 full frame, until the next frame boundary
|
||||
// (more importantly, the duration it runs for must correspond with 1 frame of input recording movies).
|
||||
// 2: This function needs to return AFTER the frame of emulation has completely finished running.
|
||||
// 3: This function needs to work when it is called from the SAME thread as the emulation (CPU thread).
|
||||
// 4: This function needs to leave the emulation in a normal, UNPAUSED state.
|
||||
|
||||
DEFINE_LUA_FUNCTION(emulua_frameadvance, "")
|
||||
{
|
||||
if(FailVerifyAtFrameBoundary(L, "emu.frameadvance", 0,1))
|
||||
return emulua_wait(L);
|
||||
|
||||
if(Core::GetState() == Core::CORE_UNINITIALIZED || Core::GetState() == Core::CORE_STOPPING)
|
||||
return emulua_wait(L);
|
||||
|
||||
int uid = luaStateToUIDMap[L];
|
||||
LuaContextInfo& info = GetCurrentInfo();
|
||||
|
||||
info.ranFrameAdvance = true;
|
||||
Frame::SetFrameStepping(true);
|
||||
|
||||
// Should step exactly one frame
|
||||
Core::SetState(Core::CORE_RUN);
|
||||
// set to stop the run loop after 1 frame
|
||||
Frame::SetFrameStopping(true);
|
||||
|
||||
//while(Core::GetState() != Core::CORE_PAUSE && !info.panic);
|
||||
// run 1 frame
|
||||
if(info.speedMode == SPEEDMODE_MAXIMUM)
|
||||
CPluginManager::GetInstance().GetVideo()->Video_SetRendering(false);
|
||||
if(Core::GetState() == Core::CORE_PAUSE)
|
||||
Core::SetState(Core::CORE_RUN);
|
||||
PowerPC::RunLoop();
|
||||
|
||||
// continue as normal
|
||||
if(info.speedMode == SPEEDMODE_MAXIMUM)
|
||||
CPluginManager::GetInstance().GetVideo()->Video_SetRendering(true);
|
||||
Frame::SetFrameStopping(false);
|
||||
*PowerPC::GetStatePtr() = PowerPC::CPU_RUNNING;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1407,7 +1411,7 @@ DEFINE_LUA_FUNCTION(emulua_redraw, "")
|
||||
|
||||
DEFINE_LUA_FUNCTION(memory_readbyte, "address")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
unsigned char value = Memory::Read_U8(address);
|
||||
lua_settop(L,0);
|
||||
lua_pushinteger(L, value);
|
||||
@ -1415,7 +1419,7 @@ DEFINE_LUA_FUNCTION(memory_readbyte, "address")
|
||||
}
|
||||
DEFINE_LUA_FUNCTION(memory_readbytesigned, "address")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
signed char value = (signed char)(Memory::Read_U8(address));
|
||||
lua_settop(L,0);
|
||||
lua_pushinteger(L, value);
|
||||
@ -1423,7 +1427,7 @@ DEFINE_LUA_FUNCTION(memory_readbytesigned, "address")
|
||||
}
|
||||
DEFINE_LUA_FUNCTION(memory_readword, "address")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
unsigned short value = Memory::Read_U16(address);
|
||||
lua_settop(L,0);
|
||||
lua_pushinteger(L, value);
|
||||
@ -1431,7 +1435,7 @@ DEFINE_LUA_FUNCTION(memory_readword, "address")
|
||||
}
|
||||
DEFINE_LUA_FUNCTION(memory_readwordsigned, "address")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
signed short value = (signed short)(Memory::Read_U16(address));
|
||||
lua_settop(L,0);
|
||||
lua_pushinteger(L, value);
|
||||
@ -1439,7 +1443,7 @@ DEFINE_LUA_FUNCTION(memory_readwordsigned, "address")
|
||||
}
|
||||
DEFINE_LUA_FUNCTION(memory_readdword, "address")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
unsigned long value = Memory::Read_U32(address);
|
||||
lua_settop(L,0);
|
||||
lua_pushinteger(L, value);
|
||||
@ -1447,7 +1451,7 @@ DEFINE_LUA_FUNCTION(memory_readdword, "address")
|
||||
}
|
||||
DEFINE_LUA_FUNCTION(memory_readdwordsigned, "address")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
signed long value = (signed long)(Memory::Read_U32(address));
|
||||
lua_settop(L,0);
|
||||
lua_pushinteger(L, value);
|
||||
@ -1455,7 +1459,7 @@ DEFINE_LUA_FUNCTION(memory_readdwordsigned, "address")
|
||||
}
|
||||
DEFINE_LUA_FUNCTION(memory_readqword, "address")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
unsigned long long value = Memory::Read_U64(address);
|
||||
lua_settop(L,0);
|
||||
lua_pushinteger(L, (lua_Integer)value);
|
||||
@ -1463,7 +1467,7 @@ DEFINE_LUA_FUNCTION(memory_readqword, "address")
|
||||
}
|
||||
DEFINE_LUA_FUNCTION(memory_readqwordsigned, "address")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
signed long long value = (signed long long)(Memory::Read_U64(address));
|
||||
lua_settop(L,0);
|
||||
lua_pushinteger(L, (lua_Integer)value);
|
||||
@ -1472,28 +1476,28 @@ DEFINE_LUA_FUNCTION(memory_readqwordsigned, "address")
|
||||
|
||||
DEFINE_LUA_FUNCTION(memory_writebyte, "address,value")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
unsigned char value = (unsigned char)(luaL_checkinteger(L,2) & 0xFF);
|
||||
Memory::Write_U8(value, address);
|
||||
return 0;
|
||||
}
|
||||
DEFINE_LUA_FUNCTION(memory_writeword, "address,value")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
unsigned short value = (unsigned short)(luaL_checkinteger(L,2) & 0xFFFF);
|
||||
Memory::Write_U16(value, address);
|
||||
return 0;
|
||||
}
|
||||
DEFINE_LUA_FUNCTION(memory_writedword, "address,value")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
unsigned long value = (unsigned long)(luaL_checkinteger(L,2));
|
||||
Memory::Write_U32(value, address);
|
||||
return 0;
|
||||
}
|
||||
DEFINE_LUA_FUNCTION(memory_writeqword, "address,value")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
unsigned long value = (unsigned long)(luaL_checkinteger(L,2));
|
||||
Memory::Write_U64(value, address);
|
||||
return 0;
|
||||
@ -1501,7 +1505,7 @@ DEFINE_LUA_FUNCTION(memory_writeqword, "address,value")
|
||||
|
||||
DEFINE_LUA_FUNCTION(memory_readbyterange, "address,length")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
int length = (int)luaL_checkinteger(L,2);
|
||||
|
||||
if(length < 0)
|
||||
@ -1530,7 +1534,7 @@ DEFINE_LUA_FUNCTION(memory_readbyterange, "address,length")
|
||||
|
||||
DEFINE_LUA_FUNCTION(memory_isvalid, "address")
|
||||
{
|
||||
unsigned long address = (unsigned long)luaL_checknumber(L,1);
|
||||
unsigned long address = luaL_checkinteger(L,1);
|
||||
lua_settop(L,0);
|
||||
lua_pushboolean(L, Memory::IsRAMAddress(address));
|
||||
return 1;
|
||||
@ -2963,7 +2967,7 @@ DEFINE_LUA_FUNCTION(input_getcurrentinputstatus, "")
|
||||
{
|
||||
lua_newtable(L);
|
||||
|
||||
// TODO: Use pad plugin's input
|
||||
// TODO: implement this (NOT using the pad plugin's input, because that's useless for this purpose)
|
||||
/*
|
||||
// keyboard and mouse button status
|
||||
{
|
||||
@ -3632,6 +3636,8 @@ void RequestAbortLuaScript(int uid, const char* message)
|
||||
info.L->hookcount = 1; // run hook function as soon as possible
|
||||
info.panic = true; // and call luaL_error once we're inside the hook function
|
||||
|
||||
info.restart = false; // also cancel prior restart requests
|
||||
|
||||
if(message)
|
||||
{
|
||||
strncpy(info.panicMessage, message, sizeof(info.panicMessage));
|
||||
@ -3793,9 +3799,6 @@ void StopLuaScript(int uid)
|
||||
|
||||
LuaContextInfo& info = *infoPtr;
|
||||
|
||||
if(info.ranFrameAdvance)
|
||||
Frame::SetFrameStepping(false);
|
||||
|
||||
if(info.running)
|
||||
{
|
||||
// if it's currently running then we can't stop it now without crashing
|
||||
|
@ -21,12 +21,14 @@
|
||||
#include "PluginManager.h"
|
||||
#include "Thread.h"
|
||||
#include "FileUtil.h"
|
||||
#include "PowerPC/PowerPC.h"
|
||||
|
||||
Common::CriticalSection cs_frameSkip;
|
||||
|
||||
namespace Frame {
|
||||
|
||||
bool g_bFrameStep = false;
|
||||
bool g_bFrameStop = false;
|
||||
bool g_bAutoFire = false;
|
||||
u32 g_autoFirstKey = 0, g_autoSecondKey = 0;
|
||||
bool g_bFirstKey = true;
|
||||
@ -53,6 +55,11 @@ void FrameUpdate() {
|
||||
if (g_bFrameStep)
|
||||
Core::SetState(Core::CORE_PAUSE);
|
||||
|
||||
// ("framestop") the only purpose of this is to cause interpreter/jit Run() to return temporarily.
|
||||
// after that we set it back to CPU_RUNNING and continue as normal.
|
||||
if (g_bFrameStop)
|
||||
*PowerPC::GetStatePtr() = PowerPC::CPU_STEPPING;
|
||||
|
||||
if(g_framesToSkip)
|
||||
FrameSkipping();
|
||||
|
||||
@ -123,6 +130,9 @@ bool IsAutoFiring() {
|
||||
void SetFrameStepping(bool bEnabled) {
|
||||
g_bFrameStep = bEnabled;
|
||||
}
|
||||
void SetFrameStopping(bool bEnabled) {
|
||||
g_bFrameStop = bEnabled;
|
||||
}
|
||||
|
||||
void ModifyController(SPADStatus *PadStatus, int controllerID)
|
||||
{
|
||||
|
@ -100,6 +100,7 @@ void SetAutoHold(bool bEnabled, u32 keyToHold = 0);
|
||||
void SetAutoFire(bool bEnabled, u32 keyOne = 0, u32 keyTwo = 0);
|
||||
|
||||
void SetFrameStepping(bool bEnabled);
|
||||
void SetFrameStopping(bool bEnabled);
|
||||
|
||||
void SetFrameSkipping(unsigned int framesToSkip);
|
||||
int FrameSkippingFactor();
|
||||
|
@ -51,8 +51,8 @@ void LuaStop(int uid, bool ok)
|
||||
{
|
||||
if(ok)
|
||||
g_contextMap[uid]->PrintMessage("Script completed successfully!\n");
|
||||
else
|
||||
g_contextMap[uid]->PrintMessage("Script failed\n");
|
||||
//else // disabled because this message makes no sense in certain contexts, and there's always an earlier error message anyway.
|
||||
// g_contextMap[uid]->PrintMessage("Script failed.\n");
|
||||
|
||||
g_contextMap[uid]->OnStop();
|
||||
}
|
||||
@ -173,7 +173,7 @@ void wxLuaWindow::OnEvent_ScriptStop_Press(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
CoreTiming::ScheduleEvent_Threadsafe_Immediate(ev_LuaStop, luaID);
|
||||
OnStop();
|
||||
PrintMessage("Script stopped!\n");
|
||||
PrintMessage("Stopping script...\n");
|
||||
}
|
||||
|
||||
void wxLuaWindow::OnStop()
|
||||
|
Loading…
x
Reference in New Issue
Block a user