Skip to content
This repository has been archived by the owner on Dec 24, 2020. It is now read-only.

Commit

Permalink
v1.19.5 update (fixes a CALLF bug and a VGA ATC bug, and adds improve…
Browse files Browse the repository at this point in the history
…d WDEB386-style load notifications)
  • Loading branch information
jeffpar committed Sep 12, 2015
1 parent 039e961 commit 2122e48
Show file tree
Hide file tree
Showing 8 changed files with 1,349 additions and 1,267 deletions.
784 changes: 392 additions & 392 deletions docs/pcjs/demos/pc-dbg.js

Large diffs are not rendered by default.

466 changes: 233 additions & 233 deletions docs/pcjs/demos/pc.js

Large diffs are not rendered by default.

60 changes: 55 additions & 5 deletions modules/pcjs/lib/debugger.js
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,7 @@ if (DEBUGGER) {

if (Interrupts.WINDBG.ENABLED || Interrupts.WINDBGRM.ENABLED) {
this.fWinDbg = null;
this.cpu.addIntNotify(Interrupts.WINCB.VECTOR, this.intWindowsCallBack.bind(this));
this.cpu.addIntNotify(Interrupts.WINDBG.VECTOR, this.intWindowsDebugger.bind(this));
}
if (Interrupts.WINDBGRM.ENABLED) {
Expand Down Expand Up @@ -1336,13 +1337,13 @@ if (DEBUGGER) {
var len = this.getLong(dbgAddr, 4);
var dbgAddrDevice = this.newAddr(this.getLong(dbgAddr, 4), this.getShort(dbgAddr, 2));
var dbgAddrModule = this.newAddr(this.getLong(dbgAddr, 4), this.getShort(dbgAddr, 2));
sel = this.getShort(dbgAddr, 2) || sel;
// sel = this.getShort(dbgAddr, 2) || sel;
var sModule = this.getSZ(dbgAddrModule).toUpperCase();
var sDevice = this.getSZ(dbgAddrDevice).toUpperCase();
var sSection = (fCode? "_CODE" : "_DATA") + str.toHex(nSeg, 2);
if (fPrint) {
/*
* Mimic WDEB386 output
* Mimics WDEB386 output, except that WDEB386 only displays a linear address, omitting the selector.
*/
this.println(sModule + '!' + sDevice + "!undefined " + (fCode? "code" : "data") + '(' + str.toHex(nSeg, 4) + ")=" + str.toHex(sel, 4) + ':' + str.toHex(off) + " len " + str.toHex(len));
}
Expand All @@ -1351,6 +1352,55 @@ if (DEBUGGER) {
this.addSymbols(sel, off, len, aSymbols);
};

/**
* intWindowsCallBack()
*
* This intercepts calls to Windows callback addresses, which use INT 0x30 (aka Transfer Space Fault).
*
* We're only interested in one particular callback: the one specifying VW32_Int41Dispatch (0x002A002A)
* in EAX.
*
* At the time that INT 0x30 occurs, a far 32-bit call has been made, preceded by a near 32-bit call,
* preceded by a 32-bit push of the Windows Debugger function # that would normally be in EAX if this had
* been an actual INT 0x41.
*
* NOTE: Regardless whether we're "handling" INT 0x41 or merely "monitoring" INT 0x41, as far as THIS
* interrupt is concerned, we always let the system process it, because execution never continues at the
* instruction following an INT 0x30; in fact, execution doesn't even continue after the far 32-bit call
* (even though the kernel places a "RET 4" after that call). So, rather than recreate all that automatic
* address popping, we let the system do it for us, since it's designed to work whether a debugger (eg,
* WDEB386's Debug VXD) is installed or not.
*
* @this {Debugger}
* @param {number} addr
* @return {boolean} true to proceed with the INT 0x30 software interrupt
*/
Debugger.prototype.intWindowsCallBack = function(addr)
{
var cpu = this.cpu;

if (this.fWinDbg != null && cpu.regEAX == 0x002A002A) {

var DX = cpu.regEDX & 0xffff;
var SI = cpu.regESI & 0xffff;
var dbgAddr = this.newAddr(cpu.getSP() + 0x0C, cpu.getSS());
var EAX = this.getLong(dbgAddr);

switch(EAX) {
case Interrupts.WINDBG.LOAD_SEG32:
/*
* SI == segment type:
* 0x0 code selector
* 0x1 data selector
* DX:EBX -> D386_Device_Params structure (see addSectionInfo() for details)
*/
this.addSectionInfo(this.newAddr(cpu.regEBX, DX), !SI, this.fWinDbg);
break;
}
}
return true;
};

/**
* intWindowsDebugger()
*
Expand Down Expand Up @@ -1430,7 +1480,7 @@ if (DEBUGGER) {
break;

default:
if (this.fWinDbg) {
if (MAXDEBUG && this.fWinDbg) {
this.println("INT 0x41: " + str.toHexWord(AX));
}
break;
Expand Down Expand Up @@ -1561,7 +1611,7 @@ if (DEBUGGER) {
break;

default:
if (this.fWinDbgRM) {
if (MAXDEBUG && this.fWinDbgRM) {
this.println("INT 0x68: " + str.toHexByte(AH));
}
break;
Expand Down Expand Up @@ -1616,7 +1666,7 @@ if (DEBUGGER) {
{
var cpu = this.cpu;
var AL = cpu.regEAX & 0xff;
this.println("INT 0x68 callback: " + str.toHexByte(AL));
if (MAXDEBUG) this.println("INT 0x68 callback: " + str.toHexByte(AL));
if (AL == 5) {
cpu.regECX = cpu.regESI = 0; // our in-machine debugger footprint is zero
cpu.regEAX = (cpu.regEAX & ~0xff) | 0x01;
Expand Down
9 changes: 6 additions & 3 deletions modules/pcjs/lib/interrupts.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,23 +61,26 @@ var Interrupts = {
MOUSE: 0x33,
ALT_DISK: 0x40, // HDC BIOS saves original FDC BIOS vector here
ALT_VIDEO: 0x6D, // IBM VGA BIOS saves original video BIOS vector here
WINDBG: { // Windows Debugger protected-mode interface
WINCB: {
VECTOR: 0x30 // Windows PM call-back interface (aka Transfer Space Fault)
},
WINDBG: { // Windows Debugger protected-mode interface
VECTOR: 0x41, // (AX==command)
IS_LOADED: 0x004F, // DS_DebLoaded
LOADED: 0xF386, // DS_DebPresent (returned in AX if Windows Debugger loaded)
LOAD_SEG: 0x0050, // DS_LoadSeg (SI==0 if code, 1 if data; BX==segnum-1; CX==selector; ES:[E]DI->module name)
LOAD_SEG32: 0x0150, // DS_LoadSeg_32 (SI==0 if code, 1 if data; DX:EBX->D386_Device_Params)
ENABLED: true // support for WINDBG interrupts can be disabled (but NOT if WINDBGRM is enabled)
},
WINDBGRM: { // Windows Debugger real-mode interface
WINDBGRM: { // Windows Debugger real-mode interface
VECTOR: 0x68, // (AH==command)
IS_LOADED: 0x43, // D386_Identify
LOADED: 0xF386, // D386_Id (returned in AX if Windows Debugger loaded)
PREP_PMODE: 0x44, // D386_Prepare_PMode (must return a 16:32 address in ES:EDI to a "PMinit" handler)
LOAD_SEG: 0x50, // D386_Load_Segment (AL=segment type, ES:DI->D386_Device_Params)
ENABLED: true // support for WINDBGRM interrupts can be disabled
},
FUNCS: {} // filled in only if DEBUGGER is true
FUNCS: {} // filled in only if DEBUGGER is true
};

if (DEBUGGER) {
Expand Down
41 changes: 33 additions & 8 deletions modules/pcjs/lib/video.js
Original file line number Diff line number Diff line change
Expand Up @@ -2461,6 +2461,7 @@ Card.prototype.dumpVideoCard = function()
this.dumpRegs(" GRC", this.regGRCIndx, this.regGRCData, this.asGRCRegs);
this.dumpRegs(" SEQ", this.regSEQIndx, this.regSEQData, this.asSEQRegs);
this.dumpRegs(" ATC", this.regATCIndx, this.regATCData, this.asATCRegs);
this.dumpRegs(" ATCINDX", this.regATCIndx);
this.dbg.println(" ATCDATA: " + this.fATCData);
this.dumpRegs(" FEAT", this.regFeat);
this.dumpRegs(" MISC", this.regMisc);
Expand Down Expand Up @@ -5894,20 +5895,44 @@ Video.prototype.outFeat = function(port, bOut, addrFrom)
};

/**
* inATC(port, addrFrom)
* inATCIndx(port, addrFrom)
*
* Technically, port 0x3C0 is readable only on a VGA, but we allow reads on an EGA as well,
* primarily for debugging purposes. Moreover, ATC port reads do NOT toggle the ATC address/data
* flip-flop; only writes have that effect.
*
* @this {Video}
* @param {number} port (0x3C0)
* @param {number} [addrFrom] (not defined whenever the Debugger tries to read the specified port)
* @return {number}
*/
Video.prototype.inATC = function(port, addrFrom)
Video.prototype.inATCIndx = function(port, addrFrom)
{
var b = this.cardEGA.regATCIndx;
if (!addrFrom || this.messageEnabled()) {
this.printMessageIO(Card.ATC.PORT, null, addrFrom, "ATC.INDX", b);
}
return b;
};

/**
* inATCData(port, addrFrom)
*
* Technically, port 0x3C0 is readable only on a VGA, but we allow reads on an EGA as well,
* primarily for debugging purposes. Moreover, ATC port reads do NOT toggle the ATC address/data
* flip-flop; only writes have that effect.
*
* @this {Video}
* @param {number} port (0x3C1)
* @param {number} [addrFrom] (not defined whenever the Debugger tries to read the specified port)
* @return {number}
*/
Video.prototype.inATCData = function(port, addrFrom)
{
var b = this.cardEGA.fATCData? this.cardEGA.regATCData[this.cardEGA.regATCIndx & Card.ATC.INDX_MASK] : this.cardEGA.regATCIndx;
var b = this.cardEGA.regATCData[this.cardEGA.regATCIndx & Card.ATC.INDX_MASK];
if (!addrFrom || this.messageEnabled()) {
this.printMessageIO(Card.ATC.PORT, null, addrFrom, "ATC." + (this.cardEGA.fATCData? this.cardEGA.asATCRegs[this.cardEGA.regATCIndx & Card.ATC.INDX_MASK] : "INDX"), b);
this.printMessageIO(Card.ATC.PORT, null, addrFrom, "ATC." + this.cardEGA.asATCRegs[this.cardEGA.regATCIndx & Card.ATC.INDX_MASK], b);
}
this.cardEGA.fATCData = !this.cardEGA.fATCData;
return b;
};

Expand Down Expand Up @@ -6880,8 +6905,8 @@ Video.aCGAPortOutput = {
};

Video.aEGAPortInput = {
0x3C0: Video.prototype.inATC, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
0x3C1: Video.prototype.inATC, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
0x3C0: Video.prototype.inATCIndx, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
0x3C1: Video.prototype.inATCData, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
0x3C2: Video.prototype.inStatus0,
0x3C4: Video.prototype.inSEQIndx, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
0x3C5: Video.prototype.inSEQData, // technically, only readable on a VGA, but I want the Debugger to be able to read this, too
Expand All @@ -6892,7 +6917,7 @@ Video.aEGAPortInput = {
/*
* WARNING: Unlike the EGA, a standard VGA does not support writes to 0x3C1, but it's easier for me to leave that
* ability in place, treating the VGA as a superset of the EGA as much as possible; will any code break because word
* I/O to port 0x3C0 actually works? Possibly, but highly unlikely.
* OUTs to port 0x3C0 (and/or byte OUTs to port 0x3C1) actually work? Possibly, but highly unlikely.
*/
Video.aEGAPortOutput = {
0x3BA: Video.prototype.outFeat,
Expand Down
6 changes: 5 additions & 1 deletion modules/pcjs/lib/x86func.js
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ X86.fnCALLF = function CALLF(off, sel)
{
var oldCS = this.getCS();
var oldIP = this.getIP();
var oldSize = this.segCS.sizeData;
var oldSize = (I386? this.sizeData : 2);
if (this.setCSIP(off, sel, true) != null) {
this.pushData(oldCS, oldSize);
this.pushData(oldIP, oldSize);
Expand Down Expand Up @@ -1415,6 +1415,10 @@ X86.fnINT = function INT(nIDT, nError, nCycles)
var oldIP = this.getIP();
var addr = this.segCS.loadIDT(nIDT);
if (addr !== X86.ADDR_INVALID) {
/*
* TODO: Harmonize this with the code in fnCALLF(), which relies on the OPERAND size in
* effect at the time of the call, NOT the size of the new segCS.
*/
var size = this.segCS.sizeFrame;
this.pushData(oldPS, size);
this.pushData(oldCS, size);
Expand Down
Loading

0 comments on commit 2122e48

Please sign in to comment.