Merge pull request #1511 from shygoo2/onexecopcode
[Debugger] Add events.onopcode to JS API
This commit is contained in:
commit
be73dcd459
File diff suppressed because it is too large
Load Diff
|
@ -391,6 +391,7 @@ void CDebuggerUI::CPUStepStarted()
|
|||
uint32_t JumpToLocation = R4300iOp::m_JumpToLocation;
|
||||
|
||||
m_ScriptSystem->HookCPUExec()->InvokeByParamInRange(PROGRAM_COUNTER);
|
||||
m_ScriptSystem->HookCPUExecOpcode()->InvokeByParamInRangeWithMaskedValue(PROGRAM_COUNTER, R4300iOp::m_Opcode.Hex);
|
||||
|
||||
// Memory breakpoints
|
||||
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
#include "ScriptInstance.h"
|
||||
#include "ScriptSystem.h"
|
||||
|
||||
int CScriptHook::Add(CScriptInstance* scriptInstance, void* heapptr, uint32_t param, uint32_t param2, bool bOnce)
|
||||
int CScriptHook::Add(CScriptInstance* scriptInstance, void* heapptr, uint32_t param, uint32_t param2,
|
||||
uint32_t param3, uint32_t param4, bool bOnce)
|
||||
{
|
||||
JSCALLBACK jsCallback;
|
||||
jsCallback.scriptInstance = scriptInstance;
|
||||
|
@ -12,6 +13,8 @@ int CScriptHook::Add(CScriptInstance* scriptInstance, void* heapptr, uint32_t pa
|
|||
jsCallback.callbackId = m_ScriptSystem->GetNextCallbackId();
|
||||
jsCallback.param = param;
|
||||
jsCallback.param2 = param2;
|
||||
jsCallback.param3 = param3;
|
||||
jsCallback.param4 = param4;
|
||||
jsCallback.bOnce = bOnce;
|
||||
m_Callbacks.push_back(jsCallback);
|
||||
return jsCallback.callbackId;
|
||||
|
@ -56,6 +59,22 @@ void CScriptHook::InvokeByParamInRange(uint32_t param)
|
|||
}
|
||||
}
|
||||
|
||||
void CScriptHook::InvokeByParamInRangeWithMaskedValue(uint32_t param, uint32_t value)
|
||||
{
|
||||
int nCallbacks = m_Callbacks.size();
|
||||
for (int i = 0; i < nCallbacks; i++)
|
||||
{
|
||||
if (param == m_Callbacks[i].param || (param >= m_Callbacks[i].param && param < m_Callbacks[i].param2))
|
||||
{
|
||||
if ((m_Callbacks[i].param3 & m_Callbacks[i].param4) == (value & m_Callbacks[i].param4))
|
||||
{
|
||||
m_Callbacks[i].scriptInstance->Invoke(m_Callbacks[i].heapptr, param);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CScriptHook::InvokeAll()
|
||||
{
|
||||
int nCallbacks = m_Callbacks.size();
|
||||
|
|
|
@ -13,6 +13,8 @@ private:
|
|||
void* heapptr;
|
||||
uint32_t param;
|
||||
uint32_t param2;
|
||||
uint32_t param3;
|
||||
uint32_t param4;
|
||||
int callbackId;
|
||||
bool bOnce;
|
||||
} JSCALLBACK;
|
||||
|
@ -25,12 +27,15 @@ private:
|
|||
public:
|
||||
CScriptHook(CScriptSystem* scriptSystem);
|
||||
~CScriptHook();
|
||||
int Add(CScriptInstance* scriptInstance, void* heapptr, uint32_t param = 0, uint32_t param2 = 0, bool bOnce = false);
|
||||
int Add(CScriptInstance* scriptInstance, void* heapptr, uint32_t param = 0, uint32_t param2 = 0,
|
||||
uint32_t param3 = 0, uint32_t param4 = 0, bool bOnce = false);
|
||||
void InvokeAll();
|
||||
void InvokeById(int callbackId);
|
||||
void InvokeByParam(uint32_t param);
|
||||
/* invoke if param >= cb.param && param < cb.param2*/
|
||||
void InvokeByParamInRange(uint32_t param);
|
||||
/* invoke if param >= cb.param && param < cb.param2 && (value & cb.param4) == cb.param3 */
|
||||
void InvokeByParamInRangeWithMaskedValue(uint32_t param, uint32_t value);
|
||||
void RemoveById(int callbackId);
|
||||
void RemoveByParam(uint32_t tag);
|
||||
void RemoveByInstance(CScriptInstance* scriptInstance);
|
||||
|
|
|
@ -741,6 +741,8 @@ duk_ret_t CScriptInstance::js_AddCallback(duk_context* ctx)
|
|||
void* heapptr;
|
||||
uint32_t param = 0;
|
||||
uint32_t param2 = 0;
|
||||
uint32_t param3 = 0;
|
||||
uint32_t param4 = 0;
|
||||
bool bOnce = false;
|
||||
|
||||
int argc = duk_get_top(ctx);
|
||||
|
@ -748,25 +750,18 @@ duk_ret_t CScriptInstance::js_AddCallback(duk_context* ctx)
|
|||
hookId = duk_get_string(ctx, 0);
|
||||
heapptr = duk_get_heapptr(ctx, 1);
|
||||
|
||||
if (argc >= 3)
|
||||
{
|
||||
param = duk_get_uint(ctx, 2);
|
||||
if (argc > 3)
|
||||
{
|
||||
param2 = duk_get_uint(ctx, 3);
|
||||
if (argc > 4)
|
||||
{
|
||||
bOnce = duk_get_boolean(ctx, 4) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (argc >= 3) param = duk_get_uint(ctx, 2);
|
||||
if (argc >= 4) param2 = duk_get_uint(ctx, 3);
|
||||
if (argc >= 5) param3 = duk_get_uint(ctx, 4);
|
||||
if (argc >= 6) param4 = duk_get_uint(ctx, 5);
|
||||
if (argc >= 7) bOnce = (duk_get_boolean(ctx, 6) != 0);
|
||||
|
||||
int callbackId = -1;
|
||||
|
||||
CScriptHook* hook = _this->m_ScriptSystem->GetHook(hookId);
|
||||
if (hook != NULL)
|
||||
{
|
||||
callbackId = hook->Add(_this, heapptr, param, param2, bOnce);
|
||||
callbackId = hook->Add(_this, heapptr, param, param2, param3, param4, bOnce);
|
||||
}
|
||||
|
||||
duk_pop_n(ctx, argc);
|
||||
|
|
|
@ -25,6 +25,7 @@ CScriptSystem::CScriptSystem(CDebuggerUI* debugger)
|
|||
m_Debugger = debugger;
|
||||
|
||||
m_HookCPUExec = new CScriptHook(this);
|
||||
m_HookCPUExecOpcode = new CScriptHook(this);
|
||||
m_HookCPURead = new CScriptHook(this);
|
||||
m_HookCPUWrite = new CScriptHook(this);
|
||||
m_HookFrameDrawn = new CScriptHook(this);
|
||||
|
@ -32,6 +33,7 @@ CScriptSystem::CScriptSystem(CDebuggerUI* debugger)
|
|||
RegisterHook("exec", m_HookCPUExec);
|
||||
RegisterHook("read", m_HookCPURead);
|
||||
RegisterHook("write", m_HookCPUWrite);
|
||||
RegisterHook("onopcode", m_HookCPUExecOpcode);
|
||||
RegisterHook("draw", m_HookFrameDrawn);
|
||||
|
||||
HMODULE hInst = GetModuleHandle(NULL);
|
||||
|
|
|
@ -54,6 +54,7 @@ private:
|
|||
CScriptHook* m_HookCPUExec;
|
||||
CScriptHook* m_HookCPURead;
|
||||
CScriptHook* m_HookCPUWrite;
|
||||
CScriptHook* m_HookCPUExecOpcode;
|
||||
|
||||
CScriptHook* m_HookFrameDrawn;
|
||||
|
||||
|
@ -120,6 +121,11 @@ public:
|
|||
return m_HookCPUWrite;
|
||||
}
|
||||
|
||||
CScriptHook* HookCPUExecOpcode()
|
||||
{
|
||||
return m_HookCPUExecOpcode;
|
||||
}
|
||||
|
||||
CScriptHook* HookFrameDrawn()
|
||||
{
|
||||
return m_HookFrameDrawn;
|
||||
|
|
86
apidoc.htm
86
apidoc.htm
|
@ -75,7 +75,7 @@ span.tag {
|
|||
color: #885;
|
||||
font-weight: bold;
|
||||
padding: 0px 2px;
|
||||
font-size: 12px;
|
||||
font-size: 11px;
|
||||
}
|
||||
span.tag2 {
|
||||
float: right;
|
||||
|
@ -86,7 +86,7 @@ span.tag2 {
|
|||
color: #588;
|
||||
font-weight: bold;
|
||||
padding: 0px 2px;
|
||||
font-size: 12px;
|
||||
font-size: 11px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
@ -213,7 +213,7 @@ Player.prototype.move = function(x, y, z)
|
|||
|
||||
Player.prototype.heal = function()
|
||||
{
|
||||
this.health = 100;
|
||||
this.health = 100
|
||||
}
|
||||
|
||||
var player = new Player(0x8033B1AC)
|
||||
|
@ -266,10 +266,10 @@ console.log('Internal ROM name: ' + romName)</div>
|
|||
</div>-->
|
||||
<div class="property">
|
||||
<span class="tag2">emulation thread</span>
|
||||
<span class="tag">interpreter mode</span>
|
||||
<span class="tag">interpreter mode only</span>
|
||||
<div class="propertyname">events.onexec(address, callback)</div>
|
||||
<div class="propertydesc">
|
||||
Adds a CPU execution callback for a virtual address or <a href="AddressRange">AddressRange</a> and returns a callback ID.
|
||||
Adds a CPU execution callback for a virtual address or <a href="#AddressRange">AddressRange</a> and returns a callback ID.
|
||||
<span class="snip">callback</span> will be invoked at the beginning of a CPU step if the program counter is at <span class="snip">address</span>.
|
||||
<span class="snip">callback</span> receives the program counter address at which the event is fired.
|
||||
<pre class="example">
|
||||
|
@ -279,60 +279,106 @@ events.onexec(0x802CB1C0, function()
|
|||
})
|
||||
</pre>
|
||||
<pre class="example">
|
||||
events.onexec(ADDR_ANY, function(addr))
|
||||
events.onexec(ADDR_ANY, function(pc))
|
||||
{
|
||||
// Log every step!
|
||||
console.log('CPU is executing ' + addr.hex())
|
||||
console.log('CPU is executing 0x' + pc.hex())
|
||||
})
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
<span class="tag2">emulation thread</span>
|
||||
<span class="tag">interpreter mode</span>
|
||||
<span class="tag">interpreter mode only</span>
|
||||
<div class="propertyname">events.onread(address, callback)</div>
|
||||
<div class="propertydesc">
|
||||
Adds a CPU read callback for a virtual address or <a href="AddressRange">AddressRange</a> and returns a callback ID.
|
||||
Adds a CPU read callback for a virtual address or <a href="#AddressRange">AddressRange</a> and returns a callback ID.
|
||||
<span class="snip">callback</span> will be invoked at the beginning of a CPU step if the current instruction is going to read from <span class="snip">address</span>.
|
||||
<span class="snip">callback</span> receives the virtual address that the CPU is going to read.
|
||||
<pre class="example">
|
||||
events.onread(0x8033B1B0, function()
|
||||
{
|
||||
console.log('CPU is reading 8033B1B0')
|
||||
console.log('CPU is reading 0x8033B1B0')
|
||||
})
|
||||
</pre>
|
||||
<pre class="example">
|
||||
const addr_range_rom = {start: 0xB0000000, end: 0xB6000000}
|
||||
|
||||
events.onread(addr_range_rom, function(addr)
|
||||
events.onread(ADDR_ANY_CART_ROM_UNC, function(addr)
|
||||
{
|
||||
console.log('CPU is reading ROM ' + addr)
|
||||
console.log('CPU is reading ROM 0x' + addr.hex())
|
||||
})
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
<span class="tag2">emulation thread</span>
|
||||
<span class="tag">interpreter mode</span>
|
||||
<span class="tag">interpreter mode only</span>
|
||||
<div class="propertyname">events.onwrite(address, callback)</div>
|
||||
<div class="propertydesc">
|
||||
Adds a CPU write callback for a virtual address or <a href="AddressRange">AddressRange</a> and returns a callback ID.
|
||||
Adds a CPU write callback for a virtual address or <a href="#AddressRange">AddressRange</a> and returns a callback ID.
|
||||
<span class="snip">callback</span> will be invoked at the beginning of a CPU step if the current instruction is going to write to <span class="snip">address</span>.
|
||||
<span class="snip">callback</span> receives the virtual address that the CPU is going to write to.
|
||||
<pre class="example">
|
||||
events.onwrite(0x8033B1B0, function()
|
||||
{
|
||||
console.log('CPU is modifying 8033B1B0')
|
||||
console.log('CPU is modifying 0x8033B1B0')
|
||||
})
|
||||
</pre>
|
||||
<pre class="example">
|
||||
events.onwrite({0xB0000000, 0x90000000}, function(addr)
|
||||
events.onwrite(ADDR_ANY_CART_ROM_UNC, function(addr)
|
||||
{
|
||||
console.log(gpr.pc.hex() + ': wrote to cartridge ' + addr.hex());
|
||||
console.log(gpr.pc.hex() + ': wrote to cartridge ' + addr.hex())
|
||||
})
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
<span class="tag2">emulation thread</span>
|
||||
<span class="tag">interpreter mode only</span>
|
||||
<div class="propertyname">events.onopcode(address, opcode, callback)</div>
|
||||
<div class="propertydesc">
|
||||
Adds a CPU executions callback for a virtual address or <a href="#AddressRange">AddressRange</a> and returns a callback ID.
|
||||
<span class="snip">callback</span> will be invoked at the beginning of a CPU step if the program counter is at <span class="snip">address</span> and <span class="snip">opcode</span> is equal to the opcode to be executed.
|
||||
<span class="snip">callback</span> receives the program counter address at which the event is fired.
|
||||
<pre class="example">
|
||||
const JR_RA = 0x03E00008 // 'jr ra' command
|
||||
|
||||
events.onopcode(ADDR_ANY, JR_RA, function(pc)
|
||||
{
|
||||
console.log(pc.hex()) // log pc at every 'jr ra'
|
||||
})
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
<span class="tag2">emulation thread</span>
|
||||
<span class="tag">interpreter mode only</span>
|
||||
<div class="propertyname">events.onopcode(address, opcode, mask, callback)</div>
|
||||
<div class="propertydesc">
|
||||
Adds a CPU executions callback for a virtual address or <a href="#AddressRange">AddressRange</a> and returns a callback ID.
|
||||
<span class="snip">callback</span> will be invoked at the beginning of a CPU step if the program counter is at <span class="snip">address</span> and <span class="snip">opcode</span> is equal to the opcode to be executed ANDed with <span class="snip">mask</span>.
|
||||
<span class="snip">callback</span> receives the program counter address at which the event is fired.
|
||||
<pre class="example">
|
||||
const ADDIU_SP_SP = 0x27BD0000 // 'addiu sp, sp, 0x0000'
|
||||
const NO_IMM16 = 0xFFFF0000 // mask off immediate field
|
||||
|
||||
events.onopcode(ADDR_ANY, ADDIU_SP_SP, NO_IMM16, function(pc)
|
||||
{
|
||||
// log pc at every 'addiu sp, sp, x' regardless of the immediate value
|
||||
console.log(pc.hex())
|
||||
})
|
||||
</pre>
|
||||
<pre class="example">
|
||||
const JAL = 0x0C000000 // 'jal 0x00000000'
|
||||
const NO_TARGET = 0xFC000000 // mask off target field
|
||||
|
||||
events.onopcode(ADDR_ANY, JAL, NO_TARGET, function(pc)
|
||||
{
|
||||
// log pc at every 'jal' regardless of the target address
|
||||
console.log(pc.hex())
|
||||
})
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
<span class="tag2">emulation thread</span>
|
||||
<div class="propertyname">events.ondraw(callback)</div>
|
||||
|
@ -468,7 +514,7 @@ console.log('size: ' + stats.size)
|
|||
<div class="property">
|
||||
<div class="propertyname">fs.stat(path)</div>
|
||||
<div class="propertydesc">
|
||||
Returns an <a href="#fs.Stats">fs.Stats</a> object describing the file or directory pointed to by <span class="snip">path</span>. Returns <span class="snip">false</span> if the operation failed..
|
||||
Returns an <a href="#fs.Stats">fs.Stats</a> object describing the file or directory pointed to by <span class="snip">path</span>. Returns <span class="snip">false</span> if the operation failed.
|
||||
</div>
|
||||
</div>
|
||||
<div class="property">
|
||||
|
|
Loading…
Reference in New Issue