mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-22 18:32:44 +01:00
Remove breakpoint system from ScriptMachine
This commit is contained in:
parent
0a982c1fca
commit
8a985309f9
@ -27,11 +27,6 @@ bool SCMOpcodes::findOpcode(ScriptFunctionID id, ScriptFunctionMeta** out)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMachine::interuptNext()
|
|
||||||
{
|
|
||||||
interupt = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptMachine::executeThread(SCMThread &t, int msPassed)
|
void ScriptMachine::executeThread(SCMThread &t, int msPassed)
|
||||||
{
|
{
|
||||||
if( t.wakeCounter > 0 ) {
|
if( t.wakeCounter > 0 ) {
|
||||||
@ -39,8 +34,6 @@ void ScriptMachine::executeThread(SCMThread &t, int msPassed)
|
|||||||
}
|
}
|
||||||
if( t.wakeCounter > 0 ) return;
|
if( t.wakeCounter > 0 ) return;
|
||||||
|
|
||||||
bool hasDebugging = !! bpHandler;
|
|
||||||
|
|
||||||
while( t.wakeCounter == 0 ) {
|
while( t.wakeCounter == 0 ) {
|
||||||
auto pc = t.programCounter;
|
auto pc = t.programCounter;
|
||||||
auto opcode = _file->read<SCMOpcode>(pc);
|
auto opcode = _file->read<SCMOpcode>(pc);
|
||||||
@ -128,22 +121,6 @@ void ScriptMachine::executeThread(SCMThread &t, int msPassed)
|
|||||||
|
|
||||||
ScriptArguments sca(¶meters, &t, this);
|
ScriptArguments sca(¶meters, &t, this);
|
||||||
|
|
||||||
if( hasDebugging )
|
|
||||||
{
|
|
||||||
auto activeBreakpoint = findBreakpoint(t, pc);
|
|
||||||
if( activeBreakpoint || interupt )
|
|
||||||
{
|
|
||||||
interupt = false;
|
|
||||||
SCMBreakpoint bp;
|
|
||||||
bp.pc = t.programCounter;
|
|
||||||
bp.thread = &t;
|
|
||||||
bp.vm = this;
|
|
||||||
bp.function = &code;
|
|
||||||
bp.args = &sca;
|
|
||||||
bpHandler(bp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if RW_SCRIPT_DEBUG
|
#if RW_SCRIPT_DEBUG
|
||||||
static auto sDebugThreadName = getenv("OPENRW_DEBUG_THREAD");
|
static auto sDebugThreadName = getenv("OPENRW_DEBUG_THREAD");
|
||||||
if (!sDebugThreadName || strncmp(t.name, sDebugThreadName, 8) == 0)
|
if (!sDebugThreadName || strncmp(t.name, sDebugThreadName, 8) == 0)
|
||||||
@ -213,7 +190,7 @@ void ScriptMachine::executeThread(SCMThread &t, int msPassed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ScriptMachine::ScriptMachine(GameState* _state, SCMFile *file, SCMOpcodes *ops)
|
ScriptMachine::ScriptMachine(GameState* _state, SCMFile *file, SCMOpcodes *ops)
|
||||||
: _file(file), _ops(ops), state(_state), interupt(false)
|
: _file(file), _ops(ops), state(_state)
|
||||||
{
|
{
|
||||||
auto globals = _file->getGlobalsSize();
|
auto globals = _file->getGlobalsSize();
|
||||||
globalData.resize(globals);
|
globalData.resize(globals);
|
||||||
@ -267,49 +244,3 @@ void ScriptMachine::execute(float dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SCMBreakpointInfo* ScriptMachine::findBreakpoint(SCMThread& t, SCMThread::pc_t pc)
|
|
||||||
{
|
|
||||||
for(std::vector<SCMBreakpointInfo>::iterator bp = breakpoints.begin(); bp != breakpoints.end(); ++bp)
|
|
||||||
{
|
|
||||||
if( (bp->breakpointFlags & SCMBreakpointInfo::BP_ProgramCounter) == SCMBreakpointInfo::BP_ProgramCounter )
|
|
||||||
{
|
|
||||||
if( bp->programCounter != pc )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( (bp->breakpointFlags & SCMBreakpointInfo::BP_ThreadName) == SCMBreakpointInfo::BP_ThreadName )
|
|
||||||
{
|
|
||||||
if( std::strcmp(bp->threadName, t.name) != 0 )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &(*bp);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptMachine::setBreakpointHandler(const ScriptMachine::BreakpointHandler& handler)
|
|
||||||
{
|
|
||||||
bpHandler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptMachine::addBreakpoint(const SCMBreakpointInfo& bpi)
|
|
||||||
{
|
|
||||||
breakpoints.push_back(bpi);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptMachine::removeBreakpoint(const SCMBreakpointInfo& bpi)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < breakpoints.size(); ++i)
|
|
||||||
{
|
|
||||||
if (bpi == breakpoints[i])
|
|
||||||
{
|
|
||||||
breakpoints.erase(breakpoints.begin() + i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -136,59 +136,6 @@ struct SCMThread
|
|||||||
std::array<pc_t, SCM_STACK_DEPTH> calls;
|
std::array<pc_t, SCM_STACK_DEPTH> calls;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
/**
|
|
||||||
* Stores information about where breakpoints should be triggered.
|
|
||||||
*
|
|
||||||
* breakpointFlags stores the state to be checked against.
|
|
||||||
*/
|
|
||||||
struct SCMBreakpointInfo
|
|
||||||
{
|
|
||||||
enum /* Breakpoint Flags */ {
|
|
||||||
BP_ProgramCounter = 1,
|
|
||||||
BP_ThreadName = 2
|
|
||||||
};
|
|
||||||
uint8_t breakpointFlags;
|
|
||||||
SCMThread::pc_t programCounter;
|
|
||||||
char threadName[17];
|
|
||||||
|
|
||||||
bool operator == (const SCMBreakpointInfo& rhs) const
|
|
||||||
{
|
|
||||||
if (breakpointFlags != rhs.breakpointFlags) return false;
|
|
||||||
if ((breakpointFlags & BP_ProgramCounter) != 0)
|
|
||||||
{
|
|
||||||
if (programCounter != rhs.programCounter) return false;
|
|
||||||
}
|
|
||||||
if ((breakpointFlags & BP_ThreadName) != 0)
|
|
||||||
{
|
|
||||||
if (strncmp(threadName, rhs.threadName, 17) != 0) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SCMBreakpointInfo breakThreadName(char threadName[17])
|
|
||||||
{
|
|
||||||
SCMBreakpointInfo i;
|
|
||||||
i.breakpointFlags = BP_ThreadName;
|
|
||||||
std::strncpy(i.threadName, threadName, 17);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information about breakpoints that have been hit
|
|
||||||
*/
|
|
||||||
struct SCMBreakpoint
|
|
||||||
{
|
|
||||||
SCMThread::pc_t pc;
|
|
||||||
SCMThread* thread;
|
|
||||||
ScriptMachine* vm;
|
|
||||||
ScriptFunctionMeta* function;
|
|
||||||
ScriptArguments* args;
|
|
||||||
/** The breakpoint entry that triggered this breakpoint */
|
|
||||||
SCMBreakpointInfo* info;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the actual fetch-execute mechanism for the game script virtual machine.
|
* Implements the actual fetch-execute mechanism for the game script virtual machine.
|
||||||
*
|
*
|
||||||
@ -205,9 +152,6 @@ struct SCMBreakpoint
|
|||||||
* Within ScriptMachine, each thread's program counter is used to execute an instruction
|
* Within ScriptMachine, each thread's program counter is used to execute an instruction
|
||||||
* by consuming the correct number of arguments, allowing the next instruction to be found,
|
* by consuming the correct number of arguments, allowing the next instruction to be found,
|
||||||
* and then dispatching a call to the opcode's function.
|
* and then dispatching a call to the opcode's function.
|
||||||
*
|
|
||||||
* Breakpoints can be set which will call the breakpoint hander, where it is possible
|
|
||||||
* to halt execution by refusing to return until the handler is ready to continue.
|
|
||||||
*/
|
*/
|
||||||
class ScriptMachine
|
class ScriptMachine
|
||||||
{
|
{
|
||||||
@ -228,32 +172,6 @@ public:
|
|||||||
|
|
||||||
GameState* getState() const { return state; }
|
GameState* getState() const { return state; }
|
||||||
|
|
||||||
typedef std::function<void (const SCMBreakpoint&)> BreakpointHandler;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the breakpoint handler callback.
|
|
||||||
*
|
|
||||||
* When the VM reaches an instruction marked as a brekapoint
|
|
||||||
* by addBreakpoint, the handler will be called with information
|
|
||||||
* about the state of the VM and the active thread.
|
|
||||||
*/
|
|
||||||
void setBreakpointHandler(const BreakpointHandler& handler);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a breakpoint
|
|
||||||
*/
|
|
||||||
void addBreakpoint(const SCMBreakpointInfo& bpi);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a breakpoint.
|
|
||||||
*/
|
|
||||||
void removeBreakpoint(const SCMBreakpointInfo& bpi);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interupt VM execution at the start of the next instruction
|
|
||||||
*/
|
|
||||||
void interuptNext();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief executes threads until they are all in waiting state.
|
* @brief executes threads until they are all in waiting state.
|
||||||
*/
|
*/
|
||||||
@ -263,18 +181,12 @@ private:
|
|||||||
SCMFile* _file;
|
SCMFile* _file;
|
||||||
SCMOpcodes* _ops;
|
SCMOpcodes* _ops;
|
||||||
GameState* state;
|
GameState* state;
|
||||||
bool interupt;
|
|
||||||
|
|
||||||
std::list<SCMThread> _activeThreads;
|
std::list<SCMThread> _activeThreads;
|
||||||
|
|
||||||
void executeThread(SCMThread& t, int msPassed);
|
void executeThread(SCMThread& t, int msPassed);
|
||||||
|
|
||||||
SCMBreakpointInfo* findBreakpoint(SCMThread& t, SCMThread::pc_t pc);
|
|
||||||
|
|
||||||
std::vector<SCMByte> globalData;
|
std::vector<SCMByte> globalData;
|
||||||
|
|
||||||
BreakpointHandler bpHandler;
|
|
||||||
std::vector<SCMBreakpointInfo> breakpoints;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -255,26 +255,6 @@ void RWGame::startScript(const std::string& name)
|
|||||||
|
|
||||||
script = new ScriptMachine(state, f, opcodes);
|
script = new ScriptMachine(state, f, opcodes);
|
||||||
|
|
||||||
// Set up breakpoint handler
|
|
||||||
script->setBreakpointHandler(
|
|
||||||
[&](const SCMBreakpoint& bp)
|
|
||||||
{
|
|
||||||
log.info("Script", "Breakpoint hit!");
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << " " << bp.function->description << ".";
|
|
||||||
ss << " Args:";
|
|
||||||
for(size_t a = 0; a < bp.args->getParameters().size(); a++)
|
|
||||||
{
|
|
||||||
auto& arg = bp.args->getParameters()[a];
|
|
||||||
ss << " " << arg.integerValue();
|
|
||||||
if( a != bp.args->getParameters().size()-1 )
|
|
||||||
{
|
|
||||||
ss << ",";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("Script", ss.str());
|
|
||||||
});
|
|
||||||
state->script = script;
|
state->script = script;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
Loading…
Reference in New Issue
Block a user