Supoprt for tape images in the Absolute Loader format has been moved to the RAM component, so that those images can be preloaded into RAM in the same way that raw bootstrap images can; the RAM component now provides Absolute Loader image parsing as a service to other components that need it (specifically, the PC11 tape reader)
This commit is contained in:
parent
69b7a682d8
commit
13a1dedbc7
21 changed files with 800 additions and 693 deletions
|
|
@ -66,8 +66,8 @@ function RAM8080(parmsRAM)
|
|||
|
||||
this.addrRAM = parmsRAM['addr'];
|
||||
this.sizeRAM = parmsRAM['size'];
|
||||
this.nFileLoad = parmsRAM['load'];
|
||||
this.nFileExec = parmsRAM['exec'];
|
||||
this.addrLoad = parmsRAM['load'];
|
||||
this.addrExec = parmsRAM['exec'];
|
||||
|
||||
this.fInstalled = (!!this.sizeRAM); // 0 is the default value for 'size' when none is specified
|
||||
this.fAllocated = false;
|
||||
|
|
@ -197,8 +197,8 @@ RAM8080.prototype.doneLoad = function(sURL, sData, nErrorCode)
|
|||
if (resource) {
|
||||
this.abInit = resource.aBytes;
|
||||
this.aSymbols = resource.aSymbols;
|
||||
if (this.nFileLoad == null && resource.nLoad != null) this.nFileLoad = resource.nLoad;
|
||||
if (this.nFileExec == null && resource.nExec != null) this.nFileExec = resource.nExec;
|
||||
if (this.addrLoad == null) this.addrLoad = resource.addrLoad;
|
||||
if (this.addrExec == null) this.addrExec = resource.addrExec;
|
||||
} else {
|
||||
this.sFilePath = null;
|
||||
}
|
||||
|
|
@ -232,19 +232,19 @@ RAM8080.prototype.initRAM = function()
|
|||
if (!this.abInit || !this.bus) return;
|
||||
|
||||
var addr = this.addrRAM;
|
||||
if (this.nFileLoad !== null) addr = this.nFileLoad;
|
||||
if (this.addrLoad !== null) addr = this.addrLoad;
|
||||
for (var i = 0; i < this.abInit.length; i++) {
|
||||
this.bus.setByteDirect(addr + i, this.abInit[i]);
|
||||
}
|
||||
|
||||
if (this.nFileExec !== null) {
|
||||
if (this.addrExec !== null) {
|
||||
/*
|
||||
* Here's where we enable our "Fake CP/M" support, triggered by the user loading a "writable" ROM image
|
||||
* at offset 0x100. Fake CP/M support works by installing HLT opcodes at well-known CP/M addresses
|
||||
* (namely, 0x0000, which is the CP/M reset vector, and 0x0005, which is the CP/M system call vector) and
|
||||
* then telling the CPU to call us whenever a HLT occurs, so we can check PC for one of these addresses.
|
||||
*/
|
||||
if (this.nFileExec == RAM8080.CPM.INIT) {
|
||||
if (this.addrExec == RAM8080.CPM.INIT) {
|
||||
for (i = 0; i < RAM8080.CPM.VECTORS.length; i++) {
|
||||
this.bus.setByteDirect(RAM8080.CPM.VECTORS[i], CPUDef8080.OPCODE.HLT);
|
||||
}
|
||||
|
|
@ -255,7 +255,7 @@ RAM8080.prototype.initRAM = function()
|
|||
};
|
||||
}(this));
|
||||
}
|
||||
this.cpu.setReset(this.nFileExec);
|
||||
this.cpu.setReset(this.addrExec);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1278,7 +1278,7 @@ FDC.prototype.autoMount = function(fRemount)
|
|||
if (this.configMount) {
|
||||
for (var sDrive in this.configMount) {
|
||||
var configDrive = this.configMount[sDrive];
|
||||
var sDiskettePath = configDrive['path'];
|
||||
var sDiskettePath = configDrive['path'] || "";
|
||||
var sDisketteName = configDrive['name'] || this.findDiskette(sDiskettePath);
|
||||
if (sDiskettePath && sDisketteName) {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -369,6 +369,13 @@ CPUStatePDP11.prototype.setReset = function(addr)
|
|||
{
|
||||
this.addrReset = addr;
|
||||
this.setPC(addr);
|
||||
if (this.dbg) {
|
||||
/*
|
||||
* TODO: Review the decision to always stop the CPU if the Debugger is loaded.
|
||||
*/
|
||||
this.stopCPU();
|
||||
this.dbg.updateStatus();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ function DebuggerPDP11(parmsDbg)
|
|||
/*
|
||||
* Since this Debugger doesn't use replaceRegs(), we can use parentheses instead of braces.
|
||||
*/
|
||||
this.fInit = false;
|
||||
this.fParens = true;
|
||||
|
||||
/*
|
||||
|
|
@ -1217,6 +1218,7 @@ if (DEBUGGER) {
|
|||
*/
|
||||
DebuggerPDP11.prototype.init = function()
|
||||
{
|
||||
this.fInit = true;
|
||||
this.println("Type ? for help with PDP11 Debugger commands");
|
||||
this.updateStatus();
|
||||
if (this.sInitCommands) {
|
||||
|
|
@ -1367,6 +1369,8 @@ if (DEBUGGER) {
|
|||
*/
|
||||
DebuggerPDP11.prototype.updateStatus = function(fRegs)
|
||||
{
|
||||
if (!this.fInit) return;
|
||||
|
||||
if (fRegs === undefined) fRegs = true;
|
||||
|
||||
this.dbgAddrNextCode = this.newAddr(this.cpu.getPC());
|
||||
|
|
|
|||
|
|
@ -220,6 +220,7 @@ PC11.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
this.bus = bus;
|
||||
this.cpu = cpu;
|
||||
this.dbg = dbg;
|
||||
this.ram = cmp.getMachineComponent("RAM");
|
||||
|
||||
var pc11 = this;
|
||||
|
||||
|
|
@ -310,7 +311,7 @@ PC11.prototype.autoMount = function(fRemount)
|
|||
{
|
||||
if (!fRemount) this.cAutoMount = 0;
|
||||
if (this.configMount) {
|
||||
var sTapePath = this.configMount['path'];
|
||||
var sTapePath = this.configMount['path'] || "";
|
||||
var sTapeName = this.configMount['name'] || this.findTape(sTapePath);
|
||||
if (sTapePath && sTapeName) {
|
||||
/*
|
||||
|
|
@ -320,7 +321,11 @@ PC11.prototype.autoMount = function(fRemount)
|
|||
this.setReady(false);
|
||||
}
|
||||
} else {
|
||||
this.notice("Incorrect auto-mount settings for PC11 (" + JSON.stringify(this.configMount) + ")");
|
||||
/*
|
||||
* This likely happened because there was no autoMount setting (or it was overridden with an empty value),
|
||||
* so just make sure the current selection is set to "None".
|
||||
*/
|
||||
this.displayTape();
|
||||
}
|
||||
}
|
||||
return !!this.cAutoMount;
|
||||
|
|
@ -360,7 +365,7 @@ PC11.prototype.loadSelectedTape = function(sTapeName, sTapePath, nTapeTarget, fi
|
|||
sTapePath = window.prompt("Enter the URL of a remote tape image.", "") || "";
|
||||
if (!sTapePath) return;
|
||||
sTapeName = str.getBaseName(sTapePath);
|
||||
if (DEBUG) this.println("Attempting to load " + sTapePath + " as \"" + sTapeName + "\"");
|
||||
this.status("Attempting to load " + sTapePath + " as \"" + sTapeName + "\"");
|
||||
this.sTapeSource = PC11.SOURCE.REMOTE;
|
||||
}
|
||||
else {
|
||||
|
|
@ -395,7 +400,7 @@ PC11.prototype.loadTape = function(sTapeName, sTapePath, nTapeTarget, fAutoMount
|
|||
this.notice("PC11 busy");
|
||||
}
|
||||
else {
|
||||
// if (DEBUG) this.println("tape queued: " + sTapeName);
|
||||
// this.status("tape queued: " + sTapeName);
|
||||
if (fAutoMount) {
|
||||
this.cAutoMount++;
|
||||
if (this.messageEnabled()) this.printMessage("auto-loading tape: " + sTapeName);
|
||||
|
|
@ -407,7 +412,7 @@ PC11.prototype.loadTape = function(sTapeName, sTapePath, nTapeTarget, fAutoMount
|
|||
}
|
||||
}
|
||||
}
|
||||
if (DEBUG && nResult) this.println(this.nTapeTarget == PC11.TARGET.READER? "tape attached" : "tape loaded");
|
||||
if (nResult) this.status(this.nTapeTarget == PC11.TARGET.READER? "tape attached" : "tape loaded");
|
||||
return nResult;
|
||||
};
|
||||
|
||||
|
|
@ -496,7 +501,7 @@ PC11.prototype.doneLoad = function(sTapeName, sTapePath, nTapeTarget, sTapeData,
|
|||
Component.addMachineResource(this.idMachine, sURL, sTapeData);
|
||||
var resource = web.parseMemoryResource(sURL, sTapeData);
|
||||
if (resource) {
|
||||
this.parseTape(sTapeName, sTapePath, nTapeTarget, resource.aBytes);
|
||||
this.parseTape(sTapeName, sTapePath, nTapeTarget, resource.aBytes, resource.addrLoad, resource.addrExec);
|
||||
}
|
||||
}
|
||||
this.flags.busy = false;
|
||||
|
|
@ -597,107 +602,50 @@ PC11.prototype.displayTape = function()
|
|||
};
|
||||
|
||||
/**
|
||||
* parseTape(sTapeName, sTapePath, nTapeTarget, aBytes)
|
||||
* parseTape(sTapeName, sTapePath, nTapeTarget, aBytes, addrLoad, addrExec)
|
||||
*
|
||||
* @this {PC11}
|
||||
* @param {string} sTapeName
|
||||
* @param {string} sTapePath
|
||||
* @param {number} nTapeTarget
|
||||
* @param {Array|Uint8Array} aBytes
|
||||
* @param {number|null} [addrLoad]
|
||||
* @param {number|null} [addrExec]
|
||||
*/
|
||||
PC11.prototype.parseTape = function(sTapeName, sTapePath, nTapeTarget, aBytes)
|
||||
PC11.prototype.parseTape = function(sTapeName, sTapePath, nTapeTarget, aBytes, addrLoad, addrExec)
|
||||
{
|
||||
this.sTapeName = sTapeName;
|
||||
this.sTapePath = sTapePath;
|
||||
this.nTapeTarget = nTapeTarget;
|
||||
|
||||
if (nTapeTarget == PC11.TARGET.MEMORY) {
|
||||
/*
|
||||
* Data on tapes is organized into blocks; each block begins with a 6-byte header:
|
||||
* Use the RAM component's loadImage() service to do our dirty work. If the load succeeds, then
|
||||
* depending on whether there was also exec address, either the CPU will be stopped or the PC wil be
|
||||
* reset.
|
||||
*
|
||||
* 2-byte signature (0x01,0x00)
|
||||
* 2-byte length (N + 6)
|
||||
* 2-byte load address
|
||||
* NOTE: Some tapes are not in the Absolute Loader format, so if the JSON-encoded tape resource file
|
||||
* we downloaded didn't ALSO include a load address, the load will fail.
|
||||
*
|
||||
* followed by N data bytes. If N is zero, then the 2-byte load address is the exec address,
|
||||
* unless the address is odd (usually 1), in which case stop.
|
||||
*
|
||||
* After the data bytes, there is a single checksum byte. The sum of all the bytes (including
|
||||
* the checksum byte) should be zero.
|
||||
*
|
||||
* ANOMALIES: Tape files don't always begin with a signature word, so I allow any number of
|
||||
* leading zeros before the first signature. Tape files don't always end cleanly either, so as
|
||||
* soon as I see an invalid signature, I break out of the loop without signalling an error, as
|
||||
* long as at least ONE block was successfully processed.
|
||||
* For example, the "Absolute Loader" tape is NOT itself in the Absolute Loader format. You just have
|
||||
* to know that in order to load that tape, you must first load the appropriate "Bootstrap Loader" (which
|
||||
* DOES include its own hard-coded load address), attach the "Absolute Loader" tape, and then run the
|
||||
* "Bootstrap Loader".
|
||||
*/
|
||||
var off = 0;
|
||||
var fError = false, cBlocks = 0;
|
||||
while (off < aBytes.length - 1) {
|
||||
var w = (aBytes[off] & 0xff) | ((aBytes[off+1] & 0xff) << 8);
|
||||
if (!w) { // ignore pairs of leading zeros
|
||||
off += 2;
|
||||
continue;
|
||||
}
|
||||
if (!(w & 0xff)) { // as well as single bytes of zero
|
||||
off++;
|
||||
continue;
|
||||
}
|
||||
var offBlock = off;
|
||||
if (w != 0x0001) {
|
||||
if (DEBUG) this.println("invalid signature (" + str.toHexWord(w) + ") at offset " + str.toHexWord(offBlock));
|
||||
if (!cBlocks) fError = true;
|
||||
break;
|
||||
}
|
||||
if (off + 6 >= aBytes.length) {
|
||||
if (DEBUG) this.println("invalid block at offset " + str.toHexWord(offBlock));
|
||||
fError = true;
|
||||
break;
|
||||
}
|
||||
off += 2;
|
||||
var checksum = w;
|
||||
var len = (aBytes[off++] & 0xff) | ((aBytes[off++] & 0xff) << 8);
|
||||
var addr = (aBytes[off++] & 0xff) | ((aBytes[off++] & 0xff) << 8);
|
||||
checksum += (len & 0xff) + (len >> 8) + (addr & 0xff) + (addr >> 8);
|
||||
var offData = off, cbData = len -= 6;
|
||||
while (len > 0 && off < aBytes.length - 1) {
|
||||
checksum += aBytes[off++] & 0xff;
|
||||
len--;
|
||||
}
|
||||
if (len != 0 || off >= aBytes.length) {
|
||||
if (DEBUG) this.println("insufficient data for block at offset " + str.toHexWord(offBlock));
|
||||
fError = true;
|
||||
break;
|
||||
}
|
||||
checksum += aBytes[off++] & 0xff;
|
||||
if (checksum & 0xff) {
|
||||
if (DEBUG) this.println("invalid checksum (" + str.toHexByte(checksum) + ") for block at offset " + str.toHexWord(offBlock));
|
||||
fError = true;
|
||||
break;
|
||||
}
|
||||
if (!cbData) {
|
||||
if (!(addr & 0x1)) {
|
||||
this.cpu.setPC(addr);
|
||||
}
|
||||
} else {
|
||||
while (cbData--) {
|
||||
this.cpu.setByteDirect(addr++, aBytes[offData++] & 0xff);
|
||||
}
|
||||
}
|
||||
cBlocks++;
|
||||
}
|
||||
if (fError) {
|
||||
if (!this.ram || !this.ram.loadImage(aBytes, addrLoad, addrExec)) {
|
||||
this.sTapeName = "";
|
||||
this.sTapePath = "";
|
||||
this.sTapeSource = PC11.SOURCE.NONE;
|
||||
this.nTapeTarget = PC11.TARGET.NONE;
|
||||
if (DEBUG) this.println("error loading tape: " + sTapeName);
|
||||
this.status("error loading tape: " + sTapeName);
|
||||
return;
|
||||
}
|
||||
if (DEBUG) this.println("tape loaded: " + sTapeName);
|
||||
this.status("tape loaded: " + sTapeName);
|
||||
return;
|
||||
}
|
||||
this.iTapeData = 0;
|
||||
this.aTapeData = aBytes;
|
||||
if (DEBUG) this.println("tape attached: " + sTapeName);
|
||||
this.status("tape attached: " + sTapeName);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -715,7 +663,7 @@ PC11.prototype.unloadTape = function(fLoading)
|
|||
* Avoid any unnecessary hysteresis regarding the display if this unload is merely a prelude to another load.
|
||||
*/
|
||||
if (!fLoading) {
|
||||
if (DEBUG && this.nTapeTarget) this.println(this.nTapeTarget == PC11.TARGET.READER? "tape detached" : "tape unloaded");
|
||||
if (this.nTapeTarget) this.status(this.nTapeTarget == PC11.TARGET.READER? "tape detached" : "tape unloaded");
|
||||
this.sTapeSource = PC11.SOURCE.NONE;
|
||||
this.nTapeTarget = PC11.TARGET.NONE;
|
||||
this.displayTape();
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ function RAMPDP11(parmsRAM)
|
|||
|
||||
this.addrRAM = parmsRAM['addr'];
|
||||
this.sizeRAM = parmsRAM['size'];
|
||||
this.nFileLoad = parmsRAM['load'];
|
||||
this.nFileExec = parmsRAM['exec'];
|
||||
this.addrLoad = parmsRAM['load'];
|
||||
this.addrExec = parmsRAM['exec'];
|
||||
|
||||
this.fInstalled = (!!this.sizeRAM); // 0 is the default value for 'size' when none is specified
|
||||
this.fAllocated = false;
|
||||
|
|
@ -175,8 +175,8 @@ RAMPDP11.prototype.doneLoad = function(sURL, sData, nErrorCode)
|
|||
if (resource) {
|
||||
this.abInit = resource.aBytes;
|
||||
this.aSymbols = resource.aSymbols;
|
||||
if (this.nFileLoad == null && resource.nLoad != null) this.nFileLoad = resource.nLoad;
|
||||
if (this.nFileExec == null && resource.nExec != null) this.nFileExec = resource.nExec;
|
||||
if (this.addrLoad == null) this.addrLoad = resource.addrLoad;
|
||||
if (this.addrExec == null) this.addrExec = resource.addrExec;
|
||||
} else {
|
||||
this.sFilePath = null;
|
||||
}
|
||||
|
|
@ -194,6 +194,8 @@ RAMPDP11.prototype.doneLoad = function(sURL, sData, nErrorCode)
|
|||
*/
|
||||
RAMPDP11.prototype.initRAM = function()
|
||||
{
|
||||
if (!this.bus) return;
|
||||
|
||||
if (!this.fAllocated && this.sizeRAM) {
|
||||
if (this.bus.addMemory(this.addrRAM, this.sizeRAM, MemoryPDP11.TYPE.RAM)) {
|
||||
this.fAllocated = true;
|
||||
|
|
@ -209,15 +211,7 @@ RAMPDP11.prototype.initRAM = function()
|
|||
*/
|
||||
if (!this.abInit || !this.bus) return;
|
||||
|
||||
var addr = this.addrRAM;
|
||||
if (this.nFileLoad !== null) addr = this.nFileLoad;
|
||||
for (var i = 0; i < this.abInit.length; i++) {
|
||||
this.bus.setByteDirect(addr + i, this.abInit[i]);
|
||||
}
|
||||
|
||||
if (this.nFileExec !== null) {
|
||||
this.cpu.setReset(this.nFileExec);
|
||||
}
|
||||
this.loadImage(this.abInit, this.addrLoad, this.addrExec, this.addrRAM);
|
||||
|
||||
/*
|
||||
* TODO: Consider an option to retain this data and give the user a way of restoring the initial contents.
|
||||
|
|
@ -240,6 +234,108 @@ RAMPDP11.prototype.reset = function()
|
|||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* loadImage(aBytes, addrLoad, addrExec, addrInit)
|
||||
*
|
||||
* @this {RAMPDP11}
|
||||
* @param {Array|Uint8Array} aBytes
|
||||
* @param {number|null} [addrLoad]
|
||||
* @param {number|null} [addrExec]
|
||||
* @param {number|null} [addrInit]
|
||||
* @return {boolean} (true if loaded, false if not)
|
||||
*/
|
||||
RAMPDP11.prototype.loadImage = function(aBytes, addrLoad, addrExec, addrInit)
|
||||
{
|
||||
var fLoaded = false;
|
||||
/*
|
||||
* Data on tapes is organized into blocks; each block begins with a 6-byte header:
|
||||
*
|
||||
* 2-byte signature (0x0001)
|
||||
* 2-byte block length (N + 6, because it includes the 6-byte header)
|
||||
* 2-byte load address
|
||||
*
|
||||
* followed by N data bytes. If N is zero, then the 2-byte load address is the exec address,
|
||||
* unless the address is odd (usually 1). DEC's "Absolute Loader" jumps to the exec address
|
||||
* in former case, halts in the latter.
|
||||
*
|
||||
* All values are stored "little endian" (low byte first, followed by high byte), just like
|
||||
* the PDP-11 does.
|
||||
*
|
||||
* After the data bytes, there is a single checksum byte. The 8-bit sum of all the bytes in
|
||||
* the block (including the header bytes and checksum byte) should be zero.
|
||||
*
|
||||
* ANOMALIES: Tape files don't always begin with a signature word, so I allow any number of
|
||||
* leading zeros before the first signature. Tape files don't always end cleanly either, so as
|
||||
* soon as I see an invalid signature, I break out of the loop without signalling an error, as
|
||||
* long as at least ONE block was successfully processed.
|
||||
*/
|
||||
if (addrLoad == null) {
|
||||
var off = 0, fError = false;
|
||||
while (off < aBytes.length - 1) {
|
||||
var w = (aBytes[off] & 0xff) | ((aBytes[off+1] & 0xff) << 8);
|
||||
if (!w) { // ignore pairs of leading zeros
|
||||
off += 2;
|
||||
continue;
|
||||
}
|
||||
if (!(w & 0xff)) { // as well as single bytes of zero
|
||||
off++;
|
||||
continue;
|
||||
}
|
||||
var offBlock = off;
|
||||
if (w != 0x0001) {
|
||||
if (MAXDEBUG) this.println("invalid signature (" + str.toHexWord(w) + ") at offset " + str.toHexWord(offBlock));
|
||||
break;
|
||||
}
|
||||
if (off + 6 >= aBytes.length) {
|
||||
if (MAXDEBUG) this.println("invalid block at offset " + str.toHexWord(offBlock));
|
||||
break;
|
||||
}
|
||||
off += 2;
|
||||
var checksum = w;
|
||||
var len = (aBytes[off++] & 0xff) | ((aBytes[off++] & 0xff) << 8);
|
||||
var addr = (aBytes[off++] & 0xff) | ((aBytes[off++] & 0xff) << 8);
|
||||
checksum += (len & 0xff) + (len >> 8) + (addr & 0xff) + (addr >> 8);
|
||||
var offData = off, cbData = len -= 6;
|
||||
while (len > 0 && off < aBytes.length) {
|
||||
checksum += aBytes[off++] & 0xff;
|
||||
len--;
|
||||
}
|
||||
if (len != 0 || off >= aBytes.length) {
|
||||
if (MAXDEBUG) this.println("insufficient data for block at offset " + str.toHexWord(offBlock));
|
||||
break;
|
||||
}
|
||||
checksum += aBytes[off++] & 0xff;
|
||||
if (checksum & 0xff) {
|
||||
if (MAXDEBUG) this.println("invalid checksum (" + str.toHexByte(checksum) + ") for block at offset " + str.toHexWord(offBlock));
|
||||
break;
|
||||
}
|
||||
if (!cbData) {
|
||||
if (addr & 0x1) {
|
||||
this.cpu.stopCPU();
|
||||
} else {
|
||||
this.cpu.setReset(addr);
|
||||
}
|
||||
} else {
|
||||
while (cbData--) {
|
||||
this.cpu.setByteDirect(addr++, aBytes[offData++] & 0xff);
|
||||
}
|
||||
}
|
||||
fLoaded = true;
|
||||
}
|
||||
}
|
||||
if (!fLoaded) {
|
||||
if (addrLoad == null) addrLoad = addrInit;
|
||||
if (addrLoad != null) {
|
||||
for (var i = 0; i < aBytes.length; i++) {
|
||||
this.cpu.setByteDirect(addrLoad + i, aBytes[i]);
|
||||
}
|
||||
if (addrExec != null) this.cpu.setReset(addrExec);
|
||||
fLoaded = true;
|
||||
}
|
||||
}
|
||||
return fLoaded;
|
||||
};
|
||||
|
||||
/**
|
||||
* RAMPDP11.init()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -295,8 +295,8 @@ web.parseMemoryResource = function(sURL, sData)
|
|||
var resource = {
|
||||
aBytes: null,
|
||||
aSymbols: null,
|
||||
nLoad: null,
|
||||
nExec: null
|
||||
addrLoad: null,
|
||||
addrExec: null
|
||||
};
|
||||
|
||||
if (sData.charAt(0) == "[" || sData.charAt(0) == "{") {
|
||||
|
|
@ -338,8 +338,8 @@ web.parseMemoryResource = function(sURL, sData)
|
|||
data = eval("(" + sData + ")");
|
||||
}
|
||||
|
||||
resource.nLoad = data['load'];
|
||||
resource.nExec = data['exec'];
|
||||
resource.addrLoad = data['load'];
|
||||
resource.addrExec = data['exec'];
|
||||
|
||||
if (a = data['bytes']) {
|
||||
resource.aBytes = a;
|
||||
|
|
|
|||
Loading…
Reference in a new issue