Cleaned up debugger message handling

This commit is contained in:
Jeff Parsons 2014-11-30 12:56:59 -08:00 committed by jeffpar
commit 2ff339f190
31 changed files with 640 additions and 735 deletions

View file

@ -171,7 +171,7 @@ module.exports = function(grunt) {
banner: '"use strict";\n\n', banner: '"use strict";\n\n',
process: function(src, filepath) { process: function(src, filepath) {
return "// " + filepath + "\n\n" + return "// " + filepath + "\n\n" +
src.replace(/(^|\n)[ \t]*(['"])use strict\2;?\s*/g, '$1').replace(/[ \t]*if\s*\(typeof\s+(module|APP_PCJS)\s*!==\s*(['"])undefined\2\)\s*(\{[^}]*}|[^\n]*)(\n|$)/gm, ''); src.replace(/(^|\n)[ \t]*(['"])use strict\2;?\s*/g, '$1').replace(/[ \t]*if\s*\(typeof\s+(module|APP_PCJS)\s*!==\s*(['"])undefined\2\)\s*(\{[^}]*}|[^\n]*)(\n|$)/gm, '').replace(/[ \t]*[A-Za-z_][A-Za-z0-9_\.]*\.assert\(.*\);[^\n]*(\n|$)/g, '');
} }
} }
}, },
@ -182,7 +182,7 @@ module.exports = function(grunt) {
banner: '"use strict";\n\n', banner: '"use strict";\n\n',
process: function(src, filepath) { process: function(src, filepath) {
return "// " + filepath + "\n\n" + return "// " + filepath + "\n\n" +
src.replace(/(^|\n)[ \t]*(['"])use strict\2;?\s*/g, '$1').replace(/[ \t]*if\s*\(typeof\s+(module|APP_PCJS)\s*!==\s*(['"])undefined\2\)\s*(\{[^}]*}|[^\n]*)(\n|$)/gm, ''); src.replace(/(^|\n)[ \t]*(['"])use strict\2;?\s*/g, '$1').replace(/[ \t]*if\s*\(typeof\s+(module|APP_PCJS)\s*!==\s*(['"])undefined\2\)\s*(\{[^}]*}|[^\n]*)(\n|$)/gm, '').replace(/[ \t]*[A-Za-z_][A-Za-z0-9_\.]*\.assert\(.*\);[^\n]*(\n|$)/g, '');
} }
} }
} }

View file

@ -32,8 +32,10 @@
"global": true, "global": true,
"module": true, "module": true,
"require": true, "require": true,
"FileReader": false,
"setTimeout": false, "setTimeout": false,
"clearTimeout": false, "clearTimeout": false,
"Image": false "Image": false,
"DumpAPI": false
} }
} }

View file

@ -49,6 +49,7 @@ function C1PDebugger(parmsDbg)
Component.call(this, "C1PDebugger", parmsDbg); Component.call(this, "C1PDebugger", parmsDbg);
this.dbg = this;
/* /*
* This keeps track of instruction activity, but only when tracing or when * This keeps track of instruction activity, but only when tracing or when
* Debugger checks have been enabled (eg, one or more breakpoints have been set). * Debugger checks have been enabled (eg, one or more breakpoints have been set).
@ -122,7 +123,7 @@ function C1PDebugger(parmsDbg)
this.MESSAGE_SERIAL = 0x80; this.MESSAGE_SERIAL = 0x80;
this.MESSAGE_NONE = 0x00; this.MESSAGE_NONE = 0x00;
// this.MESSAGE_ALL = 0xff; // this.MESSAGE_ALL = 0xff;
this.bMessages = this.MESSAGE_NONE; this.bitsMessage = this.MESSAGE_NONE;
this.aMessageCategories = { this.aMessageCategories = {
'port': this.MESSAGE_PORT, 'port': this.MESSAGE_PORT,
'kbd': this.MESSAGE_KBD, 'kbd': this.MESSAGE_KBD,
@ -694,7 +695,7 @@ if (DEBUGGER) {
]; ];
for (iMode=0; iMode < this.aOpModes.length; iMode++) { for (iMode=0; iMode < this.aOpModes.length; iMode++) {
sMode = this.aOpModes[iMode]; sMode = this.aOpModes[iMode];
sRegEx += "(" + sMode.replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/nnnn/g, "[0-9A-F][0-9A-F][0-9A-F][0-9A-F]?").replace(/nn/g, "[0-9A-F][0-9A-F]?").replace(/\+/g, "\\+") + "|)"; sRegEx += "(" + sMode.replace(/\[/g, "\\[").replace(/]/g, "\\]").replace(/nnnn/g, "[0-9A-F][0-9A-F][0-9A-F][0-9A-F]?").replace(/nn/g, "[0-9A-F][0-9A-F]?").replace(/\+/g, "\\+") + "|)";
} }
this.regexOpModes = new RegExp(sRegEx); this.regexOpModes = new RegExp(sRegEx);
} }
@ -732,31 +733,18 @@ if (DEBUGGER) {
} }
}; };
/**
* @this {C1PDebugger}
* @param {number} bMessage is one or more Debugger MESSAGE_* category flag(s)
* @return {boolean} true if message category is enabled, false if not
*
* NOTE: If the caller specifies MULTIPLE category flags, then ALL the corresponding flags
* in the Debugger's bMessages variable must be enabled as well, else the result will be false
*/
C1PDebugger.prototype.messageEnabled = function(bMessage)
{
return ((this.bMessages & bMessage) === bMessage);
};
/** /**
* @this {C1PDebugger} * @this {C1PDebugger}
* @param {Component} component * @param {Component} component
* @param {number} addr * @param {number} addr
* @param {number|undefined} addrFrom * @param {number|undefined} addrFrom
* @param {boolean} bMessage is a Debugger MESSAGE_* category flag * @param {boolean} bitsMessage is a Debugger MESSAGE_* category flag
* @param {boolean|undefined} [fWrite] is true if this was a write, false (or undefined) if read * @param {boolean|undefined} [fWrite] is true if this was a write, false (or undefined) if read
* @param {string|undefined} [name] of the port, if any * @param {string|undefined} [name] of the port, if any
*/ */
C1PDebugger.prototype.messagePort = function(component, addr, addrFrom, bMessage, fWrite, name) C1PDebugger.prototype.messageIO = function(component, addr, addrFrom, bitsMessage, fWrite, name)
{ {
if ((this.bMessages & bMessage) == bMessage) { if ((this.bitsMessage & bitsMessage) == bitsMessage) {
var b = this.cpu.getByte(addr); var b = this.cpu.getByte(addr);
this.message(component.id + "." + (fWrite? "setByte":"getByte") + "(" + str.toHexWord(addr) + ")" + (addrFrom !== undefined? (" @" + str.toHexWord(addrFrom)) : "") + ": " + (name? (name + "=") : "") + str.toHexByte(b)); this.message(component.id + "." + (fWrite? "setByte":"getByte") + "(" + str.toHexWord(addr) + ")" + (addrFrom !== undefined? (" @" + str.toHexWord(addrFrom)) : "") + ": " + (name? (name + "=") : "") + str.toHexByte(b));
} }
@ -1947,25 +1935,25 @@ if (DEBUGGER) {
this.println("modern syntax enabled"); this.println("modern syntax enabled");
break; break;
case "msg": case "msg":
var bMessage = 0; var bitsMessage = 0;
if (asArgs[2] !== undefined) { if (asArgs[2] !== undefined) {
if (asArgs[2] == "all") if (asArgs[2] == "all")
bMessage = 0xff; bitsMessage = 0xff;
else if (this.aMessageCategories[asArgs[2]] !== undefined) else if (this.aMessageCategories[asArgs[2]] !== undefined)
bMessage = this.aMessageCategories[asArgs[2]]; bitsMessage = this.aMessageCategories[asArgs[2]];
if (bMessage) { if (bitsMessage) {
if (asArgs[3] == "on") { if (asArgs[3] == "on") {
this.bMessages |= bMessage; this.bitsMessage |= bitsMessage;
} }
else if (asArgs[3] == "off") { else if (asArgs[3] == "off") {
this.bMessages &= ~bMessage; this.bitsMessage &= ~bitsMessage;
} }
} }
} }
for (var sCategory in this.aMessageCategories) { for (var sCategory in this.aMessageCategories) {
if (asArgs[2] !== undefined && (asArgs[2] != "all" && asArgs[2] != sCategory)) continue; if (asArgs[2] !== undefined && (asArgs[2] != "all" && asArgs[2] != sCategory)) continue;
bMessage = this.aMessageCategories[sCategory]; bitsMessage = this.aMessageCategories[sCategory];
this.println(sCategory + " messages: " + ((this.bMessages & bMessage)? "on" : "off")); this.println(sCategory + " messages: " + ((this.bitsMessage & bitsMessage)? "on" : "off"));
} }
break; break;
default: default:

View file

@ -970,7 +970,7 @@ C1PDiskController.prototype.getByte = function(addr, addrFrom)
if (addrFrom !== undefined) { if (addrFrom !== undefined) {
var port = addr - this.addrController; var port = addr - this.addrController;
var reg = this.getReg(port, false); var reg = this.getReg(port, false);
if (DEBUGGER && this.dbg) this.dbg.messagePort(this, addr, addrFrom, this.dbg.MESSAGE_DISK, false, reg.sName); if (DEBUGGER && this.dbg) this.dbg.messageIO(this, addr, addrFrom, this.dbg.MESSAGE_DISK, false, reg.sName);
reg.read(); reg.read();
} }
}; };
@ -991,7 +991,7 @@ C1PDiskController.prototype.setByte = function(addr, addrFrom)
var port = addr - this.addrController; var port = addr - this.addrController;
var reg = this.getReg(port, true); var reg = this.getReg(port, true);
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(this.dbg.MESSAGE_DISK | this.dbg.MESSAGE_PORT)) { if (DEBUGGER && this.dbg && this.dbg.messageEnabled(this.dbg.MESSAGE_DISK | this.dbg.MESSAGE_PORT)) {
this.dbg.messagePort(this, addr, addrFrom, this.dbg.MESSAGE_DISK, true, reg.sName); this.dbg.messageIO(this, addr, addrFrom, this.dbg.MESSAGE_DISK, true, reg.sName);
if (reg.aBitIDs) { if (reg.aBitIDs) {
var bTest = 0x80; var bTest = 0x80;
var bChanged = reg.bits ^ b; var bChanged = reg.bits ^ b;

View file

@ -127,7 +127,7 @@ C1PROM.prototype.setByte = function(addr, addrFrom)
* we need to allow the Debugger to modify ROM contents). * we need to allow the Debugger to modify ROM contents).
*/ */
if (addrFrom !== undefined) { if (addrFrom !== undefined) {
if (DEBUGGER && this.dbg) this.dbg.messagePort(this, addr, addrFrom, this.dbg.MESSAGE_PORT, true); if (DEBUGGER && this.dbg) this.dbg.messageIO(this, addr, addrFrom, this.dbg.MESSAGE_PORT, true);
var offset = (addr - this.offROM); var offset = (addr - this.offROM);
Component.assert(offset >= 0 && offset < this.cbROM); Component.assert(offset >= 0 && offset < this.cbROM);
if (!this.abImage) if (!this.abImage)

View file

@ -141,7 +141,7 @@ C1PSerialPort.prototype.setBinding = function(sHTMLType, sBinding, control)
var fieldset = control.children[0]; var fieldset = control.children[0];
var files = fieldset.children[0].files; var files = fieldset.children[0].files;
var submit = fieldset.children[1]; var submit = fieldset.children[1];
submit.disabled = (files.length == 0); submit.disabled = !files.length;
}); });
control.onsubmit = function(event) { control.onsubmit = function(event) {
@ -321,7 +321,7 @@ C1PSerialPort.prototype.setByte = function(addr, addrFrom)
* the Debugger performed this write (need a special Debugger I/O command if/when you really want to do that). * the Debugger performed this write (need a special Debugger I/O command if/when you really want to do that).
*/ */
if (addrFrom !== undefined) { if (addrFrom !== undefined) {
if (DEBUGGER && this.dbg) this.dbg.messagePort(this, addr, addrFrom, this.dbg.MESSAGE_SERIAL, true); if (DEBUGGER && this.dbg) this.dbg.messageIO(this, addr, addrFrom, this.dbg.MESSAGE_SERIAL, true);
/* /*
* WARNING: I don't yet care what state the CPU puts the port into. When it's time to support serial output, * WARNING: I don't yet care what state the CPU puts the port into. When it's time to support serial output,
* obviously that will become an issue. * obviously that will become an issue.

View file

@ -364,7 +364,7 @@ C1PVideo.prototype.getByte = function(addr, addrFrom)
{ {
var b = this.cpu.getByte(addr); var b = this.cpu.getByte(addr);
if (addrFrom !== undefined) { if (addrFrom !== undefined) {
if (DEBUGGER && this.dbg) this.dbg.messagePort(this, addr, addrFrom, this.dbg.MESSAGE_VIDEO); if (DEBUGGER && this.dbg) this.dbg.messageIO(this, addr, addrFrom, this.dbg.MESSAGE_VIDEO);
} }
/* /*
* The only documented READ bit in addrVideoPort is bit 7, which is supposed to alternate between * The only documented READ bit in addrVideoPort is bit 7, which is supposed to alternate between
@ -388,7 +388,7 @@ C1PVideo.prototype.getByte = function(addr, addrFrom)
C1PVideo.prototype.setByte = function(addr, addrFrom) C1PVideo.prototype.setByte = function(addr, addrFrom)
{ {
if (addrFrom !== undefined) { if (addrFrom !== undefined) {
if (DEBUGGER && this.dbg) this.dbg.messagePort(this, addr, addrFrom, this.dbg.MESSAGE_VIDEO); if (DEBUGGER && this.dbg) this.dbg.messageIO(this, addr, addrFrom, this.dbg.MESSAGE_VIDEO);
} }
}; };
@ -404,7 +404,7 @@ C1PVideo.prototype.tripGuard = function(addr, addrFrom)
* the Debugger performed this read (need a special Debugger I/O command if/when you really want to do that). * the Debugger performed this read (need a special Debugger I/O command if/when you really want to do that).
*/ */
if (addrFrom !== undefined) { if (addrFrom !== undefined) {
if (DEBUGGER && this.dbg) this.dbg.messagePort(this, addr, addrFrom, this.dbg.MESSAGE_VIDEO, true); if (DEBUGGER && this.dbg) this.dbg.messageIO(this, addr, addrFrom, this.dbg.MESSAGE_VIDEO, true);
/* /*
* The CPU has just written to the guard address we established just beyond the video buffer's 1K boundary, * The CPU has just written to the guard address we established just beyond the video buffer's 1K boundary,
* implying that the system thinks we have a 2K buffer instead. So we bump our model to 540, bump the * implying that the system thinks we have a 2K buffer instead. So we bump our model to 540, bump the

View file

@ -10,6 +10,7 @@
"APPNAME": false, "APPNAME": false,
"APPVERSION": false, "APPVERSION": false,
"SITEHOST": false, "SITEHOST": false,
"COMPILED": true,
"DEBUG": true, "DEBUG": true,
"MAXDEBUG": false, "MAXDEBUG": false,
"PCJSCLASS": true, "PCJSCLASS": true,
@ -18,6 +19,7 @@
"EAFUNCS": true, "EAFUNCS": true,
"FATARRAYS": true, "FATARRAYS": true,
"TYPEDARRAYS": true, "TYPEDARRAYS": true,
"SAMPLER": true,
"Component": true, "Component": true,
"State": true, "State": true,
"Bus": true, "Bus": true,
@ -47,9 +49,14 @@
"str": true, "str": true,
"usr": true, "usr": true,
"web": true, "web": true,
"document": true,
"global": true, "global": true,
"module": true, "module": true,
"require": true, "require": true,
"ArrayBuffer": false,
"DataView": false,
"FileReader": false,
"Uint8Array": false,
"setTimeout": false, "setTimeout": false,
"clearTimeout": false, "clearTimeout": false,
"webkitAudioContext": false, "webkitAudioContext": false,

View file

@ -290,7 +290,7 @@ Bus.prototype.getA20 = function()
*/ */
Bus.prototype.setA20 = function(fEnable) Bus.prototype.setA20 = function(fEnable)
{ {
if (DEBUG) this.assert(fEnable !== undefined); this.assert(fEnable !== undefined);
if (fEnable !== undefined) { if (fEnable !== undefined) {
if (this.nBusWidth > 20) { if (this.nBusWidth > 20) {
var addrMask = (this.addrMask & ~0x100000) | (fEnable? 0x100000 : 0); var addrMask = (this.addrMask & ~0x100000) | (fEnable? 0x100000 : 0);
@ -643,7 +643,7 @@ Bus.prototype.checkPortInputNotify = function(port, addrFrom)
} }
else { else {
if (DEBUGGER && this.dbg) { if (DEBUGGER && this.dbg) {
this.dbg.messagePort(this, port, null, addrFrom); this.dbg.messageIO(this, port, null, addrFrom);
if (this.fPortInputBreakAll) this.dbg.checkPortInput(port, bIn); if (this.fPortInputBreakAll) this.dbg.checkPortInput(port, bIn);
} }
} }
@ -759,7 +759,7 @@ Bus.prototype.checkPortOutputNotify = function(port, bOut, addrFrom)
} }
else { else {
if (DEBUGGER && this.dbg) { if (DEBUGGER && this.dbg) {
this.dbg.messagePort(this, port, bOut, addrFrom); this.dbg.messageIO(this, port, bOut, addrFrom);
if (this.fPortOutputBreakAll) this.dbg.checkPortOutput(port, bOut); if (this.fPortOutputBreakAll) this.dbg.checkPortOutput(port, bOut);
} }
} }

View file

@ -88,7 +88,7 @@ if (typeof module !== 'undefined') {
* a valid stack causes the system to crash after the next IRET. The BIOS should have either halted or modified * a valid stack causes the system to crash after the next IRET. The BIOS should have either halted or modified
* the actual memory size to match the results of the memory test. * the actual memory size to match the results of the memory test.
* *
* This component provides support for many of the following components (except where a separate component is noted). * This module provides support for many of the following components (except where a separate component is noted).
* This list is taken from p.1-8 ("System Unit") of the IBM 5160 (PC XT) Technical Reference Manual (as revised * This list is taken from p.1-8 ("System Unit") of the IBM 5160 (PC XT) Technical Reference Manual (as revised
* April 1983), only because I didn't see a similar listing in the original 5150 TechRef. * April 1983), only because I didn't see a similar listing in the original 5150 TechRef.
* *
@ -147,7 +147,7 @@ if (typeof module !== 'undefined') {
*/ */
function ChipSet(parmsChipSet) function ChipSet(parmsChipSet)
{ {
Component.call(this, "ChipSet", parmsChipSet, ChipSet); Component.call(this, "ChipSet", parmsChipSet, ChipSet, Debugger.MESSAGE.CHIPSET);
this.model = parmsChipSet['model']; this.model = parmsChipSet['model'];
this.model = (this.model? parseInt(this.model, 10) : ChipSet.MODEL_5150); this.model = (this.model? parseInt(this.model, 10) : ChipSet.MODEL_5150);
@ -187,15 +187,18 @@ function ChipSet(parmsChipSet)
} }
/* /*
* SW2 describes the number of 32Kb blocks of I/O expansion RAM that's present in the system. The MODEL_5150 ROM BIOS * SW2 describes the number of 32Kb blocks of I/O expansion RAM that's present in the system. The MODEL_5150
* only checked/supported the first four switches, so the maximum amount of additional RAM specifiable was 15 * 32Kb, * ROM BIOS only checked/supported the first four switches, so the maximum amount of additional RAM specifiable
* or 480Kb. With a maximum of 64Kb on the motherboard, the MODEL_5150 ROM BIOS could support a grand total of 544Kb. * was 15 * 32Kb, or 480Kb. With a maximum of 64Kb on the motherboard, the MODEL_5150 ROM BIOS could support
* a grand total of 544Kb.
* *
* For MODEL_5160 (PC XT) and up, memory expansion cards had their own configuration switches, and the motherboard SW2 * For MODEL_5160 (PC XT) and up, memory expansion cards had their own configuration switches, and the motherboard
* switches for I/O expansion RAM were eliminated. Instead, the ROM BIOS scans the entire address space (up to 0xA0000) * SW2 switches for I/O expansion RAM were eliminated. Instead, the ROM BIOS scans the entire address space
* looking for additional memory. As a result, the only mechanism we provide for adding RAM (above the maximum of 256Kb * (up to 0xA0000) looking for additional memory. As a result, the only mechanism we provide for adding RAM
* supported on the motherboard) is the "size" parameter of the RAM component. NOTE: If you use the "size" parameter, * (above the maximum of 256Kb supported on the motherboard) is the "size" parameter of the RAM component.
* you will not be able to dynamically alter the memory configuration; the RAM component will ignore any changes to SW1. *
* NOTE: If you use the "size" parameter, you will not be able to dynamically alter the memory configuration;
* the RAM component will ignore any changes to SW1.
*/ */
this.sw2Init = this.parseSwitches(parmsChipSet['sw2'] || "11110000", 0); this.sw2Init = this.parseSwitches(parmsChipSet['sw2'] || "11110000", 0);
@ -214,7 +217,7 @@ function ChipSet(parmsChipSet)
/* /*
* Here, I'm finally getting around to trying the Web Audio API. Fortunately, based on what little I know about * Here, I'm finally getting around to trying the Web Audio API. Fortunately, based on what little I know about
* sound generation, using the API to make the same noises as the IBM PC speaker should be straightforward. * sound generation, using the API to make the same noises as the IBM PC speaker seems straightforward.
* *
* To start, we create an audio context, unless the 'sound' parameter has been explicitly set to false. * To start, we create an audio context, unless the 'sound' parameter has been explicitly set to false.
* *
@ -426,8 +429,8 @@ ChipSet.DMA_HDC = 0x03; // DMA channel assigned to the Hard Drive Contro
* *
* ICW4 is typically set to 0x09, indicating 8086 mode, non-automatic EOI, buffered/slave mode. * ICW4 is typically set to 0x09, indicating 8086 mode, non-automatic EOI, buffered/slave mode.
* *
* QUESTION: Why did the original ROM BIOS choose buffered/slave over buffered/master? Did it simply * TODO: Determine why the original ROM BIOS chose buffered/slave over buffered/master.
* not matter in pre-AT systems with only one PIC, or am I misreading something? * Did it simply not matter in pre-AT systems with only one PIC, or am I misreading something?
* *
* TODO: Consider support for level-triggered PIC interrupts, even though the original IBM PCs * TODO: Consider support for level-triggered PIC interrupts, even though the original IBM PCs
* (up through MODEL_5170) used only edge-triggered interrupts. * (up through MODEL_5170) used only edge-triggered interrupts.
@ -643,6 +646,7 @@ ChipSet.PPI_SW = {
* *
* Similarly, port 0x61 is designated KBC.RWREG rather than PPI_B; the BIOS also refers to it as "PORT_B: 8042 * Similarly, port 0x61 is designated KBC.RWREG rather than PPI_B; the BIOS also refers to it as "PORT_B: 8042
* READ WRITE REGISTER", but it is not otherwise discussed in the MODEL_5170 TechRef's 8042 documentation. * READ WRITE REGISTER", but it is not otherwise discussed in the MODEL_5170 TechRef's 8042 documentation.
*
* There are brief references to bits 0 and 1 (KBC.RWREG.CLK_TIMER2 and KBC.RWREG.SPK_TIMER2), and the BIOS sets * There are brief references to bits 0 and 1 (KBC.RWREG.CLK_TIMER2 and KBC.RWREG.SPK_TIMER2), and the BIOS sets
* bits 2-7 to "DISABLE PARITY CHECKERS" (principally KBC.RWREG.DISABLE_CHK, which are bits 2 and 3); why the BIOS * bits 2-7 to "DISABLE PARITY CHECKERS" (principally KBC.RWREG.DISABLE_CHK, which are bits 2 and 3); why the BIOS
* also sets bits 4-7 (or if those bits are even settable) is unclear, since it uses 11111100B rather than defined * also sets bits 4-7 (or if those bits are even settable) is unclear, since it uses 11111100B rather than defined
@ -655,7 +659,7 @@ ChipSet.PPI_SW = {
* PPI_C and PPI_CTRL don't seem to be documented or used by the MODEL_5170 BIOS, so I'm assuming they're obsolete. * PPI_C and PPI_CTRL don't seem to be documented or used by the MODEL_5170 BIOS, so I'm assuming they're obsolete.
* *
* NOTE: For more information on the 8042 Controller, including information on undocumented commands, refer to the * NOTE: For more information on the 8042 Controller, including information on undocumented commands, refer to the
* documents in /devices/pc/keyboard/, as well as the following websites: * documents in /devices/pc/keyboard, as well as the following websites:
* *
* http://halicery.com/8042/8042_INTERN_TXT.htm * http://halicery.com/8042/8042_INTERN_TXT.htm
* http://www.os2museum.com/wp/?p=589 ("IBM PC/AT 8042 Keyboard Controller Commands") * http://www.os2museum.com/wp/?p=589 ("IBM PC/AT 8042 Keyboard Controller Commands")
@ -863,9 +867,9 @@ ChipSet.CMOS = {
* This port corresponds to a read/write register in the DMA page register (74LS6I2)." * This port corresponds to a read/write register in the DMA page register (74LS6I2)."
* *
* 0x80 is the neighborhood, but that particular port is not documented as a DMA page register. * 0x80 is the neighborhood, but that particular port is not documented as a DMA page register.
* We'll refer to it as manufacturing port (see bMFGData). Be aware that the MODEL_5170 BIOS is littered * We'll refer to it as a "manufacturing port" (see bMFGData). Be aware that the MODEL_5170 BIOS is
* with manufacturing test ("MFG_TST") code which, if enabled, writes to other DMA page registers, * littered with manufacturing test ("MFG_TST") code which, if enabled, writes to other DMA page
* perhaps treating them as scratch registers. * registers, presumably treating them as scratch registers.
*/ */
ChipSet.MFG = { // this.bMFGData ChipSet.MFG = { // this.bMFGData
PORT: 0x80 PORT: 0x80
@ -1130,11 +1134,11 @@ ChipSet.prototype.reset = function(fHard)
* *
* NOTE: There are two approaches we could take here: always store the RTC bytes in binary, and convert them * NOTE: There are two approaches we could take here: always store the RTC bytes in binary, and convert them
* to/from BCD on-demand (ie, as the simulation reads/writes the CMOS RTC registers); or init/update them in the * to/from BCD on-demand (ie, as the simulation reads/writes the CMOS RTC registers); or init/update them in the
* format specified by CMOS_STATUSB.BINARY (1 for binary, 0 for BCD). Both approaches require BCD conversion * format specified by CMOS.STATUSB.BINARY (1 for binary, 0 for BCD). Both approaches require BCD conversion
* functions, but the former seems more efficient, in part because the periodic calls to updateRTCTime() won't * functions, but the former seems more efficient, in part because the periodic calls to updateRTCTime() won't
* require any conversions. * require any conversions.
* *
* We take the same approach with the CMOS_STATUSB.HOUR24 setting: internally, we always operate in 24-hour mode, * We take the same approach with the CMOS.STATUSB.HOUR24 setting: internally, we always operate in 24-hour mode,
* but externally, we convert the RTC hour values to the 12-hour format as needed. * but externally, we convert the RTC hour values to the 12-hour format as needed.
* *
* Thus, all I/O to the RTC bytes must be routed through the getRTCByte() and setRTCByte() functions, to ensure * Thus, all I/O to the RTC bytes must be routed through the getRTCByte() and setRTCByte() functions, to ensure
@ -1206,7 +1210,7 @@ ChipSet.prototype.initRTCTime = function(sDate)
*/ */
ChipSet.prototype.getRTCByte = function(iRTC) ChipSet.prototype.getRTCByte = function(iRTC)
{ {
if (DEBUG) this.assert(iRTC >= 0 && iRTC <= ChipSet.CMOS.ADDR.STATUSD); this.assert(iRTC >= 0 && iRTC <= ChipSet.CMOS.ADDR.STATUSD);
var b = this.abCMOSData[iRTC]; var b = this.abCMOSData[iRTC];
@ -1258,7 +1262,7 @@ ChipSet.prototype.getRTCByte = function(iRTC)
*/ */
ChipSet.prototype.setRTCByte = function(iRTC, b) ChipSet.prototype.setRTCByte = function(iRTC, b)
{ {
if (DEBUG) this.assert(iRTC >= 0 && iRTC <= ChipSet.CMOS.ADDR.STATUSD); this.assert(iRTC >= 0 && iRTC <= ChipSet.CMOS.ADDR.STATUSD);
if (iRTC < ChipSet.CMOS.ADDR.STATUSA) { if (iRTC < ChipSet.CMOS.ADDR.STATUSA) {
var fBCD = false; var fBCD = false;
@ -1276,8 +1280,8 @@ ChipSet.prototype.setRTCByte = function(iRTC, b)
* If the original BCD hour was 0x81-0x92, then the previous BINARY-to-BCD conversion * If the original BCD hour was 0x81-0x92, then the previous BINARY-to-BCD conversion
* transformed it to 0x51-0x5C, so we must add 0x30. * transformed it to 0x51-0x5C, so we must add 0x30.
*/ */
if (b > 12) { if (b > 23) {
if (DEBUG) this.assert(b >= 0x51 && b <= 0x5c); this.assert(b >= 0x51 && b <= 0x5c);
b += 0x30; b += 0x30;
} }
} }
@ -1328,17 +1332,17 @@ ChipSet.prototype.getRTCCycleLimit = function(nCycles)
if (nCyclesUpdate > 0) { if (nCyclesUpdate > 0) {
if (nCycles > nCyclesUpdate) { if (nCycles > nCyclesUpdate) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.RTC)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.RTC)) {
this.messageDebugger("getRTCCycleLimit(" + nCycles + "): reduced to " + nCyclesUpdate + " cycles", Debugger.MESSAGE.RTC); this.messageDebugger("getRTCCycleLimit(" + nCycles + "): reduced to " + nCyclesUpdate + " cycles");
} }
nCycles = nCyclesUpdate; nCycles = nCyclesUpdate;
} else { } else {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.RTC)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.RTC)) {
this.messageDebugger("getRTCCycleLimit(" + nCycles + "): already less than " + nCyclesUpdate + " cycles", Debugger.MESSAGE.RTC); this.messageDebugger("getRTCCycleLimit(" + nCycles + "): already less than " + nCyclesUpdate + " cycles");
} }
} }
} else { } else {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.RTC)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.RTC)) {
this.messageDebugger("RTC next update has passed by " + nCyclesUpdate + " cycles", Debugger.MESSAGE.RTC); this.messageDebugger("RTC next update has passed by " + nCyclesUpdate + " cycles");
} }
} }
} }
@ -1434,7 +1438,7 @@ ChipSet.prototype.updateRTCTime = function()
* Step 3: Update the RTC date/time and deal with Update Interrupts * Step 3: Update the RTC date/time and deal with Update Interrupts
*/ */
var nCyclesDelta = nCyclesUpdate - this.nRTCCyclesLastUpdate; var nCyclesDelta = nCyclesUpdate - this.nRTCCyclesLastUpdate;
if (DEBUG) this.assert(nCyclesDelta >= 0); this.assert(nCyclesDelta >= 0);
var nSecondsDelta = Math.floor(nCyclesDelta / nCyclesPerSecond); var nSecondsDelta = Math.floor(nCyclesDelta / nCyclesPerSecond);
/* /*
@ -1444,7 +1448,7 @@ ChipSet.prototype.updateRTCTime = function()
* (nCyclesDelta % nCyclesPerSecond) back into nRTCCyclesLastUpdate, so that we will eventually * (nCyclesDelta % nCyclesPerSecond) back into nRTCCyclesLastUpdate, so that we will eventually
* see a one-second delta. * see a one-second delta.
*/ */
if (DEBUG) this.assert(nSecondsDelta <= 1); this.assert(nSecondsDelta <= 1);
/* /*
* Make sure that CMOS.STATUSB.SET isn't set; if it is, then the once-per-second RTC updates must be * Make sure that CMOS.STATUSB.SET isn't set; if it is, then the once-per-second RTC updates must be
@ -1512,8 +1516,8 @@ ChipSet.prototype.initCMOSData = function()
} }
/* /*
* We propagate all compatible "legacy" SW1 bits to the CMOS_EQUIP byte using the old SW masks, but any further * We propagate all compatible "legacy" SW1 bits to the CMOS.EQUIP byte using the old SW masks, but any further
* access to CMOS_ADDR.EQUIP should use the new CMOS_EQUIP flags (eg, CMOS_EQUIP.COPROC, CMOS_EQUIP.MONITOR.CGA80, etc). * access to CMOS.ADDR.EQUIP should use the new CMOS_EQUIP flags (eg, CMOS.EQUIP.COPROC, CMOS.EQUIP.MONITOR.CGA80, etc).
*/ */
this.abCMOSData[ChipSet.CMOS.ADDR.EQUIP] = this.sw1 & (ChipSet.PPI_SW.MONITOR.MASK | ChipSet.PPI_SW.COPROC | ChipSet.PPI_SW.FDRIVE.IPL | ChipSet.PPI_SW.FDRIVE.MASK); this.abCMOSData[ChipSet.CMOS.ADDR.EQUIP] = this.sw1 & (ChipSet.PPI_SW.MONITOR.MASK | ChipSet.PPI_SW.COPROC | ChipSet.PPI_SW.FDRIVE.IPL | ChipSet.PPI_SW.FDRIVE.MASK);
this.abCMOSData[ChipSet.CMOS.ADDR.FDRIVE] = (this.getSWFloppyDriveType(0) << 4) | this.getSWFloppyDriveType(1); this.abCMOSData[ChipSet.CMOS.ADDR.FDRIVE] = (this.getSWFloppyDriveType(0) << 4) | this.getSWFloppyDriveType(1);
@ -1538,7 +1542,7 @@ ChipSet.prototype.initCMOSData = function()
ChipSet.prototype.setCMOSByte = function(iCMOS, b) ChipSet.prototype.setCMOSByte = function(iCMOS, b)
{ {
if (this.abCMOSData) { if (this.abCMOSData) {
if (DEBUG) this.assert(iCMOS >= ChipSet.CMOS.ADDR.FDRIVE && iCMOS < ChipSet.CMOS.ADDR.CHKSUM_HI); this.assert(iCMOS >= ChipSet.CMOS.ADDR.FDRIVE && iCMOS < ChipSet.CMOS.ADDR.CHKSUM_HI);
this.abCMOSData[iCMOS] = b; this.abCMOSData[iCMOS] = b;
this.updateCMOSChecksum(); this.updateCMOSChecksum();
return true; return true;
@ -1590,7 +1594,7 @@ ChipSet.prototype.setCMOSDriveType = function(iDrive, bType)
{ {
if (this.abCMOSData) { if (this.abCMOSData) {
var b = this.abCMOSData[ChipSet.CMOS.ADDR.HDRIVE]; var b = this.abCMOSData[ChipSet.CMOS.ADDR.HDRIVE];
if (DEBUG) this.assert(bType > 0 && bType < 0xf); this.assert(bType > 0 && bType < 0xf);
if (iDrive) { if (iDrive) {
b = (b & ChipSet.CMOS.HDRIVE.D0_MASK) | bType; b = (b & ChipSet.CMOS.HDRIVE.D0_MASK) | bType;
} else { } else {
@ -1690,7 +1694,7 @@ ChipSet.prototype.restore = function(data)
a = data[5]; a = data[5];
if (a) { if (a) {
if (DEBUG) this.assert(this.model >= ChipSet.MODEL_5170); this.assert(this.model >= ChipSet.MODEL_5170);
this.b8042Status = a[0]; this.b8042Status = a[0];
this.b8042InBuff = a[1]; this.b8042InBuff = a[1];
this.b8042CmdData = a[2]; this.b8042CmdData = a[2];
@ -1701,7 +1705,7 @@ ChipSet.prototype.restore = function(data)
a = data[6]; a = data[6];
if (a) { if (a) {
if (DEBUG) this.assert(this.model >= ChipSet.MODEL_5170); this.assert(this.model >= ChipSet.MODEL_5170);
this.bMFGData = a[0]; this.bMFGData = a[0];
this.abDMAPageSpare = a[1]; this.abDMAPageSpare = a[1];
this.bCMOSAddr = a[2]; this.bCMOSAddr = a[2];
@ -1734,7 +1738,7 @@ ChipSet.prototype.initDMAController = function(iDMAC, aState)
{ {
var controller = this.aDMACs[iDMAC]; var controller = this.aDMACs[iDMAC];
if (!controller) { if (!controller) {
if (DEBUG) this.assert(!aState); this.assert(!aState);
controller = { controller = {
aChannels: new Array(4) aChannels: new Array(4)
}; };
@ -1765,7 +1769,7 @@ ChipSet.prototype.initDMAChannel = function(controller, iChannel, aState)
{ {
var channel = controller.aChannels[iChannel]; var channel = controller.aChannels[iChannel];
if (!channel) { if (!channel) {
if (DEBUG) this.assert(!aState); this.assert(!aState);
channel = { channel = {
addrInit: [0,0], addrInit: [0,0],
countInit: [0,0], countInit: [0,0],
@ -2041,7 +2045,7 @@ ChipSet.prototype.getSWFloppyDriveType = function(iDrive)
return ChipSet.CMOS.FDRIVE.FD1440; return ChipSet.CMOS.FDRIVE.FD1440;
} }
} }
if (DEBUG) this.assert(false); // we should never get here (else something is out of out sync) this.assert(false); // we should never get here (else something is out of out sync)
} }
return ChipSet.CMOS.FDRIVE.NONE; return ChipSet.CMOS.FDRIVE.NONE;
}; };
@ -2062,7 +2066,7 @@ ChipSet.prototype.getSWFloppyDriveSize = function(iDrive)
if (iDrive < this.aFloppyDrives.length) { if (iDrive < this.aFloppyDrives.length) {
return this.aFloppyDrives[iDrive]; return this.aFloppyDrives[iDrive];
} }
if (DEBUG) this.assert(false); // we should never get here (else something is out of out sync) this.assert(false); // we should never get here (else something is out of out sync)
} }
return 0; return 0;
}; };
@ -2285,7 +2289,7 @@ ChipSet.prototype.inDMAChannelAddr = function(iDMAC, iChannel, port, addrFrom)
var channel = controller.aChannels[iChannel]; var channel = controller.aChannels[iChannel];
var b = channel.addrCurrent[controller.bIndex]; var b = channel.addrCurrent[controller.bIndex];
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".ADDR[" + controller.bIndex + "]", Debugger.MESSAGE.DMA, b); this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".ADDR[" + controller.bIndex + "]", 0, b);
} }
controller.bIndex ^= 0x1; controller.bIndex ^= 0x1;
/* /*
@ -2322,7 +2326,7 @@ ChipSet.prototype.outDMAChannelAddr = function outDMAChannelAddr(iDMAC, iChannel
{ {
var controller = this.aDMACs[iDMAC]; var controller = this.aDMACs[iDMAC];
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".ADDR[" + controller.bIndex + "]", Debugger.MESSAGE.DMA); this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".ADDR[" + controller.bIndex + "]");
} }
var channel = controller.aChannels[iChannel]; var channel = controller.aChannels[iChannel];
channel.addrCurrent[controller.bIndex] = channel.addrInit[controller.bIndex] = bOut; channel.addrCurrent[controller.bIndex] = channel.addrInit[controller.bIndex] = bOut;
@ -2345,7 +2349,7 @@ ChipSet.prototype.inDMAChannelCount = function(iDMAC, iChannel, port, addrFrom)
var channel = controller.aChannels[iChannel]; var channel = controller.aChannels[iChannel];
var b = channel.countCurrent[controller.bIndex]; var b = channel.countCurrent[controller.bIndex];
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".COUNT[" + controller.bIndex + "]", Debugger.MESSAGE.DMA, b); this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".COUNT[" + controller.bIndex + "]", 0, b);
} }
controller.bIndex ^= 0x1; controller.bIndex ^= 0x1;
/* /*
@ -2386,7 +2390,7 @@ ChipSet.prototype.outDMAChannelCount = function(iDMAC, iChannel, port, bOut, add
{ {
var controller = this.aDMACs[iDMAC]; var controller = this.aDMACs[iDMAC];
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".COUNT[" + controller.bIndex + "]", Debugger.MESSAGE.DMA); this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".COUNT[" + controller.bIndex + "]");
} }
var channel = controller.aChannels[iChannel]; var channel = controller.aChannels[iChannel];
channel.countCurrent[controller.bIndex] = channel.countInit[controller.bIndex] = bOut; channel.countCurrent[controller.bIndex] = channel.countInit[controller.bIndex] = bOut;
@ -2429,7 +2433,7 @@ ChipSet.prototype.inDMAStatus = function(iDMAC, port, addrFrom)
var b = controller.bStatus | ChipSet.DMA_STATUS.CH0_TC; var b = controller.bStatus | ChipSet.DMA_STATUS.CH0_TC;
controller.bStatus &= ~ChipSet.DMA_STATUS.ALL_TC; controller.bStatus &= ~ChipSet.DMA_STATUS.ALL_TC;
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".STATUS", Debugger.MESSAGE.DMA, b); this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".STATUS", 0, b);
} }
return b; return b;
}; };
@ -2446,7 +2450,7 @@ ChipSet.prototype.inDMAStatus = function(iDMAC, port, addrFrom)
ChipSet.prototype.outDMACmd = function(iDMAC, port, bOut, addrFrom) ChipSet.prototype.outDMACmd = function(iDMAC, port, bOut, addrFrom)
{ {
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CMD", Debugger.MESSAGE.DMA); this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CMD");
} }
this.aDMACs[iDMAC].bCmd = bOut; this.aDMACs[iDMAC].bCmd = bOut;
}; };
@ -2474,7 +2478,7 @@ ChipSet.prototype.outDMAReq = function(iDMAC, port, bOut, addrFrom)
{ {
var controller = this.aDMACs[iDMAC]; var controller = this.aDMACs[iDMAC];
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".REQ", Debugger.MESSAGE.DMA); this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".REQ");
} }
/* /*
* Bits 0-1 contain the channel number * Bits 0-1 contain the channel number
@ -2501,7 +2505,7 @@ ChipSet.prototype.outDMAMask = function(iDMAC, port, bOut, addrFrom)
{ {
var controller = this.aDMACs[iDMAC]; var controller = this.aDMACs[iDMAC];
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MASK", Debugger.MESSAGE.DMA); this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MASK");
} }
var iChannel = bOut & ChipSet.DMA_MASK.CHANNEL; var iChannel = bOut & ChipSet.DMA_MASK.CHANNEL;
var channel = controller.aChannels[iChannel]; var channel = controller.aChannels[iChannel];
@ -2521,7 +2525,7 @@ ChipSet.prototype.outDMAMask = function(iDMAC, port, bOut, addrFrom)
ChipSet.prototype.outDMAMode = function(iDMAC, port, bOut, addrFrom) ChipSet.prototype.outDMAMode = function(iDMAC, port, bOut, addrFrom)
{ {
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MODE", Debugger.MESSAGE.DMA); this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MODE");
} }
var iChannel = bOut & ChipSet.DMA_MODE.CHANNEL; var iChannel = bOut & ChipSet.DMA_MODE.CHANNEL;
this.aDMACs[iDMAC].aChannels[iChannel].mode = bOut; this.aDMACs[iDMAC].aChannels[iChannel].mode = bOut;
@ -2542,7 +2546,7 @@ ChipSet.prototype.outDMAMode = function(iDMAC, port, bOut, addrFrom)
ChipSet.prototype.outDMAResetFF = function(iDMAC, port, bOut, addrFrom) ChipSet.prototype.outDMAResetFF = function(iDMAC, port, bOut, addrFrom)
{ {
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".RESET_FF", Debugger.MESSAGE.DMA); this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".RESET_FF");
} }
this.aDMACs[iDMAC].bIndex = 0; this.aDMACs[iDMAC].bIndex = 0;
}; };
@ -2559,7 +2563,7 @@ ChipSet.prototype.outDMAResetFF = function(iDMAC, port, bOut, addrFrom)
ChipSet.prototype.outDMAMasterClear = function(iDMAC, port, bOut, addrFrom) ChipSet.prototype.outDMAMasterClear = function(iDMAC, port, bOut, addrFrom)
{ {
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MASTER_CLEAR", Debugger.MESSAGE.DMA); this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".MASTER_CLEAR");
} }
/* /*
* The value written to this port doesn't matter; any write triggers a "master clear" operation * The value written to this port doesn't matter; any write triggers a "master clear" operation
@ -2586,7 +2590,7 @@ ChipSet.prototype.inDMAPageReg = function(iDMAC, iChannel, port, addrFrom)
{ {
var bIn = this.aDMACs[iDMAC].aChannels[iChannel].bPage; var bIn = this.aDMACs[iDMAC].aChannels[iChannel].bPage;
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".PAGE", Debugger.MESSAGE.DMA, bIn); this.messagePort(port, null, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".PAGE", 0, bIn);
} }
return bIn; return bIn;
}; };
@ -2604,7 +2608,7 @@ ChipSet.prototype.inDMAPageReg = function(iDMAC, iChannel, port, addrFrom)
ChipSet.prototype.outDMAPageReg = function(iDMAC, iChannel, port, bOut, addrFrom) ChipSet.prototype.outDMAPageReg = function(iDMAC, iChannel, port, bOut, addrFrom)
{ {
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".PAGE", Debugger.MESSAGE.DMA); this.messagePort(port, bOut, addrFrom, "DMA" + iDMAC + ".CHANNEL" + iChannel + ".PAGE");
} }
this.aDMACs[iDMAC].aChannels[iChannel].bPage = bOut; this.aDMACs[iDMAC].aChannels[iChannel].bPage = bOut;
}; };
@ -2622,7 +2626,7 @@ ChipSet.prototype.inDMAPageSpare = function(iSpare, port, addrFrom)
{ {
var bIn = this.abDMAPageSpare[iSpare]; var bIn = this.abDMAPageSpare[iSpare];
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "DMA.SPARE" + iSpare + ".PAGE", Debugger.MESSAGE.DMA, bIn); this.messagePort(port, null, addrFrom, "DMA.SPARE" + iSpare + ".PAGE", 0, bIn);
} }
return bIn; return bIn;
}; };
@ -2639,7 +2643,7 @@ ChipSet.prototype.inDMAPageSpare = function(iSpare, port, addrFrom)
ChipSet.prototype.outDMAPageSpare = function(iSpare, port, bOut, addrFrom) ChipSet.prototype.outDMAPageSpare = function(iSpare, port, bOut, addrFrom)
{ {
if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "DMA.SPARE" + iSpare + ".PAGE", Debugger.MESSAGE.DMA); this.messagePort(port, bOut, addrFrom, "DMA.SPARE" + iSpare + ".PAGE");
} }
this.abDMAPageSpare[iSpare] = bOut; this.abDMAPageSpare[iSpare] = bOut;
}; };
@ -2709,7 +2713,7 @@ ChipSet.prototype.requestDMA = function(iDMAChannel, done)
if (!channel.component || !channel.fnTransfer || !channel.obj) { if (!channel.component || !channel.fnTransfer || !channel.obj) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.OTHER)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.OTHER)) {
this.messageDebugger("requestDMA(" + iDMAChannel + "): not connected to a component", Debugger.MESSAGE.DMA | Debugger.MESSAGE.OTHER); this.messageDebugger("requestDMA(" + iDMAChannel + "): not connected to a component");
} }
if (done) done(true); if (done) done(true);
return; return;
@ -2726,7 +2730,7 @@ ChipSet.prototype.requestDMA = function(iDMAChannel, done)
if (channel.masked) { if (channel.masked) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.OTHER)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.OTHER)) {
this.messageDebugger("requestDMA(" + iDMAChannel + "): channel masked, request queued", Debugger.MESSAGE.DMA | Debugger.MESSAGE.OTHER); this.messageDebugger("requestDMA(" + iDMAChannel + "): channel masked, request queued");
} }
return; return;
} }
@ -2778,8 +2782,8 @@ ChipSet.prototype.advanceDMA = function(channel, fInit)
var addr = (channel.bPage << 16) | (channel.addrCurrent[1] << 8) | channel.addrCurrent[0]; var addr = (channel.bPage << 16) | (channel.addrCurrent[1] << 8) | channel.addrCurrent[0];
if (DEBUG && DEBUGGER && channel.sAddrDebug === null) { if (DEBUG && DEBUGGER && channel.sAddrDebug === null) {
channel.sAddrDebug = str.toHex(addr >> 4, 4) + ":" + str.toHex(addr & 0xf, 4); channel.sAddrDebug = str.toHex(addr >> 4, 4) + ":" + str.toHex(addr & 0xf, 4);
if (this.messageEnabled(Debugger.MESSAGE.DMA | (iDMAChannel == ChipSet.DMA_FDC? Debugger.MESSAGE.FDC : (iDMAChannel == ChipSet.DMA_HDC? Debugger.MESSAGE.HDC : 0))) && channel.xfer != ChipSet.DMA_MODE.XFER_WRITE) { if (this.messageEnabled(this.messageBitsDMA(iDMAChannel)) && channel.xfer != ChipSet.DMA_MODE.XFER_WRITE) {
this.dbg.message("advanceDMA(" + iDMAChannel + ") transferring " + channel.cbDebug + " bytes from " + channel.sAddrDebug); this.messageDebugger("advanceDMA(" + iDMAChannel + ") transferring " + channel.cbDebug + " bytes from " + channel.sAddrDebug);
this.dbg.doDump("db", channel.sAddrDebug, "l" + Math.floor((channel.cbDebug + 15) / 16)); this.dbg.doDump("db", channel.sAddrDebug, "l" + Math.floor((channel.cbDebug + 15) / 16));
} }
} }
@ -2790,7 +2794,7 @@ ChipSet.prototype.advanceDMA = function(channel, fInit)
if (b < 0) { if (b < 0) {
if (!channel.fWarning) { if (!channel.fWarning) {
if (DEBUG && obj.messageEnabled(Debugger.MESSAGE.DMA)) { if (DEBUG && obj.messageEnabled(Debugger.MESSAGE.DMA)) {
obj.messageDebugger("advanceDMA(" + iDMAChannel + ") ran out of data, assuming 0xff", Debugger.MESSAGE.DMA); obj.messageDebugger("advanceDMA(" + iDMAChannel + ") ran out of data, assuming 0xff");
} }
channel.fWarning = true; channel.fWarning = true;
} }
@ -2839,7 +2843,7 @@ ChipSet.prototype.advanceDMA = function(channel, fInit)
} }
else { else {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.WARN)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.DMA | Debugger.MESSAGE.WARN)) {
this.messageDebugger("advanceDMA(" + iDMAChannel + ") unsupported xfer mode: " + str.toHexWord(channel.xfer), Debugger.MESSAGE.DMA | Debugger.MESSAGE.WARN); this.messageDebugger("advanceDMA(" + iDMAChannel + ") unsupported xfer mode: " + str.toHexWord(channel.xfer));
} }
channel.fError = true; channel.fError = true;
} }
@ -2892,8 +2896,8 @@ ChipSet.prototype.updateDMA = function(channel)
channel.component = channel.obj = null; channel.component = channel.obj = null;
} }
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.DMA | (iDMAChannel == ChipSet.DMA_FDC? Debugger.MESSAGE.FDC : (iDMAChannel == ChipSet.DMA_HDC? Debugger.MESSAGE.HDC : 0))) && channel.xfer == ChipSet.DMA_MODE.XFER_WRITE && channel.sAddrDebug) { if (DEBUG && this.messageEnabled(this.messageBitsDMA(iDMAChannel)) && channel.xfer == ChipSet.DMA_MODE.XFER_WRITE && channel.sAddrDebug) {
this.dbg.message("updateDMA(" + iDMAChannel + ") transferred " + channel.cbDebug + " bytes to " + channel.sAddrDebug); this.messageDebugger("updateDMA(" + iDMAChannel + ") transferred " + channel.cbDebug + " bytes to " + channel.sAddrDebug);
this.dbg.doDump("db", channel.sAddrDebug, "l" + Math.floor((channel.cbDebug + 15) / 16)); this.dbg.doDump("db", channel.sAddrDebug, "l" + Math.floor((channel.cbDebug + 15) / 16));
} }
@ -2935,7 +2939,7 @@ ChipSet.prototype.inPICLo = function(iPIC, addrFrom)
} }
} }
if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) {
this.messagePort(pic.port, null, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC, b); this.messagePort(pic.port, null, addrFrom, "PIC" + iPIC, 0, b);
} }
return b; return b;
}; };
@ -2952,7 +2956,7 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
{ {
var pic = this.aPICs[iPIC]; var pic = this.aPICs[iPIC];
if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) {
this.messagePort(pic.port, bOut, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC); this.messagePort(pic.port, bOut, addrFrom, "PIC" + iPIC);
} }
if (bOut & ChipSet.PIC_LO.ICW1) { if (bOut & ChipSet.PIC_LO.ICW1) {
/* /*
@ -3035,23 +3039,23 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
} }
var nIRQ = (nIRL == null? undefined : pic.nIRQBase + nIRL); var nIRQ = (nIRL == null? undefined : pic.nIRQBase + nIRL);
if (pic.bISR & bIREnd) { if (pic.bISR & bIREnd) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC, nIRQ)) { if (DEBUG && this.messageEnabled(this.messageBitsIRQ(nIRQ))) {
this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): IRQ " + nIRQ + " going out of service", Debugger.MESSAGE.PIC, nIRQ); this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): IRQ " + nIRQ + " going out of service");
} }
pic.bISR &= ~bIREnd; pic.bISR &= ~bIREnd;
this.checkIRR(iPIC); this.checkIRR(iPIC);
} else { } else {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unexpected EOI command, IRQ " + nIRQ + " not in service", Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN); this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unexpected EOI command, IRQ " + nIRQ + " not in service");
if (this.dbg && !SAMPLER && MAXDEBUG) this.dbg.stopCPU(); if (!SAMPLER && MAXDEBUG) this.dbg.stopCPU();
} }
} }
/* /*
* TODO: Support EOI commands with automatic rotation (eg, ChipSet.PIC_LO.OCW2_EOI_ROT and ChipSet.PIC_LO.OCW2_EOI_ROTSPEC) * TODO: Support EOI commands with automatic rotation (eg, ChipSet.PIC_LO.OCW2_EOI_ROT and ChipSet.PIC_LO.OCW2_EOI_ROTSPEC)
*/ */
if (DEBUG && (bOCW2 & ChipSet.PIC_LO.OCW2_SET_ROTAUTO) && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) { if (DEBUG && (bOCW2 & ChipSet.PIC_LO.OCW2_SET_ROTAUTO) && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unsupported OCW2 rotate command: " + str.toHexByte(bOut), Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN); this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unsupported OCW2 rotate command: " + str.toHexByte(bOut));
if (this.dbg) this.dbg.stopCPU(); this.dbg.stopCPU();
} }
} }
else if (bOCW2 == ChipSet.PIC_LO.OCW2_SET_PRI) { else if (bOCW2 == ChipSet.PIC_LO.OCW2_SET_PRI) {
@ -3065,8 +3069,8 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
* TODO: Remaining commands to support: ChipSet.PIC_LO.OCW2_SET_ROTAUTO and ChipSet.PIC_LO.OCW2_CLR_ROTAUTO * TODO: Remaining commands to support: ChipSet.PIC_LO.OCW2_SET_ROTAUTO and ChipSet.PIC_LO.OCW2_CLR_ROTAUTO
*/ */
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unsupported OCW2 automatic EOI command: " + str.toHexByte(bOut), Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN); this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unsupported OCW2 automatic EOI command: " + str.toHexByte(bOut));
if (this.dbg) this.dbg.stopCPU(); this.dbg.stopCPU();
} }
} }
} else { } else {
@ -3078,7 +3082,7 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
*/ */
if (bOut & (ChipSet.PIC_LO.OCW3_POLL_CMD | ChipSet.PIC_LO.OCW3_SMM_CMD)) { if (bOut & (ChipSet.PIC_LO.OCW3_POLL_CMD | ChipSet.PIC_LO.OCW3_SMM_CMD)) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unsupported OCW3 command: " + str.toHexByte(bOut), Debugger.MESSAGE.PIC | Debugger.MESSAGE.WARN); this.messageDebugger("outPIC" + iPIC + "(" + str.toHexByte(pic.port) + "): unsupported OCW3 command: " + str.toHexByte(bOut));
} }
} }
pic.bOCW3 = bOut; pic.bOCW3 = bOut;
@ -3098,7 +3102,7 @@ ChipSet.prototype.inPICHi = function(iPIC, addrFrom)
var pic = this.aPICs[iPIC]; var pic = this.aPICs[iPIC];
var b = pic.bIMR; var b = pic.bIMR;
if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) {
this.messagePort(pic.port+1, null, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC, b); this.messagePort(pic.port+1, null, addrFrom, "PIC" + iPIC, 0, b);
} }
return b; return b;
}; };
@ -3115,7 +3119,7 @@ ChipSet.prototype.outPICHi = function(iPIC, bOut, addrFrom)
{ {
var pic = this.aPICs[iPIC]; var pic = this.aPICs[iPIC];
if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.PIC | Debugger.MESSAGE.PORT)) {
this.messagePort(pic.port+1, bOut, addrFrom, "PIC" + iPIC, Debugger.MESSAGE.PIC); this.messagePort(pic.port+1, bOut, addrFrom, "PIC" + iPIC);
} }
if (pic.nICW < pic.aICW.length) { if (pic.nICW < pic.aICW.length) {
pic.aICW[pic.nICW++] = bOut; pic.aICW[pic.nICW++] = bOut;
@ -3174,8 +3178,8 @@ ChipSet.prototype.setIRR = function(nIRQ, nDelay)
var nIRL = nIRQ & 0x7; var nIRL = nIRQ & 0x7;
var pic = this.aPICs[iPIC]; var pic = this.aPICs[iPIC];
pic.bIRR |= 1 << nIRL; pic.bIRR |= 1 << nIRL;
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC, nIRQ)) { if (DEBUG && this.messageEnabled(this.messageBitsIRQ(nIRQ))) {
this.messageDebugger("setIRR(" + nIRQ + ")", Debugger.MESSAGE.PIC, nIRQ); this.messageDebugger("setIRR(" + nIRQ + ")");
} }
pic.nDelay = nDelay || 0; pic.nDelay = nDelay || 0;
/* /*
@ -3199,8 +3203,8 @@ ChipSet.prototype.clearIRR = function(nIRQ)
var bIRR = (1 << nIRL); var bIRR = (1 << nIRL);
if (pic.bIRR & bIRR) { if (pic.bIRR & bIRR) {
pic.bIRR &= ~bIRR; pic.bIRR &= ~bIRR;
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PIC, nIRQ)) { if (DEBUG && this.messageEnabled(this.messageBitsIRQ(nIRQ))) {
this.messageDebugger("clearIRR(" + nIRQ + ")", Debugger.MESSAGE.PIC, nIRQ); this.messageDebugger("clearIRR(" + nIRQ + ")");
} }
/* /*
* When all slave IRRs go low, I'm assuming that the master's slave IRR line should go low as well * When all slave IRRs go low, I'm assuming that the master's slave IRR line should go low as well
@ -3297,8 +3301,8 @@ ChipSet.prototype.getIRRVector = function(iPIC)
} }
var nIRQ = pic.nIRQBase + nIRL; var nIRQ = pic.nIRQBase + nIRL;
if (DEBUG && this.messageEnabled(0, nIRQ)) { if (DEBUG && this.messageEnabled(this.messageBitsIRQ(nIRQ))) {
this.messageDebugger("getIRRVector(): IRQ " + nIRQ + " interrupting @" + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel) + " stack=" + str.toHexAddr(this.cpu.regSP, this.cpu.segSS.sel), 0, nIRQ); this.messageDebugger("getIRRVector(): IRQ " + nIRQ + " interrupting @" + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel) + " stack=" + str.toHexAddr(this.cpu.regSP, this.cpu.segSS.sel));
} }
if (MAXDEBUG && DEBUGGER) { if (MAXDEBUG && DEBUGGER) {
this.acInterrupts[nIRQ]++; this.acInterrupts[nIRQ]++;
@ -3334,7 +3338,7 @@ ChipSet.prototype.inTimer = function(iTimer, addrFrom)
this.updateTimer(iTimer); this.updateTimer(iTimer);
b = timer.countCurrent[timer.countIndex++]; b = timer.countCurrent[timer.countIndex++];
if (this.messageEnabled(Debugger.MESSAGE.TIMER | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.TIMER | Debugger.MESSAGE.PORT)) {
this.messagePort(ChipSet.TIMER0.PORT + iTimer, null, addrFrom, "TIMER" + iTimer, Debugger.MESSAGE.TIMER, b); this.messagePort(ChipSet.TIMER0.PORT + iTimer, null, addrFrom, "TIMER" + iTimer, 0, b);
} }
return b; return b;
}; };
@ -3359,7 +3363,7 @@ ChipSet.prototype.inTimer = function(iTimer, addrFrom)
ChipSet.prototype.outTimer = function(iTimer, bOut, addrFrom) ChipSet.prototype.outTimer = function(iTimer, bOut, addrFrom)
{ {
if (this.messageEnabled(Debugger.MESSAGE.TIMER | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.TIMER | Debugger.MESSAGE.PORT)) {
this.messagePort(ChipSet.TIMER0.PORT + iTimer, bOut, addrFrom, "TIMER" + iTimer, Debugger.MESSAGE.TIMER); this.messagePort(ChipSet.TIMER0.PORT + iTimer, bOut, addrFrom, "TIMER" + iTimer);
} }
var timer = this.aTimers[iTimer]; var timer = this.aTimers[iTimer];
if (timer.countIndex == timer.countBytes) this.resetTimerIndex(iTimer); if (timer.countIndex == timer.countBytes) this.resetTimerIndex(iTimer);
@ -3486,7 +3490,7 @@ ChipSet.prototype.outTimerCtrl = function(port, bOut, addrFrom)
timer.countStart[1] = timer.countInit[1]; timer.countStart[1] = timer.countInit[1];
timer.nCyclesStart = this.cpu.getCycles(this.fScaleTimers); timer.nCyclesStart = this.cpu.getCycles(this.fScaleTimers);
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) {
this.messageDebugger("TIMER0 count reset @" + timer.nCyclesStart + " cycles", Debugger.MESSAGE.TIMER); this.messageDebugger("TIMER0 count reset @" + timer.nCyclesStart + " cycles");
} }
} }
} }
@ -3540,11 +3544,11 @@ ChipSet.prototype.getTimerCycleLimit = function(iTimer, nCycles)
if (timer.fCounting) { if (timer.fCounting) {
var nCyclesUpdate = this.cpu.getCycles(this.fScaleTimers); var nCyclesUpdate = this.cpu.getCycles(this.fScaleTimers);
var ticksElapsed = ((nCyclesUpdate - timer.nCyclesStart) / this.nTicksDivisor) | 0; var ticksElapsed = ((nCyclesUpdate - timer.nCyclesStart) / this.nTicksDivisor) | 0;
if (DEBUG) this.assert(ticksElapsed >= 0); this.assert(ticksElapsed >= 0);
var countStart = this.getTimerStart(iTimer); var countStart = this.getTimerStart(iTimer);
var count = countStart - ticksElapsed; var count = countStart - ticksElapsed;
if (timer.mode == ChipSet.TIMER_CTRL.MODE3) count -= ticksElapsed; if (timer.mode == ChipSet.TIMER_CTRL.MODE3) count -= ticksElapsed;
if (DEBUG) this.assert(count > 0); this.assert(count > 0);
var nCyclesRemain = (count * this.nTicksDivisor) | 0; var nCyclesRemain = (count * this.nTicksDivisor) | 0;
if (timer.mode == ChipSet.TIMER_CTRL.MODE3) nCyclesRemain >>= 1; if (timer.mode == ChipSet.TIMER_CTRL.MODE3) nCyclesRemain >>= 1;
if (nCycles > nCyclesRemain) nCycles = nCyclesRemain; if (nCycles > nCyclesRemain) nCycles = nCyclesRemain;
@ -3689,7 +3693,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
if (ticksElapsed < 0) { if (ticksElapsed < 0) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): negative tick count (" + ticksElapsed + ")", Debugger.MESSAGE.TIMER); this.messageDebugger("updateTimer(" + iTimer + "): negative tick count (" + ticksElapsed + ")");
} }
timer.nCyclesStart = nCycles; timer.nCyclesStart = nCycles;
ticksElapsed = 0; ticksElapsed = 0;
@ -3709,7 +3713,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
if (timer.mode == ChipSet.TIMER_CTRL.MODE0) { if (timer.mode == ChipSet.TIMER_CTRL.MODE0) {
if (count <= 0) count = 0; if (count <= 0) count = 0;
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): MODE0 timer count=" + count, Debugger.MESSAGE.TIMER); this.messageDebugger("updateTimer(" + iTimer + "): MODE0 timer count=" + count);
} }
if (!count) { if (!count) {
timer.fOUT = true; timer.fOUT = true;
@ -3744,7 +3748,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
count = countInit + count; count = countInit + count;
if (count <= 0) { if (count <= 0) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): underflow=" + count, Debugger.MESSAGE.TIMER); this.messageDebugger("updateTimer(" + iTimer + "): underflow=" + count);
} }
count = countInit; count = countInit;
} }
@ -3776,7 +3780,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
count = countInit + count; count = countInit + count;
if (count <= 0) { if (count <= 0) {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): underflow=" + count, Debugger.MESSAGE.TIMER); this.messageDebugger("updateTimer(" + iTimer + "): underflow=" + count);
} }
count = countInit; count = countInit;
} }
@ -4232,7 +4236,7 @@ ChipSet.prototype.in8042Status = function(port, addrFrom)
ChipSet.prototype.out8042InBuffCmd = function(port, bOut, addrFrom) ChipSet.prototype.out8042InBuffCmd = function(port, bOut, addrFrom)
{ {
this.messagePort(port, bOut, addrFrom, "8042_INBUFF.CMD", Debugger.MESSAGE.C8042); this.messagePort(port, bOut, addrFrom, "8042_INBUFF.CMD", Debugger.MESSAGE.C8042);
if (DEBUG) this.assert(!(this.b8042Status & ChipSet.KBC.STATUS.INBUFF_FULL)); this.assert(!(this.b8042Status & ChipSet.KBC.STATUS.INBUFF_FULL));
this.b8042InBuff = bOut; this.b8042InBuff = bOut;
this.b8042Status |= ChipSet.KBC.STATUS.CMD_FLAG; this.b8042Status |= ChipSet.KBC.STATUS.CMD_FLAG;
@ -4298,8 +4302,8 @@ ChipSet.prototype.out8042InBuffCmd = function(port, bOut, addrFrom)
default: default:
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.C8042)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.C8042)) {
this.messageDebugger("unrecognized 8042 command: " + str.toHexByte(this.b8042InBuff), Debugger.MESSAGE.C8042); this.messageDebugger("unrecognized 8042 command: " + str.toHexByte(this.b8042InBuff));
if (this.dbg) this.dbg.stopCPU(); this.dbg.stopCPU();
} }
break; break;
} }
@ -4315,7 +4319,7 @@ ChipSet.prototype.set8042CmdData = function(b)
{ {
var bClockWasEnabled = !(this.b8042CmdData & ChipSet.KBC.DATA.CMD.NO_CLOCK); var bClockWasEnabled = !(this.b8042CmdData & ChipSet.KBC.DATA.CMD.NO_CLOCK);
this.b8042CmdData = b; this.b8042CmdData = b;
if (DEBUG) this.assert(ChipSet.KBC.DATA.CMD.SYS_FLAG === ChipSet.KBC.STATUS.SYS_FLAG); this.assert(ChipSet.KBC.DATA.CMD.SYS_FLAG === ChipSet.KBC.STATUS.SYS_FLAG);
this.b8042Status = (this.b8042Status & ~ChipSet.KBC.STATUS.SYS_FLAG) | (b & ChipSet.KBC.DATA.CMD.SYS_FLAG); this.b8042Status = (this.b8042Status & ~ChipSet.KBC.STATUS.SYS_FLAG) | (b & ChipSet.KBC.DATA.CMD.SYS_FLAG);
if (this.kbd) { if (this.kbd) {
/* /*
@ -4374,9 +4378,9 @@ ChipSet.prototype.set8042OutPort = function(b)
* KBC.CMD.PULSE_OUTPORT command, so if a RESET is detected via this command, we should try to * KBC.CMD.PULSE_OUTPORT command, so if a RESET is detected via this command, we should try to
* determine if that's what the caller intended. * determine if that's what the caller intended.
*/ */
if (DEBUG) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.C8042)) {
this.messageDebugger("unexpected 8042 output port reset: " + str.toHexByte(b)); this.messageDebugger("unexpected 8042 output port reset: " + str.toHexByte(b));
if (this.dbg) this.dbg.stopCPU(); this.dbg.stopCPU();
} }
this.cpu.resetRegs(); this.cpu.resetRegs();
} }
@ -4489,7 +4493,7 @@ ChipSet.prototype.notifyKbdData = function(fAvail)
*/ */
ChipSet.prototype.inCMOSAddr = function(port, addrFrom) ChipSet.prototype.inCMOSAddr = function(port, addrFrom)
{ {
this.messagePort(port, null, addrFrom, "CMOS_ADDR", Debugger.MESSAGE.CMOS, this.bCMOSAddr); this.messagePort(port, null, addrFrom, "CMOS.ADDR", Debugger.MESSAGE.CMOS, this.bCMOSAddr);
return this.bCMOSAddr; return this.bCMOSAddr;
}; };
@ -4503,7 +4507,7 @@ ChipSet.prototype.inCMOSAddr = function(port, addrFrom)
*/ */
ChipSet.prototype.outCMOSAddr = function(port, bOut, addrFrom) ChipSet.prototype.outCMOSAddr = function(port, bOut, addrFrom)
{ {
this.messagePort(port, bOut, addrFrom, "CMOS_ADDR", Debugger.MESSAGE.CMOS); this.messagePort(port, bOut, addrFrom, "CMOS.ADDR", Debugger.MESSAGE.CMOS);
this.bCMOSAddr = bOut; this.bCMOSAddr = bOut;
this.bNMI = (bOut & ChipSet.CMOS.ADDR.NMI_DISABLE)? ChipSet.NMI.DISABLE : ChipSet.NMI.ENABLE; this.bNMI = (bOut & ChipSet.CMOS.ADDR.NMI_DISABLE)? ChipSet.NMI.DISABLE : ChipSet.NMI.ENABLE;
}; };
@ -4521,7 +4525,7 @@ ChipSet.prototype.inCMOSData = function(port, addrFrom)
var bAddr = this.bCMOSAddr & ChipSet.CMOS.ADDR.MASK; var bAddr = this.bCMOSAddr & ChipSet.CMOS.ADDR.MASK;
var bIn = (bAddr <= ChipSet.CMOS.ADDR.STATUSD? this.getRTCByte(bAddr) : this.abCMOSData[bAddr]); var bIn = (bAddr <= ChipSet.CMOS.ADDR.STATUSD? this.getRTCByte(bAddr) : this.abCMOSData[bAddr]);
if (this.messageEnabled(Debugger.MESSAGE.CMOS | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.CMOS | Debugger.MESSAGE.PORT)) {
this.messagePort(port, null, addrFrom, "CMOS_DATA[" + str.toHexByte(bAddr) + "]", Debugger.MESSAGE.CMOS, bIn); this.messagePort(port, null, addrFrom, "CMOS.DATA[" + str.toHexByte(bAddr) + "]", 0, bIn);
} }
if (addrFrom != null) { if (addrFrom != null) {
if (bAddr == ChipSet.CMOS.ADDR.STATUSC) { if (bAddr == ChipSet.CMOS.ADDR.STATUSC) {
@ -4556,7 +4560,7 @@ ChipSet.prototype.outCMOSData = function(port, bOut, addrFrom)
{ {
var bAddr = this.bCMOSAddr & ChipSet.CMOS.ADDR.MASK; var bAddr = this.bCMOSAddr & ChipSet.CMOS.ADDR.MASK;
if (this.messageEnabled(Debugger.MESSAGE.CMOS | Debugger.MESSAGE.PORT)) { if (this.messageEnabled(Debugger.MESSAGE.CMOS | Debugger.MESSAGE.PORT)) {
this.messagePort(port, bOut, addrFrom, "CMOS_DATA[" + str.toHexByte(bAddr) + "]", Debugger.MESSAGE.CMOS); this.messagePort(port, bOut, addrFrom, "CMOS.DATA[" + str.toHexByte(bAddr) + "]");
} }
var bDelta = bOut ^ this.abCMOSData[bAddr]; var bDelta = bOut ^ this.abCMOSData[bAddr];
this.abCMOSData[bAddr] = (bAddr <= ChipSet.CMOS.ADDR.STATUSD? this.setRTCByte(bAddr, bOut) : bOut); this.abCMOSData[bAddr] = (bAddr <= ChipSet.CMOS.ADDR.STATUSD? this.setRTCByte(bAddr, bOut) : bOut);
@ -4708,7 +4712,7 @@ ChipSet.prototype.setSpeaker = function(fOn)
if (this.sourceAudio) { if (this.sourceAudio) {
this.sourceAudio['frequency']['value'] = freq; this.sourceAudio['frequency']['value'] = freq;
if (this.messageEnabled(Debugger.MESSAGE.SPEAKER)) { if (this.messageEnabled(Debugger.MESSAGE.SPEAKER)) {
this.messageDebugger("speaker set to " + freq + "hz", Debugger.MESSAGE.SPEAKER); this.messageDebugger("speaker set to " + freq + "hz");
} }
} else { } else {
this.sourceAudio = this.contextAudio['createOscillator'](); this.sourceAudio = this.contextAudio['createOscillator']();
@ -4716,7 +4720,7 @@ ChipSet.prototype.setSpeaker = function(fOn)
this.sourceAudio['connect'](this.contextAudio['destination']); this.sourceAudio['connect'](this.contextAudio['destination']);
this.sourceAudio['frequency']['value'] = freq; this.sourceAudio['frequency']['value'] = freq;
if (this.messageEnabled(Debugger.MESSAGE.SPEAKER)) { if (this.messageEnabled(Debugger.MESSAGE.SPEAKER)) {
this.messageDebugger("speaker on at " + freq + "hz", Debugger.MESSAGE.SPEAKER); this.messageDebugger("speaker on at " + freq + "hz");
} }
this.sourceAudio['noteOn'](0); // aka start() this.sourceAudio['noteOn'](0); // aka start()
} }
@ -4726,7 +4730,7 @@ ChipSet.prototype.setSpeaker = function(fOn)
this.sourceAudio['disconnect'](); // QUESTION: is this automatic following a stop(), since this particular source cannot be started again? this.sourceAudio['disconnect'](); // QUESTION: is this automatic following a stop(), since this particular source cannot be started again?
delete this.sourceAudio; // QUESTION: ditto? delete this.sourceAudio; // QUESTION: ditto?
if (this.messageEnabled(Debugger.MESSAGE.SPEAKER)) { if (this.messageEnabled(Debugger.MESSAGE.SPEAKER)) {
this.messageDebugger("speaker off at " + freq + "hz", Debugger.MESSAGE.SPEAKER); this.messageDebugger("speaker off at " + freq + "hz");
} }
} }
} }
@ -4736,69 +4740,41 @@ ChipSet.prototype.setSpeaker = function(fOn)
}; };
/** /**
* messageEnabled(bitsMessage, nIRQ) * messageBitsDMA(iChannel)
*
* @this {ChipSet}
* @param {number} [iChannel] if the message is associated with a particular IRQ #
* @return {number}
*/
ChipSet.prototype.messageBitsDMA = function(iChannel)
{
var bitsMessage = Debugger.MESSAGE.DMA;
if (iChannel == ChipSet.DMA_FDC) {
bitsMessage |= Debugger.MESSAGE.FDC;
} else if (iChannel == ChipSet.DMA_HDC) {
bitsMessage |= Debugger.MESSAGE.HDC;
}
return bitsMessage;
};
/**
* messageBitsIRQ(nIRQ)
* *
* @this {ChipSet} * @this {ChipSet}
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
* @param {number|undefined} [nIRQ] if the message is associated with a particular IRQ # * @param {number|undefined} [nIRQ] if the message is associated with a particular IRQ #
* @return {boolean} * @return {number}
*/ */
ChipSet.prototype.messageEnabled = function(bitsMessage, nIRQ) ChipSet.prototype.messageBitsIRQ = function(nIRQ)
{ {
if (DEBUGGER && this.dbg) { var bitsMessage = Debugger.MESSAGE.PIC;
if (bitsMessage == null) { if (nIRQ == ChipSet.IRQ.TIMER0) {
bitsMessage = Debugger.MESSAGE.CHIPSET; bitsMessage |= Debugger.MESSAGE.TIMER;
} } else if (nIRQ == ChipSet.IRQ.KBD) {
if (nIRQ !== undefined) { bitsMessage |= Debugger.MESSAGE.KBD;
bitsMessage |= (nIRQ == ChipSet.IRQ.TIMER0? Debugger.MESSAGE.TIMER : (nIRQ == ChipSet.IRQ.KBD? Debugger.MESSAGE.KBD : (nIRQ == ChipSet.IRQ.FDC? Debugger.MESSAGE.FDC : 0))) | Debugger.MESSAGE.PIC; } else if (nIRQ == ChipSet.IRQ.FDC) {
} bitsMessage |= Debugger.MESSAGE.FDC;
return this.dbg.messageEnabled(bitsMessage);
}
return false;
};
/**
* messageDebugger(sMessage, bitsMessage, nIRQ)
*
* @this {ChipSet}
* @param {string} sMessage is any caller-defined message string
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
* @param {number} [nIRQ] if the message is associated with a particular IRQ #
*
* This is a combination of the Debugger's messageEnabled() and message() functions, for convenience.
*
* NOTE: If the caller specifies multiple MESSAGE category flags, then ALL the corresponding message
* categories in the Debugger must be enabled as well, else the message will not be displayed.
*/
ChipSet.prototype.messageDebugger = function(sMessage, bitsMessage, nIRQ)
{
if (DEBUGGER && this.dbg) {
if (this.messageEnabled(bitsMessage, nIRQ)) this.dbg.message(sMessage);
}
};
/**
* messagePort(port, bOut, addrFrom, name, bitsMessage, bIn)
*
* @this {ChipSet}
* @param {number} port
* @param {number|null} bOut if an output operation
* @param {number|null} [addrFrom]
* @param {string|null} [name] of the port, if any
* @param {number|null} [bitsMessage] is one or more a Debugger MESSAGE_* category flag(s)
* @param {number} [bIn] is the input value, if known, on an input operation
*
* This is an internal version of the Debugger's messagePort() function, for convenience.
*
* NOTE: If the caller specifies multiple MESSAGE category flags, then ALL the corresponding message
* categories in the Debugger must be enabled as well, else the message will not be displayed.
*/
ChipSet.prototype.messagePort = function(port, bOut, addrFrom, name, bitsMessage, bIn)
{
if (DEBUGGER && this.dbg) {
if (bitsMessage == null) bitsMessage = Debugger.MESSAGE.CHIPSET;
this.dbg.messagePort(this, port, bOut, addrFrom, name, bitsMessage, bIn);
} }
return bitsMessage;
}; };
/* /*

View file

@ -122,7 +122,7 @@ if (typeof module !== 'undefined') {
*/ */
function Computer(parmsComputer, parmsMachine, fSuspended) { function Computer(parmsComputer, parmsMachine, fSuspended) {
Component.call(this, "Computer", parmsComputer, Computer); Component.call(this, "Computer", parmsComputer, Computer, Debugger.MESSAGE.COMPUTER);
this.bitField.fPowered = false; this.bitField.fPowered = false;
this.nBusWidth = parmsComputer['buswidth']; this.nBusWidth = parmsComputer['buswidth'];
@ -174,7 +174,7 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
} }
} }
if (DEBUG) this.messageDebugger("PREFETCH: " + PREFETCH + ", TYPEDARRAYS: " + TYPEDARRAYS); if (DEBUG && this.messageEnabled()) this.messageDebugger("PREFETCH: " + PREFETCH + ", TYPEDARRAYS: " + TYPEDARRAYS);
/* /*
* Iterate through all the components again and call their initBus() handler, if any * Iterate through all the components again and call their initBus() handler, if any
@ -319,7 +319,9 @@ Computer.prototype.onLoadSetReady = function(sStateFile, sStateData, nErrorCode)
{ {
if (!nErrorCode) { if (!nErrorCode) {
this.sStateData = sStateData; this.sStateData = sStateData;
if (DEBUG) this.messageDebugger("loaded state file " + sStateFile.replace(this.sUserID || "xxx", "xxx")); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("loaded state file " + sStateFile.replace(this.sUserID || "xxx", "xxx"));
}
} else { } else {
this.sResumePath = null; this.sResumePath = null;
this.fServerState = false; this.fServerState = false;
@ -360,7 +362,7 @@ Computer.prototype.wait = function(fn, parms)
return; return;
} }
} }
if (DEBUG) this.messageDebugger("Computer.wait(ready)"); if (DEBUG && this.messageEnabled()) this.messageDebugger("Computer.wait(ready)");
fn.call(this, parms); fn.call(this, parms);
}; };
@ -385,7 +387,9 @@ Computer.prototype.validateState = function(stateComputer)
fValid = false; fValid = false;
if (!stateComputer) stateValidate.clear(); if (!stateComputer) stateValidate.clear();
} else { } else {
if (DEBUG) this.messageDebugger("Last state: " + sTimestampComputer + " (validate: " + sTimestampValidate + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Last state: " + sTimestampComputer + " (validate: " + sTimestampValidate + ")");
}
} }
} }
return fValid; return fValid;
@ -405,7 +409,9 @@ Computer.prototype.powerOn = function(resume)
resume = this.resume || (this.sStateData? Computer.RESUME_AUTO : Computer.RESUME_NONE); resume = this.resume || (this.sStateData? Computer.RESUME_AUTO : Computer.RESUME_NONE);
} }
if (DEBUG) this.messageDebugger("Computer.powerOn(" + (resume == Computer.RESUME_REPOWER ? "repower" : (resume ? "resume" : "")) + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Computer.powerOn(" + (resume == Computer.RESUME_REPOWER ? "repower" : (resume ? "resume" : "")) + ")");
}
var fRepower = false; var fRepower = false;
var fRestore = false; var fRestore = false;
@ -642,7 +648,9 @@ Computer.prototype.donePowerOn = function(aParms)
var fRepower = (aParms[1] < 0); var fRepower = (aParms[1] < 0);
var fRestore = aParms[2]; var fRestore = aParms[2];
if (DEBUG && this.bitField.fPowered) this.messageDebugger("Computer.donePowerOn(): redundant"); if (DEBUG && this.bitField.fPowered && this.messageEnabled()) {
this.messageDebugger("Computer.donePowerOn(): redundant");
}
this.bitField.fPowered = true; this.bitField.fPowered = true;
@ -726,7 +734,9 @@ Computer.prototype.powerOff = function(fSave, fShutdown)
var data; var data;
var sState = "none"; var sState = "none";
if (DEBUG) this.messageDebugger("Computer.powerOff(" + (fSave ? "save" : "nosave") + (fShutdown ? ",shutdown" : "") + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Computer.powerOff(" + (fSave ? "save" : "nosave") + (fShutdown ? ",shutdown" : "") + ")");
}
var stateComputer = new State(this, Computer.sAppVer); var stateComputer = new State(this, Computer.sAppVer);
var stateValidate = new State(this, Computer.sAppVer, Computer.STATE_VALIDATE); var stateValidate = new State(this, Computer.sAppVer, Computer.STATE_VALIDATE);
@ -832,14 +842,14 @@ Computer.prototype.powerOff = function(fSave, fShutdown)
Computer.prototype.reset = function() Computer.prototype.reset = function()
{ {
if (this.bus && this.bus.reset) { if (this.bus && this.bus.reset) {
this.messageDebugger("Resetting " + this.bus.type, true); this.messageDebugger("Resetting " + this.bus.type);
this.bus.reset(); this.bus.reset();
} }
var aComponents = Component.getComponents(this.id); var aComponents = Component.getComponents(this.id);
for (var iComponent = 0; iComponent < aComponents.length; iComponent++) { for (var iComponent = 0; iComponent < aComponents.length; iComponent++) {
var component = aComponents[iComponent]; var component = aComponents[iComponent];
if (component !== this && component !== this.bus && component.reset) { if (component !== this && component !== this.bus && component.reset) {
this.messageDebugger("Resetting " + component.type, true); this.messageDebugger("Resetting " + component.type);
component.reset(); component.reset();
} }
} }
@ -978,7 +988,8 @@ Computer.prototype.queryUserID = function(fPrompt)
Computer.prototype.verifyUserID = function(sUserID) Computer.prototype.verifyUserID = function(sUserID)
{ {
this.sUserID = null; this.sUserID = null;
if (DEBUG) this.messageDebugger("verifyUserID(" + sUserID + ")"); var fMessages = DEBUG && this.messageEnabled();
if (fMessages) this.messageDebugger("verifyUserID(" + sUserID + ")");
var sRequest = web.getHost() + UserAPI.ENDPOINT + '?' + UserAPI.QUERY.REQ + '=' + UserAPI.REQ.VERIFY + '&' + UserAPI.QUERY.USER + '=' + sUserID; var sRequest = web.getHost() + UserAPI.ENDPOINT + '?' + UserAPI.QUERY.REQ + '=' + UserAPI.REQ.VERIFY + '&' + UserAPI.QUERY.USER + '=' + sUserID;
var response = web.loadResource(sRequest); var response = web.loadResource(sRequest);
var nErrorCode = response[0]; var nErrorCode = response[0];
@ -988,16 +999,16 @@ Computer.prototype.verifyUserID = function(sUserID)
response = eval("(" + sResponse + ")"); response = eval("(" + sResponse + ")");
if (response.code && response.code == UserAPI.CODE.OK) { if (response.code && response.code == UserAPI.CODE.OK) {
web.setLocalStorageItem(Computer.STATE_USERID, response.data); web.setLocalStorageItem(Computer.STATE_USERID, response.data);
if (DEBUG) this.messageDebugger(Computer.STATE_USERID + " updated: " + response.data); if (fMessages) this.messageDebugger(Computer.STATE_USERID + " updated: " + response.data);
this.sUserID = response.data; this.sUserID = response.data;
} else { } else {
if (DEBUG) this.messageDebugger(response.code + ": " + response.data); if (fMessages) this.messageDebugger(response.code + ": " + response.data);
} }
} catch (e) { } catch (e) {
Component.error(e.message + " (" + sResponse + ")"); Component.error(e.message + " (" + sResponse + ")");
} }
} else { } else {
if (DEBUG) this.messageDebugger("invalid response (error " + nErrorCode + ")"); if (fMessages) this.messageDebugger("invalid response (error " + nErrorCode + ")");
} }
return this.sUserID; return this.sUserID;
}; };
@ -1012,10 +1023,14 @@ Computer.prototype.getServerStatePath = function()
{ {
var sStatePath = null; var sStatePath = null;
if (this.sUserID) { if (this.sUserID) {
if (DEBUG) this.messageDebugger(Computer.STATE_USERID + " for load: " + this.sUserID); if (DEBUG && this.messageEnabled()) {
this.messageDebugger(Computer.STATE_USERID + " for load: " + this.sUserID);
}
sStatePath = web.getHost() + UserAPI.ENDPOINT + '?' + UserAPI.QUERY.REQ + '=' + UserAPI.REQ.LOAD + '&' + UserAPI.QUERY.USER + '=' + this.sUserID + '&' + UserAPI.QUERY.STATE + '=' + State.key(this, Computer.sAppVer); sStatePath = web.getHost() + UserAPI.ENDPOINT + '?' + UserAPI.QUERY.REQ + '=' + UserAPI.REQ.LOAD + '&' + UserAPI.QUERY.USER + '=' + this.sUserID + '&' + UserAPI.QUERY.STATE + '=' + State.key(this, Computer.sAppVer);
} else { } else {
if (DEBUG) this.messageDebugger(Computer.STATE_USERID + " unavailable"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger(Computer.STATE_USERID + " unavailable");
}
} }
return sStatePath; return sStatePath;
}; };
@ -1035,7 +1050,9 @@ Computer.prototype.saveServerState = function(sUserID, sState)
* tend to blow off alerts() and the like when closing down. * tend to blow off alerts() and the like when closing down.
*/ */
if (sState) { if (sState) {
if (DEBUG) this.messageDebugger("size of server state: " + sState.length + " bytes"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("size of server state: " + sState.length + " bytes");
}
var response = this.storeServerState(sUserID, sState, true); var response = this.storeServerState(sUserID, sState, true);
if (response && response[UserAPI.RES.CODE] == UserAPI.CODE.OK) { if (response && response[UserAPI.RES.CODE] == UserAPI.CODE.OK) {
this.notice("Machine state saved to server"); this.notice("Machine state saved to server");
@ -1050,7 +1067,9 @@ Computer.prototype.saveServerState = function(sUserID, sState)
this.resetUserID(); this.resetUserID();
} }
} else { } else {
if (DEBUG) this.messageDebugger("no state to store"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("no state to store");
}
} }
}; };
@ -1065,7 +1084,9 @@ Computer.prototype.saveServerState = function(sUserID, sState)
*/ */
Computer.prototype.storeServerState = function(sUserID, sState, fSync) Computer.prototype.storeServerState = function(sUserID, sState, fSync)
{ {
if (DEBUG) this.messageDebugger(Computer.STATE_USERID + " for store: " + sUserID); if (DEBUG && this.messageEnabled()) {
this.messageDebugger(Computer.STATE_USERID + " for store: " + sUserID);
}
/* /*
* TODO: Determine whether or not any browsers cancel our request if we're called during a browser "shutdown" event, * TODO: Determine whether or not any browsers cancel our request if we're called during a browser "shutdown" event,
* and whether or not it matters if we do an async request (currently, we're not, to try to ensure the request goes through). * and whether or not it matters if we do an async request (currently, we're not, to try to ensure the request goes through).
@ -1089,7 +1110,7 @@ Computer.prototype.storeServerState = function(sUserID, sState, fSync)
} }
sResponse = '{"' + UserAPI.RES.CODE + '":' + response[0] + ',"' + UserAPI.RES.DATA + '":"' + sResponse + '"}'; sResponse = '{"' + UserAPI.RES.CODE + '":' + response[0] + ',"' + UserAPI.RES.DATA + '":"' + sResponse + '"}';
} }
if (DEBUG) this.messageDebugger(sResponse); if (DEBUG && this.messageEnabled()) this.messageDebugger(sResponse);
return JSON.parse(sResponse); return JSON.parse(sResponse);
} }
return null; return null;
@ -1165,22 +1186,6 @@ Computer.prototype.getComponentByType = function(sType, componentPrev)
return null; return null;
}; };
/**
* messageDebugger(sMessage, fForce)
*
* This is a combination of the Debugger's messageEnabled(MESSAGE_COMPUTER) and message() functions, for convenience.
*
* @this {Computer}
* @param {string} sMessage is any caller-defined message string
* @param {boolean} [fForce] is true to force display of the message
*/
Computer.prototype.messageDebugger = function(sMessage, fForce)
{
if (DEBUGGER && this.dbg) {
if (fForce || this.dbg.messageEnabled(Debugger.MESSAGE.COMPUTER)) this.dbg.message(sMessage);
}
};
/** /**
* Computer.init() * Computer.init()
* *
@ -1213,7 +1218,9 @@ Computer.init = function()
*/ */
var computer = new Computer(parmsComputer, parmsMachine, true); var computer = new Computer(parmsComputer, parmsMachine, true);
if (DEBUG) computer.messageDebugger("onInit(" + computer.bitField.fPowered + ")"); if (DEBUG && computer.messageEnabled()) {
computer.messageDebugger("onInit(" + computer.bitField.fPowered + ")");
}
/* /*
* For now, all we support are "reset" and "save" buttons. We may eventually add a "power" * For now, all we support are "reset" and "save" buttons. We may eventually add a "power"
@ -1243,7 +1250,9 @@ Computer.show = function()
var computer = Component.getComponentByType("Computer", parmsComputer['id']); var computer = Component.getComponentByType("Computer", parmsComputer['id']);
if (computer) { if (computer) {
if (DEBUG) computer.messageDebugger("onShow(" + computer.fInitialized + "," + computer.bitField.fPowered + ")"); if (DEBUG && computer.messageEnabled()) {
computer.messageDebugger("onShow(" + computer.fInitialized + "," + computer.bitField.fPowered + ")");
}
if (computer.fInitialized && !computer.bitField.fPowered) { if (computer.fInitialized && !computer.bitField.fPowered) {
/** /**
@ -1290,7 +1299,9 @@ Computer.exit = function()
var computer = Component.getComponentByType("Computer", parmsComputer['id']); var computer = Component.getComponentByType("Computer", parmsComputer['id']);
if (computer) { if (computer) {
if (DEBUG) computer.messageDebugger("onExit(" + computer.bitField.fPowered + ")"); if (DEBUG && computer.messageEnabled()) {
computer.messageDebugger("onExit(" + computer.bitField.fPowered + ")");
}
if (computer.bitField.fPowered) { if (computer.bitField.fPowered) {
/** /**

View file

@ -75,7 +75,7 @@ if (typeof module !== 'undefined') {
*/ */
function CPU(parmsCPU, nCyclesDefault) function CPU(parmsCPU, nCyclesDefault)
{ {
Component.call(this, "CPU", parmsCPU, CPU); Component.call(this, "CPU", parmsCPU, CPU, Debugger.MESSAGE.CPU);
var nCycles = parmsCPU['cycles'] || nCyclesDefault; var nCycles = parmsCPU['cycles'] || nCyclesDefault;
@ -865,7 +865,7 @@ CPU.prototype.calcStartTime = function()
* in case, I make absolutely sure it cannot happen, since doing so could result in negative * in case, I make absolutely sure it cannot happen, since doing so could result in negative
* speed calculations. * speed calculations.
*/ */
if (DEBUG) this.assert(this.aCounts.msStartRun <= this.aCounts.msStartThisRun); this.assert(this.aCounts.msStartRun <= this.aCounts.msStartThisRun);
if (this.aCounts.msStartRun > this.aCounts.msStartThisRun) { if (this.aCounts.msStartRun > this.aCounts.msStartThisRun) {
this.aCounts.msStartRun = this.aCounts.msStartThisRun; this.aCounts.msStartRun = this.aCounts.msStartThisRun;
} }
@ -936,7 +936,7 @@ CPU.prototype.calcRemainingTime = function()
*/ */
this.aCounts.nCyclesRecalc += this.aCounts.nCyclesThisRun; this.aCounts.nCyclesRecalc += this.aCounts.nCyclesThisRun;
if (DEBUG && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.LOG) && msRemainsThisRun) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.LOG) && msRemainsThisRun) {
this.log("calcRemainingTime: " + msRemainsThisRun + "ms to sleep after " + this.aCounts.msEndThisRun + "ms"); this.log("calcRemainingTime: " + msRemainsThisRun + "ms to sleep after " + this.aCounts.msEndThisRun + "ms");
} }

View file

@ -1558,14 +1558,15 @@ if (DEBUGGER) {
*/ */
Debugger.prototype.initMessages = function(sEnable) Debugger.prototype.initMessages = function(sEnable)
{ {
this.afnDumpers = []; this.dbg = this;
this.bitsMessageEnabled = Debugger.MESSAGE.WARN; this.bitsMessage = this.bitsWarning = Debugger.MESSAGE.WARN;
this.sMessagePrev = null; this.sMessagePrev = null;
this.afnDumpers = [];
var aEnable = this.parseCommand(sEnable); var aEnable = this.parseCommand(sEnable);
if (aEnable.length) { if (aEnable.length) {
for (var m in Debugger.MESSAGES) { for (var m in Debugger.MESSAGES) {
if (aEnable.indexOf(m) >= 0) { if (aEnable.indexOf(m) >= 0) {
this.bitsMessageEnabled |= Debugger.MESSAGES[m]; this.bitsMessage |= Debugger.MESSAGES[m];
this.println(m + " messages enabled"); this.println(m + " messages enabled");
} }
} }
@ -1591,24 +1592,6 @@ if (DEBUGGER) {
return false; return false;
}; };
/**
* messageEnabled(bitsMessage)
*
* NOTE: If the caller specifies multiple MESSAGE category flags, then ALL the corresponding flags
* in the Debugger's bitsMessageEnabled variable must be enabled as well, else the result will be false.
*
* One wrinkle is MESSAGE.WARN: if that category is enabled, then ANY value with that bit will return true.
*
* @this {Debugger}
* @param {number} bitsMessage is one or more Debugger MESSAGE_* category flag(s)
* @return {boolean} true if message category is enabled, false if not
*/
Debugger.prototype.messageEnabled = function(bitsMessage)
{
var bitsEnabled = this.bitsMessageEnabled & bitsMessage;
return (bitsEnabled === bitsMessage || !!(bitsEnabled & Debugger.MESSAGE.WARN));
};
/** /**
* messageRegs() * messageRegs()
* *
@ -1652,8 +1635,8 @@ if (DEBUGGER) {
{ {
var nCategory = Debugger.INT_MESSAGE[nInt]; var nCategory = Debugger.INT_MESSAGE[nInt];
var fMessage = nCategory && this.messageEnabled(nCategory); var fMessage = nCategory && this.messageEnabled(nCategory);
if (fMessage) {
var AH = this.cpu.regAX >> 8; var AH = this.cpu.regAX >> 8;
if (fMessage) {
var DL = this.cpu.regDX & 0xff; var DL = this.cpu.regDX & 0xff;
if (nInt == Debugger.INT.DOS && AH == 0x0b || if (nInt == Debugger.INT.DOS && AH == 0x0b ||
nCategory == Debugger.MESSAGE.FDC && DL >= 0x80 || nCategory == Debugger.MESSAGE.HDC && DL < 0x80) { nCategory == Debugger.MESSAGE.FDC && DL >= 0x80 || nCategory == Debugger.MESSAGE.HDC && DL < 0x80) {
@ -1693,31 +1676,7 @@ if (DEBUGGER) {
}; };
/** /**
* messageMem(component, addr, fWrite, addrFrom, name, bitsMessage) * messageIO(component, port, bOut, addrFrom, name, bIn, bitsMessage)
*
* NOTE: Not currently used
*
* @this {Debugger}
* @param {Component} component
* @param {number} addr
* @param {boolean} fWrite is true if this was a write, false if read
* @param {number|null} [addrFrom]
* @param {string|null} [name] of the memory address, if any
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
*
Debugger.prototype.messageMem = function(component, addr, fWrite, addrFrom, name, bitsMessage)
{
if (!bitsMessage) bitsMessage = 0;
bitsMessage |= Debugger.MESSAGES_MEM;
if (addrFrom == null || (this.bitsMessageEnabled & bitsMessage) == bitsMessage) {
var b = this.bus.getByteDirect(addr);
this.message(component.idComponent + "." + (fWrite? "setByte" : "getByte") + "(0x" + str.toHexAddr(addr) + ")" + (addrFrom != null? (" at " + str.toHexAddr(addrFrom)) : "") + ": " + (name? (name + "=") : "") + str.toHexByte(b));
}
};
*/
/**
* messagePort(component, port, bOut, addrFrom, name, bitsMessage, bIn)
* *
* @this {Debugger} * @this {Debugger}
* @param {Component} component * @param {Component} component
@ -1725,14 +1684,14 @@ if (DEBUGGER) {
* @param {number|null} bOut if an output operation * @param {number|null} bOut if an output operation
* @param {number|null} [addrFrom] * @param {number|null} [addrFrom]
* @param {string|null} [name] of the port, if any * @param {string|null} [name] of the port, if any
* @param {number|null} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
* @param {number} [bIn] is the input value, if known, on an input operation * @param {number} [bIn] is the input value, if known, on an input operation
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
*/ */
Debugger.prototype.messagePort = function(component, port, bOut, addrFrom, name, bitsMessage, bIn) Debugger.prototype.messageIO = function(component, port, bOut, addrFrom, name, bIn, bitsMessage)
{ {
if (!bitsMessage) bitsMessage = 0; if (!bitsMessage) bitsMessage = 0;
bitsMessage |= Debugger.MESSAGE.PORT; bitsMessage |= Debugger.MESSAGE.PORT;
if (addrFrom == null || (this.bitsMessageEnabled & bitsMessage) == bitsMessage) { if (addrFrom == null || (this.bitsMessage & bitsMessage) == bitsMessage) {
var segFrom = null; var segFrom = null;
if (addrFrom != null) { if (addrFrom != null) {
segFrom = this.cpu.segCS.sel; segFrom = this.cpu.segCS.sel;
@ -1743,13 +1702,18 @@ if (DEBUGGER) {
}; };
/** /**
* message(sMessage) * message(sMessage, fAddress)
* *
* @this {Debugger} * @this {Debugger}
* @param {string} sMessage is any caller-defined message string * @param {string} sMessage is any caller-defined message string
* @param {boolean} [fAddress] is true to display the current CS:IP
*/ */
Debugger.prototype.message = function(sMessage) Debugger.prototype.message = function(sMessage, fAddress)
{ {
if (fAddress) {
sMessage += " @" + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel);
}
if (this.sMessagePrev && sMessage == this.sMessagePrev) return; if (this.sMessagePrev && sMessage == this.sMessagePrev) return;
if (!SAMPLER) this.println(sMessage); // + " (" + this.cpu.getCycles() + " cycles)" if (!SAMPLER) this.println(sMessage); // + " (" + this.cpu.getCycles() + " cycles)"
@ -1757,7 +1721,7 @@ if (DEBUGGER) {
this.sMessagePrev = sMessage; this.sMessagePrev = sMessage;
if (this.cpu) { if (this.cpu) {
if (this.bitsMessageEnabled & Debugger.MESSAGE.HALT) { if (this.bitsMessage & Debugger.MESSAGE.HALT) {
this.cpu.stopCPU(); this.cpu.stopCPU();
} }
/* /*
@ -2073,7 +2037,7 @@ if (DEBUGGER) {
var state = new State(this); var state = new State(this);
state.set(0, this.aAddrNextCode); state.set(0, this.aAddrNextCode);
state.set(1, this.aAddrAssemble); state.set(1, this.aAddrAssemble);
state.set(2, [this.aPrevCmds, this.fAssemble, this.bitsMessageEnabled]); state.set(2, [this.aPrevCmds, this.fAssemble, this.bitsMessage]);
return state.data(); return state.data();
}; };
@ -2095,16 +2059,16 @@ if (DEBUGGER) {
this.aPrevCmds = data[i][0]; this.aPrevCmds = data[i][0];
if (typeof this.aPrevCmds == "string") this.aPrevCmds = [this.aPrevCmds]; if (typeof this.aPrevCmds == "string") this.aPrevCmds = [this.aPrevCmds];
this.fAssemble = data[i][1]; this.fAssemble = data[i][1];
if (!this.bitsMessageEnabled) { if (!this.bitsMessage) {
/* /*
* It's actually kinda annoying that a restored (or predefined) state will trump my initial state, * It's actually kind of annoying that a restored (or predefined) state will trump my initial state,
* at least in situations where I've changed the initial state, if I want to diagnose something. * at least in situations where I've changed the initial state, if I want to diagnose something.
* Perhaps I should save/restore both the initial and current bitsMessageEnabled, and if the initial * Perhaps I should save/restore both the initial and current bitsMessageEnabled, and if the initial
* values don't agree, then leave the current value alone. * values don't agree, then leave the current value alone.
* *
* But, it's much easier to just leave bitsMessageEnabled alone whenever it already contains set bits. * But, it's much easier to just leave bitsMessageEnabled alone whenever it already contains set bits.
*/ */
this.bitsMessageEnabled = data[i][2]; this.bitsMessage = data[i][2];
} }
} }
return true; return true;
@ -2213,12 +2177,8 @@ if (DEBUGGER) {
*/ */
Debugger.prototype.checkInstruction = function(addr, fSkipBP) Debugger.prototype.checkInstruction = function(addr, fSkipBP)
{ {
/* if (!fSkipBP && this.cpu.segCS.cpl == 3 && !(this.cpu.regPS & X86.PS.IF)) {
* Assert that general-purpose register contents remain within their respective ranges; return true;
* this isn't intended to be complete, just a spot-check.
*/
if (DEBUG) {
this.assert(!(this.cpu.regAX & ~0xffff) && !(this.cpu.regBX & ~0xffff) && !(this.cpu.regCX & ~0xffff) && !(this.cpu.regDX & ~0xffff), "register out of bounds");
} }
if (!fSkipBP && this.checkBreakpoint(addr, this.aBreakExec)) { if (!fSkipBP && this.checkBreakpoint(addr, this.aBreakExec)) {
@ -2410,7 +2370,7 @@ if (DEBUGGER) {
var addr = this.getAddr(aAddr, false, 0); var addr = this.getAddr(aAddr, false, 0);
if (addr >= 0) { if (addr >= 0) {
b = this.bus.getByteDirect(addr); b = this.bus.getByteDirect(addr);
if (DEBUG) this.assert((b == (b & 0xff)), "invalid byte (" + b + ") at address: " + this.hexAddr(aAddr)); this.assert((b == (b & 0xff)), "invalid byte (" + b + ") at address: " + this.hexAddr(aAddr));
if (inc !== undefined) this.incAddr(aAddr, inc); if (inc !== undefined) this.incAddr(aAddr, inc);
} }
return b; return b;
@ -2430,7 +2390,7 @@ if (DEBUGGER) {
var addr = this.getAddr(aAddr, false, 1); var addr = this.getAddr(aAddr, false, 1);
if (addr >= 0) { if (addr >= 0) {
w = this.bus.getWordDirect(addr); w = this.bus.getWordDirect(addr);
if (DEBUG) this.assert((w == (w & 0xffff)), "invalid word (" + w + ") at address: " + this.hexAddr(aAddr)); this.assert((w == (w & 0xffff)), "invalid word (" + w + ") at address: " + this.hexAddr(aAddr));
if (inc !== undefined) this.incAddr(aAddr, inc); if (inc !== undefined) this.incAddr(aAddr, inc);
} }
return w; return w;
@ -4181,7 +4141,7 @@ if (DEBUGGER) {
for (m in Debugger.MESSAGES) { for (m in Debugger.MESSAGES) {
if (sCategory == m) { if (sCategory == m) {
bitsMessage = Debugger.MESSAGES[m]; bitsMessage = Debugger.MESSAGES[m];
fCriteria = !!(this.bitsMessageEnabled & bitsMessage); fCriteria = !!(this.bitsMessage & bitsMessage);
break; break;
} }
} }
@ -4192,11 +4152,11 @@ if (DEBUGGER) {
} }
if (bitsMessage) { if (bitsMessage) {
if (asArgs[2] == "on") { if (asArgs[2] == "on") {
this.bitsMessageEnabled |= bitsMessage; this.bitsMessage |= bitsMessage;
fCriteria = true; fCriteria = true;
} }
else if (asArgs[2] == "off") { else if (asArgs[2] == "off") {
this.bitsMessageEnabled &= ~bitsMessage; this.bitsMessage &= ~bitsMessage;
fCriteria = false; fCriteria = false;
} }
} }
@ -4210,7 +4170,7 @@ if (DEBUGGER) {
for (m in Debugger.MESSAGES) { for (m in Debugger.MESSAGES) {
if (!sCategory || sCategory == m) { if (!sCategory || sCategory == m) {
var bitMessage = Debugger.MESSAGES[m]; var bitMessage = Debugger.MESSAGES[m];
var fEnabled = !!(this.bitsMessageEnabled & bitMessage); var fEnabled = !!(this.bitsMessage & bitMessage);
if (fCriteria !== null && fCriteria != fEnabled) continue; if (fCriteria !== null && fCriteria != fEnabled) continue;
if (sCategories) sCategories += ","; if (sCategories) sCategories += ",";
if (!(++n % 10)) sCategories += "\n\t"; // jshint ignore:line if (!(++n % 10)) sCategories += "\n\t"; // jshint ignore:line

View file

@ -231,7 +231,7 @@ if (typeof module !== 'undefined') {
*/ */
function Disk(controller, drive, mode) function Disk(controller, drive, mode)
{ {
Component.call(this, "Disk", {'id': controller.idMachine + ".disk" + Disk.nDisks++}, Disk); Component.call(this, "Disk", {'id': controller.idMachine + ".disk" + Disk.nDisks++}, Disk, Debugger.MESSAGE.DISK);
/* /*
* Route all non-Debugger messages (eg, notice() and println() calls) through * Route all non-Debugger messages (eg, notice() and println() calls) through
@ -444,7 +444,9 @@ Disk.prototype.create = function(mode, nCylinders, nHeads, nSectors, cbSector)
* it wouldn't hurt to let create() do its thing, too, but it's a waste of time. * it wouldn't hurt to let create() do its thing, too, but it's a waste of time.
*/ */
if (this.mode != DiskAPI.MODE.PRELOAD) { if (this.mode != DiskAPI.MODE.PRELOAD) {
if (DEBUG) this.messageDebugger("blank disk for \"" + this.sDiskName + "\": " + this.nCylinders + " cylinders, " + this.nHeads + " head(s)"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("blank disk for \"" + this.sDiskName + "\": " + this.nCylinders + " cylinders, " + this.nHeads + " head(s)");
}
var aCylinders = new Array(this.nCylinders); var aCylinders = new Array(this.nCylinders);
for (var iCylinder = 0; iCylinder < aCylinders.length; iCylinder++) { for (var iCylinder = 0; iCylinder < aCylinders.length; iCylinder++) {
var aHeads = new Array(this.nHeads); var aHeads = new Array(this.nHeads);
@ -656,7 +658,9 @@ Disk.prototype.doneLoad = function(sDiskFile, sDiskData, nErrorCode, sDiskPath)
if (this.fOnDemand) { if (this.fOnDemand) {
if (!nErrorCode) { if (!nErrorCode) {
if (DEBUG) this.messageDebugger('Disk.doneLoad("' + sDiskFile + '","' + sDiskPath + '")'); if (DEBUG && this.messageEnabled()) {
this.messageDebugger('Disk.doneLoad("' + sDiskFile + '","' + sDiskPath + '")');
}
this.fRemote = true; this.fRemote = true;
disk = this; disk = this;
} else { } else {
@ -673,7 +677,9 @@ Disk.prototype.doneLoad = function(sDiskFile, sDiskData, nErrorCode, sDiskPath)
*/ */
this.controller.notice("Unable to load disk \"" + this.sDiskName + "\" (error " + nErrorCode + ")", fPrintOnly); this.controller.notice("Unable to load disk \"" + this.sDiskName + "\" (error " + nErrorCode + ")", fPrintOnly);
} else { } else {
if (DEBUG) this.messageDebugger('Disk.doneLoad("' + sDiskFile + '","' + sDiskPath + '")'); if (DEBUG && this.messageEnabled()) {
this.messageDebugger('Disk.doneLoad("' + sDiskFile + '","' + sDiskPath + '")');
}
try { try {
/* /*
* The following code was a hack to turn on write-protection for a disk image if there was * The following code was a hack to turn on write-protection for a disk image if there was
@ -764,13 +770,13 @@ Disk.prototype.doneLoad = function(sDiskFile, sDiskData, nErrorCode, sDiskPath)
* conversion to a forward-compatible 'data' array. * conversion to a forward-compatible 'data' array.
*/ */
else { else {
if (MAXDEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.DISK)) { if (MAXDEBUG && this.messageEnabled()) {
var sCylinders = aDiskData.length + " track" + (aDiskData.length > 1 ? "s" : ""); var sCylinders = aDiskData.length + " track" + (aDiskData.length > 1 ? "s" : "");
var nHeads = aDiskData[0].length; var nHeads = aDiskData[0].length;
var sHeads = nHeads + " head" + (nHeads > 1 ? "s" : ""); var sHeads = nHeads + " head" + (nHeads > 1 ? "s" : "");
var nSectorsPerTrack = aDiskData[0][0].length; var nSectorsPerTrack = aDiskData[0][0].length;
var sSectorsPerTrack = nSectorsPerTrack + " sector" + (nSectorsPerTrack > 1 ? "s" : "") + "/track"; var sSectorsPerTrack = nSectorsPerTrack + " sector" + (nSectorsPerTrack > 1 ? "s" : "") + "/track";
this.dbg.message(sCylinders + ", " + sHeads + ", " + sSectorsPerTrack); this.messageDebugger(sCylinders + ", " + sHeads + ", " + sSectorsPerTrack);
} }
/* /*
* Before the image is usable, we must "normalize" all the sectors. In the past, this meant * Before the image is usable, we must "normalize" all the sectors. In the past, this meant
@ -811,7 +817,7 @@ Disk.prototype.doneLoad = function(sDiskFile, sDiskData, nErrorCode, sDiskPath)
* pattern, if any, into a dword pattern. * pattern, if any, into a dword pattern.
*/ */
adw = []; adw = [];
if (DEBUG) this.assert((dwPattern & 0xff) == dwPattern); this.assert((dwPattern & 0xff) == dwPattern);
dwPattern = sector['pattern'] = (dwPattern | (dwPattern << 8) | (dwPattern << 16) | (dwPattern << 24)); dwPattern = sector['pattern'] = (dwPattern | (dwPattern << 8) | (dwPattern << 16) | (dwPattern << 24));
sector['data'] = adw; sector['data'] = adw;
} else { } else {
@ -913,7 +919,9 @@ Disk.prototype.onLoadParseSectors = function(sURLName, sURLData, nErrorCode, sec
var nSectors = sectorInfo[3]; var nSectors = sectorInfo[3];
fAsync = sectorInfo[4]; fAsync = sectorInfo[4];
if (DEBUG) this.messageDebugger("Disk.onLoadParseSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.onLoadParseSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + ")");
}
var abData = JSON.parse(sURLData); var abData = JSON.parse(sURLData);
var offData = 0; var offData = 0;
@ -929,7 +937,9 @@ Disk.prototype.onLoadParseSectors = function(sURLName, sURLData, nErrorCode, sec
*/ */
var sector = this.seek(iCylinder, iHead, iSector, true); var sector = this.seek(iCylinder, iHead, iSector, true);
if (!sector) { if (!sector) {
if (DEBUG) this.messageDebugger("Disk.onLoadParseSectors(): seek(" + iCylinder + "," + iHead + "," + iSector + ") failed"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.onLoadParseSectors(): seek(" + iCylinder + "," + iHead + "," + iSector + ") failed");
}
break; break;
} }
this.fill(sector, abData, offData); this.fill(sector, abData, offData);
@ -979,7 +989,9 @@ Disk.prototype.connectRemoteDisk = function(sDiskPath)
*/ */
Disk.prototype.readRemoteSectors = function(iCylinder, iHead, iSector, cbSector, nSectors, done) Disk.prototype.readRemoteSectors = function(iCylinder, iHead, iSector, cbSector, nSectors, done)
{ {
if (DEBUG) this.messageDebugger("Disk.readRemoteSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + "," + cbSector + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.readRemoteSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + "," + cbSector + ")");
}
if (this.fRemote) { if (this.fRemote) {
var sParms = DiskAPI.QUERY.ACTION + '=' + DiskAPI.ACTION.READ; var sParms = DiskAPI.QUERY.ACTION + '=' + DiskAPI.ACTION.READ;
@ -1017,7 +1029,9 @@ Disk.prototype.readRemoteSectors = function(iCylinder, iHead, iSector, cbSector,
*/ */
Disk.prototype.writeRemoteSectors = function(iCylinder, iHead, iSector, nSectors, abSectors, fAsync) Disk.prototype.writeRemoteSectors = function(iCylinder, iHead, iSector, nSectors, abSectors, fAsync)
{ {
if (DEBUG) this.messageDebugger("Disk.writeRemoteSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.writeRemoteSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + ")");
}
if (this.fRemote) { if (this.fRemote) {
var data = {}; var data = {};
@ -1084,7 +1098,9 @@ Disk.prototype.queueDirtySector = function(sector, fAsync)
this.aDirtySectors.push(sector); this.aDirtySectors.push(sector);
this.aDirtyTimestamps.push(usr.getTime()); this.aDirtyTimestamps.push(usr.getTime());
if (DEBUG) this.messageDebugger("Disk.queueDirtySector(" + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + "): " + this.aDirtySectors.length + " dirty"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.queueDirtySector(" + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + "): " + this.aDirtySectors.length + " dirty");
}
return fAsync && this.updateWriteTimer(); return fAsync && this.updateWriteTimer();
}; };
@ -1152,15 +1168,17 @@ Disk.prototype.findDirtySectors = function(fAsync)
var sectorNext = this.aDiskData[iCylinder][iHead][i]; var sectorNext = this.aDiskData[iCylinder][iHead][i];
if (!sectorNext.fDirty) break; if (!sectorNext.fDirty) break;
var j = this.aDirtySectors.indexOf(sectorNext); var j = this.aDirtySectors.indexOf(sectorNext);
if (DEBUG) this.assert(j >= 0, "dirty sector (" + iCylinder + ":" + iHead + ":" + sectorNext['sector'] + ") missing from aDirtySectors"); this.assert(j >= 0, "dirty sector (" + iCylinder + ":" + iHead + ":" + sectorNext['sector'] + ") missing from aDirtySectors");
if (DEBUG) this.messageDebugger("Disk.findDirtySectors(" + iCylinder + ":" + iHead + ":" + sectorNext['sector'] + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.findDirtySectors(" + iCylinder + ":" + iHead + ":" + sectorNext['sector'] + ")");
}
this.aDirtySectors.splice(j, 1); this.aDirtySectors.splice(j, 1);
this.aDirtyTimestamps.splice(j, 1); this.aDirtyTimestamps.splice(j, 1);
abSectors = abSectors.concat(this.toBytes(sectorNext)); abSectors = abSectors.concat(this.toBytes(sectorNext));
sectorNext.fDirty = false; sectorNext.fDirty = false;
nSectors++; nSectors++;
} }
if (DEBUG) this.assert(!!abSectors.length, "no data for dirty sector (" + iCylinder + ":" + iHead + ":" + sector['sector'] + ")"); this.assert(!!abSectors.length, "no data for dirty sector (" + iCylinder + ":" + iHead + ":" + sector['sector'] + ")");
var response = this.writeRemoteSectors(iCylinder, iHead, iSector, nSectors, abSectors, fAsync); var response = this.writeRemoteSectors(iCylinder, iHead, iSector, nSectors, abSectors, fAsync);
return fAsync || response; return fAsync || response;
} }
@ -1188,7 +1206,9 @@ Disk.prototype.onWriteCleanSectors = function(sURLName, sURLData, nErrorCode, se
for (var i = iSector - 1; nSectors-- > 0 && i >= 0 && i < this.aDiskData[iCylinder][iHead].length; i++) { for (var i = iSector - 1; nSectors-- > 0 && i >= 0 && i < this.aDiskData[iCylinder][iHead].length; i++) {
var sector = this.aDiskData[iCylinder][iHead][i]; var sector = this.aDiskData[iCylinder][iHead][i];
if (DEBUG) this.messageDebugger("Disk.onWriteCleanSectors(" + iCylinder + ":" + iHead + ":" + sector['sector'] + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.onWriteCleanSectors(" + iCylinder + ":" + iHead + ":" + sector['sector'] + ")");
}
if (!nErrorCode) { if (!nErrorCode) {
if (!sector.fDirty) { if (!sector.fDirty) {
@ -1318,7 +1338,9 @@ Disk.prototype.seek = function(iCylinder, iHead, iSector, fWrite, done)
}); });
return null; return null;
} else { } else {
if (DEBUG) this.messageDebugger('Disk.seek("' + this.sDiskName + '"): uninitialized sector ' + iCylinder + ':' + iHead + ':' + iSector); if (DEBUG && this.messageEnabled()) {
this.messageDebugger('Disk.seek("' + this.sDiskName + '"): uninitialized sector ' + iCylinder + ':' + iHead + ':' + iSector);
}
} }
} }
break; break;
@ -1395,7 +1417,9 @@ Disk.prototype.read = function(sector, ibSector, fCompare)
{ {
var b = -1; var b = -1;
if (DEBUG && !ibSector && !fCompare) this.messageDebugger("Disk.read(" + this.controller.id + ":" + this.drive.iDrive + "," + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + ")"); if (DEBUG && !ibSector && !fCompare && this.messageEnabled()) {
this.messageDebugger("Disk.read(" + this.controller.id + ":" + this.drive.iDrive + "," + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + ")");
}
if (ibSector < sector['length']) { if (ibSector < sector['length']) {
var adw = sector['data']; var adw = sector['data'];
@ -1420,7 +1444,9 @@ Disk.prototype.write = function(sector, ibSector, b)
if (this.fWriteProtected) if (this.fWriteProtected)
return false; return false;
if (DEBUG && !ibSector) this.messageDebugger("Disk.write(" + this.controller.id + ":" + this.drive.iDrive + "," + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + ")"); if (DEBUG && !ibSector && this.messageEnabled()) {
this.messageDebugger("Disk.write(" + this.controller.id + ":" + this.drive.iDrive + "," + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + ")");
}
if (ibSector < sector['length']) { if (ibSector < sector['length']) {
if (b != this.read(sector, ibSector, true)) { if (b != this.read(sector, ibSector, true)) {
@ -1490,7 +1516,9 @@ Disk.prototype.save = function()
} }
} }
} }
if (DEBUG) this.messageDebugger('Disk.save("' + this.sDiskName + '"): saved ' + (deltas.length - 1) + ' change(s)'); if (DEBUG && this.messageEnabled()) {
this.messageDebugger('Disk.save("' + this.sDiskName + '"): saved ' + (deltas.length - 1) + ' change(s)');
}
return deltas; return deltas;
}; };
@ -1618,28 +1646,13 @@ Disk.prototype.restore = function(deltas)
if (nChanges < 0) { if (nChanges < 0) {
this.controller.notice("unable to restore disk '" + this.sDiskName + ": " + sReason); this.controller.notice("unable to restore disk '" + this.sDiskName + ": " + sReason);
} else { } else {
if (DEBUG) this.messageDebugger('Disk.restore("' + this.sDiskName + '"): restored ' + nChanges + ' change(s)'); if (DEBUG && this.messageEnabled()) {
this.messageDebugger('Disk.restore("' + this.sDiskName + '"): restored ' + nChanges + ' change(s)');
}
} }
return nChanges; return nChanges;
}; };
/**
* messageDebugger(sMessage)
*
* This is a combination of the Debugger's messageEnabled(MESSAGE_DISK) and message() functions, for convenience.
*
* @this {Disk}
* @param {string} sMessage is any caller-defined message string
*/
Disk.prototype.messageDebugger = function(sMessage)
{
if (DEBUGGER && this.dbg) {
if (this.dbg.messageEnabled(Debugger.MESSAGE.DISK)) {
this.dbg.message(sMessage);
}
}
};
if (typeof APP_PCJS !== 'undefined') APP_PCJS.Disk = Disk; if (typeof APP_PCJS !== 'undefined') APP_PCJS.Disk = Disk;
if (typeof module !== 'undefined') module.exports = Disk; if (typeof module !== 'undefined') module.exports = Disk;

View file

@ -137,7 +137,7 @@ function FDC(parmsFDC) {
* TODO: Indicate the type of diskette image being loaded (this might help folks understand what's going * TODO: Indicate the type of diskette image being loaded (this might help folks understand what's going
* on when they try to load a diskette image that's larger than what the selected operating system supports). * on when they try to load a diskette image that's larger than what the selected operating system supports).
*/ */
Component.call(this, "FDC", parmsFDC, FDC); Component.call(this, "FDC", parmsFDC, FDC, Debugger.MESSAGE.FDC);
this['dmaRead'] = this.dmaRead; this['dmaRead'] = this.dmaRead;
this['dmaWrite'] = this.dmaWrite; this['dmaWrite'] = this.dmaWrite;
@ -211,7 +211,7 @@ if (DEBUG) {
ST1: "ST1", // Status Register 1 ST1: "ST1", // Status Register 1
ST2: "ST2", // Status Register 2 ST2: "ST2", // Status Register 2
ST3: "ST3" // Status Register 3 ST3: "ST3" // Status Register 3
} };
} else { } else {
FDC.TERMS = {}; FDC.TERMS = {};
} }
@ -390,7 +390,7 @@ if (DEBUG) {
READ_ID: "READ ID", READ_ID: "READ ID",
FORMAT: "FORMAT", FORMAT: "FORMAT",
SEEK: "SEEK" SEEK: "SEEK"
} };
} else { } else {
FDC.CMDS = {}; FDC.CMDS = {};
} }
@ -483,7 +483,7 @@ FDC.prototype.setBinding = function(sHTMLType, sBinding, control)
var fieldset = control.children[0]; var fieldset = control.children[0];
var files = fieldset.children[0].files; var files = fieldset.children[0].files;
var submit = fieldset.children[1]; var submit = fieldset.children[1];
submit.disabled = (files.length == 0); submit.disabled = !files.length;
}); });
control.onsubmit = function(event) { control.onsubmit = function(event) {
@ -740,6 +740,7 @@ FDC.prototype.initController = function(data)
/* falls through */ /* falls through */
case 320: case 320:
case 360: case 360:
/* falls through */
default: // drives that don't have a recognized capacity default to 360 default: // drives that don't have a recognized capacity default to 360
drive.nCylinders = 40; drive.nCylinders = 40;
drive.nSectors = 9; // drives capable of writing 8 sectors/track can also write 9 sectors/track drive.nSectors = 9; // drives capable of writing 8 sectors/track can also write 9 sectors/track
@ -1525,7 +1526,7 @@ FDC.prototype.unloadAllDrives = function(fDiscard)
FDC.prototype.addDiskHistory = function(sDisketteName, sDiskettePath, disk) FDC.prototype.addDiskHistory = function(sDisketteName, sDiskettePath, disk)
{ {
var i; var i;
if (DEBUG) this.assert(!!sDiskettePath); this.assert(!!sDiskettePath);
for (i = 0; i < this.aDiskHistory.length; i++) { for (i = 0; i < this.aDiskHistory.length; i++) {
if (this.aDiskHistory[i][1] == sDiskettePath) { if (this.aDiskHistory[i][1] == sDiskettePath) {
var nChanges = disk.restore(this.aDiskHistory[i][2]); var nChanges = disk.restore(this.aDiskHistory[i][2]);
@ -1719,7 +1720,7 @@ FDC.prototype.outFDCData = function(port, bOut, addrFrom)
} }
if (DEBUG && this.messageEnabled()) { if (DEBUG && this.messageEnabled()) {
this.messageDebugger("unsupported FDC command: " + str.toHexByte(bCmd)); this.messageDebugger("unsupported FDC command: " + str.toHexByte(bCmd));
if (DEBUGGER) this.cpu.stopCPU(); this.dbg.stopCPU();
} }
}; };
@ -1814,7 +1815,7 @@ FDC.prototype.doCmd = function()
* Controller docs say that H should always match HD, so I assert that, but what if someone * Controller docs say that H should always match HD, so I assert that, but what if someone
* made a mistake and didn't program them identically -- what would happen? Which should we honor? * made a mistake and didn't program them identically -- what would happen? Which should we honor?
*/ */
if (DEBUG) this.assert(h == bHead); this.assert(h == bHead);
r = drive.bSector = this.popCmd(FDC.TERMS.R); // R r = drive.bSector = this.popCmd(FDC.TERMS.R); // R
n = this.popCmd(FDC.TERMS.N); // N n = this.popCmd(FDC.TERMS.N); // N
drive.nBytes = 128 << n; // 0 => 128, 1 => 256, 2 => 512, 3 => 1024 drive.nBytes = 128 << n; // 0 => 128, 1 => 256, 2 => 512, 3 => 1024
@ -1938,7 +1939,7 @@ FDC.prototype.doCmd = function()
* update() function that all FDC commands can use. This code is merely sufficient to get us * update() function that all FDC commands can use. This code is merely sufficient to get us
* through the "DSKETTE_SETUP" gauntlet in the MODEL_5170 BIOS. * through the "DSKETTE_SETUP" gauntlet in the MODEL_5170 BIOS.
*/ */
if (drive.bCylinder == 0) { if (!drive.bCylinder) {
drive.resCode |= FDC.REG_DATA.RES.TRACK0; drive.resCode |= FDC.REG_DATA.RES.TRACK0;
} }
this.beginResult(); // like FDC.REG_DATA.CMD.RECALIBRATE, no results are provided this.beginResult(); // like FDC.REG_DATA.CMD.RECALIBRATE, no results are provided
@ -1948,7 +1949,7 @@ FDC.prototype.doCmd = function()
default: default:
if (DEBUG && this.messageEnabled()) { if (DEBUG && this.messageEnabled()) {
this.messageDebugger("FDC operation unsupported (command=0x: " + str.toHexByte(bCmd) + ")"); this.messageDebugger("FDC operation unsupported (command=0x: " + str.toHexByte(bCmd) + ")");
if (DEBUGGER) this.cpu.stopCPU(); this.dbg.stopCPU();
} }
break; break;
} }
@ -2023,12 +2024,12 @@ FDC.prototype.pushResults = function(drive, bCmd, bHead, c, h, r, n)
*/ */
FDC.prototype.popCmd = function(name) FDC.prototype.popCmd = function(name)
{ {
if (DEBUG) this.assert((!this.regDataIndex || name !== undefined) && this.regDataIndex < this.regDataTotal); this.assert((!this.regDataIndex || name !== undefined) && this.regDataIndex < this.regDataTotal);
var bCmd = this.regDataArray[this.regDataIndex]; var bCmd = this.regDataArray[this.regDataIndex];
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PORT)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PORT)) {
var bCmdMasked = bCmd & FDC.REG_DATA.CMD.MASK; var bCmdMasked = bCmd & FDC.REG_DATA.CMD.MASK;
if (!name && !this.regDataIndex && FDC.aCmdInfo[bCmdMasked]) name = FDC.aCmdInfo[bCmdMasked].name; if (!name && !this.regDataIndex && FDC.aCmdInfo[bCmdMasked]) name = FDC.aCmdInfo[bCmdMasked].name;
this.messageDebugger("FDC.CMD[" + (name || this.regDataIndex) + "]: 0x" + str.toHexByte(bCmd), Debugger.MESSAGE.PORT); this.messageDebugger("FDC.CMD[" + (name || this.regDataIndex) + "]: 0x" + str.toHexByte(bCmd));
} }
this.regDataIndex++; this.regDataIndex++;
return bCmd; return bCmd;
@ -2080,7 +2081,7 @@ FDC.prototype.beginResult = function()
FDC.prototype.pushResult = function(bResult, name) FDC.prototype.pushResult = function(bResult, name)
{ {
if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PORT)) { if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PORT)) {
this.messageDebugger("FDC.RES[" + (name || this.regDataTotal) + "]: 0x" + str.toHexByte(bResult), Debugger.MESSAGE.PORT); this.messageDebugger("FDC.RES[" + (name || this.regDataTotal) + "]: 0x" + str.toHexByte(bResult));
} }
this.regDataArray[this.regDataTotal++] = bResult; this.regDataArray[this.regDataTotal++] = bResult;
}; };
@ -2396,7 +2397,7 @@ FDC.prototype.writeByte = function(drive, b)
*/ */
FDC.prototype.advanceSector = function(drive) FDC.prototype.advanceSector = function(drive)
{ {
if (DEBUG) this.assert(drive.bCylinder < drive.nDiskCylinders); this.assert(drive.bCylinder < drive.nDiskCylinders);
drive.bSector++; drive.bSector++;
var bSectorStart = 1; var bSectorStart = 1;
if (drive.bSector >= drive.nDiskSectors + bSectorStart) { if (drive.bSector >= drive.nDiskSectors + bSectorStart) {
@ -2441,64 +2442,6 @@ FDC.prototype.writeFormat = function(drive, b)
return b; return b;
}; };
/**
* messageEnabled(bitsMessage)
*
* @this {FDC}
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
* @return {boolean}
*/
FDC.prototype.messageEnabled = function(bitsMessage)
{
if (DEBUGGER && this.dbg) {
if (bitsMessage == null) {
bitsMessage = Debugger.MESSAGE.FDC;
} else {
bitsMessage |= Debugger.MESSAGE.FDC;
}
return this.dbg.messageEnabled(bitsMessage);
}
return false;
};
/**
* messageDebugger(sMessage, bitsMessage)
*
* This is a combination of the Debugger's messageEnabled(MESSAGE_FDC) and message() functions, for convenience.
*
* @this {FDC}
* @param {string} sMessage is any caller-defined message string
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
*/
FDC.prototype.messageDebugger = function(sMessage, bitsMessage)
{
if (DEBUGGER && this.dbg) {
if (bitsMessage == null) {
bitsMessage = Debugger.MESSAGE.FDC;
} else {
bitsMessage |= Debugger.MESSAGE.FDC;
}
if (this.dbg.messageEnabled(bitsMessage)) this.dbg.message(sMessage);
}
};
/**
* messagePort(port, bOut, addrFrom, name, bIn)
*
* This is an internal version of the Debugger's messagePort() function, for convenience.
*
* @this {FDC}
* @param {number} port
* @param {number|null} bOut if an output operation
* @param {number|null} [addrFrom]
* @param {string|null} [name] of the port, if any
* @param {number} [bIn] is the input value, if known, on an input operation
*/
FDC.prototype.messagePort = function(port, bOut, addrFrom, name, bIn)
{
if (DEBUGGER && this.dbg) this.dbg.messagePort(this, port, bOut, addrFrom, name, Debugger.MESSAGE.FDC, bIn);
};
/* /*
* Port input notification table * Port input notification table
* *

View file

@ -78,7 +78,7 @@ if (typeof module !== 'undefined') {
*/ */
function HDC(parmsHDC) { function HDC(parmsHDC) {
Component.call(this, "HDC", parmsHDC, HDC); Component.call(this, "HDC", parmsHDC, HDC, Debugger.MESSAGE.HDC);
this['dmaRead'] = this.dmaRead; this['dmaRead'] = this.dmaRead;
this['dmaWrite'] = this.dmaWrite; this['dmaWrite'] = this.dmaWrite;
@ -747,7 +747,9 @@ HDC.prototype.initController = function(data, fHard)
this.regConfig |= (drive.type & 0x3) << ((1 - iDrive) << 1); this.regConfig |= (drive.type & 0x3) << ((1 - iDrive) << 1);
} }
} }
if (DEBUG) this.messageDebugger("HDC initialized for " + this.aDrives.length + " drive(s)"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC initialized for " + this.aDrives.length + " drive(s)");
}
return fSuccess; return fSuccess;
}; };
@ -1147,7 +1149,7 @@ HDC.prototype.loadDisk = function(iDrive, sDiskName, sDiskPath, fAutoMount)
if (fAutoMount) { if (fAutoMount) {
drive.fAutoMount = true; drive.fAutoMount = true;
this.cAutoMount++; this.cAutoMount++;
this.messageDebugger("loading " + sDiskName); if (this.messageEnabled()) this.messageDebugger("loading " + sDiskName);
} }
var disk = drive.disk || new Disk(this, drive, drive.mode); var disk = drive.disk || new Disk(this, drive, drive.mode);
disk.load(sDiskName, sDiskPath, null, this.doneLoadDisk); disk.load(sDiskName, sDiskPath, null, this.doneLoadDisk);
@ -1399,7 +1401,7 @@ HDC.prototype.inATCData = function(port, addrFrom)
* well, then the caller will get 0xff. * well, then the caller will get 0xff.
*/ */
bIn = this.readByte(this.drive); bIn = this.readByte(this.drive);
if (DEBUG) this.assert(bIn >= 0); this.assert(bIn >= 0);
/* /*
* Now that we've supplied a full sector of data, see if the caller's expecting additional sectors; * Now that we've supplied a full sector of data, see if the caller's expecting additional sectors;
@ -1420,7 +1422,7 @@ HDC.prototype.inATCData = function(port, addrFrom)
/* /*
* I shouldn't have to set BUSY (or DATA_REQ) again, because it should still be set, no? * I shouldn't have to set BUSY (or DATA_REQ) again, because it should still be set, no?
*/ */
if (DEBUG) hdc.assert(!!(hdc.regStatus & HDC.ATC.STATUS.BUSY)); hdc.assert(!!(hdc.regStatus & HDC.ATC.STATUS.BUSY));
} else { } else {
/* /*
* TODO: It would be nice to be a bit more specific about the error (if any) that just occurred. * TODO: It would be nice to be a bit more specific about the error (if any) that just occurred.
@ -1432,7 +1434,7 @@ HDC.prototype.inATCData = function(port, addrFrom)
} }
}, false); }, false);
} else { } else {
if (DEBUG) this.assert(this.drive.nBytes == 0); this.assert(!this.drive.nBytes);
this.regStatus = HDC.ATC.STATUS.READY | HDC.ATC.STATUS.SEEK_OK; this.regStatus = HDC.ATC.STATUS.READY | HDC.ATC.STATUS.SEEK_OK;
} }
} }
@ -1454,7 +1456,7 @@ HDC.prototype.outATCData = function(port, bOut, addrFrom)
/* /*
* messagePort() calls, if enabled, can be overwhelming for this port, so limit them to the first byte. * messagePort() calls, if enabled, can be overwhelming for this port, so limit them to the first byte.
*/ */
if (!this.drive || this.drive.ibSector == 0) this.messagePort(port, bOut, addrFrom, "DATA"); if (!this.drive || !this.drive.ibSector) this.messagePort(port, bOut, addrFrom, "DATA");
if (this.drive) { if (this.drive) {
if (this.drive.nBytes >= this.drive.cbSector) { if (this.drive.nBytes >= this.drive.cbSector) {
@ -1465,7 +1467,9 @@ HDC.prototype.outATCData = function(port, bOut, addrFrom)
*/ */
this.regStatus = HDC.ATC.STATUS.ERROR; this.regStatus = HDC.ATC.STATUS.ERROR;
this.regError = HDC.ATC.ERROR.NO_CHS; this.regError = HDC.ATC.ERROR.NO_CHS;
if (DEBUG) this.messageDebugger("HDC.outATCData(" + str.toHexByte(bOut) + "): write failed"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.outATCData(" + str.toHexByte(bOut) + "): write failed");
}
} }
else if (this.drive.ibSector == this.drive.cbSector) { else if (this.drive.ibSector == this.drive.cbSector) {
this.drive.nBytes -= this.drive.cbSector; this.drive.nBytes -= this.drive.cbSector;
@ -1475,9 +1479,9 @@ HDC.prototype.outATCData = function(port, bOut, addrFrom)
/* /*
* I shouldn't have to set BUSY (or DATA_REQ) again, because it should still be set, no? * I shouldn't have to set BUSY (or DATA_REQ) again, because it should still be set, no?
*/ */
if (DEBUG) this.assert(!!(this.regStatus & HDC.ATC.STATUS.BUSY)); this.assert(!!(this.regStatus & HDC.ATC.STATUS.BUSY));
} else { } else {
if (DEBUG) this.assert(this.drive.nBytes == 0); this.assert(!this.drive.nBytes);
this.regStatus = HDC.ATC.STATUS.READY | HDC.ATC.STATUS.SEEK_OK; this.regStatus = HDC.ATC.STATUS.READY | HDC.ATC.STATUS.SEEK_OK;
} }
} }
@ -1485,13 +1489,17 @@ HDC.prototype.outATCData = function(port, bOut, addrFrom)
/* /*
* TODO: What to do about unexpected writes? The number of bytes has exceeded what the command specified. * TODO: What to do about unexpected writes? The number of bytes has exceeded what the command specified.
*/ */
if (DEBUG) this.messageDebugger("HDC.outATCData(" + str.toHexByte(bOut) + "): write exceeds count (" + this.drive.nBytes + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.outATCData(" + str.toHexByte(bOut) + "): write exceeds count (" + this.drive.nBytes + ")");
}
} }
} else { } else {
/* /*
* TODO: What to do about unexpected writes? The number of bytes has exceeded what the command specified. * TODO: What to do about unexpected writes? The number of bytes has exceeded what the command specified.
*/ */
if (DEBUG) this.messageDebugger("HDC.outATCData(" + str.toHexByte(bOut) + "): write without command"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.outATCData(" + str.toHexByte(bOut) + "): write without command");
}
} }
}; };
@ -1791,7 +1799,9 @@ HDC.prototype.doATCommand = function()
this.drive = drive; this.drive = drive;
} }
if (DEBUG) this.messageDebugger("HDC.doATCommand(" + str.toHexByte(bCmd) + "): " + HDC.aATCCommands[bCmd], Debugger.MESSAGE.PORT | Debugger.MESSAGE.HDC); if (DEBUG && this.messageEnabled(Debugger.MESSAGE.PORT | Debugger.MESSAGE.HDC)) {
this.messageDebugger("HDC.doATCommand(" + str.toHexByte(bCmd) + "): " + HDC.aATCCommands[bCmd]);
}
switch (bCmd & HDC.ATC.COMMAND.MASK) { switch (bCmd & HDC.ATC.COMMAND.MASK) {
@ -1868,16 +1878,18 @@ HDC.prototype.doATCommand = function()
* The importance of SECCNT (nSectors) and DRVHD (nHeads) is controlling how multi-sector operations * The importance of SECCNT (nSectors) and DRVHD (nHeads) is controlling how multi-sector operations
* advance to the next sector; see advanceSector(). * advance to the next sector; see advanceSector().
*/ */
if (DEBUG) this.assert(drive.nHeads == nHead + 1); this.assert(drive.nHeads == nHead + 1);
if (DEBUG) this.assert(drive.nSectors == nSectors); this.assert(drive.nSectors == nSectors);
drive.nHeads = nHead + 1; drive.nHeads = nHead + 1;
drive.nSectors = nSectors; drive.nSectors = nSectors;
fInterrupt = true; fInterrupt = true;
break; break;
default: default:
if (DEBUG) this.messageDebugger("HDC.doATCommand(" + str.toHexByte(this.regCommand) + "): " + (bCmd < 0? ("invalid drive (" + iDrive + ")") : "unsupported operation")); if (DEBUG && this.messageEnabled()) {
if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.HDC) && bCmd >= 0) this.cpu.stopCPU(); this.messageDebugger("HDC.doATCommand(" + str.toHexByte(this.regCommand) + "): " + (bCmd < 0? ("invalid drive (" + iDrive + ")") : "unsupported operation"));
if (bCmd >= 0) this.dbg.stopCPU();
}
break; break;
} }
@ -2009,7 +2021,9 @@ HDC.prototype.doXTCommand = function()
case HDC.XTC.DATA.CMD.RECALIBRATE: // 0x01 case HDC.XTC.DATA.CMD.RECALIBRATE: // 0x01
drive.bControl = bControl; drive.bControl = bControl;
if (DEBUG) this.messageDebugger("HDC.doXTCommand(): drive " + iDrive + " control byte: 0x" + str.toHexByte(bControl)); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.doXTCommand(): drive " + iDrive + " control byte: 0x" + str.toHexByte(bControl));
}
this.beginResult(HDC.XTC.DATA.STATUS_OK | bDrive); this.beginResult(HDC.XTC.DATA.STATUS_OK | bDrive);
break; break;
@ -2044,9 +2058,11 @@ HDC.prototype.doXTCommand = function()
break; break;
default: default:
if (DEBUG) this.messageDebugger("HDC.doXTCommand(" + str.toHexByte(bCmdOrig) + "): " + (bCmd < 0? ("invalid drive (" + iDrive + ")") : "unsupported operation"));
this.beginResult(HDC.XTC.DATA.STATUS_ERROR | bDrive); this.beginResult(HDC.XTC.DATA.STATUS_ERROR | bDrive);
if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.HDC) && bCmd >= 0) this.cpu.stopCPU(); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.doXTCommand(" + str.toHexByte(bCmdOrig) + "): " + (bCmd < 0? ("invalid drive (" + iDrive + ")") : "unsupported operation"));
if (bCmd >= 0) this.dbg.stopCPU();
}
break; break;
} }
} }
@ -2064,7 +2080,9 @@ HDC.prototype.popCmd = function()
var bCmdIndex = this.regDataIndex; var bCmdIndex = this.regDataIndex;
if (bCmdIndex < this.regDataTotal) { if (bCmdIndex < this.regDataTotal) {
bCmd = this.regDataArray[this.regDataIndex++]; bCmd = this.regDataArray[this.regDataIndex++];
if (DEBUG) this.messageDebugger("HDC.CMD[" + bCmdIndex + "]: 0x" + str.toHexByte(bCmd) + (!bCmdIndex && HDC.aXTCCommands[bCmd]? (" (" + HDC.aXTCCommands[bCmd] + ")") : ""), (bCmdIndex > 0? Debugger.MESSAGE.PORT : 0) | Debugger.MESSAGE.HDC); if (DEBUG && this.messageEnabled((bCmdIndex > 0? Debugger.MESSAGE.PORT : 0) | Debugger.MESSAGE.HDC)) {
this.messageDebugger("HDC.CMD[" + bCmdIndex + "]: 0x" + str.toHexByte(bCmd) + (!bCmdIndex && HDC.aXTCCommands[bCmd]? (" (" + HDC.aXTCCommands[bCmd] + ")") : ""));
}
} }
return bCmd; return bCmd;
}; };
@ -2080,7 +2098,9 @@ HDC.prototype.beginResult = function(bResult)
this.regDataIndex = this.regDataTotal = 0; this.regDataIndex = this.regDataTotal = 0;
if (bResult !== undefined) { if (bResult !== undefined) {
if (DEBUG) this.messageDebugger("HDC.beginResult(0x" + str.toHexByte(bResult) + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.beginResult(0x" + str.toHexByte(bResult) + ")");
}
this.pushResult(bResult); this.pushResult(bResult);
} }
/* /*
@ -2100,7 +2120,9 @@ HDC.prototype.beginResult = function(bResult)
*/ */
HDC.prototype.pushResult = function(bResult) HDC.prototype.pushResult = function(bResult)
{ {
if (DEBUG) this.messageDebugger("HDC.RES[" + this.regDataTotal + "]: 0x" + str.toHexByte(bResult), (this.regDataTotal > 0? Debugger.MESSAGE.PORT : 0) | Debugger.MESSAGE.HDC); if (DEBUG && this.messageEnabled((this.regDataTotal > 0? Debugger.MESSAGE.PORT : 0) | Debugger.MESSAGE.HDC)) {
this.messageDebugger("HDC.RES[" + this.regDataTotal + "]: 0x" + str.toHexByte(bResult));
}
this.regDataArray[this.regDataTotal++] = bResult; this.regDataArray[this.regDataTotal++] = bResult;
}; };
@ -2193,9 +2215,9 @@ HDC.prototype.doRead = function(drive, done)
{ {
drive.errorCode = HDC.XTC.DATA.ERR.NOT_READY; drive.errorCode = HDC.XTC.DATA.ERR.NOT_READY;
if (DEBUG) this.messageDebugger("HDC.doRead(" + drive.wCylinder + ":" + drive.bHead + ":" + drive.bSector + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.doRead(" + drive.wCylinder + ":" + drive.bHead + ":" + drive.bSector + ")");
// if (DEBUG) this.messageDebugger("HDC.doRead(head=" + str.toHexByte(drive.bHead) + ",cyl=" + str.toHexWord(drive.wCylinder) + ",sec=" + str.toHexByte(drive.bSector) + ")"); }
if (drive.disk) { if (drive.disk) {
drive.sector = null; drive.sector = null;
@ -2237,9 +2259,9 @@ HDC.prototype.doWrite = function(drive, done)
{ {
drive.errorCode = HDC.XTC.DATA.ERR.NOT_READY; drive.errorCode = HDC.XTC.DATA.ERR.NOT_READY;
if (DEBUG) this.messageDebugger("HDC.doWrite(" + drive.wCylinder + ":" + drive.bHead + ":" + drive.bSector + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.doWrite(" + drive.wCylinder + ":" + drive.bHead + ":" + drive.bSector + ")");
// if (DEBUG) this.messageDebugger("HDC.doWrite(head=" + str.toHexByte(drive.bHead) + ",cyl=" + str.toHexWord(drive.wCylinder) + ",sec=" + str.toHexByte(drive.bSector) + ")"); }
if (drive.disk) { if (drive.disk) {
drive.sector = null; drive.sector = null;
@ -2340,8 +2362,6 @@ HDC.prototype.doFormat = function(drive, done)
{ {
drive.errorCode = HDC.XTC.DATA.ERR.NOT_READY; drive.errorCode = HDC.XTC.DATA.ERR.NOT_READY;
// if (DEBUG) this.messageDebugger("HDC.doFormat()");
if (drive.disk) { if (drive.disk) {
drive.sector = null; drive.sector = null;
if (this.chipset) { if (this.chipset) {
@ -2525,7 +2545,7 @@ HDC.prototype.writeByte = function(drive, b)
*/ */
HDC.prototype.advanceSector = function(drive) HDC.prototype.advanceSector = function(drive)
{ {
if (DEBUG) this.assert(drive.wCylinder < drive.nCylinders); this.assert(drive.wCylinder < drive.nCylinders);
drive.bSector++; drive.bSector++;
var bSectorStart = (1 - drive.bSectorBias); var bSectorStart = (1 - drive.bSectorBias);
if (drive.bSector >= drive.nSectors + bSectorStart) { if (drive.bSector >= drive.nSectors + bSectorStart) {
@ -2585,9 +2605,9 @@ HDC.prototype.writeFormat = function(drive, b)
drive.nBytes = 128 << drive.abFormat[3];// N (0 => 128, 1 => 256, 2 => 512, 3 => 1024) drive.nBytes = 128 << drive.abFormat[3];// N (0 => 128, 1 => 256, 2 => 512, 3 => 1024)
drive.cbFormat = 0; drive.cbFormat = 0;
if (DEBUG) this.messageDebugger("HDC.writeFormat(" + drive.wCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.writeFormat(" + drive.wCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")");
// if (DEBUG) this.messageDebugger("HDC.writeFormat(head=" + str.toHexByte(drive.bHead) + ",cyl=" + str.toHexWord(drive.wCylinder) + ",sec=" + str.toHexByte(drive.bSector) + ",len=" + str.toHexWord(drive.nBytes) + ")"); }
for (var i = 0; i < drive.nBytes; i++) { for (var i = 0; i < drive.nBytes; i++) {
if (this.writeByte(drive, drive.bFiller) < 0) { if (this.writeByte(drive, drive.bFiller) < 0) {
@ -2677,40 +2697,6 @@ HDC.prototype.intBIOSDiskette = function(addr)
return true; return true;
}; };
/**
* messageDebugger(sMessage, bitsMessage)
*
* This is a combination of the Debugger's messageEnabled(MESSAGE_HDC) and message() functions, for convenience.
*
* @this {HDC}
* @param {string} sMessage is any caller-defined message string
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
*/
HDC.prototype.messageDebugger = function(sMessage, bitsMessage)
{
if (DEBUGGER && this.dbg) {
if (bitsMessage == null) bitsMessage = Debugger.MESSAGE.HDC;
if (this.dbg.messageEnabled(bitsMessage)) this.dbg.message(sMessage);
}
};
/**
* messagePort(port, bOut, addrFrom, name, bIn)
*
* This is an internal version of the Debugger's messagePort() function, for convenience.
*
* @this {HDC}
* @param {number} port
* @param {number|null} bOut if an output operation
* @param {number|null} [addrFrom]
* @param {string|null} [name] of the port, if any
* @param {number} [bIn] is the input value, if known, on an input operation
*/
HDC.prototype.messagePort = function(port, bOut, addrFrom, name, bIn)
{
if (DEBUGGER && this.dbg) this.dbg.messagePort(this, port, bOut, addrFrom, name, Debugger.MESSAGE.HDC, bIn);
};
/* /*
* Port input notification tables * Port input notification tables
*/ */

View file

@ -60,9 +60,9 @@ if (typeof module !== 'undefined') {
* @extends Component * @extends Component
* @param {Object} parmsKbd * @param {Object} parmsKbd
*/ */
function Keyboard(parmsKbd) { function Keyboard(parmsKbd)
{
Component.call(this, "Keyboard", parmsKbd, Keyboard); Component.call(this, "Keyboard", parmsKbd, Keyboard, Debugger.MESSAGE.KBD);
this.nDefaultModel = parmsKbd['model']; this.nDefaultModel = parmsKbd['model'];
this.fEscapeDisabled = false; this.fEscapeDisabled = false;
@ -842,7 +842,7 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control)
this.bindings[id] = control; this.bindings[id] = control;
control.onclick = function(kbd, sKey, keyCode) { control.onclick = function(kbd, sKey, keyCode) {
return function onClickKeyboard(event) { return function onClickKeyboard(event) {
if (DEBUG) kbd.messageDebugger(sKey + " clicked", Debugger.MESSAGE.KEYS); if (DEBUG && kbd.messageEnabled()) kbd.messageDebugger(sKey + " clicked", Debugger.MESSAGE.KEYS);
if (kbd.cpu) kbd.cpu.setFocus(); if (kbd.cpu) kbd.cpu.setFocus();
kbd.checkShiftState(keyCode); kbd.checkShiftState(keyCode);
return !kbd.keySimulatePress(keyCode); return !kbd.keySimulatePress(keyCode);
@ -989,7 +989,9 @@ Keyboard.prototype.setEnable = function(fData, fClock)
{ {
var fReset = false; var fReset = false;
if (this.fClock !== fClock) { if (this.fClock !== fClock) {
if (DEBUG) this.messageDebugger("keyboard clock line changing to " + fClock, Debugger.MESSAGE.PORT); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("keyboard clock line changing to " + fClock, Debugger.MESSAGE.PORT);
}
/* /*
* Toggling the clock line low and then high signals a "reset", which we acknowledge once the * Toggling the clock line low and then high signals a "reset", which we acknowledge once the
* data line is high as well. * data line is high as well.
@ -997,7 +999,9 @@ Keyboard.prototype.setEnable = function(fData, fClock)
this.fClock = this.fResetOnEnable = fClock; this.fClock = this.fResetOnEnable = fClock;
} }
if (this.fData !== fData) { if (this.fData !== fData) {
if (DEBUG) this.messageDebugger("keyboard data line changing to " + fData, Debugger.MESSAGE.PORT); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("keyboard data line changing to " + fData, Debugger.MESSAGE.PORT);
}
this.fData = fData; this.fData = fData;
/* /*
* TODO: Review this code; it was added during the early days of MODEL_5150 testing and may not be * TODO: Review this code; it was added during the early days of MODEL_5150 testing and may not be
@ -1054,7 +1058,7 @@ Keyboard.prototype.readScanCode = function(fShift)
var b = 0; var b = 0;
if (this.abScanBuffer.length) { if (this.abScanBuffer.length) {
b = this.abScanBuffer[0]; b = this.abScanBuffer[0];
this.messageDebugger("scan code 0x" + str.toHexByte(b) + " delivered"); if (this.messageEnabled()) this.messageDebugger("scan code 0x" + str.toHexByte(b) + " delivered");
if (fShift) this.shiftScanCode(); if (fShift) this.shiftScanCode();
} }
return b; return b;
@ -1274,11 +1278,11 @@ Keyboard.prototype.addScanCode = function(bScan, fRepeat)
if (this.abScanBuffer) { if (this.abScanBuffer) {
if (this.abScanBuffer.length < Keyboard.LIMIT.MAX_SCANCODES) { if (this.abScanBuffer.length < Keyboard.LIMIT.MAX_SCANCODES) {
if (!fDown && !this.aScanCodesActive[bKey] || fDown && this.aScanCodesActive[bKey] && !fRepeat) { if (!fDown && !this.aScanCodesActive[bKey] || fDown && this.aScanCodesActive[bKey] && !fRepeat) {
if (MAXDEBUG) this.messageDebugger("scan code 0x" + str.toHexByte(bScan) + " redundant"); if (MAXDEBUG && this.messageEnabled()) this.messageDebugger("scan code 0x" + str.toHexByte(bScan) + " redundant");
return; return;
} }
this.aScanCodesActive[bKey] = fDown; this.aScanCodesActive[bKey] = fDown;
this.messageDebugger("scan code 0x" + str.toHexByte(bScan) + " buffered"); if (this.messageEnabled()) this.messageDebugger("scan code 0x" + str.toHexByte(bScan) + " buffered");
this.abScanBuffer.push(bScan); this.abScanBuffer.push(bScan);
if (this.abScanBuffer.length == 1) { if (this.abScanBuffer.length == 1) {
if (this.chipset) this.chipset.notifyKbdData(true); if (this.chipset) this.chipset.notifyKbdData(true);
@ -1333,7 +1337,7 @@ Keyboard.prototype.autoClear = function(notKeyCode)
{ {
if (this.prevCharDown && (notKeyCode === undefined || notKeyCode != this.prevCharDown)) { if (this.prevCharDown && (notKeyCode === undefined || notKeyCode != this.prevCharDown)) {
if (DEBUG) { if (DEBUG) {
this.messageDebugger("autoClear(" + this.prevCharDown + ")"); if (this.messageEnabled()) this.messageDebugger("autoClear(" + this.prevCharDown + ")");
this.assert(this.aKeyTimers[this.prevCharDown]); this.assert(this.aKeyTimers[this.prevCharDown]);
} }
clearTimeout(this.aKeyTimers[this.prevCharDown]); clearTimeout(this.aKeyTimers[this.prevCharDown]);
@ -1632,7 +1636,9 @@ Keyboard.prototype.keyUpDown = function(event, fDown)
fPass = !this.keySimulateUpOrDown(keyCodeSim, fDown, Keyboard.SIMCODE.KEYUPDOWN); fPass = !this.keySimulateUpOrDown(keyCodeSim, fDown, Keyboard.SIMCODE.KEYUPDOWN);
} }
if (DEBUG) this.messageDebugger(/*(fDown?"\n":"") +*/ "key" + (fDown? "Down" : "Up") + "(" + keyCode + "): " + (fPass? "pass" : "consume"), Debugger.MESSAGE.KEYS); if (DEBUG && this.messageEnabled(Debugger.MESSAGE.KEYS)) {
this.messageDebugger(/*(fDown?"\n":"") +*/ "key" + (fDown? "Down" : "Up") + "(" + keyCode + "): " + (fPass? "pass" : "consume"));
}
return fPass; return fPass;
}; };
@ -1680,7 +1686,9 @@ Keyboard.prototype.keyPress = function(event)
} }
} }
if (DEBUG) this.messageDebugger("keyPress(" + keyCode + "): " + (fPass? "pass" : "consume"), Debugger.MESSAGE.KEYS); if (DEBUG && this.messageEnabled(Debugger.MESSAGE.KEYS)) {
this.messageDebugger("keyPress(" + keyCode + "): " + (fPass? "pass" : "consume"));
}
return fPass; return fPass;
}; };
@ -1734,11 +1742,15 @@ Keyboard.prototype.keySimulatePress = function(keyCode, fCheckShift, fQuickRelea
kbd.keySimulateUpOrDown(keyCode, false, Keyboard.SIMCODE.KEYTIMEOUT); kbd.keySimulateUpOrDown(keyCode, false, Keyboard.SIMCODE.KEYTIMEOUT);
}; };
}(this), msDelay); }(this), msDelay);
if (DEBUG) this.messageDebugger("keySimulatePress(" + keyCode + "): setTimeout()"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("keySimulatePress(" + keyCode + "): setTimeout()");
}
} }
fSimulated = true; fSimulated = true;
} }
if (DEBUG) this.messageDebugger("keySimulatePress(" + keyCode + "): " + (fSimulated? "true" : "false"), Debugger.MESSAGE.KEYS); if (DEBUG && this.messageEnabled(Debugger.MESSAGE.KEYS)) {
this.messageDebugger("keySimulatePress(" + keyCode + "): " + (fSimulated? "true" : "false"));
}
return fSimulated; return fSimulated;
}; };
@ -1823,31 +1835,12 @@ Keyboard.prototype.keySimulateUpOrDown = function(keyCode, fDown, simCode)
fSimulated = true; fSimulated = true;
} }
if (DEBUG && DEBUGGER) this.messageDebugger("keySimulateUpOrDown(" + keyCode + "," + (fDown? "down" : "up") + "," + Keyboard.aSimCodeDescs[simCode] + "): " + (fSimulated? "true" : "false"), Debugger.MESSAGE.KEYS); if (DEBUG && this.messageEnabled(Debugger.MESSAGE.KEYS)) {
this.messageDebugger("keySimulateUpOrDown(" + keyCode + "," + (fDown? "down" : "up") + "," + Keyboard.aSimCodeDescs[simCode] + "): " + (fSimulated? "true" : "false"));
}
return fSimulated; return fSimulated;
}; };
/**
* messageDebugger(sMessage, bitsMessage)
*
* This is a combination of the Debugger's messageEnabled(MESSAGE_KBD) and message() functions, for convenience.
*
* @this {Keyboard}
* @param {string} sMessage is any caller-defined message string
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
*/
Keyboard.prototype.messageDebugger = function(sMessage, bitsMessage)
{
if (DEBUGGER && this.dbg) {
if (bitsMessage == null) {
bitsMessage = Debugger.MESSAGE.KBD;
} else {
bitsMessage |= Debugger.MESSAGE.KBD;
}
if (this.dbg.messageEnabled(bitsMessage)) this.dbg.message(sMessage);
}
};
/** /**
* Keyboard.init() * Keyboard.init()
* *

View file

@ -179,7 +179,7 @@ Memory.prototype = {
*/ */
writeNone: function(off, v) { writeNone: function(off, v) {
if (DEBUGGER && this.dbg.messageEnabled(Debugger.MESSAGE.MEM) && !off) { if (DEBUGGER && this.dbg.messageEnabled(Debugger.MESSAGE.MEM) && !off) {
this.dbg.message("attempt to write 0x" + str.toHexWord(v) + " to invalid block %" + str.toHex(this.addr) + " from " + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel)); this.dbg.message("attempt to write 0x" + str.toHexWord(v) + " to invalid block %" + str.toHex(this.addr), true);
} }
}, },
/** /**

View file

@ -71,7 +71,7 @@ if (typeof module !== 'undefined') {
*/ */
function Mouse(parmsMouse) function Mouse(parmsMouse)
{ {
Component.call(this, "Mouse", parmsMouse, Mouse); Component.call(this, "Mouse", parmsMouse, Mouse, Debugger.MESSAGE.MOUSE);
this.idAdapter = parmsMouse['serial']; this.idAdapter = parmsMouse['serial'];
if (this.idAdapter) { if (this.idAdapter) {
@ -543,7 +543,9 @@ Mouse.prototype.sendPacket = function(sDiag, xDiag, yDiag)
var b1 = 0x40 | (this.fButton1? 0x20 : 0) | (this.fButton2? 0x10 : 0) | ((this.yDelta & 0xC0) >> 4) | ((this.xDelta & 0xC0) >> 6); var b1 = 0x40 | (this.fButton1? 0x20 : 0) | (this.fButton2? 0x10 : 0) | ((this.yDelta & 0xC0) >> 4) | ((this.xDelta & 0xC0) >> 6);
var b2 = this.xDelta & 0x3F; var b2 = this.xDelta & 0x3F;
var b3 = this.yDelta & 0x3F; var b3 = this.yDelta & 0x3F;
this.messageDebugger((sDiag? (sDiag + ": ") : "") + (yDiag !== undefined? ("mouse (" + xDiag + "," + yDiag + "): ") : "") + "serial packet [" + str.toHexByte(b1) + "," + str.toHexByte(b2) + "," + str.toHexByte(b3) + "]", Debugger.MESSAGE.SERIAL); if (this.messageEnabled(Debugger.MESSAGE.SERIAL)) {
this.messageDebugger((sDiag? (sDiag + ": ") : "") + (yDiag !== undefined? ("mouse (" + xDiag + "," + yDiag + "): ") : "") + "serial packet [" + str.toHexByte(b1) + "," + str.toHexByte(b2) + "," + str.toHexByte(b3) + "]", 0, true);
}
this.componentAdapter.sendRBR([b1, b2, b3]); this.componentAdapter.sendRBR([b1, b2, b3]);
this.xDelta = this.yDelta = 0; this.xDelta = this.yDelta = 0;
}; };
@ -630,29 +632,6 @@ Mouse.prototype.notifyMCR = function(bMCR)
this.bMCR = bMCR; this.bMCR = bMCR;
}; };
/**
* messageDebugger(sMessage)
*
* This is a combination of the Debugger's messageEnabled(MESSAGE_MOUSE) and message() functions, for convenience.
*
* @this {Mouse}
* @param {string} sMessage is any caller-defined message string
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
*/
Mouse.prototype.messageDebugger = function(sMessage, bitsMessage)
{
if (DEBUGGER && this.dbg) {
if (bitsMessage == null) {
bitsMessage = Debugger.MESSAGE.MOUSE;
} else {
bitsMessage |= Debugger.MESSAGE.MOUSE;
}
if (this.dbg.messageEnabled(bitsMessage)) {
this.dbg.message(sMessage + " @" + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel));
}
}
};
/** /**
* Mouse.init() * Mouse.init()
* *

View file

@ -40,8 +40,8 @@
* debugger.js from the compilation process altogether. * debugger.js from the compilation process altogether.
* *
* However, when we're in "development mode" and running uncompiled code in debugger-less configurations, * However, when we're in "development mode" and running uncompiled code in debugger-less configurations,
* I would still like to skip loading debugger.js altogether. To do that, we must arrange for an additional file, * I would still like to skip loading debugger.js altogether. To do that, we must arrange for this additional file,
* nodebugger.js, to be loaded as early as possible, which must explicitly UPDATE the value of DEBUGGER to *false*. * nodebugger.js, to be loaded as early as possible, which explicitly UPDATES the value of DEBUGGER to false.
*/ */
DEBUGGER = false; DEBUGGER = false;

View file

@ -87,7 +87,7 @@ function SerialPort(parmsSerial) {
*/ */
this.controlIOBuffer = null; this.controlIOBuffer = null;
Component.call(this, "SerialPort", parmsSerial, SerialPort); Component.call(this, "SerialPort", parmsSerial, SerialPort, Debugger.MESSAGE.SERIAL);
Component.bindExternalControl(this, parmsSerial['binding'], SerialPort.sIOBuffer); Component.bindExternalControl(this, parmsSerial['binding'], SerialPort.sIOBuffer);
} }
@ -715,40 +715,6 @@ SerialPort.prototype.echoByte = function(b) {
return false; return false;
}; };
/**
* messageDebugger(sMessage)
*
* This is a combination of the Debugger's messageEnabled(MESSAGE_SERIAL) and message() functions, for convenience.
*
* @this {SerialPort}
* @param {string} sMessage is any caller-defined message string
*/
SerialPort.prototype.messageDebugger = function(sMessage) {
if (DEBUGGER && this.dbg) {
if (this.dbg.messageEnabled(Debugger.MESSAGE.SERIAL)) {
this.dbg.message(sMessage);
}
}
};
/**
* messagePort(port, bOut, addrFrom, name, bIn)
*
* This is an internal version of the Debugger's messagePort() function, for convenience.
*
* @this {SerialPort}
* @param {number} port
* @param {number|null} bOut if an output operation
* @param {number|null} [addrFrom]
* @param {string|null} [name] of the port, if any
* @param {number} [bIn] is the input value, if known, on an input operation
*/
SerialPort.prototype.messagePort = function(port, bOut, addrFrom, name, bIn) {
if (DEBUGGER && this.dbg) {
this.dbg.messagePort(this, port, bOut, addrFrom, name, Debugger.MESSAGE.SERIAL, bIn);
}
};
/* /*
* Port input notification table * Port input notification table
*/ */

View file

@ -50,7 +50,8 @@ if (typeof module !== 'undefined') {
* *
* WARNING: Since State objects are low-level objects that have no UI requirements, * WARNING: Since State objects are low-level objects that have no UI requirements,
* they do not inherit from the Component class, so you should only use class methods * they do not inherit from the Component class, so you should only use class methods
* of Component, such as Component.assert(), or Debugger methods if the Debugger is available. * of Component, such as Component.assert(), or Debugger methods if the Debugger
* is available.
* *
* @constructor * @constructor
* @param {Component} component * @param {Component} component
@ -136,12 +137,14 @@ State.decompress = function(aComp, nLength) {
/** /**
* State.compressEvenOdd(aSrc) * State.compressEvenOdd(aSrc)
* *
* This is a very simple variation on compress() that compresses all the EVEN elements of aSrc first, followed by all the ODD * This is a very simple variation on compress() that compresses all the EVEN elements of aSrc first,
* elements. This tends to work better on EGA video memory, because when odd/even addressing is enabled (eg, for text * followed by all the ODD elements. This tends to work better on EGA video memory, because when odd/even
* modes), the DWORD values tend to alternate, which is the worst case for compress(), but the best case for compressEvenOdd(). * addressing is enabled (eg, for text modes), the DWORD values tend to alternate, which is the worst case
* for compress(), but the best case for compressEvenOdd().
* *
* One wrinkle we support: if the first element is uninitialized, then we assume the entire array is undefined, and return an * One wrinkle we support: if the first element is uninitialized, then we assume the entire array is undefined,
* empty compressed array. Conversely, decompressEvenOdd() will take an empty compressed array and return an uninitialized array. * and return an empty compressed array. Conversely, decompressEvenOdd() will take an empty compressed array
* and return an uninitialized array.
* *
* @param {Array.<number>|null} aSrc * @param {Array.<number>|null} aSrc
* @return {Array.<number>|null} is either the original array (aSrc), or a smaller array of "count, value" pairs (aComp) * @return {Array.<number>|null} is either the original array (aSrc), or a smaller array of "count, value" pairs (aComp)
@ -170,9 +173,9 @@ State.compressEvenOdd = function(aSrc) {
/** /**
* State.decompressEvenOdd(aComp, nLength) * State.decompressEvenOdd(aComp, nLength)
* *
* This is the counterpart to compressEvenOdd(). Note that because there's nothing in the compressed sequence that differentiates * This is the counterpart to compressEvenOdd(). Note that because there's nothing in the compressed sequence
* a compress() sequence from a compressEvenOdd() sequence, you simply have to be consistent -- if you used even/odd compression, then * that differentiates a compress() sequence from a compressEvenOdd() sequence, you simply have to be consistent:
* you must use even/odd decompression. * if you used even/odd compression, then you must use even/odd decompression.
* *
* @param {Array.<number>} aComp * @param {Array.<number>} aComp
* @param {number} nLength is expected length of decompressed data * @param {number} nLength is expected length of decompressed data
@ -214,7 +217,7 @@ State.prototype = {
try { try {
this[this.id][id] = data; this[this.id][id] = data;
} catch(e) { } catch(e) {
Component.log(e.message) Component.log(e.message);
} }
}, },
/** /**
@ -274,7 +277,9 @@ State.prototype = {
if (s) { if (s) {
this[this.id] = s; this[this.id] = s;
this.fLoaded = true; this.fLoaded = true;
if (DEBUG) this.messageDebugger("localStorage(" + this.key + "): " + s.length + " bytes loaded"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("localStorage(" + this.key + "): " + s.length + " bytes loaded");
}
return true; return true;
} }
} }
@ -311,7 +316,9 @@ State.prototype = {
if (web.hasLocalStorage()) { if (web.hasLocalStorage()) {
var s = JSON.stringify(this[this.id]); var s = JSON.stringify(this[this.id]);
if (web.setLocalStorageItem(this.key, s)) { if (web.setLocalStorageItem(this.key, s)) {
if (DEBUG) this.messageDebugger("localStorage(" + this.key + "): " + s.length + " bytes stored"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("localStorage(" + this.key + "): " + s.length + " bytes stored");
}
} else { } else {
/* /*
* WARNING: Because browsers tend to disable all alerts() during an "unload" operation, * WARNING: Because browsers tend to disable all alerts() during an "unload" operation,
@ -369,24 +376,40 @@ State.prototype = {
var sKey = aKeys[i]; var sKey = aKeys[i];
if (sKey && (fAll || sKey.substr(0, this.key.length) == this.key)) { if (sKey && (fAll || sKey.substr(0, this.key.length) == this.key)) {
web.removeLocalStorageItem(sKey); web.removeLocalStorageItem(sKey);
if (DEBUG) this.messageDebugger("localStorage(" + sKey + ") removed"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("localStorage(" + sKey + ") removed");
}
aKeys.splice(i, 1); aKeys.splice(i, 1);
i = 0; i = 0;
} }
} }
}, },
/** /**
* messageDebugger(sMessage) * messageEnabled(bitsMessage)
* *
* This is a combination of the Debugger's messageEnabled(MESSAGE_STATE) and message() functions, for convenience. * @this {State}
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
* @return {boolean}
*/
messageEnabled: function(bitsMessage) {
if (DEBUGGER && this.dbg) {
if (bitsMessage == null) {
bitsMessage = Debugger.MESSAGE.STATE;
} else {
bitsMessage |= Debugger.MESSAGE.STATE;
}
return this.dbg.messageEnabled(bitsMessage);
}
return false;
},
/**
* messageDebugger(sMessage)
* *
* @this {State} * @this {State}
* @param {string} sMessage is any caller-defined message string * @param {string} sMessage is any caller-defined message string
*/ */
messageDebugger: function(sMessage) { messageDebugger: function(sMessage) {
if (DEBUGGER && this.dbg) { if (DEBUGGER && this.dbg) this.dbg.message(sMessage);
if (this.dbg.messageEnabled(Debugger.MESSAGE.STATE)) this.dbg.message(sMessage);
}
} }
}; };

View file

@ -106,7 +106,7 @@ if (typeof module !== 'undefined') {
*/ */
function Video(parmsVideo, canvas, context, textarea) function Video(parmsVideo, canvas, context, textarea)
{ {
Component.call(this, "Video", parmsVideo, Video); Component.call(this, "Video", parmsVideo, Video, Debugger.MESSAGE.VIDEO);
/* /*
* This records the model specified (eg, "mda", "cga", "ega" or "" if none specified); * This records the model specified (eg, "mda", "cga", "ega" or "" if none specified);
@ -2189,7 +2189,9 @@ Video.prototype.captureTouch = function()
*/ */
Video.prototype.onFocusChange = function(fFocus) Video.prototype.onFocusChange = function(fFocus)
{ {
if (this.fHasFocus != fFocus && DEBUG) this.messageDebugger("onFocusChange(): focus is now " + fFocus); if (this.fHasFocus != fFocus && DEBUG && this.messageEnabled()) {
this.messageDebugger("onFocusChange(): focus is now " + fFocus);
}
this.fHasFocus = fFocus; this.fHasFocus = fFocus;
}; };
@ -2748,7 +2750,7 @@ Video.prototype.getCardColors = function(nBitsPerPixel)
return Video.aCGAColors; return Video.aCGAColors;
} }
if (DEBUG) this.assert(this.cardColor === this.cardEGA); this.assert(this.cardColor === this.cardEGA);
var aRegs = (this.cardEGA.aATCRegs[15] != null? this.cardEGA.aATCRegs : Video.aEGAPalDef); var aRegs = (this.cardEGA.aATCRegs[15] != null? this.cardEGA.aATCRegs : Video.aEGAPalDef);
for (var i = 0; i < this.aRGB.length; i++) { for (var i = 0; i < this.aRGB.length; i++) {
@ -2867,7 +2869,10 @@ Video.prototype.buildFonts = function()
Video.prototype.buildFont = function(nFont, offData, offSplit, cxChar, cyChar, abFontData, aRGBColors, aColorMap) Video.prototype.buildFont = function(nFont, offData, offSplit, cxChar, cyChar, abFontData, aRGBColors, aColorMap)
{ {
var fChanges = false; var fChanges = false;
if (DEBUG) this.messageDebugger("buildFont(" + nFont + "): building " + Video.cardSpecs[nFont][0] + " font");
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("buildFont(" + nFont + "): building " + Video.cardSpecs[nFont][0] + " font");
}
if (this.createFont(nFont, offData, offSplit, cxChar, cyChar, abFontData, aRGBColors, aColorMap)) fChanges = true; if (this.createFont(nFont, offData, offSplit, cxChar, cyChar, abFontData, aRGBColors, aColorMap)) fChanges = true;
/* /*
@ -2877,7 +2882,9 @@ Video.prototype.buildFont = function(nFont, offData, offSplit, cxChar, cyChar, a
*/ */
if (this.fDoubleFont) { if (this.fDoubleFont) {
nFont <<= 1; nFont <<= 1;
if (DEBUG) this.messageDebugger("buildFont(" + nFont + "): building " + Video.cardSpecs[nFont >> 1][0] + " double-size font"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("buildFont(" + nFont + "): building " + Video.cardSpecs[nFont >> 1][0] + " double-size font");
}
if (this.createFont(nFont, offData, offSplit, cxChar, cyChar, abFontData, aRGBColors, aColorMap)) fChanges = true; if (this.createFont(nFont, offData, offSplit, cxChar, cyChar, abFontData, aRGBColors, aColorMap)) fChanges = true;
} }
return fChanges; return fChanges;
@ -2924,7 +2931,9 @@ Video.prototype.createFont = function(nFont, offData, offSplit, cxChar, cyChar,
var rgbColor = aRGBColors[iColor]; var rgbColor = aRGBColors[iColor];
var rgbColorOrig = font.aCSSColors[iColor]? font.aRGBColors[iColor] : []; var rgbColorOrig = font.aCSSColors[iColor]? font.aRGBColors[iColor] : [];
if (rgbColor[0] !== rgbColorOrig[0] || rgbColor[1] !== rgbColorOrig[1] || rgbColor[2] !== rgbColorOrig[2]) { if (rgbColor[0] !== rgbColorOrig[0] || rgbColor[1] !== rgbColorOrig[1] || rgbColor[2] !== rgbColorOrig[2]) {
if (DEBUG) this.messageDebugger("creating font color " + iColor + " for font " + nFont); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("creating font color " + iColor + " for font " + nFont);
}
this.createFontColor(font, iColor, rgbColor, nDouble, offData, offSplit, cxChar, cyChar, abFontData); this.createFontColor(font, iColor, rgbColor, nDouble, offData, offSplit, cxChar, cyChar, abFontData);
fChanges = true; fChanges = true;
} }
@ -3154,7 +3163,9 @@ Video.prototype.checkCursor = function()
*/ */
var iCellCursor = (this.cardActive.aCRTCRegs[Card.CRTC.CURSOR_ADDR_LO] + ((this.cardActive.aCRTCRegs[Card.CRTC.CURSOR_ADDR_HI] & Card.CRTC.ADDR_HI_MASK) << 8)); var iCellCursor = (this.cardActive.aCRTCRegs[Card.CRTC.CURSOR_ADDR_LO] + ((this.cardActive.aCRTCRegs[Card.CRTC.CURSOR_ADDR_HI] & Card.CRTC.ADDR_HI_MASK) << 8));
if (this.iCellCursor != iCellCursor) { if (this.iCellCursor != iCellCursor) {
if (DEBUG) this.messageDebugger("checkCursor(): cursor moved from " + this.iCellCursor + " to " + iCellCursor); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("checkCursor(): cursor moved from " + this.iCellCursor + " to " + iCellCursor);
}
this.removeCursor(); this.removeCursor();
this.iCellCursor = iCellCursor; this.iCellCursor = iCellCursor;
} }
@ -3207,7 +3218,9 @@ Video.prototype.removeCursor = function()
*/ */
this.updateChar(col, row, data); this.updateChar(col, row, data);
} }
if (DEBUG) this.messageDebugger("removeCursor(): removed from " + row + "," + col); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("removeCursor(): removed from " + row + "," + col);
}
this.aCellCache[this.iCellCursor] = data; this.aCellCache[this.iCellCursor] = data;
} }
} }
@ -3272,7 +3285,9 @@ Video.prototype.getAccess = function()
} }
break; break;
default: default:
if (DEBUG) this.messageDebugger("getAccess(): invalid GRC mode (" + str.toHexByte(regGRCMode) + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("getAccess(): invalid GRC mode (" + str.toHexByte(regGRCMode) + ")");
}
break; break;
} }
if (regGRCMode & Card.GRC.MODE.READ_MODE1) { if (regGRCMode & Card.GRC.MODE.READ_MODE1) {
@ -3298,7 +3313,9 @@ Video.prototype.setAccess = function(nAccess)
var card = this.cardActive; var card = this.cardActive;
if (nAccess != null && card && nAccess != card.nAccess) { if (nAccess != null && card && nAccess != card.nAccess) {
if (DEBUG) this.messageDebugger("setAccess(0x" + str.toHexWord(nAccess) + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("setAccess(0x" + str.toHexWord(nAccess) + ")");
}
card.setMemoryAccess(nAccess); card.setMemoryAccess(nAccess);
@ -3633,7 +3650,9 @@ Video.prototype.setMode = function(nMode, fForce)
{ {
if (nMode != null && (nMode != this.nMode || fForce)) { if (nMode != null && (nMode != this.nMode || fForce)) {
if (DEBUG) this.messageDebugger("setMode(0x" + str.toHexWord(nMode) + (fForce? ",force" : "") + ")"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("setMode(0x" + str.toHexWord(nMode) + (fForce? ",force" : "") + ")");
}
this.cUpdates = 0; // count updateScreen() calls as a means of driving blink updates this.cUpdates = 0; // count updateScreen() calls as a means of driving blink updates
this.nMode = nMode; this.nMode = nMode;
@ -3657,7 +3676,9 @@ Video.prototype.setMode = function(nMode, fForce)
if (this.addrBuffer) { if (this.addrBuffer) {
if (DEBUG) this.messageDebugger("setMode(" + nMode + "): removing 0x" + str.toHex(this.sizeBuffer) + " bytes from 0x" + str.toHex(this.addrBuffer)); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("setMode(" + nMode + "): removing 0x" + str.toHex(this.sizeBuffer) + " bytes from 0x" + str.toHex(this.addrBuffer));
}
if (!this.bus.removeMemory(this.addrBuffer, this.sizeBuffer)) { if (!this.bus.removeMemory(this.addrBuffer, this.sizeBuffer)) {
/* /*
@ -3674,7 +3695,9 @@ Video.prototype.setMode = function(nMode, fForce)
this.addrBuffer = card.addrBuffer; this.addrBuffer = card.addrBuffer;
this.sizeBuffer = card.sizeBuffer; this.sizeBuffer = card.sizeBuffer;
if (DEBUG) this.messageDebugger("setMode(" + nMode + "): adding 0x" + str.toHex(this.sizeBuffer) + " bytes to 0x" + str.toHex(this.addrBuffer)); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("setMode(" + nMode + "): adding 0x" + str.toHex(this.sizeBuffer) + " bytes to 0x" + str.toHex(this.addrBuffer));
}
var controller = (card === this.cardEGA? card : null); var controller = (card === this.cardEGA? card : null);
@ -3824,7 +3847,7 @@ Video.prototype.updateChar = function(col, row, data, context)
this.contextScreen.fillRect(xDst, yDst, this.cxScreenCell, this.cyScreenCell); this.contextScreen.fillRect(xDst, yDst, this.cxScreenCell, this.cyScreenCell);
} }
if (MAXDEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.VIDEO | Debugger.MESSAGE.LOG)) { if (MAXDEBUG && this.messageEnabled(Debugger.MESSAGE.VIDEO | Debugger.MESSAGE.LOG)) {
this.log("updateCharBgnd(" + col + "," + row + "," + bChar + "): filled " + xDst + "," + yDst); this.log("updateCharBgnd(" + col + "," + row + "," + bChar + "): filled " + xDst + "," + yDst);
} }
@ -3835,7 +3858,7 @@ Video.prototype.updateChar = function(col, row, data, context)
var xSrcFgnd = (bChar & 0xf) * font.cxCell; var xSrcFgnd = (bChar & 0xf) * font.cxCell;
var ySrcFgnd = (bChar >> 4) * font.cyCell; var ySrcFgnd = (bChar >> 4) * font.cyCell;
if (MAXDEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.VIDEO | Debugger.MESSAGE.LOG)) { if (MAXDEBUG && this.messageEnabled(Debugger.MESSAGE.VIDEO | Debugger.MESSAGE.LOG)) {
this.log("updateCharFgnd(" + col + "," + row + "," + bChar + "): draw from " + xSrcFgnd + "," + ySrcFgnd + " (" + font.cxCell + "," + font.cyCell + ") to " + xDst + "," + yDst); this.log("updateCharFgnd(" + col + "," + row + "," + bChar + "): draw from " + xSrcFgnd + "," + ySrcFgnd + " (" + font.cxCell + "," + font.cyCell + ") to " + xDst + "," + yDst);
} }
@ -4064,7 +4087,7 @@ Video.prototype.updateScreenText = function(addrScreen, addrScreenLimit, iCell,
if (iCell == this.iCellCursor) { if (iCell == this.iCellCursor) {
data |= ((this.cBlinks & 0x1)? (Video.ATTRS.DRAW_CURSOR << 8) : 0); data |= ((this.cBlinks & 0x1)? (Video.ATTRS.DRAW_CURSOR << 8) : 0);
} }
if (DEBUG) this.assert(iCell < this.aCellCache.length); this.assert(iCell < this.aCellCache.length);
dataCache = this.aCellCache[iCell]; dataCache = this.aCellCache[iCell];
if (dataCache != data) { if (dataCache != data) {
var col = iCell % this.nCols; var col = iCell % this.nCols;
@ -4105,7 +4128,7 @@ Video.prototype.updateScreenGraphicsCGA = function(addrScreen, addrScreenLimit)
var xDirty = this.nCols, xMaxDirty = 0, yDirty = this.nRows, yMaxDirty = 0; var xDirty = this.nCols, xMaxDirty = 0, yDirty = this.nRows, yMaxDirty = 0;
while (addr < addrScreenLimit) { while (addr < addrScreenLimit) {
data = this.bus.getWordDirect(addr); data = this.bus.getWordDirect(addr);
if (DEBUG) this.assert(iCell < this.aCellCache.length); this.assert(iCell < this.aCellCache.length);
dataCache = this.aCellCache[iCell]; dataCache = this.aCellCache[iCell];
if (dataCache === data) { if (dataCache === data) {
x += nPixelsPerCell; x += nPixelsPerCell;
@ -4183,9 +4206,9 @@ Video.prototype.updateScreenGraphicsEGA = function(addrScreen, addrScreenLimit)
var xDirty = this.nCols, xMaxDirty = 0, yDirty = this.nRows, yMaxDirty = 0; var xDirty = this.nCols, xMaxDirty = 0, yDirty = this.nRows, yMaxDirty = 0;
while (addr < addrScreenLimit) { while (addr < addrScreenLimit) {
var idw = addr++ - this.addrBuffer; var idw = addr++ - this.addrBuffer;
if (DEBUG) this.assert(idw >= 0 && idw < adwMemory.length); this.assert(idw >= 0 && idw < adwMemory.length);
data = adwMemory[idw]; data = adwMemory[idw];
if (DEBUG) this.assert(iCell < this.aCellCache.length); this.assert(iCell < this.aCellCache.length);
dataCache = this.aCellCache[iCell]; dataCache = this.aCellCache[iCell];
if (dataCache === data) { if (dataCache === data) {
x += nPixelsPerCell; x += nPixelsPerCell;
@ -4211,7 +4234,7 @@ Video.prototype.updateScreenGraphicsEGA = function(addrScreen, addrScreenLimit)
* Since assertions don't fix problems (only catch them, and only in DEBUG builds), I'm also ensuring * Since assertions don't fix problems (only catch them, and only in DEBUG builds), I'm also ensuring
* that bPixel will always default to 0 if an undefined value ever slips through again. * that bPixel will always default to 0 if an undefined value ever slips through again.
*/ */
if (DEBUG) this.assert(Video.aEGADWToByte[dwPixel] !== undefined); this.assert(Video.aEGADWToByte[dwPixel] !== undefined);
var bPixel = Video.aEGADWToByte[dwPixel] || 0; var bPixel = Video.aEGADWToByte[dwPixel] || 0;
this.setPixel(this.imageScreenBuffer, x++, y, aPixelColors[bPixel]); this.setPixel(this.imageScreenBuffer, x++, y, aPixelColors[bPixel]);
data <<= 1; data <<= 1;
@ -4355,7 +4378,9 @@ Video.prototype.outFeat = function(port, bOut, addrFrom)
Video.prototype.inATC = function(port, addrFrom) Video.prototype.inATC = function(port, addrFrom)
{ {
var b = this.cardEGA.fATCData? this.cardEGA.aATCRegs[this.cardEGA.iATCReg & Card.ATC.INDX_MASK] : this.cardEGA.iATCReg; var b = this.cardEGA.fATCData? this.cardEGA.aATCRegs[this.cardEGA.iATCReg & Card.ATC.INDX_MASK] : this.cardEGA.iATCReg;
if (this.messageEnabled()) {
this.messagePort(Card.ATC.PORT, null, addrFrom, "ATC." + (this.cardEGA.fATCData? this.cardEGA.asATCRegs[this.cardEGA.iATCReg & Card.ATC.INDX_MASK] : "INDX"), b); this.messagePort(Card.ATC.PORT, null, addrFrom, "ATC." + (this.cardEGA.fATCData? this.cardEGA.asATCRegs[this.cardEGA.iATCReg & Card.ATC.INDX_MASK] : "INDX"), b);
}
this.cardEGA.fATCData = !this.cardEGA.fATCData; this.cardEGA.fATCData = !this.cardEGA.fATCData;
return b; return b;
}; };
@ -4377,9 +4402,13 @@ Video.prototype.outATC = function(port, bOut, addrFrom)
this.cardEGA.fATCData = true; this.cardEGA.fATCData = true;
if ((bOut & Card.ATC.INDX_PAL_ENABLE) && !fPalEnabled) { if ((bOut & Card.ATC.INDX_PAL_ENABLE) && !fPalEnabled) {
if (!this.buildFonts()) { if (!this.buildFonts()) {
if (DEBUG) this.messageDebugger("outATC(" + str.toHexByte(bOut) + "): no font changes required"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("outATC(" + str.toHexByte(bOut) + "): no font changes required");
}
} else { } else {
if (DEBUG) this.messageDebugger("outATC(" + str.toHexByte(bOut) + "): redraw screen for font changes"); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("outATC(" + str.toHexByte(bOut) + "): redraw screen for font changes");
}
this.updateScreen(true); this.updateScreen(true);
} }
} }
@ -4387,7 +4416,9 @@ Video.prototype.outATC = function(port, bOut, addrFrom)
var iReg = this.cardEGA.iATCReg & Card.ATC.INDX_MASK; var iReg = this.cardEGA.iATCReg & Card.ATC.INDX_MASK;
if (iReg >= Card.ATC.PALETTE_REGS || !fPalEnabled) { if (iReg >= Card.ATC.PALETTE_REGS || !fPalEnabled) {
if (Video.TRAPALL || this.cardEGA.aATCRegs[iReg] !== bOut) { if (Video.TRAPALL || this.cardEGA.aATCRegs[iReg] !== bOut) {
if (this.messageEnabled()) {
this.messagePort(port, bOut, addrFrom, "ATC." + this.cardEGA.asATCRegs[iReg]); this.messagePort(port, bOut, addrFrom, "ATC." + this.cardEGA.asATCRegs[iReg]);
}
this.cardEGA.aATCRegs[iReg] = bOut; this.cardEGA.aATCRegs[iReg] = bOut;
} }
} }
@ -4469,7 +4500,9 @@ Video.prototype.outSEQIndx = function(port, bOut, addrFrom)
Video.prototype.inSEQData = function(port, addrFrom) Video.prototype.inSEQData = function(port, addrFrom)
{ {
var b = this.cardEGA.aSEQRegs[this.cardEGA.iSEQReg]; var b = this.cardEGA.aSEQRegs[this.cardEGA.iSEQReg];
if (this.messageEnabled()) {
this.messagePort(Card.SEQ.DATA.PORT, null, addrFrom, "SEQ" + this.cardEGA.asSEQRegs[this.cardEGA.iSEQReg], b); this.messagePort(Card.SEQ.DATA.PORT, null, addrFrom, "SEQ" + this.cardEGA.asSEQRegs[this.cardEGA.iSEQReg], b);
}
return b; return b;
}; };
@ -4484,7 +4517,9 @@ Video.prototype.inSEQData = function(port, addrFrom)
Video.prototype.outSEQData = function(port, bOut, addrFrom) Video.prototype.outSEQData = function(port, bOut, addrFrom)
{ {
if (Video.TRAPALL || this.cardEGA.aSEQRegs[this.cardEGA.iSEQReg] !== bOut) { if (Video.TRAPALL || this.cardEGA.aSEQRegs[this.cardEGA.iSEQReg] !== bOut) {
if (this.messageEnabled()) {
this.messagePort(Card.SEQ.DATA.PORT, bOut, addrFrom, "SEQ." + this.cardEGA.asSEQRegs[this.cardEGA.iSEQReg]); this.messagePort(Card.SEQ.DATA.PORT, bOut, addrFrom, "SEQ." + this.cardEGA.asSEQRegs[this.cardEGA.iSEQReg]);
}
this.cardEGA.aSEQRegs[this.cardEGA.iSEQReg] = bOut; this.cardEGA.aSEQRegs[this.cardEGA.iSEQReg] = bOut;
} }
if (this.cardEGA.iSEQReg == Card.SEQ.MAPMASK.INDX) { if (this.cardEGA.iSEQReg == Card.SEQ.MAPMASK.INDX) {
@ -4601,7 +4636,9 @@ Video.prototype.outGRCIndx = function(port, bOut, addrFrom)
Video.prototype.inGRCData = function(port, addrFrom) Video.prototype.inGRCData = function(port, addrFrom)
{ {
var b = this.cardEGA.aGRCRegs[this.cardEGA.iGRCReg]; var b = this.cardEGA.aGRCRegs[this.cardEGA.iGRCReg];
if (this.messageEnabled()) {
this.messagePort(Card.GRC.DATA.PORT, null, addrFrom, "GRC." + this.cardEGA.asGRCRegs[this.cardEGA.iGRCReg], b); this.messagePort(Card.GRC.DATA.PORT, null, addrFrom, "GRC." + this.cardEGA.asGRCRegs[this.cardEGA.iGRCReg], b);
}
return b; return b;
}; };
@ -4616,7 +4653,9 @@ Video.prototype.inGRCData = function(port, addrFrom)
Video.prototype.outGRCData = function(port, bOut, addrFrom) Video.prototype.outGRCData = function(port, bOut, addrFrom)
{ {
if (Video.TRAPALL || this.cardEGA.aGRCRegs[this.cardEGA.iGRCReg] !== bOut) { if (Video.TRAPALL || this.cardEGA.aGRCRegs[this.cardEGA.iGRCReg] !== bOut) {
if (this.messageEnabled()) {
this.messagePort(Card.GRC.DATA.PORT, bOut, addrFrom, "GRC." + this.cardEGA.asGRCRegs[this.cardEGA.iGRCReg]); this.messagePort(Card.GRC.DATA.PORT, bOut, addrFrom, "GRC." + this.cardEGA.asGRCRegs[this.cardEGA.iGRCReg]);
}
this.cardEGA.aGRCRegs[this.cardEGA.iGRCReg] = bOut; this.cardEGA.aGRCRegs[this.cardEGA.iGRCReg] = bOut;
} }
switch(this.cardEGA.iGRCReg) { switch(this.cardEGA.iGRCReg) {
@ -4741,7 +4780,9 @@ Video.prototype.outCGAMode = function(port, bOut, addrFrom)
Video.prototype.inCGAColor = function(port, addrFrom) Video.prototype.inCGAColor = function(port, addrFrom)
{ {
var b = this.cardColor.colorReg; var b = this.cardColor.colorReg;
if (this.messageEnabled()) {
this.messagePort(this.cardColor.port + 5, null, addrFrom, this.cardColor.type + ".COLOR", b); this.messagePort(this.cardColor.port + 5, null, addrFrom, this.cardColor.type + ".COLOR", b);
}
return b; return b;
}; };
@ -4755,7 +4796,9 @@ Video.prototype.inCGAColor = function(port, addrFrom)
*/ */
Video.prototype.outCGAColor = function(port, bOut, addrFrom) Video.prototype.outCGAColor = function(port, bOut, addrFrom)
{ {
if (this.messageEnabled()) {
this.messagePort(this.cardColor.port + 5, bOut, addrFrom, this.cardColor.type + ".COLOR"); this.messagePort(this.cardColor.port + 5, bOut, addrFrom, this.cardColor.type + ".COLOR");
}
if (this.cardColor.colorReg !== bOut) { if (this.cardColor.colorReg !== bOut) {
this.cardColor.colorReg = bOut; this.cardColor.colorReg = bOut;
/* /*
@ -4821,7 +4864,9 @@ Video.prototype.inCRTCData = function(card, addrFrom)
{ {
var b; var b;
if (card.iCRTCReg < card.nCRTCRegs) b = card.aCRTCRegs[card.iCRTCReg]; if (card.iCRTCReg < card.nCRTCRegs) b = card.aCRTCRegs[card.iCRTCReg];
if (this.messageEnabled()) {
this.messagePort(card.port + 1, null, addrFrom, "CRTC." + card.asCRTCRegs[card.iCRTCReg], b); this.messagePort(card.port + 1, null, addrFrom, "CRTC." + card.asCRTCRegs[card.iCRTCReg], b);
}
return b; return b;
}; };
@ -4837,7 +4882,9 @@ Video.prototype.outCRTCData = function(card, bOut, addrFrom)
{ {
if (card.iCRTCReg < card.nCRTCRegs) { if (card.iCRTCReg < card.nCRTCRegs) {
if (Video.TRAPALL || card.aCRTCRegs[card.iCRTCReg] !== bOut) { if (Video.TRAPALL || card.aCRTCRegs[card.iCRTCReg] !== bOut) {
if (this.messageEnabled()) {
this.messagePort(card.port + 1, bOut, addrFrom, "CRTC." + card.asCRTCRegs[card.iCRTCReg]); this.messagePort(card.port + 1, bOut, addrFrom, "CRTC." + card.asCRTCRegs[card.iCRTCReg]);
}
card.aCRTCRegs[card.iCRTCReg] = bOut; card.aCRTCRegs[card.iCRTCReg] = bOut;
} }
/* /*
@ -4854,7 +4901,9 @@ Video.prototype.outCRTCData = function(card, bOut, addrFrom)
} }
this.checkCursor(); this.checkCursor();
} else { } else {
if (DEBUG) this.messageDebugger("outCRTCData(): ignoring unexpected write to CRTC[" + str.toHexByte(card.iCRTCReg) + "]: " + str.toHexByte(bOut)); if (DEBUG && this.messageEnabled()) {
this.messageDebugger("outCRTCData(): ignoring unexpected write to CRTC[" + str.toHexByte(card.iCRTCReg) + "]: " + str.toHexByte(bOut));
}
} }
}; };
@ -4996,43 +5045,6 @@ Video.prototype.dumpVideo = function(sParm)
} }
}; };
/**
* messageDebugger(sMessage)
*
* This is a combination of the Debugger's messageEnabled(MESSAGE_VIDEO) and message() functions, for convenience.
*
* @this {Video}
* @param {boolean} [fForce] to display the message regardless of the MESSAGE_VIDEO setting, provided the Debugger is loaded
* @param {string} sMessage is any caller-defined message string
*/
Video.prototype.messageDebugger = function(sMessage, fForce)
{
if (DEBUGGER && this.dbg) {
if (fForce || this.dbg.messageEnabled(Debugger.MESSAGE.VIDEO)) {
this.dbg.message(sMessage);
}
}
};
/**
* messagePort(port, bOut, addrFrom, name, bIn)
*
* This is an internal version of the Debugger's messagePort() function, for convenience.
*
* @this {Video}
* @param {number} port
* @param {number|null} bOut if an output operation
* @param {number|null} [addrFrom]
* @param {string|null} [name] of the port, if any
* @param {number} [bIn] is the input value, if known, on an input operation
*/
Video.prototype.messagePort = function(port, bOut, addrFrom, name, bIn)
{
if (DEBUGGER && this.dbg) {
this.dbg.messagePort(this, port, bOut, addrFrom, name, Debugger.MESSAGE.VIDEO, bIn);
}
};
/* /*
* Port input/output notification tables * Port input/output notification tables
* *

View file

@ -966,7 +966,7 @@ X86CPU.prototype.checkIntNotify = function(nInt)
* checksEnabled() function, and therefore in fDebugCheck, so for maximum speed, we check fDebugCheck first. * checksEnabled() function, and therefore in fDebugCheck, so for maximum speed, we check fDebugCheck first.
*/ */
if (DEBUGGER && this.bitField.fDebugCheck) { if (DEBUGGER && this.bitField.fDebugCheck) {
if (this.dbg.messageEnabled(Debugger.MESSAGE.INT) && this.dbg.messageInt(nInt, this.regEIP)) { if (this.messageEnabled(Debugger.MESSAGE.INT) && this.dbg.messageInt(nInt, this.regEIP)) {
this.addIntReturn(this.regEIP, function(cpu, nCycles) { this.addIntReturn(this.regEIP, function(cpu, nCycles) {
return function onIntReturn(nLevel) { return function onIntReturn(nLevel) {
cpu.dbg.messageIntReturn(nInt, nLevel, cpu.getCycles() - nCycles); cpu.dbg.messageIntReturn(nInt, nLevel, cpu.getCycles() - nCycles);
@ -1210,7 +1210,7 @@ X86CPU.prototype.getSeg = function(sName)
* HACK: We return a fake segment register object in which only the base physical address is valid, * HACK: We return a fake segment register object in which only the base physical address is valid,
* because that's all the caller provided (ie, we must be restoring from an older state). * because that's all the caller provided (ie, we must be restoring from an older state).
*/ */
if (DEBUG) this.assert(typeof sName == "number"); this.assert(typeof sName == "number");
return [0, sName, 0, 0, ""]; return [0, sName, 0, 0, ""];
} }
}; };
@ -1311,7 +1311,7 @@ X86CPU.prototype.setIP = function(off)
*/ */
X86CPU.prototype.setCSIP = function(off, sel, fCall) X86CPU.prototype.setCSIP = function(off, sel, fCall)
{ {
if (DEBUG) this.assert((off & 0xffff) == off); this.assert((off & 0xffff) == off);
this.segCS.fCall = fCall; this.segCS.fCall = fCall;
/* /*
* We break this operation into the following discrete steps (eg, set IP, load CS, and then update EIP) * We break this operation into the following discrete steps (eg, set IP, load CS, and then update EIP)
@ -1668,7 +1668,7 @@ X86CPU.prototype.setPS = function(regPS)
/* /*
* Assert that all requested flag bits now agree with our simulated (PS_INDIRECT) bits * Assert that all requested flag bits now agree with our simulated (PS_INDIRECT) bits
*/ */
if (DEBUG) this.assert((regPS & X86.PS.INDIRECT) == (this.getPS() & X86.PS.INDIRECT)); this.assert((regPS & X86.PS.INDIRECT) == (this.getPS() & X86.PS.INDIRECT));
if (this.regPS & X86.PS.TF) { if (this.regPS & X86.PS.TF) {
this.intFlags |= X86.INTFLAG.TRAP; this.intFlags |= X86.INTFLAG.TRAP;
@ -2233,7 +2233,7 @@ X86CPU.prototype.popWord = function()
*/ */
X86CPU.prototype.pushWord = function(w) X86CPU.prototype.pushWord = function(w)
{ {
if (DEBUG) this.assert((w & 0xffff) == w); this.assert((w & 0xffff) == w);
this.setSOWord(this.segSS, (this.regSP = (this.regSP - 2) & 0xffff), w); this.setSOWord(this.segSS, (this.regSP = (this.regSP - 2) & 0xffff), w);
}; };
@ -2308,7 +2308,7 @@ X86CPU.prototype.pushWord = function(w)
*/ */
X86CPU.prototype.checkINTR = function() X86CPU.prototype.checkINTR = function()
{ {
if (DEBUG) this.assert(this.intFlags); this.assert(this.intFlags);
if (!(this.opFlags & X86.OPFLAG.NOINTR)) { if (!(this.opFlags & X86.OPFLAG.NOINTR)) {
if ((this.intFlags & X86.INTFLAG.INTR) && (this.regPS & X86.PS.IF)) { if ((this.intFlags & X86.INTFLAG.INTR) && (this.regPS & X86.PS.IF)) {
var nIDT = this.chipset.getIRRVector(); var nIDT = this.chipset.getIRRVector();
@ -2495,7 +2495,7 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
* One exception I make here is when you've asked the Debugger to display PIC messages, the idea being that * One exception I make here is when you've asked the Debugger to display PIC messages, the idea being that
* if you're watching the PIC that closely, then you want to hardware interrupts to occur regardless. * if you're watching the PIC that closely, then you want to hardware interrupts to occur regardless.
*/ */
if (!nMinCycles && this.dbg && !this.dbg.messageEnabled(Debugger.MESSAGE.PIC)) this.opFlags |= X86.OPFLAG.NOINTR; if (!nMinCycles && !this.messageEnabled(Debugger.MESSAGE.PIC)) this.opFlags |= X86.OPFLAG.NOINTR;
do { do {
var opPrefixes = this.opFlags & X86.OPFLAG.PREFIXES; var opPrefixes = this.opFlags & X86.OPFLAG.PREFIXES;
@ -2553,7 +2553,7 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
if (++this.iSampleFreq >= this.nSampleFreq) { if (++this.iSampleFreq >= this.nSampleFreq) {
this.iSampleFreq = 0; this.iSampleFreq = 0;
if (this.iSampleSkip < this.nSampleSkip) { if (this.iSampleSkip < this.nSampleSkip) {
this.iSampleSkip++ this.iSampleSkip++;
} else { } else {
if (this.iSampleNext == this.nSamples) { if (this.iSampleNext == this.nSamples) {
this.println("sample buffer full"); this.println("sample buffer full");
@ -2621,25 +2621,6 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
return (this.bitField.fComplete? this.nBurstCycles - this.nStepCycles : (this.bitField.fComplete === undefined? 0 : -1)); return (this.bitField.fComplete? this.nBurstCycles - this.nStepCycles : (this.bitField.fComplete === undefined? 0 : -1));
}; };
/**
* messageDebugger(sMessage, bitsMessage)
*
* This is a combination of the Debugger's messageEnabled(MESSAGE_CPU) and message() functions, for convenience.
*
* @this {X86CPU}
* @param {string} sMessage is any caller-defined message string
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
*/
X86CPU.prototype.messageDebugger = function(sMessage, bitsMessage)
{
if (DEBUGGER && this.dbg) {
if (bitsMessage == null) {
bitsMessage = Debugger.MESSAGE.CPU;
}
if (this.dbg.messageEnabled(bitsMessage)) this.dbg.message(sMessage);
}
};
/** /**
* X86CPU.init() * X86CPU.init()
* *

View file

@ -571,10 +571,10 @@ var X86Help = {
* JavaScript exception), and since we don't want that instruction to perform any writes that might * JavaScript exception), and since we don't want that instruction to perform any writes that might
* be destructive, we should shut off all further reads/writes for the current instruction. * be destructive, we should shut off all further reads/writes for the current instruction.
* *
* As long as we're not using EAFUNCS, this is easy for any EA-based memory accesses: simply set * As long as we're not using EAFUNCS, that's easy for any EA-based memory accesses: simply set both
* the NOREAD and NOWRITE flags. However, there may still be direct, non-EA-based memory accesses that * the NOREAD and NOWRITE flags. However, there may still be direct, non-EA-based memory accesses that
* could cause us grief. TODO: Implement the ultimate solution, which will involve setting a special * could cause us grief. TODO: Implement the ultimate solution, which will involve throwing a special
* flag and throwing an exception that the CPU must intercept and then quietly ignore. * JavaScript exception that cpu.js must intercept and quietly ignore.
*/ */
if (!EAFUNCS) { if (!EAFUNCS) {
this.opFlags &= ~(X86.OPFLAG.NOREAD | X86.OPFLAG.NOWRITE); this.opFlags &= ~(X86.OPFLAG.NOREAD | X86.OPFLAG.NOWRITE);
@ -588,24 +588,20 @@ var X86Help = {
* *
* TODO: Provide the Debugger with some UI to control its "interference" with fault dispatching, and to * TODO: Provide the Debugger with some UI to control its "interference" with fault dispatching, and to
* continue the dispatch after it has interfered. At the moment, your only option is to single-step over * continue the dispatch after it has interfered. At the moment, your only option is to single-step over
* the offending instruction to allow the fault to be dispatched. * the offending instruction, which will allow the fault to be dispatched, and then continue execution.
* *
* @this {X86CPU} * @this {X86CPU}
* @param {number} nFault * @param {number} nFault
* @param {number} [nError] * @param {number} [nError]
* @param {boolean} [fHalt] will halt the CPU if true *and* a Debugger is loaded * @param {boolean} [fHalt] true if the CPU should always be halted, false if "it depends"
* @return {boolean|undefined} true to block the fault, otherwise dispatch it * @return {boolean|undefined} true to block the fault (often desirable when fHalt is true), otherwise dispatch it
*/ */
opHelpFaultMessage: function(nFault, nError, fHalt) opHelpFaultMessage: function(nFault, nError, fHalt)
{ {
var bitsMessage = Debugger.MESSAGE.FAULT; var bitsMessage = Debugger.MESSAGE.FAULT;
var bOpcode = this.bus.getByteDirect(this.regEIP); var bOpcode = this.bus.getByteDirect(this.regEIP);
var fDebugger = false; if (this.messageEnabled(bitsMessage)) fHalt = true;
if (DEBUGGER && this.dbg) {
fDebugger = true;
if (nFault == X86.EXCEPTION.GP_FAULT) fHalt = true;
}
/* /*
* OS/2 1.0 uses an INT3 (0xCC) opcode in conjunction with an invalid IDT to trigger a triple-fault * OS/2 1.0 uses an INT3 (0xCC) opcode in conjunction with an invalid IDT to trigger a triple-fault
@ -633,15 +629,24 @@ var X86Help = {
fHalt = false; fHalt = false;
} }
if (fDebugger && this.dbg.messageEnabled(bitsMessage) || !fDebugger && fHalt) { if (this.messageEnabled(bitsMessage) || fHalt) {
var sMessage = (fHalt? '\n' : '') + "Fault " + str.toHexByte(nFault) + (nError != null? " (" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(bOpcode) + " at " + str.toHexAddr(this.regIP, this.segCS.sel) + " (%" + str.toHex(this.regEIP, 6) + ")"; var sMessage = (fHalt? '\n' : '') + "Fault " + str.toHexByte(nFault) + (nError != null? " (" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(bOpcode) + " at " + str.toHexAddr(this.regIP, this.segCS.sel) + " (%" + str.toHex(this.regEIP, 6) + ")";
if (fDebugger) { if (this.messageDebugger(sMessage)) {
this.messageDebugger(sMessage, bitsMessage);
if (fHalt) { if (fHalt) {
/*
* By setting fHalt to fRunning (which is true while running but false while single-stepping),
* this allows a fault to be dispatched when you single-step over a faulting instruction; you can
* then continue single-stepping into the fault handler, or start running again.
*/
fHalt = this.bitField.fRunning; fHalt = this.bitField.fRunning;
this.dbg.stopCPU(); this.dbg.stopCPU();
} }
} else if (fHalt) { } else {
/*
* If messageDebugger() returned false, then messageEnabled() must have returned false as well, which
* means that fHalt must be true. Which means we should shut the machine down.
*/
this.assert(fHalt);
this.notice(sMessage); this.notice(sMessage);
this.stopCPU(); this.stopCPU();
} }

View file

@ -126,6 +126,9 @@ var X86Op0F = {
*/ */
opLOADALL: function() { opLOADALL: function() {
if (this.segCS.cpl) { if (this.segCS.cpl) {
/*
* You're not allowed to use LOADALL at any privilege level other than zero
*/
X86Help.opHelpFault.call(this, X86.EXCEPTION.GP_FAULT, 0, true); X86Help.opHelpFault.call(this, X86.EXCEPTION.GP_FAULT, 0, true);
return; return;
} }

View file

@ -1980,7 +1980,7 @@ var X86OpXX = {
* op=0x9B (wait) * op=0x9B (wait)
*/ */
opWAIT: function() { opWAIT: function() {
this.messageDebugger("WAIT not implemented"); this.messageDebugger("WAIT not implemented", Debugger.MESSAGE.CPU);
this.nStepCycles--; this.nStepCycles--;
}, },
/** /**
@ -2026,7 +2026,7 @@ var X86OpXX = {
if (ah & X86.PS.ZF) this.setZF(); else this.clearZF(); if (ah & X86.PS.ZF) this.setZF(); else this.clearZF();
if (ah & X86.PS.SF) this.setSF(); else this.clearSF(); if (ah & X86.PS.SF) this.setSF(); else this.clearSF();
this.nStepCycles -= this.CYCLES.nOpCyclesLAHF; this.nStepCycles -= this.CYCLES.nOpCyclesLAHF;
if (DEBUG) this.assert((this.getPS() & X86.PS.SAHF) == (ah & X86.PS.SAHF)); this.assert((this.getPS() & X86.PS.SAHF) == (ah & X86.PS.SAHF));
}, },
/** /**
* @this {X86CPU} * @this {X86CPU}

View file

@ -193,9 +193,7 @@ X86Seg.loadProt = function loadProt(sel, fSuppress)
X86Seg.loadRealIDT = function loadRealIDT(nIDT) X86Seg.loadRealIDT = function loadRealIDT(nIDT)
{ {
var cpu = this.cpu; var cpu = this.cpu;
if (DEBUG) {
cpu.assert(nIDT >= 0 && nIDT < 256 && !cpu.addrIDT && cpu.addrIDTLimit == 0x03FF); cpu.assert(nIDT >= 0 && nIDT < 256 && !cpu.addrIDT && cpu.addrIDTLimit == 0x03FF);
}
/* /*
* Intel documentation for INT/INTO under "REAL ADDRESS MODE EXCEPTIONS" says: * Intel documentation for INT/INTO under "REAL ADDRESS MODE EXCEPTIONS" says:
* *
@ -220,7 +218,7 @@ X86Seg.loadRealIDT = function loadRealIDT(nIDT)
X86Seg.loadProtIDT = function loadProtIDT(nIDT) X86Seg.loadProtIDT = function loadProtIDT(nIDT)
{ {
var cpu = this.cpu; var cpu = this.cpu;
if (DEBUG) cpu.assert(nIDT >= 0 && nIDT < 256); cpu.assert(nIDT >= 0 && nIDT < 256);
nIDT <<= 3; nIDT <<= 3;
var addrDesc = cpu.addrIDT + nIDT; var addrDesc = cpu.addrIDT + nIDT;
@ -380,7 +378,7 @@ X86Seg.checkWriteProtDisallowed = function checkWriteProtDisallowed(off, cb, fSu
X86Seg.switchTSS = function switchTSS(selNew, fNest) X86Seg.switchTSS = function switchTSS(selNew, fNest)
{ {
var cpu = this.cpu; var cpu = this.cpu;
if (DEBUG) cpu.assert(this === cpu.segCS); cpu.assert(this === cpu.segCS);
var addrOld = cpu.segTSS.base; var addrOld = cpu.segTSS.base;
var cplOld = this.cpl; var cplOld = this.cpl;
@ -424,7 +422,7 @@ X86Seg.switchTSS = function switchTSS(selNew, fNest)
var offSS = X86.TSS.TASK_SS; var offSS = X86.TSS.TASK_SS;
var offSP = X86.TSS.TASK_SP; var offSP = X86.TSS.TASK_SP;
cpu.setPS(cpu.getWord(addrNew + X86.TSS.TASK_PS) | (fNest? X86.PS.NT : 0)); cpu.setPS(cpu.getWord(addrNew + X86.TSS.TASK_PS) | (fNest? X86.PS.NT : 0));
if (DEBUG) cpu.assert(!fNest || !!(cpu.regPS & X86.PS.NT)); cpu.assert(!fNest || !!(cpu.regPS & X86.PS.NT));
cpu.regAX = cpu.getWord(addrNew + X86.TSS.TASK_AX); cpu.regAX = cpu.getWord(addrNew + X86.TSS.TASK_AX);
cpu.regCX = cpu.getWord(addrNew + X86.TSS.TASK_CX); cpu.regCX = cpu.getWord(addrNew + X86.TSS.TASK_CX);
cpu.regDX = cpu.getWord(addrNew + X86.TSS.TASK_DX); cpu.regDX = cpu.getWord(addrNew + X86.TSS.TASK_DX);
@ -581,14 +579,14 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
if (rpl <= dpl) { if (rpl <= dpl) {
cplPrev = this.cpl; cplPrev = this.cpl;
if (this.load(selCode, true) == null) { if (this.load(selCode, true) == null) {
if (DEBUG) cpu.assert(false); cpu.assert(false);
base = null; base = null;
break; break;
} }
cpu.regIP = limit; cpu.regIP = limit;
if (this.cpl < cplPrev) { if (this.cpl < cplPrev) {
if (fCall !== true) { if (fCall !== true) {
if (DEBUG) cpu.assert(false); cpu.assert(false);
base = null; base = null;
break; break;
} }
@ -612,7 +610,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
} }
return this.base; return this.base;
} }
if (DEBUG) cpu.assert(false); cpu.assert(false);
if (!fSuppress) X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true); if (!fSuppress) X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel, true);
base = null; base = null;
break; break;
@ -628,7 +626,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
if (dpl <= this.cpl) { if (dpl <= this.cpl) {
cplPrev = this.cpl; cplPrev = this.cpl;
if (this.load(selCode, true) == null) { if (this.load(selCode, true) == null) {
if (DEBUG) cpu.assert(false); cpu.assert(false);
base = null; base = null;
break; break;
} }
@ -657,7 +655,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
} }
return this.base; return this.base;
} }
if (DEBUG) cpu.assert(false); cpu.assert(false);
if (!fSuppress) X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel | X86.ERRCODE.EXT, true); if (!fSuppress) X86Help.opHelpFault.call(cpu, X86.EXCEPTION.GP_FAULT, sel | X86.ERRCODE.EXT, true);
base = null; base = null;
break; break;
@ -674,7 +672,7 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
base = null; base = null;
break; break;
} }
if (DEBUG) cpu.assert(!!selMasked); // a null CS selector should be caught by the final preceding check cpu.assert(!!selMasked); // a null CS selector should be caught by the final preceding check
} }
else if (this.id == X86Seg.ID.DATA) { else if (this.id == X86Seg.ID.DATA) {
if (selMasked) { if (selMasked) {
@ -726,8 +724,8 @@ X86Seg.prototype.loadDesc8 = function(addrDesc, sel, fSuppress)
* *
* This is used in unusual situations where the base must be set independently; normally, the base * This is used in unusual situations where the base must be set independently; normally, the base
* is set according to the selector provided to load(), but there are a few cases where setBase() is * is set according to the selector provided to load(), but there are a few cases where setBase() is
* required (eg, in resetRegs() where the 80286 wants the real-mode CS selector to be 0xF000 but the * required (eg, in resetRegs(), where the 80286 wants the real-mode CS selector to be 0xF000 but the
* CS base must be 0xFF0000, and possibly LOADALL). * CS base must be 0xFF0000).
* *
* @this {X86Seg} * @this {X86Seg}
* @param {number} addr * @param {number} addr

View file

@ -61,7 +61,7 @@ if (typeof module !== 'undefined') {
} }
/** /**
* Component(type, parms, constructor) * Component(type, parms, constructor, bitsMessage)
* *
* A Component object requires: * A Component object requires:
* *
@ -79,8 +79,9 @@ if (typeof module !== 'undefined') {
* @param {string} type * @param {string} type
* @param {Object} [parms] * @param {Object} [parms]
* @param {Object} [constructor] * @param {Object} [constructor]
* @param {number} [bitsMessage]
*/ */
function Component(type, parms, constructor) function Component(type, parms, constructor, bitsMessage)
{ {
this.type = type; this.type = type;
@ -125,6 +126,7 @@ function Component(type, parms, constructor)
this.clearError(); this.clearError();
this.bindings = {}; this.bindings = {};
this.dbg = null; // by default, no connection to a Debugger this.dbg = null; // by default, no connection to a Debugger
this.bitsMessage = bitsMessage || -1;
Component.add(this); Component.add(this);
} }
@ -729,7 +731,7 @@ Component.prototype = {
* $('h') * $('h')
* ... * ...
* *
* If you have no desire to stop on assertions, then yes, consider this a giant no-op. * If you have no desire to stop on assertions, consider this a no-op.
*/ */
try { try {
throw new Error(s); throw new Error(s);
@ -929,6 +931,63 @@ Component.prototype = {
powerDown: function(fSave, fShutdown) { powerDown: function(fSave, fShutdown) {
if (fShutdown) this.bitField.fPowered = false; if (fShutdown) this.bitField.fPowered = false;
return true; return true;
},
/**
* messageEnabled(bitsMessage, fOnly)
*
* @this {Component}
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
* @return {boolean} true if all specified message enabled, false if not
*/
messageEnabled: function(bitsMessage) {
if (DEBUGGER && this.dbg) {
if (this === this.dbg) {
bitsMessage = bitsMessage || 0;
} else {
if (!bitsMessage) {
bitsMessage = this.bitsMessage;
}
}
var bitsEnabled = this.dbg.bitsMessage & bitsMessage;
return (bitsEnabled === bitsMessage || !!(bitsEnabled & this.dbg.bitsWarning));
}
return false;
},
/**
* messageDebugger(sMessage, bitsMessage, fAddress)
*
* @this {Component}
* @param {string} sMessage is any caller-defined message string
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
* @param {boolean} [fAddress] is true to display the current address
* @return {boolean} true if Debugger available, false if not
*/
messageDebugger: function(sMessage, bitsMessage, fAddress) {
if (DEBUGGER && this.dbg) {
if (bitsMessage == null || this.messageEnabled(bitsMessage)) {
this.dbg.message(sMessage, fAddress);
}
return true;
}
return false;
},
/**
* messagePort(port, bOut, addrFrom, name, bIn, bitsMessage)
*
* This is an internal version of the Debugger's messagePort() function, for convenience.
*
* @this {Component}
* @param {number} port
* @param {number|null} bOut if an output operation
* @param {number|null} [addrFrom]
* @param {string|null} [name] of the port, if any
* @param {number} [bIn] is the input value, if known, on an input operation
* @param {number} [bitsMessage] is one or more Debugger MESSAGE_* category flag(s)
*/
messagePort: function(port, bOut, addrFrom, name, bIn, bitsMessage) {
if (DEBUGGER && this.dbg) {
this.dbg.messageIO(this, port, bOut, addrFrom, name, bIn, bitsMessage || this.bitsMessage);
}
} }
}; };

View file

@ -284,7 +284,7 @@ function embedMachine(sName, sVersion, idElement, sXMLFile, sXSLFile, sStateFile
var doneMachine = function() { var doneMachine = function() {
Component.assert(cMachines > 0); Component.assert(cMachines > 0);
if (--cMachines == 0) { if (!--cMachines) {
if (fAsync) web.enablePageEvents(true); if (fAsync) web.enablePageEvents(true);
} }
}; };

View file

@ -389,9 +389,9 @@ web.promptUser = function(sPrompt, sDefault)
* *
* true if localStorage support exists, is enabled, and works; "falsey" otherwise * true if localStorage support exists, is enabled, and works; "falsey" otherwise
* *
* @type {boolean|undefined} * @type {boolean|null}
*/ */
web.fLocalStorage; web.fLocalStorage = null;
/** /**
* hasLocalStorage * hasLocalStorage
@ -401,7 +401,7 @@ web.fLocalStorage;
* @return {boolean} * @return {boolean}
*/ */
web.hasLocalStorage = function() { web.hasLocalStorage = function() {
if (web.fLocalStorage === undefined) { if (web.fLocalStorage == null) {
var f; var f;
var sTest = 'PCjs.localStorage'; var sTest = 'PCjs.localStorage';
try { try {