diff --git a/modules/pcjs/lib/debugger.js b/modules/pcjs/lib/debugger.js index 3673e5563..2df6a1069 100644 --- a/modules/pcjs/lib/debugger.js +++ b/modules/pcjs/lib/debugger.js @@ -166,6 +166,21 @@ function Debugger(parmsDbg) */ this.aSymbolTable = []; + /* + * aVariables is an Object with properties that grows as setVariable() assigns more variables; + * each property corresponds to one variable, where the property name is the variable name (ie, + * a string beginning with a letter or underscore, followed by zero or more additional letters, + * digits, or underscores) and the property value is the variable's numeric value. See doLet() + * and setVariable() for details. + * + * Note that parseValue(), through its reliance on str.parseInt(), assumes a default base of 16 + * if no base is explicitly indicated (eg, a trailing decimal period), and if you define variable + * names containing exclusively hex alpha characters (a-f), those variables will take precedence + * over the corresponding hex values. In other words, if you define variables "a" and "b", you + * will no longer be able to simply type "a" or "b" to specify the numeric values 10 or 11. + */ + this.aVariables = {}; + /* * clearBreakpoints() initializes the breakpoints lists: aBreakExec is a list of addresses * to halt on whenever attempting to execute an instruction at the corresponding address, @@ -269,7 +284,10 @@ if (DEBUGGER) { 't [#]': "step instruction(s)", 'u [#]': "unassemble", 'x': "execution options", - 'reset': "reset computer", + 'if': "eval expression", + 'let': "assign expression", + 'print': "print expression", + 'reset': "reset machine", 'ver': "display version" }; @@ -2244,144 +2262,204 @@ if (DEBUGGER) { }; /** - * getRegValue(iReg) + * getRegString(iReg) * * @this {Debugger} * @param {number} iReg * @return {string} */ + Debugger.prototype.getRegString = function(iReg) { + var cch = 0; + var n = this.getRegValue(iReg); + if (n !== undefined) { + switch(iReg) { + case Debugger.REG_AL: + case Debugger.REG_CL: + case Debugger.REG_DL: + case Debugger.REG_BL: + case Debugger.REG_AH: + case Debugger.REG_CH: + case Debugger.REG_DH: + case Debugger.REG_BH: + cch = 2; + break; + case Debugger.REG_AX: + case Debugger.REG_CX: + case Debugger.REG_DX: + case Debugger.REG_BX: + case Debugger.REG_SP: + case Debugger.REG_BP: + case Debugger.REG_SI: + case Debugger.REG_DI: + case Debugger.REG_IP: + case Debugger.REG_SEG + Debugger.REG_ES: + case Debugger.REG_SEG + Debugger.REG_CS: + case Debugger.REG_SEG + Debugger.REG_SS: + case Debugger.REG_SEG + Debugger.REG_DS: + case Debugger.REG_SEG + Debugger.REG_FS: + case Debugger.REG_SEG + Debugger.REG_GS: + cch = 4; + break; + case Debugger.REG_EAX: + case Debugger.REG_ECX: + case Debugger.REG_EDX: + case Debugger.REG_EBX: + case Debugger.REG_ESP: + case Debugger.REG_EBP: + case Debugger.REG_ESI: + case Debugger.REG_EDI: + case Debugger.REG_CR0: + case Debugger.REG_CR1: + case Debugger.REG_CR2: + case Debugger.REG_CR3: + case Debugger.REG_EIP: + cch = 8; + break; + case Debugger.REG_PS: + cch = this.cchReg; + break; + } + } + return cch? str.toHex(n, cch) : "??"; + }; + + /** + * getRegValue(iReg) + * + * @this {Debugger} + * @param {number} iReg + * @return {number|undefined} + */ Debugger.prototype.getRegValue = function(iReg) { - var s = "??"; + var n; if (iReg >= 0) { - var n, cch; var cpu = this.cpu; switch(iReg) { case Debugger.REG_AL: - n = cpu.regEAX; cch = 2; + n = cpu.regEAX; break; case Debugger.REG_CL: - n = cpu.regECX; cch = 2; + n = cpu.regECX; break; case Debugger.REG_DL: - n = cpu.regEDX; cch = 2; + n = cpu.regEDX; break; case Debugger.REG_BL: - n = cpu.regEBX; cch = 2; + n = cpu.regEBX; break; case Debugger.REG_AH: - n = cpu.regEAX >> 8; cch = 2; + n = cpu.regEAX >> 8; break; case Debugger.REG_CH: - n = cpu.regECX >> 8; cch = 2; + n = cpu.regECX >> 8; break; case Debugger.REG_DH: - n = cpu.regEDX >> 8; cch = 2; + n = cpu.regEDX >> 8; break; case Debugger.REG_BH: - n = cpu.regEBX >> 8; cch = 2; + n = cpu.regEBX >> 8; break; case Debugger.REG_AX: - n = cpu.regEAX; cch = 4; + n = cpu.regEAX; break; case Debugger.REG_CX: - n = cpu.regECX; cch = 4; + n = cpu.regECX; break; case Debugger.REG_DX: - n = cpu.regEDX; cch = 4; + n = cpu.regEDX; break; case Debugger.REG_BX: - n = cpu.regEBX; cch = 4; + n = cpu.regEBX; break; case Debugger.REG_SP: - n = cpu.getSP(); cch = 4; + n = cpu.getSP(); break; case Debugger.REG_BP: - n = cpu.regEBP; cch = 4; + n = cpu.regEBP; break; case Debugger.REG_SI: - n = cpu.regESI; cch = 4; + n = cpu.regESI; break; case Debugger.REG_DI: - n = cpu.regEDI; cch = 4; + n = cpu.regEDI; break; case Debugger.REG_IP: - n = cpu.getIP(); cch = 4; + n = cpu.getIP(); break; case Debugger.REG_PS: - n = cpu.getPS(); cch = this.cchReg; + n = cpu.getPS(); break; case Debugger.REG_SEG + Debugger.REG_ES: - n = cpu.getES(); cch = 4; + n = cpu.getES(); break; case Debugger.REG_SEG + Debugger.REG_CS: - n = cpu.getCS(); cch = 4; + n = cpu.getCS(); break; case Debugger.REG_SEG + Debugger.REG_SS: - n = cpu.getSS(); cch = 4; + n = cpu.getSS(); break; case Debugger.REG_SEG + Debugger.REG_DS: - n = cpu.getDS(); cch = 4; + n = cpu.getDS(); break; - } - if (!cch) { + default: if (this.cpu.model == X86.MODEL_80286) { if (iReg == Debugger.REG_CR0) { - n = cpu.regCR0; cch = 4; + n = cpu.regCR0; } } else if (I386 && this.cpu.model >= X86.MODEL_80386) { switch(iReg) { case Debugger.REG_EAX: - n = cpu.regEAX; cch = 8; + n = cpu.regEAX; break; case Debugger.REG_ECX: - n = cpu.regECX; cch = 8; + n = cpu.regECX; break; case Debugger.REG_EDX: - n = cpu.regEDX; cch = 8; + n = cpu.regEDX; break; case Debugger.REG_EBX: - n = cpu.regEBX; cch = 8; + n = cpu.regEBX; break; case Debugger.REG_ESP: - n = cpu.getSP(); cch = 8; + n = cpu.getSP(); break; case Debugger.REG_EBP: - n = cpu.regEBP; cch = 8; + n = cpu.regEBP; break; case Debugger.REG_ESI: - n = cpu.regESI; cch = 8; + n = cpu.regESI; break; case Debugger.REG_EDI: - n = cpu.regEDI; cch = 8; + n = cpu.regEDI; break; case Debugger.REG_CR0: - n = cpu.regCR0; cch = 8; + n = cpu.regCR0; break; case Debugger.REG_CR1: - n = cpu.regCR1; cch = 8; + n = cpu.regCR1; break; case Debugger.REG_CR2: - n = cpu.regCR2; cch = 8; + n = cpu.regCR2; break; case Debugger.REG_CR3: - n = cpu.regCR3; cch = 8; + n = cpu.regCR3; break; case Debugger.REG_SEG + Debugger.REG_FS: - n = cpu.getFS(); cch = 4; + n = cpu.getFS(); break; case Debugger.REG_SEG + Debugger.REG_GS: - n = cpu.getGS(); cch = 4; + n = cpu.getGS(); break; case Debugger.REG_EIP: - n = cpu.getIP(); cch = 8; + n = cpu.getIP(); break; } } + break; } - if (cch) s = str.toHex(n, cch); } - return s; + return n; }; /** @@ -2400,7 +2478,7 @@ if (DEBUGGER) { while ((i = s.indexOf('%', i)) >= 0) { var iReg = this.getRegIndex(s, i + 1); if (iReg >= 0) { - s = s.substr(0, i) + this.getRegValue(iReg) + s.substr(i + 1 + Debugger.REGS[iReg].length); + s = s.substr(0, i) + this.getRegString(iReg) + s.substr(i + 1 + Debugger.REGS[iReg].length); } i++; } @@ -2485,28 +2563,34 @@ if (DEBUGGER) { }; /** - * messageInt(nInt, addr) + * messageInt(nInt, addr, fForce) * * @this {Debugger} * @param {number} nInt * @param {number} addr (LIP after the "INT n" instruction has been fetched but not dispatched) + * @param {boolean} [fForce] (true if the message should be forced) * @return {boolean} true if message generated (which in turn triggers addIntReturn() inside checkIntNotify()), false if not */ - Debugger.prototype.messageInt = function(nInt, addr) + Debugger.prototype.messageInt = function(nInt, addr, fForce) { - var AH = this.cpu.regEAX >> 8; - var fMessage = this.messageEnabled(Messages.CPU) && nInt != 0x28 && nInt != 0x2A; - var nCategory = Debugger.INT_MESSAGES[nInt]; - if (nCategory) { - if (this.messageEnabled(nCategory)) { - fMessage = true; - } else { - fMessage = (nCategory == Messages.FDC && this.messageEnabled(nCategory = Messages.HDC)); + var fMessage, AH, DL; + if (fForce) { + fMessage = true; + } else { + fMessage = this.messageEnabled(Messages.CPU) && nInt != Interrupts.DOS_IDLE.VECTOR /* 0x28 */ && nInt != Interrupts.DOS_NETBIOS.VECTOR /* 0x2A */; + var nCategory = Debugger.INT_MESSAGES[nInt]; + if (nCategory) { + if (this.messageEnabled(nCategory)) { + fMessage = true; + } else { + fMessage = (nCategory == Messages.FDC && this.messageEnabled(nCategory = Messages.HDC)); + } } } if (fMessage) { - var DL = this.cpu.regEDX & 0xff; - if (nInt == Interrupts.DOS.VECTOR && AH == 0x0b || + AH = this.cpu.regEAX >> 8; + DL = this.cpu.regEDX & 0xff; + if (nInt == Interrupts.DOS.VECTOR /* 0x21 */ && AH == 0x0b || nCategory == Messages.FDC && DL >= 0x80 || nCategory == Messages.HDC && DL < 0x80) { fMessage = false; } @@ -3838,13 +3922,13 @@ if (DEBUGGER) { }; /** - * getFlagStr(sFlag) + * getFlagOutput(sFlag) * * @this {Debugger} * @param {string} sFlag * @return {string} value of flag */ - Debugger.prototype.getFlagStr = function(sFlag) + Debugger.prototype.getFlagOutput = function(sFlag) { var b; switch (sFlag) { @@ -3895,35 +3979,35 @@ if (DEBUGGER) { }; /** - * getRegString(iReg) + * getRegOutput(iReg) * * @this {Debugger} * @param {number} iReg * @return {string} */ - Debugger.prototype.getRegString = function(iReg) + Debugger.prototype.getRegOutput = function(iReg) { if (iReg >= Debugger.REG_AX && iReg <= Debugger.REG_DI && this.cchReg > 4) iReg += Debugger.REG_EAX - Debugger.REG_AX; var sReg = Debugger.REGS[iReg]; if (iReg == Debugger.REG_CR0 && this.cpu.model == X86.MODEL_80286) sReg = "MS"; - return sReg + '=' + this.getRegValue(iReg) + ' '; + return sReg + '=' + this.getRegString(iReg) + ' '; }; /** - * getSegString(seg, fProt) + * getSegOutput(seg, fProt) * * @this {Debugger} * @param {X86Seg} seg * @param {boolean} [fProt] * @return {string} */ - Debugger.prototype.getSegString = function(seg, fProt) + Debugger.prototype.getSegOutput = function(seg, fProt) { return seg.sName + '=' + str.toHex(seg.sel, 4) + (fProt? '[' + str.toHex(seg.base, this.cchAddr) + ',' + this.getLimitString(seg.limit) + ']' : ""); }; /** - * getDTRString(sName, sel, addr, addrLimit) + * getDTROutput(sName, sel, addr, addrLimit) * * @this {Debugger} * @param {string} sName @@ -3932,7 +4016,7 @@ if (DEBUGGER) { * @param {number} addrLimit * @return {string} */ - Debugger.prototype.getDTRString = function(sName, sel, addr, addrLimit) + Debugger.prototype.getDTROutput = function(sName, sel, addr, addrLimit) { return sName + '=' + (sel != null? str.toHex(sel, 4) : "") + '[' + str.toHex(addr, this.cchAddr) + ',' + str.toHex(addrLimit - addr, 4) + ']'; }; @@ -3985,17 +4069,17 @@ if (DEBUGGER) { { var s; if (fProt === undefined) fProt = this.getProtMode(); - s = this.getRegString(Debugger.REG_AX) + - this.getRegString(Debugger.REG_BX) + - this.getRegString(Debugger.REG_CX) + - this.getRegString(Debugger.REG_DX) + (this.cchReg > 4? '\n' : '') + - this.getRegString(Debugger.REG_SP) + - this.getRegString(Debugger.REG_BP) + - this.getRegString(Debugger.REG_SI) + - this.getRegString(Debugger.REG_DI) + '\n' + - this.getSegString(this.cpu.segSS, fProt) + ' ' + - this.getSegString(this.cpu.segDS, fProt) + ' ' + - this.getSegString(this.cpu.segES, fProt) + ' '; + s = this.getRegOutput(Debugger.REG_AX) + + this.getRegOutput(Debugger.REG_BX) + + this.getRegOutput(Debugger.REG_CX) + + this.getRegOutput(Debugger.REG_DX) + (this.cchReg > 4? '\n' : '') + + this.getRegOutput(Debugger.REG_SP) + + this.getRegOutput(Debugger.REG_BP) + + this.getRegOutput(Debugger.REG_SI) + + this.getRegOutput(Debugger.REG_DI) + '\n' + + this.getSegOutput(this.cpu.segSS, fProt) + ' ' + + this.getSegOutput(this.cpu.segDS, fProt) + ' ' + + this.getSegOutput(this.cpu.segES, fProt) + ' '; if (fProt) { var sTR = "TR=" + str.toHex(this.cpu.segTSS.sel, 4); var sA20 = "A20=" + (this.bus.getA20()? "ON " : "OFF "); @@ -4003,29 +4087,29 @@ if (DEBUGGER) { sTR = '\n' + sTR; s += sA20; sA20 = ''; } - s += '\n' + this.getSegString(this.cpu.segCS, fProt) + ' '; + s += '\n' + this.getSegOutput(this.cpu.segCS, fProt) + ' '; if (I386 && this.cpu.model >= X86.MODEL_80386) { sA20 += '\n'; - s += this.getSegString(this.cpu.segFS, fProt) + ' ' + - this.getSegString(this.cpu.segGS, fProt) + '\n'; + s += this.getSegOutput(this.cpu.segFS, fProt) + ' ' + + this.getSegOutput(this.cpu.segGS, fProt) + '\n'; } - s += this.getDTRString("LD", this.cpu.segLDT.sel, this.cpu.segLDT.base, this.cpu.segLDT.base + this.cpu.segLDT.limit) + ' ' + - this.getDTRString("GD", null, this.cpu.addrGDT, this.cpu.addrGDTLimit) + ' ' + - this.getDTRString("ID", null, this.cpu.addrIDT, this.cpu.addrIDTLimit) + ' '; + s += this.getDTROutput("LD", this.cpu.segLDT.sel, this.cpu.segLDT.base, this.cpu.segLDT.base + this.cpu.segLDT.limit) + ' ' + + this.getDTROutput("GD", null, this.cpu.addrGDT, this.cpu.addrGDTLimit) + ' ' + + this.getDTROutput("ID", null, this.cpu.addrIDT, this.cpu.addrIDTLimit) + ' '; s += sTR + ' ' + sA20; - s += this.getRegString(Debugger.REG_CR0); + s += this.getRegOutput(Debugger.REG_CR0); if (I386 && this.cpu.model >= X86.MODEL_80386) { - s += this.getRegString(Debugger.REG_CR2) + this.getRegString(Debugger.REG_CR3); + s += this.getRegOutput(Debugger.REG_CR2) + this.getRegOutput(Debugger.REG_CR3); } } else { if (I386 && this.cpu.model >= X86.MODEL_80386) { - s += this.getSegString(this.cpu.segFS, fProt) + ' ' + - this.getSegString(this.cpu.segGS, fProt) + ' '; + s += this.getSegOutput(this.cpu.segFS, fProt) + ' ' + + this.getSegOutput(this.cpu.segGS, fProt) + ' '; } } - s += this.getRegString(Debugger.REG_PS) + - this.getFlagStr('V') + this.getFlagStr('D') + this.getFlagStr('I') + this.getFlagStr('T') + - this.getFlagStr('S') + this.getFlagStr('Z') + this.getFlagStr('A') + this.getFlagStr('P') + this.getFlagStr('C'); + s += this.getRegOutput(Debugger.REG_PS) + + this.getFlagOutput('V') + this.getFlagOutput('D') + this.getFlagOutput('I') + this.getFlagOutput('T') + + this.getFlagOutput('S') + this.getFlagOutput('Z') + this.getFlagOutput('A') + this.getFlagOutput('P') + this.getFlagOutput('C'); return s; }; @@ -4282,7 +4366,7 @@ if (DEBUGGER) { } if (!fError) { value = aVals.pop(); - if (fPrint) this.println(sExpOrig + '=' + str.toHex(value) + "h (" + value + ". " + str.toBinBytes(value) + ')'); + if (fPrint) this.printValue(null, value); } else { if (fPrint) this.println("error parsing '" + sExpOrig + "' at character " + (sExpOrig.length - sExp.length)); } @@ -4302,8 +4386,14 @@ if (DEBUGGER) { var value; if (sValue !== undefined) { var iReg = this.getRegIndex(sValue); - if (iReg >= 0) sValue = this.getRegValue(iReg); - value = str.parseInt(sValue); + if (iReg >= 0) { + value = this.getRegValue(iReg); + } else { + value = this.getVariable(sValue); + if (value === undefined) { + value = str.parseInt(sValue); + } + } if (value === undefined) this.println("invalid " + (sName? sName : "value") + ": " + sValue); } else { this.println("missing " + (sName || "value")); @@ -4311,6 +4401,82 @@ if (DEBUGGER) { return value; }; + /** + * printValue(sVar, value) + * + * @this {Debugger} + * @param {string|null} sVar + * @param {number|undefined} value + * @return {boolean} true if value defined, false if not + */ + Debugger.prototype.printValue = function(sVar, value) + { + var sValue; + var fDefined = false; + if (value !== undefined) { + fDefined = true; + sValue = str.toHexLong(value) + " (" + value + ')'; /* + str.toBinBytes(value) */ + } + sVar = (sVar != null? (sVar + ": ") : ""); + this.println(sVar + sValue); + return fDefined; + }; + + /** + * printVariable(sVar) + * + * @this {Debugger} + * @param {string} [sVar] + * @return {boolean} true if all value(s) defined, false if not + */ + Debugger.prototype.printVariable = function(sVar) + { + if (sVar) { + return this.printValue(sVar, this.aVariables[sVar]); + } + var cVariables = 0; + for (sVar in this.aVariables) { + this.printValue(sVar, this.aVariables[sVar]); + cVariables++; + } + return cVariables > 0; + }; + + /** + * delVariable(sVar) + * + * @this {Debugger} + * @param {string} sVar + */ + Debugger.prototype.delVariable = function(sVar) + { + delete this.aVariables[sVar]; + }; + + /** + * getVariable(sVar) + * + * @this {Debugger} + * @param {string} sVar + * @return {number|undefined} + */ + Debugger.prototype.getVariable = function(sVar) + { + return this.aVariables[sVar]; + }; + + /** + * setVariable(sVar, value) + * + * @this {Debugger} + * @param {string} sVar + * @param {number} value + */ + Debugger.prototype.setVariable = function(sVar, value) + { + this.aVariables[sVar] = value; + }; + /** * addSymbols(addr, size, aSymbols) * @@ -4801,7 +4967,7 @@ if (DEBUGGER) { if (BACKTRACK) { this.println("\tdi [a] dump backtrack info at address a"); } - this.println("\tds [#] dump selector # descriptor info"); + this.println("\tds [#] dump descriptor info for selector #"); if (sDumpers.length) this.println("dump extensions:\n\t" + sDumpers); return; } @@ -4812,7 +4978,7 @@ if (DEBUGGER) { var cLines = 0; if (sLen) { if (sLen.charAt(0) == 'l') sLen = sLen.substr(1); - cLines = +sLen; + cLines = str.parseInt(sLen, 10); } if (sCmd == 'd') { sCmd = this.sCmdDumpPrev || "db"; @@ -4827,6 +4993,16 @@ if (DEBUGGER) { this.dumpHistory(sAddr, cLines); return; } + if (sCmd == "dos") { + /* + * The "dos" command is an undocumented command that's useful any time we're inside an internal + * DOS dispatch function where the registers are substantially the same as the corresponding INT 0x21; + * "m int on; m dos on" produces the same output, but only when an actual INT 0x21 instruction is used. + * Issuing this command at any other time should also be OK, but the results will be meaningless. + */ + this.messageInt(Interrupts.DOS.VECTOR, this.cpu.regLIP, true); + return; + } if (sCmd == "ds") { // transform a "ds" command into a "d desc" command sCmd = 'd'; sLen = sAddr; @@ -5090,6 +5266,46 @@ if (DEBUGGER) { } }; + /** + * doLet(sCmd) + * + * The command must be of the form "{variable} = [{expression}]", where expression may contain constants, + * operators, registers, symbols, other variables, or nothing at all; in the latter case, the variable, if + * any, is deleted. + * + * Other supported shorthand: "let" with no parameters prints the values of all variables, and "let {variable}" + * prints the value of the specified variable. + * + * @this {Debugger} + * @param {string} sCmd + * @return {boolean} true if valid "let" assignment, false if not + */ + Debugger.prototype.doLet = function(sCmd) + { + var a = sCmd.match(/^\s*([A-Z_]?[A-Z0-9_]*)\s*(=?)\s*(.*)$/i); + if (a) { + if (!a[1]) { + if (!this.printVariable()) this.println("no variables"); + return true; // it's not considered an error to print an empty list of variables + } + if (!a[2]) { + return this.printVariable(a[1]); + } + if (!a[3]) { + this.delVariable(a[1]); + return true; // it's not considered an error to delete a variable that didn't exist + } + var v = this.parseExpression(a[3]); + if (v !== undefined) { + this.setVariable(a[1], v); + return true; + } + return false; + } + this.println("invalid assignment:" + sCmd); + return false; + }; + /** * doList(sSymbol) * @@ -5686,6 +5902,9 @@ if (DEBUGGER) { /** * doPrint(sCmd) * + * If the string to print is a quoted string, then we run it through replaceRegs(), so that + * you can take advantage of all the special replacement options used for software interrupt logging. + * * @this {Debugger} * @param {string} sCmd */ @@ -6164,6 +6383,12 @@ if (DEBUGGER) { this.doStackTrace(); break; case 'l': + if (asArgs[0] == "let") { + if (!this.doLet(sCmd.substr(3))) { + result = false; + } + break; + } this.shiftArgs(asArgs); this.doLoad(asArgs); break; @@ -6174,6 +6399,10 @@ if (DEBUGGER) { this.doOutput(asArgs[1], asArgs[2]); break; case 'p': + if (asArgs[0] == "print") { + this.doPrint(sCmd.substr(5)); + break; + } this.doProcStep(asArgs[0]); break; case 'r': diff --git a/modules/pcjs/lib/defines.js b/modules/pcjs/lib/defines.js index b2d137a01..4e7a2bad9 100644 --- a/modules/pcjs/lib/defines.js +++ b/modules/pcjs/lib/defines.js @@ -90,7 +90,7 @@ var TYPEDARRAYS = (typeof ArrayBuffer !== 'undefined'); * we'll have to rethink that choice OR provide a Debugger command that dynamically enables/disables as much of * the backtracking support as possible. */ -var BACKTRACK = false; // !COMPILED; +var BACKTRACK = !COMPILED; /** * @define {boolean} diff --git a/modules/pcjs/lib/interrupts.js b/modules/pcjs/lib/interrupts.js index 6cbeb2f7f..1361189c3 100644 --- a/modules/pcjs/lib/interrupts.js +++ b/modules/pcjs/lib/interrupts.js @@ -70,6 +70,12 @@ var Interrupts = { DOS: { VECTOR: 0x21 }, + DOS_IDLE: { + VECTOR: 0x28 + }, + DOS_NETBIOS: { + VECTOR: 0x2A + }, MOUSE: { VECTOR: 0x33 } diff --git a/modules/pcjs/lib/x86func.js b/modules/pcjs/lib/x86func.js index 43237f3b4..fe5100e2d 100644 --- a/modules/pcjs/lib/x86func.js +++ b/modules/pcjs/lib/x86func.js @@ -3846,7 +3846,7 @@ X86.fnFaultMessage = function(nFault, nError, fHalt) fHalt = false; } } else { - if (nFault == X86.EXCEPTION.SS_FAULT || nFault == X86.EXCEPTION.GP_FAULT && this.model == X86.MODEL_80386 /* || nFault == X86.EXCEPTION.NP_FAULT && bOpcode == 0x8E */) { + if (nFault == X86.EXCEPTION.SS_FAULT || nFault == X86.EXCEPTION.PG_FAULT || nFault == X86.EXCEPTION.GP_FAULT && this.model == X86.MODEL_80386 /* || nFault == X86.EXCEPTION.NP_FAULT && bOpcode == 0x8E */) { fHalt = true; } }