diff --git a/Source/Project64/UserInterface/API.js b/Source/Project64/UserInterface/API.js index 9e27b25de..bec3727ca 100644 --- a/Source/Project64/UserInterface/API.js +++ b/Source/Project64/UserInterface/API.js @@ -1,49 +1,49 @@ Number.prototype.hex = function(len) { - len = (len || 8); - var str = (this >>> 0).toString(16).toUpperCase() - while (str.length < len) - { - str = "0" + str - } - return str + len = (len || 8); + var str = (this >>> 0).toString(16).toUpperCase() + while (str.length < len) + { + str = "0" + str + } + return str } const u8 = 'u8', u16 = 'u16', u32 = 'u32', - s8 = 's8', s16 = 's16', s32 = 's32', - float = 'float', double = 'double' + s8 = 's8', s16 = 's16', s32 = 's32', + float = 'float', double = 'double' const _typeSizes = { - u8: 1, u16: 2, u32: 4, - s8: 1, s16: 2, s32: 4, - float: 4, double: 8 + u8: 1, u16: 2, u32: 4, + s8: 1, s16: 2, s32: 4, + float: 4, double: 8 } const _regNums = { - r0: 0, at: 1, v0: 2, v1: 3, - a0: 4, a1: 5, a2: 6, a3: 7, - t0: 8, t1: 9, t2: 10, t3: 11, - t4: 12, t5: 13, t6: 14, t7: 15, - s0: 16, s1: 17, s2: 18, s3: 19, - s4: 20, s5: 21, s6: 22, s7: 23, - t8: 24, t9: 25, k0: 26, k1: 27, - gp: 28, sp: 29, fp: 30, ra: 31, + r0: 0, at: 1, v0: 2, v1: 3, + a0: 4, a1: 5, a2: 6, a3: 7, + t0: 8, t1: 9, t2: 10, t3: 11, + t4: 12, t5: 13, t6: 14, t7: 15, + s0: 16, s1: 17, s2: 18, s3: 19, + s4: 20, s5: 21, s6: 22, s7: 23, + t8: 24, t9: 25, k0: 26, k1: 27, + gp: 28, sp: 29, fp: 30, ra: 31, - f0: 0, f1: 1, f2: 2, f3: 3, - f4: 4, f5: 5, f6: 6, f7: 7, - f8: 8, f9: 9, f10: 10, f11: 11, - f12: 12, f13: 13, f14: 14, f15: 15, - f16: 16, f17: 17, f18: 18, f19: 19, - f20: 20, f21: 21, f22: 22, f23: 23, - f24: 24, f25: 25, f26: 26, f27: 27, - f28: 28, f29: 29, f30: 30, f31: 31 + f0: 0, f1: 1, f2: 2, f3: 3, + f4: 4, f5: 5, f6: 6, f7: 7, + f8: 8, f9: 9, f10: 10, f11: 11, + f12: 12, f13: 13, f14: 14, f15: 15, + f16: 16, f17: 17, f18: 18, f19: 19, + f20: 20, f21: 21, f22: 22, f23: 23, + f24: 24, f25: 25, f26: 26, f27: 27, + f28: 28, f29: 29, f30: 30, f31: 31 } function AddressRange(start, end) { - this.start = start >>> 0 - this.end = end >>> 0 - Object.freeze(this) + this.start = start >>> 0 + this.end = end >>> 0 + Object.freeze(this) } const ADDR_ANY = new AddressRange(0x00000000, 0x100000000) @@ -184,279 +184,313 @@ Object.freeze(fs.Stats) Object.freeze(fs.Stats.prototype) const system = { - pause: function() - { - _native.pause() - }, - resume: function() - { + pause: function() + { + _native.pause() + }, + resume: function() + { - }, - reset: function() - { + }, + reset: function() + { - }, - hardreset: function() - { + }, + hardreset: function() + { - }, - savestate: function() - { + }, + savestate: function() + { - }, - loadstate: function() - { + }, + loadstate: function() + { - }, - setsaveslot: function(slot) - { + }, + setsaveslot: function(slot) + { - }, - getsaveslot: function() - { + }, + getsaveslot: function() + { - }, - generatebitmap: function() - { + }, + generatebitmap: function() + { - } + } } const debug = { - showmemory: function(address) - { - - }, - showcommands: function(address) - { - _native.showCommands(address) - }, - breakhere: function() - { - debug.showcommands(gpr.pc) - system.pause() - }, - disasm: function() - { + showmemory: function(address) + { + + }, + showcommands: function(address) + { + _native.showCommands(address) + }, + breakhere: function() + { + debug.showcommands(gpr.pc) + system.pause() + }, + disasm: function() + { - } + } } const console = { - print: function(data) - { - _native.consolePrint(data); - }, - log: function() - { - for(var i in arguments) - { - console.print(arguments[i].toString()) - if(i < arguments.length - 1) - { - console.print(" ") - } - } - console.print("\r\n") - }, - clear: function() - { - _native.consoleClear(); - } + print: function(data) + { + _native.consolePrint(data); + }, + log: function() + { + for(var i in arguments) + { + console.print(arguments[i].toString()) + if(i < arguments.length - 1) + { + console.print(" ") + } + } + console.print("\r\n") + }, + clear: function() + { + _native.consoleClear(); + } } const screen = { - print: function(x, y, text) - { - _native.screenPrint(x, y, text) - } + print: function(x, y, text) + { + _native.screenPrint(x, y, text) + } } const events = (function() { - var callbacks = {}; - var nextCallbackId = 0; - return { - on: function(hook, callback, param, param2, bOnce) - { - this._stashCallback(callback) - return _native.addCallback(hook, callback, param, param2, bOnce) - }, - onexec: function(addr, callback) - { - var param = 0; - var param2 = 0; + var callbacks = {}; + var nextCallbackId = 0; + return { + on: function(hook, callback, param, param2, bOnce) + { + this._stashCallback(callback) + return _native.addCallback(hook, callback, param, param2, 0, 0, bOnce) + }, + onexec: function(addr, callback) + { + var param = 0; + var param2 = 0; - if (typeof (addr) == "object") - { - param = addr.start; - param2 = addr.end; - } - else if (typeof (addr) == "number") - { - param = addr; - } + if (typeof (addr) == "object") + { + param = addr.start; + param2 = addr.end; + } + else if (typeof (addr) == "number") + { + param = addr; + } - return events.on('exec', callback, param, param2) - }, - onread: function(addr, callback) - { - var param = 0; - var param2 = 0; + return events.on('exec', callback, param, param2) + }, + onopcode: function (addr, value, arg3, arg4) + { + // onopcode(addr, value, callback) + // onopcode(addr, value, mask, callback) - if (typeof (addr) == "object") - { - param = addr.start; - param2 = addr.end; - } - else if (typeof (addr) == "number") - { - param = addr; - } + var start = 0; + var end = 0; + var mask; + var callback; - return events.on('read', callback, param, param2) - }, - onwrite: function(addr, callback) - { - var param = 0; - var param2 = 0; + if(typeof(addr) == "object") + { + start = addr.start; + end = addr.end; + } + else if (typeof (addr) == "number") + { + start = addr; + } - if (typeof (addr) == "object") - { - param = addr.start; - param2 = addr.end; - } - else if (typeof (addr) == "number") - { - param = addr; - } + if (typeof (arg3) == "number") + { + mask = arg3; + callback = arg4; + } + else if (typeof (arg3) == "function") + { + mask = 0xFFFFFFFF; + callback = arg3; + } - return events.on('write', callback, param, param2) - }, - ondraw: function(callback) - { - return events.on('draw', callback, 0) - }, - remove: function(callbackId) - { - _native.removeCallback(callbackId) - }, - clear: function(){}, - _stashCallback: function(callback) - { - callbacks[nextCallbackId] = callback - return nextCallbackId++; - }, - _unstashCallback: function() - { - - }, - } + this._stashCallback(callback); + return _native.addCallback('onopcode', callback, start, end, value, mask) + }, + onread: function(addr, callback) + { + var param = 0; + var param2 = 0; + + if (typeof (addr) == "object") + { + param = addr.start; + param2 = addr.end; + } + else if (typeof (addr) == "number") + { + param = addr; + } + + return events.on('read', callback, param, param2) + }, + onwrite: function(addr, callback) + { + var param = 0; + var param2 = 0; + + if (typeof (addr) == "object") + { + param = addr.start; + param2 = addr.end; + } + else if (typeof (addr) == "number") + { + param = addr; + } + + return events.on('write', callback, param, param2) + }, + ondraw: function(callback) + { + return events.on('draw', callback, 0) + }, + remove: function(callbackId) + { + _native.removeCallback(callbackId) + }, + clear: function(){}, + _stashCallback: function(callback) + { + callbacks[nextCallbackId] = callback + return nextCallbackId++; + }, + _unstashCallback: function() + { + + }, + } })(); const gpr = new Proxy({}, { - get: function(obj, prop) - { - if (typeof prop == 'number' && prop < 32) - { - return _native.getGPRVal(prop) - } - if (prop in _regNums) - { - return _native.getGPRVal(_regNums[prop]) - } - switch(prop) - { - case 'pc': return _native.getPCVal(); break; - case 'hi': return _native.getHIVal(false); break; - case 'lo': return _native.getLOVal(false); break; - } - }, - set: function(obj, prop, val) - { - if (typeof prop == 'number' && prop < 32) - { - _native.setGPRVal(prop, false, val) - return - } - if (prop in _regNums) - { - _native.setGPRVal(_regNums[prop], false, val) - return - } - switch(prop) - { - case 'pc': _native.setPCVal(val); break; - case 'hi': _native.setHIVal(false, val); break; - case 'lo': _native.setLOVal(false, val); break; - } - } + get: function(obj, prop) + { + if (typeof prop == 'number' && prop < 32) + { + return _native.getGPRVal(prop) + } + if (prop in _regNums) + { + return _native.getGPRVal(_regNums[prop]) + } + switch(prop) + { + case 'pc': return _native.getPCVal(); break; + case 'hi': return _native.getHIVal(false); break; + case 'lo': return _native.getLOVal(false); break; + } + }, + set: function(obj, prop, val) + { + if (typeof prop == 'number' && prop < 32) + { + _native.setGPRVal(prop, false, val) + return + } + if (prop in _regNums) + { + _native.setGPRVal(_regNums[prop], false, val) + return + } + switch(prop) + { + case 'pc': _native.setPCVal(val); break; + case 'hi': _native.setHIVal(false, val); break; + case 'lo': _native.setLOVal(false, val); break; + } + } }) const ugpr = new Proxy({}, { - get: function (obj, prop) - { - if (typeof prop == 'number' && prop < 32) - { - return _native.getGPRVal(prop, true) - } - if (prop in _regNums) - { - return _native.getGPRVal(_regNums[prop], true) - } - switch(prop) - { - case 'hi': return _native.getHIVal(true); break; - case 'lo': return _native.getLOVal(true); break; - } - }, - set: function (obj, prop, val) - { - if (typeof prop == 'number' && prop < 32) - { - _native.setGPRVal(prop, true, val) - return - } - if (prop in _regNums) - { - _native.setGPRVal(_regNums[prop], true, val) - return - } - switch(prop) - { - case 'hi': _native.setHIVal(true, val); break; - case 'lo': _native.setLOVal(true, val); break; - } - } + get: function (obj, prop) + { + if (typeof prop == 'number' && prop < 32) + { + return _native.getGPRVal(prop, true) + } + if (prop in _regNums) + { + return _native.getGPRVal(_regNums[prop], true) + } + switch(prop) + { + case 'hi': return _native.getHIVal(true); break; + case 'lo': return _native.getLOVal(true); break; + } + }, + set: function (obj, prop, val) + { + if (typeof prop == 'number' && prop < 32) + { + _native.setGPRVal(prop, true, val) + return + } + if (prop in _regNums) + { + _native.setGPRVal(_regNums[prop], true, val) + return + } + switch(prop) + { + case 'hi': _native.setHIVal(true, val); break; + case 'lo': _native.setLOVal(true, val); break; + } + } }) const fpr = new Proxy({}, { - get: function(obj, prop) - { - if (typeof prop == 'number') - { - return _native.getFPRVal(prop) - } - if (prop in _regNums) - { - return _native.getFPRVal(_regNums[prop]) - } - }, - set: function(obj, prop, val) - { - if (typeof prop == 'number' && prop < 32) - { - _native.setFPRVal(prop, false, val) - return - } - if (prop in _regNums) - { - _native.setFPRVal(_regNums[prop], false, val) - } - } + get: function(obj, prop) + { + if (typeof prop == 'number') + { + return _native.getFPRVal(prop) + } + if (prop in _regNums) + { + return _native.getFPRVal(_regNums[prop]) + } + }, + set: function(obj, prop, val) + { + if (typeof prop == 'number' && prop < 32) + { + _native.setFPRVal(prop, false, val) + return + } + if (prop in _regNums) + { + _native.setFPRVal(_regNums[prop], false, val) + } + } }) const dfpr = new Proxy({}, @@ -487,346 +521,346 @@ const dfpr = new Proxy({}, }) const rom = { - u8: new Proxy({}, - { - get: function (obj, prop) - { - return _native.getROMInt(prop, 8, false) - } - }), - u16: new Proxy({}, - { - get: function (obj, prop) - { - return _native.getROMInt(prop, 16, false) - } - }), - u32: new Proxy({}, - { - get: function (obj, prop) - { - return _native.getROMInt(prop, 32, false) - } - }), - s8: new Proxy({}, - { - get: function (obj, prop) - { - return _native.getROMInt(prop, 8, true) - } - }), - s16: new Proxy({}, - { - get: function (obj, prop) - { - return _native.getROMInt(prop, 16, true) - } - }), - s32: new Proxy({}, - { - get: function (obj, prop) - { - return _native.getROMInt(prop, 32, true) - } - }), - 'float': new Proxy({}, - { - get: function (obj, prop) - { - return _native.getROMFloat(prop) - }, - set: function (obj, prop, val) - { - _native.setROMFloat(prop, val) - } - }), - 'double': new Proxy({}, - { - get: function (obj, prop) - { - return _native.getROMFloat(prop, true) - }, - set: function (obj, prop, val) - { - _native.setROMFloat(prop, val, true) - } - }), - getblock: function (address, size) - { - return _native.getROMBlock(address, size) - }, - getstring: function(address, maxLen) - { - return _native.getROMString(address, maxLen) - }, + u8: new Proxy({}, + { + get: function (obj, prop) + { + return _native.getROMInt(prop, 8, false) + } + }), + u16: new Proxy({}, + { + get: function (obj, prop) + { + return _native.getROMInt(prop, 16, false) + } + }), + u32: new Proxy({}, + { + get: function (obj, prop) + { + return _native.getROMInt(prop, 32, false) + } + }), + s8: new Proxy({}, + { + get: function (obj, prop) + { + return _native.getROMInt(prop, 8, true) + } + }), + s16: new Proxy({}, + { + get: function (obj, prop) + { + return _native.getROMInt(prop, 16, true) + } + }), + s32: new Proxy({}, + { + get: function (obj, prop) + { + return _native.getROMInt(prop, 32, true) + } + }), + 'float': new Proxy({}, + { + get: function (obj, prop) + { + return _native.getROMFloat(prop) + }, + set: function (obj, prop, val) + { + _native.setROMFloat(prop, val) + } + }), + 'double': new Proxy({}, + { + get: function (obj, prop) + { + return _native.getROMFloat(prop, true) + }, + set: function (obj, prop, val) + { + _native.setROMFloat(prop, val, true) + } + }), + getblock: function (address, size) + { + return _native.getROMBlock(address, size) + }, + getstring: function(address, maxLen) + { + return _native.getROMString(address, maxLen) + }, } const mem = { - u8: new Proxy({}, - { - get: function(obj, prop) - { - return _native.getRDRAMInt(prop, 8, false) - }, - set: function(obj, prop, val) - { - _native.setRDRAMInt(prop, 8, val) - } - }), - u16: new Proxy({}, - { - get: function(obj, prop) - { - return _native.getRDRAMInt(prop, 16, false) - }, - set: function(obj, prop, val) - { - _native.setRDRAMInt(prop, 16, val) - } - }), - u32: new Proxy({}, - { - get: function(obj, prop) - { - return _native.getRDRAMInt(prop, 32, false) - }, - set: function(obj, prop, val) - { - _native.setRDRAMInt(prop, 32, val) - } - }), - s8: new Proxy({}, - { - get: function(obj, prop) - { - return _native.getRDRAMInt(prop, 8, true) - }, - set: function(obj, prop, val) - { - _native.setRDRAMInt(prop, 8, val) - } - }), - s16: new Proxy({}, - { - get: function(obj, prop) - { - return _native.getRDRAMInt(prop, 16, true) - }, - set: function(obj, prop, val) - { - _native.setRDRAMInt(prop, 16, val) - } - }), - s32: new Proxy({}, - { - get: function(obj, prop) - { - return _native.getRDRAMInt(prop, 32, true) - }, - set: function(obj, prop, val) - { - _native.setRDRAMInt(prop, 32, val) - } - }), - 'float': new Proxy({}, - { - get: function(obj, prop) - { - return _native.getRDRAMFloat(prop) - }, - set: function(obj, prop, val) - { - _native.setRDRAMFloat(prop, val) - } - }), - 'double': new Proxy({}, - { - get: function(obj, prop) - { - return _native.getRDRAMFloat(prop, true) - }, - set: function(obj, prop, val) - { - _native.setRDRAMFloat(prop, val, true) - } - }), - getblock: function(address, size) - { - return _native.getRDRAMBlock(address, size) - }, - getstring: function(address, maxLen) - { - return _native.getRDRAMString(address, maxLen) - }, - bindvar: function(obj, baseAddr, name, type) - { - Object.defineProperty(obj, name, - { - get: function() - { - return mem[type][baseAddr] - }, - set: function(val) - { - mem[type][baseAddr] = val - } - }) - return obj - }, - bindvars: function(obj, list) - { - for(var i = 0; i < list.length; i++) - { - mem.bindvar(obj, list[i][0], list[i][1], list[i][2]) - } - return obj - }, - bindstruct: function(obj, baseAddr, props) - { - for (var name in props) - { - var type = props[name] - var size = _typeSizes[type] - mem.bindvar(obj, baseAddr, name, type) - baseAddr += size - } - return obj - }, - typedef: function(props, proto) - { - var size = 0 - for (var name in props) - { - size += _typeSizes[props[name]] - } - var StructClass = function(baseAddr) - { - mem.bindstruct(this, baseAddr, props) - } - StructClass.sizeof = function() - { - return size - } - /*if(proto) - { - StructClass.prototype = proto - }*/ - return StructClass - } + u8: new Proxy({}, + { + get: function(obj, prop) + { + return _native.getRDRAMInt(prop, 8, false) + }, + set: function(obj, prop, val) + { + _native.setRDRAMInt(prop, 8, val) + } + }), + u16: new Proxy({}, + { + get: function(obj, prop) + { + return _native.getRDRAMInt(prop, 16, false) + }, + set: function(obj, prop, val) + { + _native.setRDRAMInt(prop, 16, val) + } + }), + u32: new Proxy({}, + { + get: function(obj, prop) + { + return _native.getRDRAMInt(prop, 32, false) + }, + set: function(obj, prop, val) + { + _native.setRDRAMInt(prop, 32, val) + } + }), + s8: new Proxy({}, + { + get: function(obj, prop) + { + return _native.getRDRAMInt(prop, 8, true) + }, + set: function(obj, prop, val) + { + _native.setRDRAMInt(prop, 8, val) + } + }), + s16: new Proxy({}, + { + get: function(obj, prop) + { + return _native.getRDRAMInt(prop, 16, true) + }, + set: function(obj, prop, val) + { + _native.setRDRAMInt(prop, 16, val) + } + }), + s32: new Proxy({}, + { + get: function(obj, prop) + { + return _native.getRDRAMInt(prop, 32, true) + }, + set: function(obj, prop, val) + { + _native.setRDRAMInt(prop, 32, val) + } + }), + 'float': new Proxy({}, + { + get: function(obj, prop) + { + return _native.getRDRAMFloat(prop) + }, + set: function(obj, prop, val) + { + _native.setRDRAMFloat(prop, val) + } + }), + 'double': new Proxy({}, + { + get: function(obj, prop) + { + return _native.getRDRAMFloat(prop, true) + }, + set: function(obj, prop, val) + { + _native.setRDRAMFloat(prop, val, true) + } + }), + getblock: function(address, size) + { + return _native.getRDRAMBlock(address, size) + }, + getstring: function(address, maxLen) + { + return _native.getRDRAMString(address, maxLen) + }, + bindvar: function(obj, baseAddr, name, type) + { + Object.defineProperty(obj, name, + { + get: function() + { + return mem[type][baseAddr] + }, + set: function(val) + { + mem[type][baseAddr] = val + } + }) + return obj + }, + bindvars: function(obj, list) + { + for(var i = 0; i < list.length; i++) + { + mem.bindvar(obj, list[i][0], list[i][1], list[i][2]) + } + return obj + }, + bindstruct: function(obj, baseAddr, props) + { + for (var name in props) + { + var type = props[name] + var size = _typeSizes[type] + mem.bindvar(obj, baseAddr, name, type) + baseAddr += size + } + return obj + }, + typedef: function(props, proto) + { + var size = 0 + for (var name in props) + { + size += _typeSizes[props[name]] + } + var StructClass = function(baseAddr) + { + mem.bindstruct(this, baseAddr, props) + } + StructClass.sizeof = function() + { + return size + } + /*if(proto) + { + StructClass.prototype = proto + }*/ + return StructClass + } } function alert(text, caption){ - caption = caption || "" - _native.msgBox(text, caption) + caption = caption || "" + _native.msgBox(text, caption) } function Socket(fd) { - var connected = false; - - var _fd; - - if(fd) - { - // assume this was constructed from Server - _fd = fd; - connected = true; - } else { - _fd = _native.sockCreate(); - } - - var _ondata = function(data){} - var _onclose = function(){} - var _onconnect = function(){} - - var _onconnect_base = function(){ - connected = 1; - _onconnect(); - } - - var _bufferSize = 2048 - - this.write = function(data, callback) - { - _native.write(_fd, data, callback) - } - - this.close = function() - { - _native.close(_fd) - } - - this.connect = function(settings, callback) - { - if(!connected) - { - _onconnect = callback; - _native.sockConnect(_fd, settings.host || '127.0.0.1', settings.port || 80, _onconnect_base); - } - } - - var _read = function(data) - { - if(data == null) - { - connected = false; - _onclose(); - return; - } - _native.read(_fd, _bufferSize, _read) - _ondata(data) - } - - this.on = function(eventType, callback) - { - switch(eventType) - { - case 'data': - _ondata = callback - _native.read(_fd, _bufferSize, _read) - break; - case 'close': - // note: does nothing if ondata not set - _onclose = callback - break; - } - } + var connected = false; + + var _fd; + + if(fd) + { + // assume this was constructed from Server + _fd = fd; + connected = true; + } else { + _fd = _native.sockCreate(); + } + + var _ondata = function(data){} + var _onclose = function(){} + var _onconnect = function(){} + + var _onconnect_base = function(){ + connected = 1; + _onconnect(); + } + + var _bufferSize = 2048 + + this.write = function(data, callback) + { + _native.write(_fd, data, callback) + } + + this.close = function() + { + _native.close(_fd) + } + + this.connect = function(settings, callback) + { + if(!connected) + { + _onconnect = callback; + _native.sockConnect(_fd, settings.host || '127.0.0.1', settings.port || 80, _onconnect_base); + } + } + + var _read = function(data) + { + if(data == null) + { + connected = false; + _onclose(); + return; + } + _native.read(_fd, _bufferSize, _read) + _ondata(data) + } + + this.on = function(eventType, callback) + { + switch(eventType) + { + case 'data': + _ondata = callback + _native.read(_fd, _bufferSize, _read) + break; + case 'close': + // note: does nothing if ondata not set + _onclose = callback + break; + } + } } function Server(settings) { - var _this = this; - var _fd = _native.sockCreate() - - var _onconnection = function(socket){} - - if(settings.port) - { - _native.sockListen(_fd, settings.port || 80) - } - - // Intermediate callback - // convert clientFd to Socket and accept next client - var _acceptClient = function(clientFd) - { - _onconnection(new Socket(clientFd)) - _native.sockAccept(_fd, _acceptClient) - } - - this.listen = function(port) - { - _native.sockListen(_fd, port) - } - - this.on = function(eventType, callback) - { - switch(eventType) - { - case 'connection': - _onconnection = callback - _native.sockAccept(_fd, _acceptClient) - break; - } - } + var _this = this; + var _fd = _native.sockCreate() + + var _onconnection = function(socket){} + + if(settings.port) + { + _native.sockListen(_fd, settings.port || 80) + } + + // Intermediate callback + // convert clientFd to Socket and accept next client + var _acceptClient = function(clientFd) + { + _onconnection(new Socket(clientFd)) + _native.sockAccept(_fd, _acceptClient) + } + + this.listen = function(port) + { + _native.sockListen(_fd, port) + } + + this.on = function(eventType, callback) + { + switch(eventType) + { + case 'connection': + _onconnection = callback + _native.sockAccept(_fd, _acceptClient) + break; + } + } } diff --git a/Source/Project64/UserInterface/Debugger/Debugger.cpp b/Source/Project64/UserInterface/Debugger/Debugger.cpp index 69ef3cfe4..bae453abb 100644 --- a/Source/Project64/UserInterface/Debugger/Debugger.cpp +++ b/Source/Project64/UserInterface/Debugger/Debugger.cpp @@ -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 diff --git a/Source/Project64/UserInterface/Debugger/ScriptHook.cpp b/Source/Project64/UserInterface/Debugger/ScriptHook.cpp index bcbdb8bed..2d0b8ed6f 100644 --- a/Source/Project64/UserInterface/Debugger/ScriptHook.cpp +++ b/Source/Project64/UserInterface/Debugger/ScriptHook.cpp @@ -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(); diff --git a/Source/Project64/UserInterface/Debugger/ScriptHook.h b/Source/Project64/UserInterface/Debugger/ScriptHook.h index e94283ea9..f82de1968 100644 --- a/Source/Project64/UserInterface/Debugger/ScriptHook.h +++ b/Source/Project64/UserInterface/Debugger/ScriptHook.h @@ -13,6 +13,8 @@ private: void* heapptr; uint32_t param; uint32_t param2; + uint32_t param3; + uint32_t param4; int callbackId; bool bOnce; } JSCALLBACK; @@ -22,18 +24,21 @@ private: //int m_NextCallbackId; vector m_Callbacks; -public: +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); bool HasContext(CScriptInstance* scriptInstance); //bool HasTag(uint32_t tag); -}; \ No newline at end of file +}; diff --git a/Source/Project64/UserInterface/Debugger/ScriptInstance.cpp b/Source/Project64/UserInterface/Debugger/ScriptInstance.cpp index df3db2f16..d04276c7a 100644 --- a/Source/Project64/UserInterface/Debugger/ScriptInstance.cpp +++ b/Source/Project64/UserInterface/Debugger/ScriptInstance.cpp @@ -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); diff --git a/Source/Project64/UserInterface/Debugger/ScriptSystem.cpp b/Source/Project64/UserInterface/Debugger/ScriptSystem.cpp index 33c7544ca..cf4bb70c0 100644 --- a/Source/Project64/UserInterface/Debugger/ScriptSystem.cpp +++ b/Source/Project64/UserInterface/Debugger/ScriptSystem.cpp @@ -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); diff --git a/Source/Project64/UserInterface/Debugger/ScriptSystem.h b/Source/Project64/UserInterface/Debugger/ScriptSystem.h index 21dbd86ab..ea2625c44 100644 --- a/Source/Project64/UserInterface/Debugger/ScriptSystem.h +++ b/Source/Project64/UserInterface/Debugger/ScriptSystem.h @@ -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; diff --git a/apidoc.htm b/apidoc.htm index 18cd9863b..0220bf90e 100644 --- a/apidoc.htm +++ b/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; } @@ -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) -->
emulation thread - interpreter mode + interpreter mode only
events.onexec(address, callback)
- Adds a CPU execution callback for a virtual address or AddressRange and returns a callback ID. + Adds a CPU execution callback for a virtual address or AddressRange and returns a callback ID. callback will be invoked at the beginning of a CPU step if the program counter is at address. callback receives the program counter address at which the event is fired.
@@ -279,60 +279,106 @@ events.onexec(0x802CB1C0, function()
 })
 
-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())
 })
 
emulation thread - interpreter mode + interpreter mode only
events.onread(address, callback)
- Adds a CPU read callback for a virtual address or AddressRange and returns a callback ID. + Adds a CPU read callback for a virtual address or AddressRange and returns a callback ID. callback will be invoked at the beginning of a CPU step if the current instruction is going to read from address. callback receives the virtual address that the CPU is going to read.
 events.onread(0x8033B1B0, function()
 {
-    console.log('CPU is reading 8033B1B0')
+    console.log('CPU is reading 0x8033B1B0')
 })
 
-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())
 })
 
emulation thread - interpreter mode + interpreter mode only
events.onwrite(address, callback)
- Adds a CPU write callback for a virtual address or AddressRange and returns a callback ID. + Adds a CPU write callback for a virtual address or AddressRange and returns a callback ID. callback will be invoked at the beginning of a CPU step if the current instruction is going to write to address. callback receives the virtual address that the CPU is going to write to.
 events.onwrite(0x8033B1B0, function()
 {
-    console.log('CPU is modifying 8033B1B0')
+    console.log('CPU is modifying 0x8033B1B0')
 })
 
-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())
 })
 
+
+ emulation thread + interpreter mode only +
events.onopcode(address, opcode, callback)
+
+ Adds a CPU executions callback for a virtual address or AddressRange and returns a callback ID. + callback will be invoked at the beginning of a CPU step if the program counter is at address and opcode is equal to the opcode to be executed. + callback receives the program counter address at which the event is fired. +
+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'
+})
+
+
+
+
+ emulation thread + interpreter mode only +
events.onopcode(address, opcode, mask, callback)
+
+ Adds a CPU executions callback for a virtual address or AddressRange and returns a callback ID. + callback will be invoked at the beginning of a CPU step if the program counter is at address and opcode is equal to the opcode to be executed ANDed with mask. + callback receives the program counter address at which the event is fired. +
+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())
+})
+
+
+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())
+})
+
+
+
emulation thread
events.ondraw(callback)
@@ -468,7 +514,7 @@ console.log('size: ' + stats.size)
fs.stat(path)
- Returns an fs.Stats object describing the file or directory pointed to by path. Returns false if the operation failed.. + Returns an fs.Stats object describing the file or directory pointed to by path. Returns false if the operation failed.