Debugger improvements for DOS debugging
This commit is contained in:
parent
4e69520a5b
commit
ebf6933536
3 changed files with 334 additions and 293 deletions
|
|
@ -4087,9 +4087,9 @@ ChipSet.prototype.set8042OutPort = function(b)
|
|||
/**
|
||||
* notifyKbdData(fAvail)
|
||||
*
|
||||
* Previously, the Keyboard would simply call setIRR() when it had some data for the keyboard controller.
|
||||
* Now the interface is a little more nuanced, giving the ChipSet/8042 the opportunity to decide when to
|
||||
* raise IRQ.KBD.
|
||||
* In the old days of PCjs, the Keyboard component would simply call setIRR() when it had some data for the
|
||||
* keyboard controller. However, that was completely inappropriate. The sole responsibility of the Keyboard
|
||||
* is to emulate an actual keyboard and notify us whenever it has some data; it doesn't mess with IRQ lines.
|
||||
*
|
||||
* If there's an 8042, we check (this.b8042CmdData & ChipSet.KBC.DATA.CMD.NO_CLOCK); if NO_CLOCK is clear,
|
||||
* we can raise the IRQ immediately. Well, not quite immediately....
|
||||
|
|
@ -4166,7 +4166,7 @@ ChipSet.prototype.notifyKbdData = function(fAvail)
|
|||
{
|
||||
if (this.model < ChipSet.MODEL_5170) {
|
||||
/*
|
||||
* TODO: Should we be checking bPPI for PPI_B.CLK_KBD on these older machines, before called setIRR()?
|
||||
* TODO: Should we be checking bPPI for PPI_B.CLK_KBD on these older machines, before calling setIRR()?
|
||||
*/
|
||||
this.setIRR(ChipSet.IRQ.KBD, 4);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1171,7 +1171,9 @@ if (DEBUGGER) {
|
|||
}
|
||||
}
|
||||
|
||||
this.cpu.addIntNotify(Debugger.INT_DOS, this, this.intDOSCall);
|
||||
this.messageDump(Debugger.MESSAGE_DOS, function onDumpDOS(s) {
|
||||
dbg.dumpDOS(s);
|
||||
});
|
||||
|
||||
this.setReady();
|
||||
|
||||
|
|
@ -1281,6 +1283,56 @@ if (DEBUGGER) {
|
|||
if (this.controlDebug) this.controlDebug.focus();
|
||||
};
|
||||
|
||||
/**
|
||||
* dumpDOS(s)
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {string} [s]
|
||||
*/
|
||||
Debugger.prototype.dumpDOS = function(s)
|
||||
{
|
||||
if (!s) return;
|
||||
|
||||
this.println("dumpDOS(" + s + ")");
|
||||
|
||||
/*
|
||||
* If s is provided and str.parseInt(s) succeeds, then we assume it represents a starting
|
||||
* MCB (Memory Control Block) segment, and we dump the corresponding blocks.
|
||||
*/
|
||||
var seg = str.parseInt(s);
|
||||
while (seg) {
|
||||
var aAddr = this.newAddr(0, seg);
|
||||
var bSig = this.getByte(aAddr, 1);
|
||||
var wPID = this.getWord(aAddr, 2);
|
||||
var wParas = this.getWord(aAddr, 5);
|
||||
if (bSig != 0x4D && bSig != 0x5A) break;
|
||||
this.println(str.toHexAddr(0, seg) + ": '" + String.fromCharCode(bSig) + "' PID=" + str.toHexWord(wPID) + " LEN=" + str.toHexWord(wParas) + ' "' + this.dumpSZ(aAddr, 8) + '"');
|
||||
seg += 1 + wParas;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* dumpSZ(aAddr, cchMax)
|
||||
*
|
||||
* Dump helper for zero-terminated strings.
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {Array} aAddr
|
||||
* @param {number} [cchMax]
|
||||
* @return {string} (and aAddr advanced past the terminating zero)
|
||||
*/
|
||||
Debugger.prototype.dumpSZ = function(aAddr, cchMax)
|
||||
{
|
||||
var sChars = "";
|
||||
cchMax = cchMax || 256;
|
||||
while (sChars.length < cchMax) {
|
||||
var b = this.getByte(aAddr, 1);
|
||||
if (!b) break;
|
||||
sChars += (b >= 32 && b < 128? String.fromCharCode(b) : ".");
|
||||
}
|
||||
return sChars;
|
||||
};
|
||||
|
||||
/**
|
||||
* initMessages(sEnable)
|
||||
*
|
||||
|
|
@ -1373,14 +1425,21 @@ if (DEBUGGER) {
|
|||
* @this {Debugger}
|
||||
* @param {number} nInt
|
||||
* @param {number} addr
|
||||
* @return {boolean} true if message generated, false if not
|
||||
*/
|
||||
Debugger.prototype.messageInt = function(nInt, addr)
|
||||
{
|
||||
/*
|
||||
* TODO: Filtering of interrupt numbers below should be user-definable; this is very quick-and-dirty.
|
||||
*/
|
||||
if (nInt != 0x10 && nInt != 0x15 && nInt != 0x16 && nInt != 0x1A && nInt != 0x1C) {
|
||||
var fMessage = false;
|
||||
var AH = this.cpu.regAX >> 8;
|
||||
if (this.messageEnabled(Debugger.MESSAGE_DOS)) {
|
||||
fMessage = (nInt == 0x21 && AH != 0x0b);
|
||||
} else {
|
||||
fMessage = (nInt != 0x10 && nInt != 0x15 && nInt != 0x16 && nInt != 0x1A && nInt != 0x1C);
|
||||
}
|
||||
if (fMessage) {
|
||||
var aFuncs = Debugger.INT_FUNCS[nInt];
|
||||
var sFunc = (aFuncs && aFuncs[AH]) || "";
|
||||
if (sFunc) {
|
||||
|
|
@ -1389,6 +1448,7 @@ if (DEBUGGER) {
|
|||
}
|
||||
this.message("INT 0x" + str.toHexByte(nInt) + ": AH=" + str.toHexByte(AH) + " at " + str.toHexAddr(addr - this.cpu.segCS.base, this.cpu.segCS.sel) + sFunc);
|
||||
}
|
||||
return fMessage;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1402,12 +1462,7 @@ if (DEBUGGER) {
|
|||
*/
|
||||
Debugger.prototype.messageIntReturn = function(nInt, nLevel, nCycles, sResult)
|
||||
{
|
||||
/*
|
||||
* TODO: Filtering of interrupt numbers below should be user-definable; this is very quick-and-dirty.
|
||||
*/
|
||||
if (nInt < 0x20 && nInt != 0x10 && nInt != 0x15 && nInt != 0x16 && nInt != 0x1A && nInt != 0x1C) {
|
||||
this.message("INT 0x" + str.toHexByte(nInt) + "(" + nLevel + "): C=" + (this.cpu.getCF()? 1 : 0) + (sResult || "") + " (cycles=" + nCycles + ")");
|
||||
}
|
||||
this.message("INT 0x" + str.toHexByte(nInt) + ": C=" + (this.cpu.getCF()? 1 : 0) + (sResult || "") + " (cycles=" + nCycles + (nLevel? ",level=" + (nLevel+1) : "") + ")");
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1538,19 +1593,6 @@ if (DEBUGGER) {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* intDOSCall(addr)
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {number} addr
|
||||
* @return {boolean} true to proceed with the INT 0x21 software interrupt, false to skip (but we NEVER skip)
|
||||
*/
|
||||
Debugger.prototype.intDOSCall = function(addr)
|
||||
{
|
||||
if (this.messageEnabled(Debugger.MESSAGE_DOS | Debugger.MESSAGE_INT)) this.messageInt(Debugger.INT_DOS, addr);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* init()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -924,11 +924,10 @@ X86CPU.prototype.checkIntNotify = function(nInt)
|
|||
}
|
||||
else if (DEBUGGER && this.aFlags.fDebugCheck) {
|
||||
/*
|
||||
* Enabling MESSAGE_INT messages is one of the criteria that's also included in fDebugCheck, so for maximum
|
||||
* speed, we check fDebugCheck first.
|
||||
* Enabling MESSAGE_INT messages is one of the criteria that's also included in fDebugCheck,
|
||||
* so for maximum speed, we check fDebugCheck first.
|
||||
*/
|
||||
if (this.dbg.messageEnabled(Debugger.MESSAGE_INT)) {
|
||||
this.dbg.messageInt(nInt, this.regEIP);
|
||||
if (this.dbg.messageEnabled(Debugger.MESSAGE_INT) && this.dbg.messageInt(nInt, this.regEIP)) {
|
||||
this.addIntReturn(this.regEIP, function(cpu, nCycles) {
|
||||
return function onIntReturn(nLevel) {
|
||||
cpu.dbg.messageIntReturn(nInt, nLevel, cpu.getCycles() - nCycles);
|
||||
|
|
|
|||
Loading…
Reference in a new issue