[Debugger] JS API: Expand AddressRange class, misc fixes (#2168)

This commit is contained in:
shyguyhex 2022-01-12 14:36:30 -06:00 committed by GitHub
parent 16667ec4f9
commit 8559be556b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 217 additions and 54 deletions

View File

@ -1,8 +1,8 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- Generated Dec 31 2021 --> <!-- Generated Jan 12 2022 -->
<!-- YAML source: https://github.com/shygoo/pj64d-docs --> <!-- YAML source: https://github.com/shygoo/pj64d-docs -->
<head> <head>
<title>Project64 JavaScript API 2021.12.31</title> <title>Project64 JavaScript API 2022.01.12</title>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic' rel='stylesheet' type='text/css'> <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic' rel='stylesheet' type='text/css'>
<style> <style>
:root { :root {
@ -279,7 +279,7 @@ window.addEventListener('load', function() {
<div class="sidebar"> <div class="sidebar">
<div class="sidebar-content"> <div class="sidebar-content">
<div class="pagetitle">Project64 JavaScript API</div> <div class="pagetitle">Project64 JavaScript API</div>
2021.12.31 2022.01.12
<hr> <hr>
<ul> <ul>
<p><li><a class="" href="#Project64 JavaScript API">Project64 JavaScript API</a><ul> <p><li><a class="" href="#Project64 JavaScript API">Project64 JavaScript API</a><ul>
@ -345,7 +345,15 @@ window.addEventListener('load', function() {
<li><a class="" href="#events_onmousemove">events.onmousemove(callback)</a></li> <li><a class="" href="#events_onmousemove">events.onmousemove(callback)</a></li>
<li><a class="" href="#MouseEvent">MouseEvent</a></li> <li><a class="" href="#MouseEvent">MouseEvent</a></li>
<li><a class="" href="#events_remove">events.remove(callbackId)</a></li> <li><a class="" href="#events_remove">events.remove(callbackId)</a></li>
<li><a class="" href="#AddressRange">new AddressRange(start, end)</a></li> </ul></li></p>
<p><li><a class="" href="#AddressRange">AddressRange</a>: Address range class<ul>
<li><a class="" href="#new_AddressRange">new AddressRange(start, end)</a></li>
<li><a class="" href="#range_size">range.size()</a></li>
<li><a class="" href="#range_includes">range.includes(address)</a></li>
<li><a class="" href="#range_offset">range.offset(address)</a></li>
<li><a class="" href="#range_address">range.address(offset)</a></li>
<li><a class="" href="#range_start">range.start</a></li>
<li><a class="" href="#range_end">range.end</a></li>
</ul></li></p> </ul></li></p>
<p><li><a class="" href="#N64Image">N64Image</a>: N64 image class<ul> <p><li><a class="" href="#N64Image">N64Image</a>: N64 image class<ul>
<li><a class="" href="#new_N64Image">new N64Image(width, height[, format [, pixels[, palette]]])</a></li> <li><a class="" href="#new_N64Image">new N64Image(width, height[, format [, pixels[, palette]]])</a></li>
@ -438,6 +446,7 @@ window.addEventListener('load', function() {
<p><li><a class="" href="#script">script</a>: Script instance configuration interface<ul> <p><li><a class="" href="#script">script</a>: Script instance configuration interface<ul>
<li><a class="" href="#script_keepalive">script.keepalive(keepAlive)</a></li> <li><a class="" href="#script_keepalive">script.keepalive(keepAlive)</a></li>
<li><a class="" href="#script_timeout">script.timeout(milliseconds)</a></li> <li><a class="" href="#script_timeout">script.timeout(milliseconds)</a></li>
<li><a class="" href="#script_abort">script.abort()</a></li>
</ul></li></p> </ul></li></p>
<p><li><a class="" href="#Globals">Globals</a><ul> <p><li><a class="" href="#Globals">Globals</a><ul>
<li><a class="" href="#global">global</a></li> <li><a class="" href="#global">global</a></li>
@ -590,7 +599,7 @@ Pauses emulation.
Resumes emulation. Resumes emulation.
<!-- pj64_limitfps --> <!-- pj64_limitfps -->
<p><div class="prop"><span class="title" id="pj64_limitfps">pj64.limitfps(limitFps)</span></div> <p><div class="prop"><span class="title" id="pj64_limitfps">pj64.limitfps(limitFps)</span></div>
<div class="tsproto">pj64.limitfps(limitFps: boolean)</div> <div class="tsproto">pj64.limitfps(limitFps: boolean): void</div>
</p> </p>
Enables or disables the FPS limit. Enables or disables the FPS limit.
<!-- pj64.installDirectory --> <!-- pj64.installDirectory -->
@ -718,7 +727,7 @@ Returns a block of data from memory as a <a target="blank" href="https://nodejs.
</pre> </pre>
<!-- mem_setblock --> <!-- mem_setblock -->
<p><div class="prop"><span class="title" id="mem_setblock">mem.setblock(address, data[, length])</span></div> <p><div class="prop"><span class="title" id="mem_setblock">mem.setblock(address, data[, length])</span></div>
<div class="tsproto">mem.setblock(address: number, data: string | Buffer | TypedArray, length: number): Buffer</div> <div class="tsproto">mem.setblock(address: number, data: string | Buffer | TypedArray, length?: number): void</div>
</p> </p>
Writes a block of data into memory. <span class="snip">data</span> may be one of the following types&#58; Writes a block of data into memory. <span class="snip">data</span> may be one of the following types&#58;
<a target="blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer">ArrayBuffer</a>, <a target="blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer">ArrayBuffer</a>,
@ -738,7 +747,7 @@ Returns a zero-terminated ASCII string from memory.
</pre> </pre>
<!-- mem_setstring --> <!-- mem_setstring -->
<p><div class="prop"><span class="title" id="mem_setstring">mem.setstring(address, data[, length])</span></div> <p><div class="prop"><span class="title" id="mem_setstring">mem.setstring(address, data[, length])</span></div>
<div class="tsproto">mem.setstring(address: number, data: string | Buffer | TypedArray, length?: number): Buffer</div> <div class="tsproto">mem.setstring(address: number, data: string | Buffer | TypedArray, length?: number): void</div>
</p> </p>
Writes a string into memory (alias of <a href="#mem_setblock">mem.setblock</a>). Writes a string into memory (alias of <a href="#mem_setblock">mem.setblock</a>).
<!-- mem_ramSize --> <!-- mem_ramSize -->
@ -812,6 +821,7 @@ Registers a callback that is invoked at the beginning of a CPU step if the progr
<span class="snip">callback</span> receives a <a href="#CPUExecEvent">CPUExecEvent</a> object. <span class="snip">callback</span> receives a <a href="#CPUExecEvent">CPUExecEvent</a> object.
<p>Returns a callback ID.</p> <p>Returns a callback ID.</p>
<pre class="ex"> <pre class="ex">
<span class="js-comment">// SM64 US</span>
<span class="js-word">events</span>.<span class="js-word">onexec</span>(<span class="js-number">0x802CB1C0</span>, <span class="js-keyword">function</span>() { <span class="js-word">events</span>.<span class="js-word">onexec</span>(<span class="js-number">0x802CB1C0</span>, <span class="js-keyword">function</span>() {
<span class="js-word">console</span>.<span class="js-word">log</span>(<span class="js-string">"func_802CB1C0 was called"</span>); <span class="js-word">console</span>.<span class="js-word">log</span>(<span class="js-string">"func_802CB1C0 was called"</span>);
}); });
@ -845,14 +855,6 @@ Registers a callback that is invoked at the beginning of a CPU step if the CPU i
<span class="snip">address</span> may be a single address or an object containing <span class="snip">start</span> and <span class="snip">end</span> address properties (e.g. <a href="#AddressRange">AddressRange</a>). <span class="snip">address</span> may be a single address or an object containing <span class="snip">start</span> and <span class="snip">end</span> address properties (e.g. <a href="#AddressRange">AddressRange</a>).
<span class="snip">callback</span> receives a <a href="#CPUReadWriteEvent">CPUReadWriteEvent</a> object. <span class="snip">callback</span> receives a <a href="#CPUReadWriteEvent">CPUReadWriteEvent</a> object.
<p>Returns a callback ID.</p> <p>Returns a callback ID.</p>
<pre class="ex">
<span class="js-word">events</span>.<span class="js-word">onwrite</span>(<span class="js-word">PI_WR_LEN_REG</span>, <span class="js-keyword">function</span>(<span class="js-word">e</span>) {
<span class="js-keyword">var</span> <span class="js-word">romAddr</span> = <span class="js-word">mem</span>.<span class="js-word">u32</span>[<span class="js-word">PI_CART_ADDR_REG</span>] + <span class="js-word">K1BASE</span>;
<span class="js-keyword">var</span> <span class="js-word">ramAddr</span> = <span class="js-word">mem</span>.<span class="js-word">u32</span>[<span class="js-word">PI_DRAM_ADDR_REG</span>] + <span class="js-word">K0BASE</span>;
<span class="js-keyword">var</span> <span class="js-word">length</span> = <span class="js-word">e</span>.<span class="js-word">value</span> + <span class="js-number">1</span>;
<span class="js-word">console</span>.<span class="js-word">log</span>(<span class="js-string">"Loaded "</span> + <span class="js-word">romAddr</span>.<span class="js-word">hex</span>() + <span class="js-string">" -> "</span> + <span class="js-word">ramAddr</span>.<span class="js-word">hex</span>() + <span class="js-string">" (Length: "</span> + <span class="js-word">length</span>.<span class="js-word">hex</span>() + <span class="js-string">")"</span>);
});
</pre>
<!-- CPUReadWriteEvent --> <!-- CPUReadWriteEvent -->
<p><div class="prop"><span class="title" id="CPUReadWriteEvent">CPUReadWriteEvent</span></div> <p><div class="prop"><span class="title" id="CPUReadWriteEvent">CPUReadWriteEvent</span></div>
</p> </p>
@ -870,7 +872,7 @@ Registers a callback that is invoked at the beginning of a CPU step if the CPU i
</p> </p>
<p> <p>
<table> <table>
<thead><tr><td><b>e.type</b></td><td><b>Opcode(s)</b></td></tr></thead> <thead><tr><td><b>e.valueType</b></td><td><b>Opcode(s)</b></td></tr></thead>
<tr><td><span class="snip">s8</span></td><td>LB, SB</td></tr> <tr><td><span class="snip">s8</span></td><td>LB, SB</td></tr>
<tr><td><span class="snip">u8</span></td><td>LBU</td></tr> <tr><td><span class="snip">u8</span></td><td>LBU</td></tr>
<tr><td><span class="snip">s16</span></td><td>LH, SH</td></tr> <tr><td><span class="snip">s16</span></td><td>LH, SH</td></tr>
@ -1023,7 +1025,7 @@ Registers a callback that is invoked when a task is sent to the RSP.
all physical addresses are converted to KSEG0 addresses.</p> all physical addresses are converted to KSEG0 addresses.</p>
<!-- events_onpidma --> <!-- events_onpidma -->
<p><div class="prop"><span class="title" id="events_onpidma">events.onpidma(callback)</span></div> <p><div class="prop"><span class="title" id="events_onpidma">events.onpidma(callback)</span></div>
<div class="tsproto">events.onpidma(callback: (e: PIEvent) => void)</div> <div class="tsproto">events.onpidma(callback: (e: PIEvent) => void): number</div>
</p> </p>
Registers a callback that is invoked when a PI DMA transfer is going to occur. Registers a callback that is invoked when a PI DMA transfer is going to occur.
<span class="snip">callback</span> receives a <a href="#PIEvent">PIEvent</a> object. <span class="snip">callback</span> receives a <a href="#PIEvent">PIEvent</a> object.
@ -1098,8 +1100,14 @@ Unregisters the callback specified by <span class="snip">callbackId</span>.
<span class="js-word">events</span>.<span class="js-word">remove</span>(<span class="js-word">e</span>.<span class="js-word">callbackId</span>); <span class="js-word">events</span>.<span class="js-word">remove</span>(<span class="js-word">e</span>.<span class="js-word">callbackId</span>);
}); });
</pre> </pre>
</div>
<!-- AddressRange --> <!-- AddressRange -->
<p><div class="prop"><span class="title" id="AddressRange">new AddressRange(start, end)</span></div> <div class="module">
<div class="modtitle"><span class="title" id="AddressRange">AddressRange</span></div>
Address range class
<!-- new_AddressRange -->
<p><div class="prop"><span class="title" id="new_AddressRange">new AddressRange(start, end)</span></div>
<div class="tsproto">new AddressRange(start: number, end: number)</div> <div class="tsproto">new AddressRange(start: number, end: number)</div>
</p> </p>
Creates an immutable object with <span class="snip">start</span> and <span class="snip">end</span> address properties. Creates an immutable object with <span class="snip">start</span> and <span class="snip">end</span> address properties.
@ -1117,6 +1125,38 @@ Creates an immutable object with <span class="snip">start</span> and <span class
<tr><td><span class="snip">ADDR_ANY_CART_ROM</span> </td><td>0x90000000 &#58; 0x95FFFFFF</td><td>Cached cartridge ROM</td></tr> <tr><td><span class="snip">ADDR_ANY_CART_ROM</span> </td><td>0x90000000 &#58; 0x95FFFFFF</td><td>Cached cartridge ROM</td></tr>
<tr><td><span class="snip">ADDR_ANY_CART_ROM_UNC</span> </td><td>0xB0000000 &#58; 0xB5FFFFFF</td><td>Uncached cartridge ROM</td></tr> <tr><td><span class="snip">ADDR_ANY_CART_ROM_UNC</span> </td><td>0xB0000000 &#58; 0xB5FFFFFF</td><td>Uncached cartridge ROM</td></tr>
</table> </table>
<!-- range_size -->
<p><div class="prop"><span class="title" id="range_size">range.size()</span></div>
<div class="tsproto">range.size(): number</div>
</p>
Returns the byte length of the address range (<span class="snip">range.end</span> - <span class="snip">range.start</span> + 1).
<!-- range_includes -->
<p><div class="prop"><span class="title" id="range_includes">range.includes(address)</span></div>
<div class="tsproto">range.includes(address: number): boolean</div>
</p>
Returns <span class="snip">true</span> if <span class="snip">address</span> is within the bounds of the address range.
<!-- range_offset -->
<p><div class="prop"><span class="title" id="range_offset">range.offset(address)</span></div>
<div class="tsproto">range.offset(address: number): number</div>
</p>
Converts <span class="snip">address</span> to an offset and returns the result (<span class="snip">address</span> - <span class="snip">range.start</span>).
<p>Throws an error if <span class="snip">address</span> is out of bounds.</p>
<!-- range_address -->
<p><div class="prop"><span class="title" id="range_address">range.address(offset)</span></div>
<div class="tsproto">range.address(offset: number): number</div>
</p>
Converts <span class="snip">offset</span> to an address and returns the result (<span class="snip">range.start</span> + <span class="snip">offset</span>).
<p>Throws an error if <span class="snip">offset</span> is out of bounds.</p>
<!-- range_start -->
<p><div class="prop"><span class="title" id="range_start">range.start</span></div>
<div class="tsproto">range.start: number</div>
</p>
The start address.
<!-- range_end -->
<p><div class="prop"><span class="title" id="range_end">range.end</span></div>
<div class="tsproto">range.end: number</div>
</p>
The end address.
</div> </div>
<!-- N64Image --> <!-- N64Image -->
@ -1125,7 +1165,7 @@ Creates an immutable object with <span class="snip">start</span> and <span class
N64 image class N64 image class
<!-- new_N64Image --> <!-- new_N64Image -->
<p><div class="prop"><span class="title" id="new_N64Image">new N64Image(width, height[, format [, pixels[, palette]]])</span></div> <p><div class="prop"><span class="title" id="new_N64Image">new N64Image(width, height[, format [, pixels[, palette]]])</span></div>
<div class="tsproto">new N64Image(width: number, height: number, format: number = IMG_RGBA32, pixels?: Buffer, palette?: Buffer)</div> <div class="tsproto">new N64Image(width: number, height: number, format?: number = IMG_RGBA32, pixels?: Buffer, palette?: Buffer)</div>
</p> </p>
Creates an <a href="#N64Image">N64Image</a> object. Creates an <a href="#N64Image">N64Image</a> object.
<p> <p>
@ -1229,7 +1269,7 @@ Height of the image. Read-only.
The pixel data of the image. The pixel data of the image.
<!-- image_palette --> <!-- image_palette -->
<p><div class="prop"><span class="title" id="image_palette">image.palette</span></div> <p><div class="prop"><span class="title" id="image_palette">image.palette</span></div>
<div class="tsproto">image.palette: Buffer</div> <div class="tsproto">image.palette: Buffer | null</div>
</p> </p>
The palette data of the image. <span class="snip">null</span> if the image does not use a color-index format. The palette data of the image. <span class="snip">null</span> if the image does not use a color-index format.
@ -1378,7 +1418,7 @@ Encodes a single MIPS R4300i opcode. <span class="snip">address</span> is an opt
</pre> </pre>
<!-- asm_decode --> <!-- asm_decode -->
<p><div class="prop"><span class="title" id="asm_decode">asm.decode(opcode[, address])</span></div> <p><div class="prop"><span class="title" id="asm_decode">asm.decode(opcode[, address])</span></div>
<div class="tsproto">asm.decode(opcode: number, address?: number)</div> <div class="tsproto">asm.decode(opcode: number, address?: number): string</div>
</p> </p>
Decodes a single MIPS R4300i opcode. <span class="snip">address</span> is an optional parameter that may be used to hint the address of the instruction for branch address calculation. Decodes a single MIPS R4300i opcode. <span class="snip">address</span> is an optional parameter that may be used to hint the address of the instruction for branch address calculation.
<p>Returns a line of assembly code as a string.</p> <p>Returns a line of assembly code as a string.</p>
@ -1542,7 +1582,7 @@ TCP socket class
</table> </table>
<!-- socket_connect --> <!-- socket_connect -->
<p><div class="prop"><span class="title" id="socket_connect">socket.connect(port, host[, connectListener])</span></div> <p><div class="prop"><span class="title" id="socket_connect">socket.connect(port, host[, connectListener])</span></div>
<div class="tsproto">socket.connect(port: number, host: string, connectListener: () => void): void</div> <div class="tsproto">socket.connect(port: number, host: string, connectListener?: () => void): void</div>
</p> </p>
Initiates a TCP connection. Initiates a TCP connection.
Optional <span class="snip">connectListener</span> is invoked when the connection is established (i.e the socket is writable). Optional <span class="snip">connectListener</span> is invoked when the connection is established (i.e the socket is writable).
@ -1644,7 +1684,7 @@ Fully closes the socket.
<p>Returns the Socket object.</p> <p>Returns the Socket object.</p>
<!-- socket_off --> <!-- socket_off -->
<p><div class="prop"><span class="title" id="socket_off">socket.off(eventName, listener)</span></div> <p><div class="prop"><span class="title" id="socket_off">socket.off(eventName, listener)</span></div>
<div class="tsproto">socket.off(eventName: string, listener: function): Socket</div> <div class="tsproto">socket.off(eventName: string, listener: Function): Socket</div>
</p> </p>
Removes a listener. Removes a listener.
<p>Returns the Socket object.</p> <p>Returns the Socket object.</p>
@ -1702,9 +1742,9 @@ Creates a <a href="#Server">Server</a> object.
</pre> </pre>
<!-- server_listen --> <!-- server_listen -->
<p><div class="prop"><span class="title" id="server_listen">server.listen(port[, address])</span></div> <p><div class="prop"><span class="title" id="server_listen">server.listen(port[, address])</span></div>
<div class="tsproto">server.listen(port: number, address: string): void</div> <div class="tsproto">server.listen(port: number, address?: string = "0.0.0.0"): void</div>
</p> </p>
Binds the server to the specified address and port and starts listening. Binds the server to the specified port and address and starts listening.
<!-- server_close --> <!-- server_close -->
<p><div class="prop"><span class="title" id="server_close">server.close()</span></div> <p><div class="prop"><span class="title" id="server_close">server.close()</span></div>
<div class="tsproto">server.close(): void</div> <div class="tsproto">server.close(): void</div>
@ -1740,7 +1780,7 @@ Stops listening for new connections (does not affect existing connections).
<p>Returns the Server object.</p> <p>Returns the Server object.</p>
<!-- server_off --> <!-- server_off -->
<p><div class="prop"><span class="title" id="server_off">server.off(eventName, listener)</span></div> <p><div class="prop"><span class="title" id="server_off">server.off(eventName, listener)</span></div>
<div class="tsproto">server.off(eventName: string, listener: function): Server</div> <div class="tsproto">server.off(eventName: string, listener: Function): Server</div>
</p> </p>
Removes a listener. Removes a listener.
<p>Returns the Server object.</p> <p>Returns the Server object.</p>
@ -1777,6 +1817,11 @@ Useful when the default console input behavior is desired.
</p> </p>
Sets the maximum amount of time tasks may run on the script instance before errors are thrown. By default this value is 500 milliseconds. Sets the maximum amount of time tasks may run on the script instance before errors are thrown. By default this value is 500 milliseconds.
Setting this value to zero will allow tasks to run indefinitely. Setting this value to zero will allow tasks to run indefinitely.
<!-- script_abort -->
<p><div class="prop"><span class="title" id="script_abort">script.abort()</span></div>
<div class="tsproto">script.abort(): void</div>
</p>
Terminates the script instance.
</div> </div>
<!-- Globals --> <!-- Globals -->
@ -1883,7 +1928,7 @@ Shows a message box over the main window. Does not return until the message box
<p>Returns a timeout ID.</p> <p>Returns a timeout ID.</p>
<!-- clearTimeout --> <!-- clearTimeout -->
<p><div class="prop"><span class="title" id="clearTimeout">clearTimeout(timeoutId)</span></div> <p><div class="prop"><span class="title" id="clearTimeout">clearTimeout(timeoutId)</span></div>
<div class="tsproto">setTimeout(timeoutId: number): void</div> <div class="tsproto">clearTimeout(timeoutId: number): void</div>
</p> </p>
Cancels the timeout specified by <span class="snip">timeoutId</span>. Cancels the timeout specified by <span class="snip">timeoutId</span>.
<!-- setInterval --> <!-- setInterval -->
@ -1894,7 +1939,7 @@ Cancels the timeout specified by <span class="snip">timeoutId</span>.
<p>Returns an interval ID.</p> <p>Returns an interval ID.</p>
<!-- clearInterval --> <!-- clearInterval -->
<p><div class="prop"><span class="title" id="clearInterval">clearInterval(intervalId)</span></div> <p><div class="prop"><span class="title" id="clearInterval">clearInterval(intervalId)</span></div>
<div class="tsproto">setTimeout(intervalId: number): void</div> <div class="tsproto">clearInterval(intervalId: number): void</div>
</p> </p>
Cancels the interval specified by <span class="snip">intervalId</span>. Cancels the interval specified by <span class="snip">intervalId</span>.
<!-- number_hex --> <!-- number_hex -->

View File

@ -129,7 +129,6 @@ namespace ScriptAPI
duk_ret_t js_events_onwrite(duk_context* ctx); duk_ret_t js_events_onwrite(duk_context* ctx);
duk_ret_t js_events_onopcode(duk_context* ctx); duk_ret_t js_events_onopcode(duk_context* ctx);
duk_ret_t js_events_ongprvalue(duk_context* ctx); duk_ret_t js_events_ongprvalue(duk_context* ctx);
duk_ret_t js_events_ondraw(duk_context* ctx);
duk_ret_t js_events_onpifread(duk_context* ctx); duk_ret_t js_events_onpifread(duk_context* ctx);
duk_ret_t js_events_onsptask(duk_context* ctx); duk_ret_t js_events_onsptask(duk_context* ctx);
duk_ret_t js_events_onpidma(duk_context* ctx); duk_ret_t js_events_onpidma(duk_context* ctx);
@ -272,6 +271,10 @@ namespace ScriptAPI
// ScriptAPI_AddressRange // ScriptAPI_AddressRange
void Define_AddressRange(duk_context* ctx); void Define_AddressRange(duk_context* ctx);
duk_ret_t js_AddressRange__constructor(duk_context* ctx); duk_ret_t js_AddressRange__constructor(duk_context* ctx);
duk_ret_t js_AddressRange_size(duk_context* ctx);
duk_ret_t js_AddressRange_includes(duk_context* ctx);
duk_ret_t js_AddressRange_offset(duk_context* ctx);
duk_ret_t js_AddressRange_address(duk_context* ctx);
// ScriptAPI_Number_hex // ScriptAPI_Number_hex
void Define_Number_prototype_hex(duk_context* ctx); void Define_Number_prototype_hex(duk_context* ctx);

View File

@ -1,9 +1,19 @@
#include <stdafx.h> #include <stdafx.h>
#include "ScriptAPI.h" #include "ScriptAPI.h"
static void GetRange(duk_context* ctx, duk_idx_t idx, uint32_t* start, uint32_t* end);
void ScriptAPI::Define_AddressRange(duk_context* ctx) void ScriptAPI::Define_AddressRange(duk_context* ctx)
{ {
DefineGlobalClass(ctx, "AddressRange", js_AddressRange__constructor); const DukPropListEntry prototype[] = {
{ "size", DukCFunction(js_AddressRange_size) },
{ "includes", DukCFunction(js_AddressRange_includes) },
{ "offset", DukCFunction(js_AddressRange_offset) },
{ "address", DukCFunction(js_AddressRange_address) },
{ nullptr }
};
DefineGlobalClass(ctx, "AddressRange", js_AddressRange__constructor, prototype);
struct { const char* key; uint32_t start, end; } ranges[] = { struct { const char* key; uint32_t start, end; } ranges[] = {
{ "ADDR_ANY", 0x00000000, 0xFFFFFFFF }, { "ADDR_ANY", 0x00000000, 0xFFFFFFFF },
@ -19,18 +29,18 @@ void ScriptAPI::Define_AddressRange(duk_context* ctx)
}; };
duk_push_global_object(ctx); duk_push_global_object(ctx);
duk_push_c_function(ctx, js_AddressRange__constructor, DUK_VARARGS);
for(int i = 0; ranges[i].key != nullptr; i++) for(int i = 0; ranges[i].key != nullptr; i++)
{ {
duk_push_string(ctx, ranges[i].key); duk_push_string(ctx, ranges[i].key);
duk_dup(ctx, -2); duk_get_global_string(ctx, "AddressRange");
duk_push_uint(ctx, ranges[i].start); duk_push_uint(ctx, ranges[i].start);
duk_push_uint(ctx, ranges[i].end); duk_push_uint(ctx, ranges[i].end);
duk_new(ctx, 2); duk_new(ctx, 2);
duk_def_prop(ctx, -4, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_ENUMERABLE); duk_def_prop(ctx, -3, DUK_DEFPROP_HAVE_VALUE | DUK_DEFPROP_SET_ENUMERABLE);
} }
duk_pop_n(ctx, 2); duk_pop(ctx);
} }
duk_ret_t ScriptAPI::js_AddressRange__constructor(duk_context* ctx) duk_ret_t ScriptAPI::js_AddressRange__constructor(duk_context* ctx)
@ -40,13 +50,98 @@ duk_ret_t ScriptAPI::js_AddressRange__constructor(duk_context* ctx)
duk_to_uint32(ctx, 0); duk_to_uint32(ctx, 0);
duk_to_uint32(ctx, 1); duk_to_uint32(ctx, 1);
duk_uint_t start = duk_get_uint(ctx, 0);
duk_uint_t end = duk_get_uint(ctx, 1);
if (end < start)
{
duk_push_error_object(ctx, DUK_ERR_RANGE_ERROR, "invalid range; end cannot be less than start");
return duk_throw(ctx);
}
duk_push_this(ctx); duk_push_this(ctx);
duk_dup(ctx, 0); duk_push_uint(ctx, start);
duk_put_prop_string(ctx, -2, "start"); duk_put_prop_string(ctx, -2, "start");
duk_dup(ctx, 1); duk_push_uint(ctx, end);
duk_put_prop_string(ctx, -2, "end"); duk_put_prop_string(ctx, -2, "end");
duk_freeze(ctx, -1); duk_freeze(ctx, -1);
duk_pop(ctx); duk_pop(ctx);
return 0; return 0;
} }
duk_ret_t ScriptAPI::js_AddressRange_size(duk_context* ctx)
{
CheckArgs(ctx, {});
duk_uint_t start, end;
duk_push_this(ctx);
GetRange(ctx, -1, &start, &end);
duk_push_uint(ctx, end - start + 1);
return 1;
}
duk_ret_t ScriptAPI::js_AddressRange_includes(duk_context* ctx)
{
CheckArgs(ctx, { Arg_Number });
duk_to_uint32(ctx, 0);
duk_uint_t address = duk_get_uint(ctx, 0);
duk_uint_t start, end;
duk_push_this(ctx);
GetRange(ctx, -1, &start, &end);
duk_push_boolean(ctx, static_cast<duk_bool_t>(address >= start && address <= end));
return 1;
}
duk_ret_t ScriptAPI::js_AddressRange_offset(duk_context* ctx)
{
CheckArgs(ctx, { Arg_Number });
duk_to_uint32(ctx, 0);
duk_uint_t address = duk_get_uint(ctx, 0);
duk_uint_t start, end;
duk_push_this(ctx);
GetRange(ctx, -1, &start, &end);
if (address < start || address > end) {
duk_push_error_object(ctx, DUK_ERR_RANGE_ERROR, "address out of bounds");
return duk_throw(ctx);
}
duk_push_uint(ctx, address - start);
return 1;
}
duk_ret_t ScriptAPI::js_AddressRange_address(duk_context* ctx)
{
CheckArgs(ctx, { Arg_Number });
duk_int_t offset = duk_get_int(ctx, 0);
duk_uint_t start, end;
duk_push_this(ctx);
GetRange(ctx, -1, &start, &end);
duk_uint_t address = start + offset;
if (address < start || address > end) {
duk_push_error_object(ctx, DUK_ERR_RANGE_ERROR, "offset out of bounds");
return duk_throw(ctx);
}
duk_push_uint(ctx, address);
return 1;
}
static void GetRange(duk_context* ctx, duk_idx_t idx, uint32_t* start, uint32_t* end)
{
idx = duk_normalize_index(ctx, idx);
duk_get_prop_string(ctx, idx, "start");
*start = duk_get_uint(ctx, -1);
duk_get_prop_string(ctx, idx, "end");
*end = duk_get_uint(ctx, -1);
duk_pop_n(ctx, 2);
}

View File

@ -279,6 +279,7 @@ bool CScriptInstance::RegisterWorker(CScriptWorker* worker)
void CScriptInstance::UnregisterWorker(CScriptWorker* worker) void CScriptInstance::UnregisterWorker(CScriptWorker* worker)
{ {
std::vector<CScriptWorker*>::iterator it; std::vector<CScriptWorker*>::iterator it;
for (it = m_Workers.begin(); it != m_Workers.end(); it++) for (it = m_Workers.begin(); it != m_Workers.end(); it++)
{ {
if (*it == worker) if (*it == worker)

View File

@ -168,23 +168,25 @@ bool CScriptSystem::HaveAppCallbacks(JSAppHookID hookId)
void CScriptSystem::InvokeAppCallbacks(JSAppHookID hookId, void* env) void CScriptSystem::InvokeAppCallbacks(JSAppHookID hookId, void* env)
{ {
CGuard guard(m_InstancesCS); CGuard guard(m_InstancesCS);
RefreshCallbackMaps();
JSAppCallbackList& callbacks = m_AppCallbackHooks[hookId]; JSAppCallbackList& callbacks = m_AppCallbackHooks[hookId];
size_t numCallbacks = callbacks.size();
bool bNeedSweep = false; bool bNeedSweep = false;
for (JSAppCallback& callback : callbacks) for (size_t i = 0; i < numCallbacks; i++)
{ {
if (callback.m_bDisabled || !callback.m_ConditionFunc(&callback, env)) JSAppCallback& callback = callbacks[i];
CScriptInstance* instance = callback.m_Instance;
if (callback.m_bDisabled ||
instance->IsStopping() ||
m_StopsIssued.count(instance->Name()) != 0 ||
!callback.m_ConditionFunc(&callback, env))
{ {
continue; continue;
} }
CScriptInstance* instance = callback.m_Instance;
if (!instance->IsStopping())
{
instance->RawInvokeAppCallback(callback, env); instance->RawInvokeAppCallback(callback, env);
if (instance->GetRefCount() == 0) if (instance->GetRefCount() == 0)
@ -192,7 +194,6 @@ void CScriptSystem::InvokeAppCallbacks(JSAppHookID hookId, void* env)
bNeedSweep = true; bNeedSweep = true;
} }
} }
}
if (bNeedSweep) if (bNeedSweep)
{ {
@ -266,7 +267,7 @@ void CScriptSystem::RefreshCallbackMaps()
{ {
if (it->m_bDisabled) if (it->m_bDisabled)
{ {
callbacks.erase(it); it = callbacks.erase(it);
} }
else else
{ {
@ -317,6 +318,20 @@ void CScriptSystem::PostCommand(JSSysCommandID id, stdstr paramA, stdstr paramB,
{ {
CGuard guard(m_CmdQueueCS); CGuard guard(m_CmdQueueCS);
JSSysCommand cmd = { id, paramA, paramB, paramC }; JSSysCommand cmd = { id, paramA, paramB, paramC };
if (id == JS_CMD_STOP_SCRIPT)
{
JSInstanceName instName = paramA;
if (m_StopsIssued.count(instName) != 0)
{
return;
}
else
{
m_StopsIssued.insert(instName);
}
}
m_CmdQueue.push_back(cmd); m_CmdQueue.push_back(cmd);
SetEvent(m_hCmdEvent); SetEvent(m_hCmdEvent);
} }
@ -379,6 +394,7 @@ void CScriptSystem::OnStopScript(const char *name)
return; return;
} }
m_StopsIssued.erase(name);
RawRemoveInstance(name); RawRemoveInstance(name);
NotifyStatus(name, JS_STATUS_STOPPED); NotifyStatus(name, JS_STATUS_STOPPED);
} }
@ -435,7 +451,7 @@ void CScriptSystem::OnSweep(bool bIfDone)
{ {
NotifyStatus(inst->Name().c_str(), JS_STATUS_STOPPED); NotifyStatus(inst->Name().c_str(), JS_STATUS_STOPPED);
delete inst; delete inst;
m_Instances.erase(it); it = m_Instances.erase(it);
} }
else else
{ {
@ -481,6 +497,7 @@ JSAppCallbackID CScriptSystem::RawAddAppCallback(JSAppHookID hookId, JSAppCallba
callback.m_CallbackId = m_NextAppCallbackId++; callback.m_CallbackId = m_NextAppCallbackId++;
m_AppCallbackHooks[hookId].push_back(callback); m_AppCallbackHooks[hookId].push_back(callback);
m_AppCallbackCount++; m_AppCallbackCount++;
RefreshCallbackMaps();
return callback.m_CallbackId; return callback.m_CallbackId;
} }
@ -499,6 +516,7 @@ void CScriptSystem::RawRemoveAppCallback(JSAppHookID hookId, JSAppCallbackID cal
it++; it++;
} }
RefreshCallbackMaps();
} }
void CScriptSystem::ExecAutorunList() void CScriptSystem::ExecAutorunList()

View File

@ -37,6 +37,7 @@ class CScriptSystem
CriticalSection m_CmdQueueCS; CriticalSection m_CmdQueueCS;
JSSysCommandQueue m_CmdQueue; JSSysCommandQueue m_CmdQueue;
HANDLE m_hCmdEvent; HANDLE m_hCmdEvent;
std::set<JSInstanceName> m_StopsIssued;
CriticalSection m_InstancesCS; CriticalSection m_InstancesCS;
JSInstanceMap m_Instances; JSInstanceMap m_Instances;