1008 lines
23 KiB
JavaScript
1008 lines
23 KiB
JavaScript
Number.prototype.hex = function(len)
|
|
{
|
|
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'
|
|
|
|
const _typeSizes = {
|
|
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,
|
|
|
|
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
|
|
}
|
|
|
|
const _gprNames = [
|
|
'r0', 'at', 'v0', 'v1', 'a0', 'a1', 'a2', 'a3',
|
|
't0', 't1', 't2', 't3', 't4', 't5', 't6', 't7',
|
|
's0', 's1', 's2', 's3', 's4', 's5', 's6', 's7',
|
|
't8', 't9', 'k0', 'k1', 'gp', 'sp', 'fp', 'ra'
|
|
]
|
|
|
|
// When we give callbacks or objects to native code, we need to make sure we keep a strong backing reference
|
|
// to them in JavaScript so they don't get garbage collected before native code uses them
|
|
|
|
const _strongBackingReferences = (function() {
|
|
const _references = [];
|
|
const noop = function () { };
|
|
|
|
return {
|
|
"add": function _strongBackingReferences_add(obj)
|
|
{
|
|
_references.push(obj);
|
|
},
|
|
"remove": function _strongBackingReferences_remove(obj)
|
|
{
|
|
const index = _references.indexOf(obj);
|
|
if (index !== -1)
|
|
{
|
|
_references.splice(index, 1);
|
|
}
|
|
},
|
|
"singleUseCallback": function _strongBackingReferences_singleUseCallback(callback)
|
|
{
|
|
if (callback === undefined)
|
|
{
|
|
return noop;
|
|
}
|
|
|
|
const singleUseCallback = function ()
|
|
{
|
|
callback.apply(undefined, arguments);
|
|
_strongBackingReferences.remove(callback);
|
|
};
|
|
|
|
_strongBackingReferences.add(singleUseCallback);
|
|
return singleUseCallback;
|
|
}
|
|
};
|
|
}) ();
|
|
|
|
const GPR_R0 = (1 << 0)
|
|
const GPR_AT = (1 << 1)
|
|
const GPR_V0 = (1 << 2)
|
|
const GPR_V1 = (1 << 3)
|
|
const GPR_A0 = (1 << 4)
|
|
const GPR_A1 = (1 << 5)
|
|
const GPR_A2 = (1 << 6)
|
|
const GPR_A3 = (1 << 7)
|
|
const GPR_T0 = (1 << 8)
|
|
const GPR_T1 = (1 << 9)
|
|
const GPR_T2 = (1 << 10)
|
|
const GPR_T3 = (1 << 11)
|
|
const GPR_T4 = (1 << 12)
|
|
const GPR_T5 = (1 << 13)
|
|
const GPR_T6 = (1 << 14)
|
|
const GPR_T7 = (1 << 15)
|
|
const GPR_S0 = (1 << 16)
|
|
const GPR_S1 = (1 << 17)
|
|
const GPR_S2 = (1 << 18)
|
|
const GPR_S3 = (1 << 19)
|
|
const GPR_S4 = (1 << 20)
|
|
const GPR_S5 = (1 << 21)
|
|
const GPR_S6 = (1 << 22)
|
|
const GPR_S7 = (1 << 23)
|
|
const GPR_T8 = (1 << 24)
|
|
const GPR_T9 = (1 << 25)
|
|
const GPR_K0 = (1 << 26)
|
|
const GPR_K1 = (1 << 27)
|
|
const GPR_GP = (1 << 28)
|
|
const GPR_SP = (1 << 29)
|
|
const GPR_FP = (1 << 30)
|
|
const GPR_RA = (1 << 31) >>> 0
|
|
|
|
const GPR_ANY_ARG = (GPR_A0 | GPR_A1 | GPR_A2 | GPR_A3)
|
|
const GPR_ANY_TEMP = (GPR_T0 | GPR_T1 | GPR_T2 | GPR_T3 | GPR_T4 | GPR_T5 | GPR_T6 | GPR_T7 | GPR_T8 | GPR_T9)
|
|
const GPR_ANY_SAVE = (GPR_S0 | GPR_S1 | GPR_S2 | GPR_S3 | GPR_S4 | GPR_S5 | GPR_S6 | GPR_S7)
|
|
const GPR_ANY = (GPR_R0 | GPR_AT | GPR_V0 | GPR_V1 | GPR_ANY_ARG | GPR_ANY_TEMP | GPR_ANY_SAVE | GPR_K0 | GPR_K1 | GPR_GP | GPR_SP | GPR_FP | GPR_RA) >>> 0
|
|
|
|
function AddressRange(start, end)
|
|
{
|
|
this.start = start >>> 0
|
|
this.end = end >>> 0
|
|
Object.freeze(this)
|
|
}
|
|
|
|
const ADDR_ANY = new AddressRange(0x00000000, 0xFFFFFFFF)
|
|
const ADDR_ANY_KUSEG = new AddressRange(0x00000000, 0x7FFFFFFF)
|
|
const ADDR_ANY_KSEG0 = new AddressRange(0x80000000, 0x9FFFFFFF)
|
|
const ADDR_ANY_KSEG1 = new AddressRange(0xA0000000, 0xBFFFFFFF)
|
|
const ADDR_ANY_KSEG2 = new AddressRange(0xC0000000, 0xFFFFFFFF)
|
|
const ADDR_ANY_RDRAM = new AddressRange(0x80000000, 0x807FFFFF)
|
|
const ADDR_ANY_RDRAM_UNC = new AddressRange(0xA0000000, 0xA07FFFFF)
|
|
const ADDR_ANY_CART_ROM = new AddressRange(0x90000000, 0x95FFFFFF)
|
|
const ADDR_ANY_CART_ROM_UNC = new AddressRange(0xB0000000, 0xB5FFFFFF)
|
|
|
|
const asm = {
|
|
gprname: function(num)
|
|
{
|
|
if(num in _gprNames)
|
|
{
|
|
return _gprNames[num]
|
|
}
|
|
return ""
|
|
}
|
|
}
|
|
|
|
const fs = {
|
|
open: function(path, mode)
|
|
{
|
|
if (["r", "rb", "w", "wb", "a", "ab", "r+", "rb+", "r+b", "w+", "wb+", "w+b", "a+", "ab+", "a+b"].indexOf(mode) == -1)
|
|
{
|
|
return false
|
|
}
|
|
return _native.fsOpen(path, mode)
|
|
},
|
|
close: function(fd)
|
|
{
|
|
return _native.fsClose(fd)
|
|
},
|
|
write: function(fd, buffer, offset, length, position)
|
|
{
|
|
return _native.fsWrite(fd, buffer, offset, length, position)
|
|
},
|
|
writeFile: function(path, buffer)
|
|
{
|
|
var fd = fs.open(path, 'wb')
|
|
|
|
if (fd == false)
|
|
{
|
|
return false
|
|
}
|
|
|
|
fs.write(fd, buffer)
|
|
fs.close(fd)
|
|
return true
|
|
},
|
|
read: function (fd, buffer, offset, length, position)
|
|
{
|
|
return _native.fsRead(fd, buffer, offset, length, position)
|
|
},
|
|
readFile: function(path)
|
|
{
|
|
var fd = fs.open(path, 'rb')
|
|
|
|
if(fd == false)
|
|
{
|
|
return false
|
|
}
|
|
|
|
var stats = fs.fstat(fd);
|
|
|
|
var buf = new Buffer(stats.size)
|
|
|
|
fs.read(fd, buf, 0, stats.size, 0)
|
|
|
|
return buf
|
|
},
|
|
fstat: function(fd)
|
|
{
|
|
var rawStats = _native.fsFStat(fd)
|
|
if (rawStats == false)
|
|
{
|
|
return false
|
|
}
|
|
return new fs.Stats(rawStats)
|
|
},
|
|
stat: function(path)
|
|
{
|
|
var rawStats = _native.fsStat(path)
|
|
if (rawStats == false)
|
|
{
|
|
return false
|
|
}
|
|
return new fs.Stats(rawStats)
|
|
},
|
|
mkdir: function(path)
|
|
{
|
|
return _native.fsMkDir(path)
|
|
},
|
|
rmdir: function(path)
|
|
{
|
|
return _native.fsRmDir(path)
|
|
},
|
|
readdir: function(path)
|
|
{
|
|
return _native.fsReadDir(path)
|
|
},
|
|
unlink: function(path)
|
|
{
|
|
return _native.fsUnlink(path)
|
|
},
|
|
Stats: function(rawstats)
|
|
{
|
|
this.dev = rawstats.dev
|
|
this.ino = rawstats.ino
|
|
this.mode = rawstats.mode
|
|
this.nlink = rawstats.nlink
|
|
this.uid = rawstats.uid
|
|
this.gid = rawstats.gid
|
|
this.rdev = rawstats.rdev
|
|
this.size = rawstats.size
|
|
this.atimeMs = rawstats.atimeMs
|
|
this.mtimeMs = rawstats.mtimeMs
|
|
this.ctimeMs = rawstats.ctimeMs
|
|
this.atime = new Date(this.atimeMs)
|
|
this.mtime = new Date(this.mtimeMs)
|
|
this.ctime = new Date(this.ctimeMs)
|
|
Object.freeze(this)
|
|
}
|
|
}
|
|
|
|
fs.Stats.S_IFMT = 0xF000
|
|
fs.Stats.S_IFDIR = 0x4000
|
|
fs.Stats.S_IFCHR = 0x2000
|
|
fs.Stats.S_IFIFO = 0x1000
|
|
fs.Stats.S_IFREG = 0x8000
|
|
fs.Stats.S_IREAD = 0x0100
|
|
fs.Stats.S_IWRITE = 0x0080
|
|
fs.Stats.S_IEXEC = 0x0040
|
|
|
|
fs.Stats.prototype.isDirectory = function()
|
|
{
|
|
return ((this.mode & fs.Stats.S_IFMT) == fs.Stats.S_IFDIR)
|
|
}
|
|
|
|
fs.Stats.prototype.isFile = function()
|
|
{
|
|
return ((this.mode & fs.Stats.S_IFMT) == fs.Stats.S_IFREG)
|
|
}
|
|
|
|
Object.freeze(fs.Stats)
|
|
Object.freeze(fs.Stats.prototype)
|
|
|
|
const system = {
|
|
pause: function()
|
|
{
|
|
_native.pause()
|
|
},
|
|
resume: function()
|
|
{
|
|
|
|
},
|
|
reset: function()
|
|
{
|
|
|
|
},
|
|
hardreset: function()
|
|
{
|
|
|
|
},
|
|
savestate: function()
|
|
{
|
|
|
|
},
|
|
loadstate: function()
|
|
{
|
|
|
|
},
|
|
setsaveslot: function(slot)
|
|
{
|
|
|
|
},
|
|
getsaveslot: function()
|
|
{
|
|
|
|
},
|
|
generatebitmap: function()
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
const debug = {
|
|
showmemory: function(address)
|
|
{
|
|
|
|
},
|
|
showcommands: function(address)
|
|
{
|
|
_native.showCommands(address)
|
|
},
|
|
breakhere: function()
|
|
{
|
|
_native.breakHere()
|
|
},
|
|
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();
|
|
}
|
|
}
|
|
|
|
const screen = {
|
|
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, 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;
|
|
}
|
|
|
|
return events.on('exec', callback, param, param2)
|
|
},
|
|
onopcode: function (addr, value, arg3, arg4)
|
|
{
|
|
// onopcode(addr, value, callback)
|
|
// onopcode(addr, value, mask, callback)
|
|
|
|
var start = 0;
|
|
var end = 0;
|
|
var mask;
|
|
var callback;
|
|
|
|
if(typeof(addr) == "object")
|
|
{
|
|
start = addr.start;
|
|
end = addr.end;
|
|
}
|
|
else if (typeof (addr) == "number")
|
|
{
|
|
start = addr;
|
|
}
|
|
|
|
if (typeof (arg3) == "number")
|
|
{
|
|
mask = arg3;
|
|
callback = arg4;
|
|
}
|
|
else if (typeof (arg3) == "function")
|
|
{
|
|
mask = 0xFFFFFFFF;
|
|
callback = arg3;
|
|
}
|
|
|
|
this._stashCallback(callback);
|
|
return _native.addCallback('opcode', callback, start, end, value, mask)
|
|
},
|
|
ongprvalue: function(addr, registers, value, callback)
|
|
{
|
|
var start = 0;
|
|
var end = 0;
|
|
|
|
if(typeof(addr) == "object")
|
|
{
|
|
start = addr.start;
|
|
end = addr.end;
|
|
}
|
|
else if(typeof(addr) == "number")
|
|
{
|
|
start = addr;
|
|
}
|
|
|
|
this._stashCallback(callback);
|
|
return _native.addCallback('gprvalue', callback, start, end, registers, value)
|
|
},
|
|
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;
|
|
}
|
|
}
|
|
})
|
|
|
|
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;
|
|
}
|
|
}
|
|
})
|
|
|
|
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)
|
|
}
|
|
}
|
|
})
|
|
|
|
const dfpr = new Proxy({},
|
|
{
|
|
get: function (obj, prop)
|
|
{
|
|
if (typeof prop == 'number')
|
|
{
|
|
return _native.getFPRVal(prop, true)
|
|
}
|
|
if (prop in _regNums)
|
|
{
|
|
return _native.getFPRVal(_regNums[prop], true)
|
|
}
|
|
},
|
|
set: function (obj, prop, val)
|
|
{
|
|
if (typeof prop == 'number' && prop < 32)
|
|
{
|
|
_native.setFPRVal(prop, true, val)
|
|
return
|
|
}
|
|
if (prop in _regNums)
|
|
{
|
|
_native.setFPRVal(_regNums[prop], true, val)
|
|
}
|
|
}
|
|
})
|
|
|
|
const cop0 = new Proxy({},
|
|
{
|
|
get: function (obj, prop) {
|
|
if (prop == "cause") {
|
|
return _native.getCauseVal();
|
|
}
|
|
},
|
|
set: function (obj, prop, val) {
|
|
if (prop == "cause") {
|
|
_native.setCauseVal(val);
|
|
}
|
|
}
|
|
})
|
|
|
|
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)
|
|
},
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
function alert(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;
|
|
if (_onconnect !== undefined)
|
|
{
|
|
_onconnect();
|
|
}
|
|
}
|
|
|
|
var _bufferSize = 2048
|
|
|
|
this.write = function(data, callback)
|
|
{
|
|
_native.write(_fd, data, _strongBackingReferences.singleUseCallback(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, _strongBackingReferences.singleUseCallback(_onconnect_base));
|
|
}
|
|
}
|
|
|
|
var _read = function(data)
|
|
{
|
|
if(data == null)
|
|
{
|
|
connected = false;
|
|
_onclose();
|
|
return;
|
|
}
|
|
_native.read(_fd, _bufferSize, _strongBackingReferences.singleUseCallback(_read));
|
|
_ondata(data);
|
|
}
|
|
|
|
this.on = function(eventType, callback)
|
|
{
|
|
switch(eventType)
|
|
{
|
|
case 'data':
|
|
_ondata = callback
|
|
_native.read(_fd, _bufferSize, _strongBackingReferences.singleUseCallback(_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 _listening = false;
|
|
var _queued_accept = false;
|
|
|
|
var _onconnection = function(socket){}
|
|
|
|
this.listen = function (port) {
|
|
if (_native.sockListen(_fd, port || 80)) {
|
|
_listening = true;
|
|
} else {
|
|
throw new Error("Failed to listen");
|
|
}
|
|
|
|
if (_queued_accept) {
|
|
_native.sockAccept(_fd, _strongBackingReferences.singleUseCallback(_acceptClient));
|
|
}
|
|
}
|
|
|
|
if(settings.port)
|
|
{
|
|
this.listen(settings.port || 80);
|
|
}
|
|
|
|
// Intermediate callback
|
|
// convert clientFd to Socket and accept next client
|
|
var _acceptClient = function(clientFd)
|
|
{
|
|
_onconnection(new Socket(clientFd))
|
|
_native.sockAccept(_fd, _strongBackingReferences.singleUseCallback(_acceptClient))
|
|
}
|
|
|
|
this.on = function(eventType, callback)
|
|
{
|
|
switch(eventType)
|
|
{
|
|
case 'connection':
|
|
_onconnection = callback;
|
|
if (_listening) {
|
|
_native.sockAccept(_fd, _strongBackingReferences.singleUseCallback(_acceptClient));
|
|
} else {
|
|
_queued_accept = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|