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:
nitsuja- 2010-04-18 08:28:52 +00:00
parent 766818baa8
commit b31042cb10
6 changed files with 92 additions and 92 deletions

View File

@ -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)

View File

@ -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
{

View File

@ -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

View File

@ -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)
{

View File

@ -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();

View File

@ -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()