From b31042cb103a2a60ba8e0460098b632d442db98c Mon Sep 17 00:00:00 2001 From: nitsuja- Date: Sun, 18 Apr 2010 08:28:52 +0000 Subject: [PATCH] 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 --- Externals/Lua/luaconf.h | 15 +++-- Source/Core/Core/Src/CoreTiming.cpp | 65 +++++++----------- Source/Core/Core/Src/LuaInterface.cpp | 87 +++++++++++++------------ Source/Core/Core/Src/OnFrame.cpp | 10 +++ Source/Core/Core/Src/OnFrame.h | 1 + Source/Core/DolphinWX/Src/LuaWindow.cpp | 6 +- 6 files changed, 92 insertions(+), 92 deletions(-) diff --git a/Externals/Lua/luaconf.h b/Externals/Lua/luaconf.h index be7e4fe430..cb0d8db695 100644 --- a/Externals/Lua/luaconf.h +++ b/Externals/Lua/luaconf.h @@ -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 #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) diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp index 19ff68be89..a8ef993bd8 100644 --- a/Source/Core/Core/Src/CoreTiming.cpp +++ b/Source/Core/Core/Src/CoreTiming.cpp @@ -49,6 +49,7 @@ typedef LinkedListItem 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 { diff --git a/Source/Core/Core/Src/LuaInterface.cpp b/Source/Core/Core/Src/LuaInterface.cpp index 4bc4a80e4d..e9ef0d27e1 100644 --- a/Source/Core/Core/Src/LuaInterface.cpp +++ b/Source/Core/Core/Src/LuaInterface.cpp @@ -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 diff --git a/Source/Core/Core/Src/OnFrame.cpp b/Source/Core/Core/Src/OnFrame.cpp index 566bf4658e..8c9a38b251 100644 --- a/Source/Core/Core/Src/OnFrame.cpp +++ b/Source/Core/Core/Src/OnFrame.cpp @@ -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) { diff --git a/Source/Core/Core/Src/OnFrame.h b/Source/Core/Core/Src/OnFrame.h index 21103826c2..416e4dc188 100644 --- a/Source/Core/Core/Src/OnFrame.h +++ b/Source/Core/Core/Src/OnFrame.h @@ -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(); diff --git a/Source/Core/DolphinWX/Src/LuaWindow.cpp b/Source/Core/DolphinWX/Src/LuaWindow.cpp index f1c9f00f10..5b711c7d01 100644 --- a/Source/Core/DolphinWX/Src/LuaWindow.cpp +++ b/Source/Core/DolphinWX/Src/LuaWindow.cpp @@ -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()