Merge branch 'master' into gh-pages

This commit is contained in:
Jeff Parsons 2016-12-05 15:58:28 -08:00
commit 161a8e9bd7
15 changed files with 712 additions and 557 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -111,7 +111,19 @@ Keyboard8080.WASDCODES[Keys.ASCII.D] = Keys.KEYCODE.RIGHT;
Keyboard8080.WASDCODES[Keys.ASCII.L] = Keys.KEYCODE.SPACE;
/*
* Supported configurations
* Supported keyboard configurations.
*
* A word (or two) about SOFTCODES. Their main purpose is to provide a naming convention for machine-specific
* controls, without tying us to any particular keyboard mapping. They are used in two main ways.
*
* First, if we have a binding to the machine's "screen", there will, at a minimum, be onkeydown and onkeyup
* handlers attached to the screen, and those handlers will need to iterate through the SOFTCODES table, looking
* for key codes that we care about and converting them to corresponding soft codes. Some machines, like
* Space Invaders, will then act directly upon the soft code (eg, converting it to a machine-specific status bit).
*
* Second, a machine may have other bindings (eg, buttons) to one or more of these soft codes, and those bindings
* will need to know which key codes they're supposed to generate. Some machines, like the VT100, will then use
* another table (KEYMAP) to convert key codes into a machine-specific "key addresses".
*/
Keyboard8080.SI1978 = {
MODEL: 1978.1,
@ -234,7 +246,7 @@ Keyboard8080.VT100 = {
ALTCODES: {},
LEDCODES: {},
SOFTCODES: {
'num-comma': Keys.KEYCODE.F5, // since modern keypads don't typically have a comma...
'num-comma': Keys.KEYCODE.F5,// since modern keypads don't typically have a comma...
'break': Keys.KEYCODE.F6,
'line-feed': Keys.KEYCODE.F7,
'no-scroll': Keys.KEYCODE.F8,
@ -312,17 +324,17 @@ Keyboard8080.MODELS = {
Keyboard8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
{
/*
* There's a special binding that the Video component uses ("kbd") to effectively bind its
* There's a special binding that the Video component uses ("screen") to effectively bind its
* screen to the entire keyboard, in Video.powerUp(); ie:
*
* video.kbd.setBinding("canvas", "kbd", video.canvasScreen);
* video.kbd.setBinding("canvas", "screen", video.canvasScreen);
* or:
* video.kbd.setBinding("textarea", "kbd", video.textareaScreen);
* video.kbd.setBinding("textarea", "screen", video.textareaScreen);
*
* However, it's also possible for the keyboard XML definition to define a control that serves
* a similar purpose; eg:
*
* <control type="text" binding="kbd" width="2em">Kbd</control>
* <control type="text" binding="kbd" width="2em">Keyboard</control>
*
* The latter is purely experimental, while we work on finding ways to trigger the soft keyboard on
* certain pesky devices (like the Kindle Fire). Note that even if you use the latter, the former will
@ -341,10 +353,11 @@ Keyboard8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValu
switch (sBinding) {
case "kbd":
case "screen":
/*
* Recording the binding ID prevents multiple controls (or components) from attempting to erroneously
* bind a control to the same ID, but in the case of a "dual display" configuration, we actually want
* to allow BOTH video components to call setBinding() for "kbd", so that it doesn't matter which
* to allow BOTH video components to call setBinding() for "screen", so that it doesn't matter which
* display the user gives focus to.
*
* this.bindings[id] = control;
@ -366,14 +379,14 @@ Keyboard8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValu
default:
if (this.config.SOFTCODES && this.config.SOFTCODES[sBinding] !== undefined) {
this.bindings[id] = control;
var fnDown = function(kbd, softCode) {
control.onclick = function(kbd, keyCode) {
return function onKeyboardBindingDown(event) {
/*
* iOS Usability Improvement: Calling preventDefault() prevents rapid clicks from
* also being (mis)interpreted as a desire to "zoom" in on the machine.
*/
if (event.preventDefault) event.preventDefault();
kbd.onSoftKeyDown(softCode, true);
kbd.onSoftKeyDown(keyCode, true, true);
/*
* I'm assuming we only need to give focus back on the "up" event...
*
@ -381,26 +394,38 @@ Keyboard8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValu
*/
};
}(this, this.config.SOFTCODES[sBinding]);
var fnUp = function (kbd, softCode) {
return function onKeyboardBindingUp(event) {
kbd.onSoftKeyDown(softCode, false);
/*
* Give focus back to the machine (since clicking the button takes focus away).
*
* if (kbd.cmp) kbd.cmp.updateFocus();
*
* iOS Usability Improvement: NOT calling updateFocus() keeps the soft keyboard down
* (assuming it was already down).
*/
};
}(this, this.config.SOFTCODES[sBinding]);
if ('ontouchstart' in window) {
control.ontouchstart = fnDown;
control.ontouchend = fnUp;
} else {
control.onmousedown = fnDown;
control.onmouseup = control.onmouseout = fnUp;
}
//
// var fnUp = function (kbd, keyCode) {
// return function onKeyboardBindingUp(event) {
// kbd.onSoftKeyDown(keyCode, false);
// /*
// * Give focus back to the machine (since clicking the button takes focus away).
// *
// * if (kbd.cmp) kbd.cmp.updateFocus();
// *
// * iOS Usability Improvement: NOT calling updateFocus() keeps the soft keyboard down
// * (assuming it was already down).
// */
// };
// }(this, this.config.SOFTCODES[sBinding]);
//
// if ('ontouchstart' in window) {
// control.ontouchstart = fnDown;
// control.ontouchend = fnUp;
// } else {
// control.onmousedown = fnDown;
// control.onmouseup = control.onmouseout = fnUp;
// }
//
// UPDATE: Since the only controls that we explicitly bind to SOFTCODES are buttons, I'm simplifying
// the above code with a conventional "onclick" handler. The only corresponding change I had to make
// to the onclick (formerly fnDown) function was to set fAutoRelease on its call to onSoftKeyDown(),
// since we're no longer attempting to detect when the control (ie, the button) is actually released.
//
// This change also resolves a problem I ran into with the Epiphany (WebKit-based) web browser running
// on the "elementary" (Ubuntu-based) OS, where clicks on the SET-UP button were ignored; perhaps its
// buttons don't generate mouse and/or touch events. Anyway, an argument for keeping things simple.
//
return true;
}
break;
@ -848,17 +873,17 @@ Keyboard8080.prototype.onSoftKeyDown = function(softCode, fDown, fAutoRelease)
var i = this.indexOfSoftKey(softCode);
if (fDown) {
// this.println(softCode + " down");
fAutoRelease = fAutoRelease || false;
if (i < 0) {
this.aKeysActive.push({
softCode: softCode,
msDown: Date.now(),
fAutoRelease: fAutoRelease
fAutoRelease: fAutoRelease || false
});
} else {
this.aKeysActive[i].msDown = Date.now();
this.aKeysActive[i].fAutoRelease = fAutoRelease;
this.aKeysActive[i].fAutoRelease = fAutoRelease || false;
}
if (fAutoRelease) this.checkSoftKeysToRelease(); // prime the pump
} else if (i >= 0) {
// this.println(softCode + " up");
if (!this.aKeysActive[i].fAutoRelease) {

View file

@ -421,7 +421,7 @@ Video8080.prototype.initBus = function(cmp, bus, cpu, dbg)
this.kbd.setBinding("led", s, this.ledBindings[s]);
}
if (this.canvasScreen) {
this.kbd.setBinding(this.textareaScreen? "textarea" : "canvas", "kbd", this.inputScreen);
this.kbd.setBinding(this.textareaScreen? "textarea" : "canvas", "screen", this.inputScreen);
}
}

View file

@ -951,17 +951,17 @@ Keyboard.LIMIT = {
Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
{
/*
* There's a special binding that the Video component uses ("kbd") to effectively bind its
* There's a special binding that the Video component uses ("screen") to effectively bind its
* screen to the entire keyboard, in Video.powerUp(); ie:
*
* video.kbd.setBinding("canvas", "kbd", video.canvasScreen);
* video.kbd.setBinding("canvas", "screen", video.canvasScreen);
* or:
* video.kbd.setBinding("textarea", "kbd", video.textareaScreen);
* video.kbd.setBinding("textarea", "screen", video.textareaScreen);
*
* However, it's also possible for the keyboard XML definition to define a control that serves
* a similar purpose; eg:
*
* <control type="text" binding="kbd" width="2em">Kbd</control>
* <control type="text" binding="kbd" width="2em">Keyboard</control>
*
* The latter is purely experimental, while we work on finding ways to trigger the soft keyboard on
* certain pesky devices (like the Kindle Fire). Note that even if you use the latter, the former will
@ -974,10 +974,11 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
if (this.bindings[id] === undefined) {
switch (sBinding) {
case "kbd":
case "screen":
/*
* Recording the binding ID prevents multiple controls (or components) from attempting to erroneously
* bind a control to the same ID, but in the case of a "dual display" configuration, we actually want
* to allow BOTH video components to call setBinding() for "kbd", so that it doesn't matter which
* to allow BOTH video components to call setBinding() for "screen", so that it doesn't matter which
* display the user gives focus to.
*
* this.bindings[id] = control;

View file

@ -2961,7 +2961,7 @@ Video.prototype.initBus = function(cmp, bus, cpu, dbg)
for (var s in this.bindings) {
if (s.indexOf("lock") > 0) this.kbd.setBinding("led", s, this.bindings[s]);
}
this.kbd.setBinding(this.textareaScreen? "textarea" : "canvas", "kbd", this.inputScreen);
this.kbd.setBinding(this.textareaScreen? "textarea" : "canvas", "screen", this.inputScreen);
}
this.bEGASwitches = 0x09; // our default "switches" setting (see aEGAMonitorSwitches)

View file

@ -177,7 +177,7 @@ BusPDP11.IOHANDLER = {
WRITE_BYTE: 1,
READ_WORD: 2,
WRITE_WORD: 3,
NAME: 4,
REG_NAME: 4,
MSG_CATEGORY: 5,
DBG_BREAK: 6
};
@ -235,6 +235,10 @@ BusPDP11.IOController = {
var bus = this.controller;
var afn = bus.aIOHandlers[off];
if (DEBUGGER && this.dbg) {
this.dbg.checkMemoryRead(addr, 1);
}
/*
* Since addr is primarily used to advise an I/O handler of the target IOPAGE address, and since we don't want
* our handlers to worry about the current IOPAGE location, we truncate addr to 16 bits (the IOPAGE's lowest location).
@ -268,7 +272,7 @@ BusPDP11.IOController = {
}
if (b >= 0) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS | afn[BusPDP11.IOHANDLER.MSG_CATEGORY])) {
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.NAME] + ".readByte(" + this.dbg.toStrBase(addr) + "): " + this.dbg.toStrBase(b), true, !bus.nDisableFaults);
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.REG_NAME] + ".readByte(" + this.dbg.toStrBase(addr) + "): " + this.dbg.toStrBase(b), true, !bus.nDisableFaults);
}
return b;
}
@ -295,6 +299,10 @@ BusPDP11.IOController = {
var bus = this.controller;
var afn = bus.aIOHandlers[off];
if (DEBUGGER && this.dbg) {
this.dbg.checkMemoryWrite(addr, 1);
}
/*
* Since addr is primarily used to advise an I/O handler of the target IOPAGE address, and since we don't want
* our handlers to worry about the current IOPAGE location, we truncate addr to 16 bits (the IOPAGE's lowest location).
@ -349,7 +357,7 @@ BusPDP11.IOController = {
}
if (fWrite) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS | afn[BusPDP11.IOHANDLER.MSG_CATEGORY])) {
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.NAME] + ".writeByte(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(b) + ")", true, !bus.nDisableFaults);
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.REG_NAME] + ".writeByte(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(b) + ")", true, !bus.nDisableFaults);
}
return;
}
@ -373,6 +381,10 @@ BusPDP11.IOController = {
var bus = this.controller;
var afn = bus.aIOHandlers[off];
if (DEBUGGER && this.dbg) {
this.dbg.checkMemoryRead(addr, 2);
}
/*
* Since addr is primarily used to advise an I/O handler of the target IOPAGE address, and since we don't want
* our handlers to worry about the current IOPAGE location, we truncate addr to 16 bits (the IOPAGE's lowest location).
@ -388,7 +400,7 @@ BusPDP11.IOController = {
}
if (w >= 0) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS | afn[BusPDP11.IOHANDLER.MSG_CATEGORY])) {
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.NAME] + ".readWord(" + this.dbg.toStrBase(addr) + "): " + this.dbg.toStrBase(w), true, !bus.nDisableFaults);
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.REG_NAME] + ".readWord(" + this.dbg.toStrBase(addr) + "): " + this.dbg.toStrBase(w), true, !bus.nDisableFaults);
}
return w;
}
@ -414,6 +426,10 @@ BusPDP11.IOController = {
var bus = this.controller;
var afn = bus.aIOHandlers[off];
if (DEBUGGER && this.dbg) {
this.dbg.checkMemoryWrite(addr, 2);
}
/*
* Since addr is primarily used to advise an I/O handler of the target IOPAGE address, and since we don't want
* our handlers to worry about the current IOPAGE location, we truncate addr to 16 bits (the IOPAGE's lowest location).
@ -432,7 +448,7 @@ BusPDP11.IOController = {
}
if (fWrite) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS | afn[BusPDP11.IOHANDLER.MSG_CATEGORY])) {
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.NAME] + ".writeWord(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(w) + ")", true, !bus.nDisableFaults);
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.REG_NAME] + ".writeWord(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(w) + ")", true, !bus.nDisableFaults);
}
return;
}
@ -467,11 +483,14 @@ BusPDP11.prototype.initMemory = function()
for (var iBlock = 0; iBlock < this.nBlockTotal; iBlock++) {
this.aBusBlocks[iBlock] = this.aMemBlocks[iBlock] = block;
}
/*
* NOTE: Don't confuse the Bus addrIOPage with the CPU's addrIOPage; ours is fixed,
* based on the machine's Bus width, whereas the CPU's varies according to the MMU setting.
*/
this.addrIOPage = this.addrTotal - BusPDP11.IOPAGE_LENGTH;
this.addMemory(this.addrIOPage, BusPDP11.IOPAGE_LENGTH, MemoryPDP11.TYPE.CONTROLLER, this);
var addrIOPage = this.addrTotal - BusPDP11.IOPAGE_LENGTH;
this.addMemory(addrIOPage, BusPDP11.IOPAGE_LENGTH, MemoryPDP11.TYPE.CONTROLLER, this);
this.iBlockIOPageBus = (addrIOPage & this.nBusMask) >>> this.nBlockShift;
this.iBlockIOPageBus = (this.addrIOPage & this.nBusMask) >>> this.nBlockShift;
this.iBlockIOPageMem = this.iBlockIOPageBus;
this.nIOPageRange = 0;
@ -1224,13 +1243,16 @@ BusPDP11.prototype.getMemoryLimit = function(type)
*/
BusPDP11.prototype.addIOHandlers = function(start, end, fnReadByte, fnWriteByte, fnReadWord, fnWriteWord, message, sName)
{
var index = (start == end? -1 : 0);
for (var addr = start; addr <= end; addr += 2) {
var off = addr & BusPDP11.IOPAGE_MASK;
if (this.aIOHandlers[off] !== undefined) {
Component.warning("I/O address already registered: " + str.toHexLong(addr));
return false;
}
this.aIOHandlers[off] = [fnReadByte, fnWriteByte, fnReadWord, fnWriteWord, sName || "unknown", message || MessagesPDP11.BUS, false];
var s = sName || "unknown";
if (s && index >= 0) s += index++;
this.aIOHandlers[off] = [fnReadByte, fnWriteByte, fnReadWord, fnWriteWord, s, message || MessagesPDP11.BUS, false];
if (MAXDEBUG) this.log("addIOHandlers(" + str.toHexLong(addr) + ")");
}
return true;
@ -1298,6 +1320,48 @@ BusPDP11.prototype.addIOTable = function(component, table, offReg)
return true;
};
/**
* getAddrInfo(addr)
*
* Determine if the physical address is a known IOPAGE address, and return information about it (ie, the name).
*
* @this {BusPDP11}
* @param {number} addr (physical)
* @return {string|null}
*/
BusPDP11.prototype.getAddrInfo = function(addr)
{
var sName = null;
if (addr >= this.addrIOPage) {
var off = addr & BusPDP11.IOPAGE_MASK;
var afn = this.aIOHandlers[off];
if (afn) sName = afn[BusPDP11.IOHANDLER.REG_NAME];
}
return sName;
};
/**
* getAddrByName(sName)
*
* Determine if the specified name has a corresponding physical address.
*
* @this {BusPDP11}
* @param {string} sName
* @return {number|null}
*/
BusPDP11.prototype.getAddrByName = function(sName)
{
sName = sName.toUpperCase();
for (var i in this.aIOHandlers) {
var off = +i;
var afn = this.aIOHandlers[off];
if (afn[BusPDP11.IOHANDLER.REG_NAME] == sName) {
return off + this.addrIOPage;
}
}
return null;
};
/**
* addResetHandler(fnReset)
*

View file

@ -1250,6 +1250,20 @@ if (DEBUGGER) {
return value;
};
/**
* getSymbolValue(sSymbol)
*
* NOTE: At this time, the only symbols we support are those IOPAGE symbols that the Bus component knows about.
*
* @this {DebuggerPDP11}
* @param {string} sSymbol
* @return {number|undefined|null}
*/
DebuggerPDP11.prototype.getSymbolValue = function(sSymbol)
{
return this.bus.getAddrByName(sSymbol);
};
/**
* replaceRegs(s)
*
@ -2206,8 +2220,7 @@ if (DEBUGGER) {
/*
* If getOperand() returns an Array rather than a string, then the first element is the original
* operand, and the second element contains an alternate representation of the operand (eg, target
* address, memory contents, etc).
* operand, and the second element contains additional information (eg, the target) of the operand.
*/
if (typeof sOperand != "string") {
sTarget = sOperand[1];
@ -2239,7 +2252,10 @@ if (DEBUGGER) {
var nCycles = this.cpu.getCycles();
sLine += "cycles=" + nCycles.toString() + " cs=" + str.toHex(this.cpu.nChecksum);
}
if (sTarget) sLine += " @" + sTarget;
if (sTarget) {
if (sLine.slice(-1) != ';') sLine += ' ';
sLine += sTarget;
}
}
return sLine;
};
@ -2248,11 +2264,8 @@ if (DEBUGGER) {
* getOperand(opCode, opType, dbgAddr)
*
* If getOperand() returns an Array rather than a string, then the first element is the original
* operand, and the second element is a comment containing an alternate representation of the operand.
*
* TODO: For PC-relative addresses, we now return the effective address directly, rather than as the
* second element of an Array; however, I still envision using Array return values to include current
* memory operands, so support for such values is being left in place.
* operand, and the second element is a comment containing additional information (eg, the target)
* of the operand.
*
* @this {DebuggerPDP11}
* @param {number} opCode
@ -2295,6 +2308,7 @@ if (DEBUGGER) {
* Isolate all OP_SRC or OP_DST bits from opcode in the opMode variable.
*/
var opMode = opCode & opType;
/*
* Convert OP_SRC bits into OP_DST bits, since they use the same format.
*/
@ -2304,18 +2318,23 @@ if (DEBUGGER) {
}
if (opType & DebuggerPDP11.OP_DST) {
var wIndex;
var sTarget = null;
var reg = opMode & DebuggerPDP11.OP_DSTREG;
/*
* Note that opcodes that specify only REG bits in the opType mask (ie, no MOD bits)
* will automatically default to OPMODE_REG below.
*/
switch((opMode & DebuggerPDP11.OP_DSTMODE)) {
case PDP11.OPMODE.REG: // 0x0: REGISTER
sOperand = this.getRegName(reg);
break;
case PDP11.OPMODE.REGD: // 0x1: REGISTER DEFERRED
sOperand = '@' + this.getRegName(reg);
sTarget = this.getTarget(this.cpu.regsGen[reg]);
break;
case PDP11.OPMODE.POSTINC: // 0x2: POST-INCREMENT
if (reg < 7) {
sOperand = '(' + this.getRegName(reg) + ")+";
@ -2327,6 +2346,7 @@ if (DEBUGGER) {
sOperand = '#' + this.toStrBase(wIndex, 0, true);
}
break;
case PDP11.OPMODE.POSTINCD: // 0x3: POST-INCREMENT DEFERRED
if (reg < 7) {
sOperand = "@(" + this.getRegName(reg) + ")+";
@ -2336,14 +2356,18 @@ if (DEBUGGER) {
*/
wIndex = this.getWord(dbgAddr, 2);
sOperand = "@#" + this.toStrBase(wIndex, 0, true);
sTarget = this.getTarget(wIndex);
}
break;
case PDP11.OPMODE.PREDEC: // 0x4: PRE-DECREMENT
sOperand = "-(" + this.getRegName(reg) + ")";
break;
case PDP11.OPMODE.PREDECD: // 0x5: PRE-DECREMENT DEFERRED
sOperand = "@-(" + this.getRegName(reg) + ")";
break;
case PDP11.OPMODE.INDEX: // 0x6: INDEX
wIndex = this.getWord(dbgAddr, 2);
sOperand = this.toStrBase(wIndex, 0, true) + '(' + this.getRegName(reg) + ')';
@ -2362,9 +2386,11 @@ if (DEBUGGER) {
*
* sOperand = [sOperand, this.toStrBase((wIndex + dbgAddr.addr) & 0xffff)];
*/
sOperand = this.toStrBase((wIndex + dbgAddr.addr) & 0xffff);
sOperand = this.toStrBase(wIndex = (wIndex + dbgAddr.addr) & 0xffff);
sTarget = this.getTarget(wIndex);
}
break;
case PDP11.OPMODE.INDEXD: // 0x7: INDEX DEFERRED
wIndex = this.getWord(dbgAddr, 2);
sOperand = '@' + this.toStrBase(wIndex) + '(' + this.getRegName(reg) + ')';
@ -2375,13 +2401,17 @@ if (DEBUGGER) {
*
* sOperand = [sOperand, this.toStrBase((wIndex + dbgAddr.addr) & 0xffff)];
*/
sOperand = '@' + this.toStrBase((wIndex + dbgAddr.addr) & 0xffff);
sOperand = '@' + this.toStrBase(wIndex = (wIndex + dbgAddr.addr) & 0xffff);
sTarget = this.getTarget(this.cpu.getWordSafe(wIndex));
}
break;
default:
this.assert(false);
break;
}
if (sTarget) sOperand = [sOperand, sTarget];
}
else {
this.assert(false);
@ -2390,6 +2420,24 @@ if (DEBUGGER) {
return sOperand;
};
/**
* getTarget(addr)
*
* @this {DebuggerPDP11}
* @param {number} addr
* @return {string|null}
*/
DebuggerPDP11.prototype.getTarget = function(addr)
{
var sTarget = null;
var a = this.cpu.getAddrInfo(addr);
var addrPhysical = a[0];
if (addrPhysical >= this.cpu.addrIOPage && addrPhysical < this.bus.addrIOPage) {
addrPhysical = (addrPhysical - this.cpu.addrIOPage) + this.bus.addrIOPage;
}
return this.bus.getAddrInfo(addrPhysical);
};
/**
* parseInstruction(sOp, sOperand, addr)
*

View file

@ -179,6 +179,20 @@ if (DEBUGGER) {
return undefined;
};
/**
* getSymbolValue(sSymbol)
*
* NOTE: This must be implemented by the individual debuggers.
*
* @this {Debugger}
* @param {string} sSymbol
* @return {number|undefined|null}
*/
Debugger.prototype.getSymbolValue = function(sSymbol)
{
return undefined;
};
/**
* parseAddrReference(s, sAddr)
*
@ -577,7 +591,12 @@ if (DEBUGGER) {
value = this.getRegValue(iReg);
} else {
value = this.getVariable(sValue);
if (value == null) value = str.parseInt(sValue, this.nBase);
if (value == null) {
value = this.getSymbolValue(sValue);
if (value == null) {
value = str.parseInt(sValue, this.nBase);
}
}
}
if (value == null && !fQuiet) this.println("invalid " + (sName? sName : "value") + ": " + sValue);
} else {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long