Final preparations for open source roll-out
This commit is contained in:
parent
e96f0eecd9
commit
60669365f9
40 changed files with 2814 additions and 2639 deletions
|
|
@ -480,7 +480,7 @@ Bus.prototype.restoreMemory = function(a)
|
|||
* configuration since it was last saved (the most likely explanation) or there's some internal
|
||||
* inconsistency (eg, the block size is wrong).
|
||||
*/
|
||||
this.error("Unable to restore memory block " + iBlock);
|
||||
Component.error("Unable to restore memory block " + iBlock);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -554,7 +554,7 @@ Bus.prototype.addPortInputNotify = function(start, end, component, fn)
|
|||
if (fn !== undefined) {
|
||||
for (var port = start; port <= end; port++) {
|
||||
if (this.aPortInputNotify[port] !== undefined) {
|
||||
this.warning("Input port " + str.toHexWord(port) + " registered by " + this.aPortInputNotify[port][0].id + ", ignoring " + component.id);
|
||||
Component.warning("Input port " + str.toHexWord(port) + " registered by " + this.aPortInputNotify[port][0].id + ", ignoring " + component.id);
|
||||
continue;
|
||||
}
|
||||
this.aPortInputNotify[port] = [component, fn, false, false];
|
||||
|
|
@ -674,7 +674,7 @@ Bus.prototype.addPortOutputNotify = function(start, end, component, fn)
|
|||
if (fn !== undefined) {
|
||||
for (var port = start; port <= end; port++) {
|
||||
if (this.aPortOutputNotify[port] !== undefined) {
|
||||
this.warning("Output port " + str.toHexWord(port) + " registered by " + this.aPortOutputNotify[port][0].id + ", ignoring " + component.id);
|
||||
Component.warning("Output port " + str.toHexWord(port) + " registered by " + this.aPortOutputNotify[port][0].id + ", ignoring " + component.id);
|
||||
continue;
|
||||
}
|
||||
this.aPortOutputNotify[port] = [component, fn, false, false];
|
||||
|
|
@ -764,7 +764,7 @@ Bus.prototype.removePortOutputNotify = function(start, end, component, fn)
|
|||
*/
|
||||
Bus.prototype.reportError = function(op, addr, size)
|
||||
{
|
||||
this.error("Memory block error (" + op + "," + str.toHex(addr) + "," + str.toHex(size) + ")");
|
||||
Component.error("Memory block error (" + op + "," + str.toHex(addr) + "," + str.toHex(size) + ")");
|
||||
return false;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -157,12 +157,6 @@ function ChipSet(parmsChipSet)
|
|||
* and (on the MODEL_5160) whether or not a coprocessor is installed. If no SW1 settings are provided,
|
||||
* we look for individual 'fdrives' and 'monitor' settings and build a default SW1 value.
|
||||
*
|
||||
* TODO: Get rid of reliance on SW1 for MODEL_5170 and later; omitting it now results in a BIOS warning:
|
||||
*
|
||||
* ' 162-System Options Not Set-(Run SETUP)'
|
||||
*
|
||||
* ' (RESUME = "F1" KEY)'
|
||||
*
|
||||
* The defaults below select max memory, monochrome monitor (EGA monitor for MODEL_5170), and two floppies.
|
||||
* Don't get too excited about "max memory" either: on a MODEL_5150, the max was 64Kb, and on a MODEL_5160,
|
||||
* the max was 256Kb. However, the RAM component is free to install as much base memory as it likes,
|
||||
|
|
@ -2566,14 +2560,14 @@ ChipSet.prototype.updateDMA = function(channel)
|
|||
};
|
||||
|
||||
/**
|
||||
* inPICL(iPIC, addrFrom)
|
||||
* inPICLo(iPIC, addrFrom)
|
||||
*
|
||||
* @this {ChipSet}
|
||||
* @param {number} iPIC
|
||||
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
||||
* @return {number} simulated port value
|
||||
*/
|
||||
ChipSet.prototype.inPICL = function(iPIC, addrFrom)
|
||||
ChipSet.prototype.inPICLo = function(iPIC, addrFrom)
|
||||
{
|
||||
var b = 0;
|
||||
var pic = this.aPICs[iPIC];
|
||||
|
|
@ -2595,14 +2589,14 @@ ChipSet.prototype.inPICL = function(iPIC, addrFrom)
|
|||
};
|
||||
|
||||
/**
|
||||
* outPICL(iPIC, bOut, addrFrom)
|
||||
* outPICLo(iPIC, bOut, addrFrom)
|
||||
*
|
||||
* @this {ChipSet}
|
||||
* @param {number} iPIC
|
||||
* @param {number} bOut
|
||||
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
||||
*/
|
||||
ChipSet.prototype.outPICL = function(iPIC, bOut, addrFrom)
|
||||
ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
|
||||
{
|
||||
var pic = this.aPICs[iPIC];
|
||||
this.messagePort(pic.port, bOut, addrFrom, "PIC" + iPIC, ChipSet.MESSAGE_PIC);
|
||||
|
|
@ -2613,7 +2607,7 @@ ChipSet.prototype.outPICL = function(iPIC, bOut, addrFrom)
|
|||
pic.nICW = 0;
|
||||
pic.aICW[pic.nICW++] = bOut;
|
||||
/*
|
||||
* I used to do the rest of this initialization in outPICH(), once all the ICW commands had been received,
|
||||
* I used to do the rest of this initialization in outPICHi(), once all the ICW commands had been received,
|
||||
* but a closer reading of the 8259A spec indicates that that should happen now, on receipt on ICW1.
|
||||
*
|
||||
* Also, on p.10 of that spec, it says "The Interrupt Mask Register is cleared". I originally took that to
|
||||
|
|
@ -2711,7 +2705,7 @@ ChipSet.prototype.outPICL = function(iPIC, bOut, addrFrom)
|
|||
}
|
||||
} else {
|
||||
/*
|
||||
* This must be an OCW3 request. If it's a "Read Register" command (PIC_LO.OCW3_READ_CMD), inPICL() will take care it.
|
||||
* This must be an OCW3 request. If it's a "Read Register" command (PIC_LO.OCW3_READ_CMD), inPICLo() will take care it.
|
||||
*
|
||||
* TODO: If OCW3 specified a "Poll" command (PIC_LO.OCW3_POLL_CMD) or a "Special Mask Mode" command (PIC_LO.OCW3_SMM_CMD),
|
||||
* that's unfortunate, because I don't support them yet.
|
||||
|
|
@ -2724,14 +2718,14 @@ ChipSet.prototype.outPICL = function(iPIC, bOut, addrFrom)
|
|||
};
|
||||
|
||||
/**
|
||||
* inPICH(iPIC, addrFrom)
|
||||
* inPICHi(iPIC, addrFrom)
|
||||
*
|
||||
* @this {ChipSet}
|
||||
* @param {number} iPIC
|
||||
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
||||
* @return {number} simulated port value
|
||||
*/
|
||||
ChipSet.prototype.inPICH = function(iPIC, addrFrom)
|
||||
ChipSet.prototype.inPICHi = function(iPIC, addrFrom)
|
||||
{
|
||||
var pic = this.aPICs[iPIC];
|
||||
var b = pic.bIMR;
|
||||
|
|
@ -2740,14 +2734,14 @@ ChipSet.prototype.inPICH = function(iPIC, addrFrom)
|
|||
};
|
||||
|
||||
/**
|
||||
* outPICH(iPIC, bOut, addrFrom)
|
||||
* outPICHi(iPIC, bOut, addrFrom)
|
||||
*
|
||||
* @this {ChipSet}
|
||||
* @param {number} iPIC
|
||||
* @param {number} bOut
|
||||
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
||||
*/
|
||||
ChipSet.prototype.outPICH = function(iPIC, bOut, addrFrom)
|
||||
ChipSet.prototype.outPICHi = function(iPIC, bOut, addrFrom)
|
||||
{
|
||||
var pic = this.aPICs[iPIC];
|
||||
this.messagePort(pic.port+1, bOut, addrFrom, "PIC" + iPIC, ChipSet.MESSAGE_PIC);
|
||||
|
|
@ -4230,8 +4224,8 @@ ChipSet.aPortInput = {
|
|||
0x06: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelAddr(ChipSet.DMA0.INDEX, 3, port, addrFrom); },
|
||||
0x07: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelCount(ChipSet.DMA0.INDEX, 3, port, addrFrom); },
|
||||
0x08: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAStatus(ChipSet.DMA0.INDEX, port, addrFrom); },
|
||||
0x20: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICL(ChipSet.PIC0.INDEX, addrFrom); },
|
||||
0x21: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICH(ChipSet.PIC0.INDEX, addrFrom); },
|
||||
0x20: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICLo(ChipSet.PIC0.INDEX, addrFrom); },
|
||||
0x21: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICHi(ChipSet.PIC0.INDEX, addrFrom); },
|
||||
0x40: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER0.INDEX, addrFrom); },
|
||||
0x41: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER1.INDEX, addrFrom); },
|
||||
0x42: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER2.INDEX, addrFrom); },
|
||||
|
|
@ -4267,8 +4261,8 @@ ChipSet.aPortInput5170 = {
|
|||
0x8D: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageSpare(5, port, addrFrom); },
|
||||
0x8E: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageSpare(6, port, addrFrom); },
|
||||
0x8F: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageReg(ChipSet.DMA1.INDEX, 0, port, addrFrom); },
|
||||
0xA0: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICL(ChipSet.PIC1.INDEX, addrFrom); },
|
||||
0xA1: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICH(ChipSet.PIC1.INDEX, addrFrom); },
|
||||
0xA0: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICLo(ChipSet.PIC1.INDEX, addrFrom); },
|
||||
0xA1: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICHi(ChipSet.PIC1.INDEX, addrFrom); },
|
||||
0xC0: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelAddr(ChipSet.DMA1.INDEX, 0, port, addrFrom); },
|
||||
0xC2: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelCount(ChipSet.DMA1.INDEX, 0, port, addrFrom); },
|
||||
0xC4: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAChannelAddr(ChipSet.DMA1.INDEX, 1, port, addrFrom); },
|
||||
|
|
@ -4298,8 +4292,8 @@ ChipSet.aPortOutput = {
|
|||
0x0B: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAMode(ChipSet.DMA0.INDEX, port, bOut, addrFrom); },
|
||||
0x0C: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAIndex(ChipSet.DMA0.INDEX, port, bOut, addrFrom); },
|
||||
0x0D: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAClear(ChipSet.DMA0.INDEX, port, bOut, addrFrom); },
|
||||
0x20: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICL(ChipSet.PIC0.INDEX, bOut, addrFrom); },
|
||||
0x21: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICH(ChipSet.PIC0.INDEX, bOut, addrFrom); },
|
||||
0x20: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICLo(ChipSet.PIC0.INDEX, bOut, addrFrom); },
|
||||
0x21: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICHi(ChipSet.PIC0.INDEX, bOut, addrFrom); },
|
||||
0x40: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER0.INDEX, bOut, addrFrom); },
|
||||
0x41: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER1.INDEX, bOut, addrFrom); },
|
||||
0x42: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER2.INDEX, bOut, addrFrom); },
|
||||
|
|
@ -4336,8 +4330,8 @@ ChipSet.aPortOutput5170 = {
|
|||
0x8D: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageSpare(5, port, bOut, addrFrom); },
|
||||
0x8E: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageSpare(6, port, bOut, addrFrom); },
|
||||
0x8F: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageReg(ChipSet.DMA1.INDEX, 0, port, bOut, addrFrom); },
|
||||
0xA0: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICL(ChipSet.PIC1.INDEX, bOut, addrFrom); },
|
||||
0xA1: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICH(ChipSet.PIC1.INDEX, bOut, addrFrom); },
|
||||
0xA0: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICLo(ChipSet.PIC1.INDEX, bOut, addrFrom); },
|
||||
0xA1: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICHi(ChipSet.PIC1.INDEX, bOut, addrFrom); },
|
||||
0xC0: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAChannelAddr(ChipSet.DMA1.INDEX, 0, port, bOut, addrFrom); },
|
||||
0xC2: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAChannelCount(ChipSet.DMA1.INDEX, 0, port, bOut, addrFrom); },
|
||||
0xC4: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAChannelAddr(ChipSet.DMA1.INDEX, 1, port, bOut, addrFrom); },
|
||||
|
|
|
|||
|
|
@ -139,15 +139,15 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
|
|||
this.sUserID = this.queryUserID();
|
||||
|
||||
/*
|
||||
* Find the appropriate CPU (and the Debugger, if any)
|
||||
* Find the appropriate CPU (and Debugger and Control Panel, if any)
|
||||
*/
|
||||
this.cpu = Component.getComponentByType("CPU", this.id);
|
||||
if (!this.cpu) {
|
||||
Component.error("Unable to find CPU component");
|
||||
return;
|
||||
}
|
||||
|
||||
this.dbg = Component.getComponentByType("Debugger", this.id);
|
||||
this.panel = Component.getComponentByType("Panel", this.id);
|
||||
|
||||
/*
|
||||
* Initialize the Bus component
|
||||
|
|
@ -160,6 +160,20 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
|
|||
var aComponents = Component.getComponents(this.id);
|
||||
for (var iComponent = 0; iComponent < aComponents.length; iComponent++) {
|
||||
var component = aComponents[iComponent];
|
||||
/*
|
||||
* I can think of many "cleaner" ways for the Control Panel component to pass its
|
||||
* notice(), println(), etc, overrides on to all the other components, but it's just
|
||||
* too darn convenient to slam those overrides into the components directly.
|
||||
*
|
||||
* Adding more initBus() parameters was another option, but that function is already
|
||||
* looking a bit unwieldy, and Control Panel functionality is a little far afield
|
||||
* from Bus initialization.
|
||||
*/
|
||||
if (this.panel && this.panel.controlPrint) {
|
||||
component.notice = this.panel.notice;
|
||||
component.println = this.panel.println;
|
||||
component.controlPrint = this.panel.controlPrint;
|
||||
}
|
||||
if (component.initBus) component.initBus(this, this.bus, this.cpu, this.dbg);
|
||||
}
|
||||
|
||||
|
|
@ -557,7 +571,7 @@ Computer.prototype.powerRestore = function(component, stateComputer, fRepower, f
|
|||
*/
|
||||
if (!component.powerUp(data, fRepower)) {
|
||||
if (data) {
|
||||
this.error("Unable to restore state for " + component.type);
|
||||
Component.error("Unable to restore state for " + component.type);
|
||||
/*
|
||||
* If this is a resume error for a machine that also has a predefined state
|
||||
* AND we're not restoring from that state, then throw away the current state,
|
||||
|
|
@ -1179,6 +1193,7 @@ Computer.init = function()
|
|||
|
||||
var eComputer = aeComputers[iComputer];
|
||||
var parmsComputer = Component.getComponentParms(eComputer);
|
||||
|
||||
/*
|
||||
* We set fSuspended in the Computer constructor because we want to "power up" the
|
||||
* computer ourselves, after any/all bindings are in place.
|
||||
|
|
|
|||
|
|
@ -254,11 +254,15 @@ CPU.prototype.powerUp = function(data, fRepower)
|
|||
this.dbg.init();
|
||||
} else {
|
||||
/*
|
||||
* TODO: Once we get rid of those nasty Component method overrides, this test will have to be revised as well
|
||||
* The Computer (this.cmp) knows if there's a Control Panel (this.cmp.panel), and the Control Panel
|
||||
* knows if there's a "print" control (this.cmp.panel.controlPrint), and if there IS a "print" control
|
||||
* but no debugger, the machine is probably misconfigured (most likely, the page simply neglected to
|
||||
* load the Debugger component).
|
||||
*
|
||||
* However, we don't actually need to check all that; it's always safe use println(), regardless whether
|
||||
* a Control Panel with a "print" control is present or not.
|
||||
*/
|
||||
if (Component.controlPrint) {
|
||||
this.warning("No debugger detected");
|
||||
}
|
||||
this.println("No debugger detected");
|
||||
}
|
||||
}
|
||||
this.fPowered = true;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* @fileoverview Implements the PCjs Debugger component.
|
||||
* @fileoverview Implements the PCjs Debugger component.
|
||||
* @author <a href="mailto:Jeff@pcjs.org">Jeff Parsons</a>
|
||||
* @version 1.0
|
||||
* @suppress {missingProperties}
|
||||
|
|
@ -1562,7 +1562,7 @@ if (DEBUGGER) {
|
|||
*/
|
||||
if (fUpdateCPU !== false) this.cpu.updateCPU();
|
||||
|
||||
this.updateStatus(fRegs, false);
|
||||
this.updateStatus(fRegs || false, false);
|
||||
return (this.nCycles > 0);
|
||||
};
|
||||
|
||||
|
|
@ -2846,8 +2846,8 @@ if (DEBUGGER) {
|
|||
value = this.cpu.segSS.sel;
|
||||
break;
|
||||
/*
|
||||
* I used to alias "PC" to "IP", until I discovered that early (perhaps even ALL?) versions of DEBUG
|
||||
* treat "PC" as an alias for the 16-bit flags register. TODO: Add support for "PC" that matches DEBUG.
|
||||
* I used to alias "PC" to "IP", until I discovered that early (perhaps even ALL?) versions of DEBUG.COM
|
||||
* treat "PC" as an alias for the 16-bit flags register. TODO: Add support for "PC".
|
||||
*/
|
||||
case "IP":
|
||||
value = this.cpu.regIP;
|
||||
|
|
@ -3283,9 +3283,10 @@ if (DEBUGGER) {
|
|||
*/
|
||||
Debugger.prototype.doClear = function(sCmd)
|
||||
{
|
||||
if (Component.controlPrint) {
|
||||
Component.controlPrint.value = "";
|
||||
}
|
||||
/*
|
||||
* TODO: There should be a clear() component method that the Control Panel overrides to perform this function.
|
||||
*/
|
||||
if (this.controlPrint) this.controlPrint.value = "";
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -4275,7 +4276,7 @@ if (DEBUGGER) {
|
|||
/*
|
||||
* Limiting the amount of disassembled code to 256 bytes in non-DEBUG builds is partly to
|
||||
* prevent the user from wedging the browser by dumping too many lines, but also a recognition
|
||||
* that, in non-DEBUG builds, Component.println() keeps print output buffer truncated to 8Kb anyway.
|
||||
* that, in non-DEBUG builds, this.println() keeps print output buffer truncated to 8Kb anyway.
|
||||
*/
|
||||
this.println("range too large");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -613,10 +613,10 @@ Disk.prototype.onLoadDisk = function(sDiskFile, sDiskData, nErrorCode, sDiskPath
|
|||
}
|
||||
|
||||
if (!aDiskData.length) {
|
||||
this.error("Empty disk image: " + this.sDiskName);
|
||||
Component.error("Empty disk image: " + this.sDiskName);
|
||||
}
|
||||
else if (aDiskData.length == 1) {
|
||||
this.error(aDiskData[0]);
|
||||
Component.error(aDiskData[0]);
|
||||
}
|
||||
/*
|
||||
* aDiskData is an array of cylinders, each of which is an array of heads, each of which
|
||||
|
|
@ -731,7 +731,7 @@ Disk.prototype.onLoadDisk = function(sDiskFile, sDiskData, nErrorCode, sDiskPath
|
|||
disk = this;
|
||||
}
|
||||
} catch (e) {
|
||||
this.error("Disk image error: " + e.message);
|
||||
Component.error("Disk image error: " + e.message);
|
||||
}
|
||||
}
|
||||
if (this.fnNotify) {
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ function FDC(parmsFDC) {
|
|||
*/
|
||||
this.pAutoMount = eval("(" + parmsFDC['autoMount'] + ")");
|
||||
} catch (e) {
|
||||
this.error("FDC auto-mount error: " + e.message + " (" + parmsFDC['autoMount'] + ")");
|
||||
Component.error("FDC auto-mount error: " + e.message + " (" + parmsFDC['autoMount'] + ")");
|
||||
this.pAutoMount = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -395,7 +395,7 @@ FDC.prototype.setBinding = function(sHTMLClass, sHTMLType, sBinding, control)
|
|||
try {
|
||||
dataValue = eval("({" + sValue + "})");
|
||||
} catch (e) {
|
||||
fdc.error("FDC option error: " + (e.message || e));
|
||||
Component.error("FDC option error: " + (e.message || e));
|
||||
}
|
||||
}
|
||||
var sDesc = dataValue['desc'];
|
||||
|
|
@ -744,6 +744,10 @@ FDC.prototype.saveController = function()
|
|||
|
||||
/**
|
||||
* initDrive(drive, iDrive, data)
|
||||
*
|
||||
* TODO: Consider a separate Drive class that both FDC and HDC can use, since there's a lot of commonality
|
||||
* between the drive objects created by both controllers. This will clean up overall drive management and allow
|
||||
* us to factor out some common Drive methods (eg, advanceSector()).
|
||||
*
|
||||
* @this {FDC}
|
||||
* @param {Object} drive
|
||||
|
|
@ -1933,8 +1937,7 @@ FDC.prototype.doFormat = function(drive)
|
|||
* NOTE: Since the FDC isn't aware of the extent of the transfer, all readByte() can do is return bytes
|
||||
* until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
||||
*
|
||||
* TODO: Research the requirements, if any, for multi-track I/O and determine what if anything needs to be
|
||||
* done. At the very least, if it must be supported, there would need to be some head-incrementing somewhere.
|
||||
* TODO: Research the requirements, if any, for multi-track I/O and determine what else needs to be done.
|
||||
*
|
||||
* @this {FDC}
|
||||
* @param {Object} drive
|
||||
|
|
@ -1958,7 +1961,11 @@ FDC.prototype.readByte = function(drive, done)
|
|||
break;
|
||||
}
|
||||
drive.ibSector = 0;
|
||||
drive.bSector++;
|
||||
/*
|
||||
* We "pre-advance" bSector et al now, instead of waiting to advance it right before the seek().
|
||||
* This allows the initial call to readByte() to perform a seek without triggering an unwanted advance.
|
||||
*/
|
||||
this.advanceSector(drive);
|
||||
} while (true);
|
||||
}
|
||||
done(b, false);
|
||||
|
|
@ -1981,8 +1988,7 @@ FDC.prototype.readByte = function(drive, done)
|
|||
* NOTE: Since the FDC isn't aware of the extent of the transfer, all writeByte() can do is accept bytes
|
||||
* until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
||||
*
|
||||
* TODO: Research the requirements, if any, for multi-track I/O and determine what if anything needs to be
|
||||
* done. At the very least, if it must be supported, there would need to be some head-incrementing somewhere.
|
||||
* TODO: Research the requirements, if any, for multi-track I/O and determine what else needs to be done.
|
||||
*
|
||||
* @this {FDC}
|
||||
* @param {Object} drive
|
||||
|
|
@ -2010,11 +2016,40 @@ FDC.prototype.writeByte = function(drive, b)
|
|||
break;
|
||||
}
|
||||
drive.ibSector = 0;
|
||||
drive.bSector++;
|
||||
/*
|
||||
* We "pre-advance" bSector et al now, instead of waiting to advance it right before the seek().
|
||||
* This allows the initial call to writeByte() to perform a seek without triggering an unwanted advance.
|
||||
*/
|
||||
this.advanceSector(drive);
|
||||
} while (true);
|
||||
return b;
|
||||
};
|
||||
|
||||
/**
|
||||
* advanceSector(drive)
|
||||
*
|
||||
* This increments the sector number; when the sector number reaches drive.nSectors on the current track, we
|
||||
* increment drive.bHead and reset drive.bSector, and when drive.bHead reaches drive.nHeads, we reset drive.bHead
|
||||
* and increment drive.bCylinder.
|
||||
*
|
||||
* @this {FDC}
|
||||
* @param {Object} drive
|
||||
*/
|
||||
FDC.prototype.advanceSector = function(drive)
|
||||
{
|
||||
Component.assert(drive.bCylinder < drive.nCylinders);
|
||||
drive.bSector++;
|
||||
var bSectorStart = 1;
|
||||
if (drive.bSector >= drive.nSectors + bSectorStart) {
|
||||
drive.bSector = bSectorStart;
|
||||
drive.bHead++;
|
||||
if (drive.bHead >= drive.nHeads) {
|
||||
drive.bHead = 0;
|
||||
drive.bCylinder++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* writeFormat(drive, b)
|
||||
*
|
||||
|
|
@ -2085,9 +2120,9 @@ FDC.prototype.intBIOSDiskette = function(addr)
|
|||
var DL = this.cpu.regDX & 0xff;
|
||||
var DH = this.cpu.regDX >> 8;
|
||||
if (this.dbg && this.dbg.messageEnabled(this.dbg.MESSAGE_FDC) && DL < 0x80) {
|
||||
this.dbg.message("FDC.intBIOS(AH=" + str.toHexByte(AH) + ",D=" + str.toHexByte(DL) + ",C=" + str.toHexByte(CH) + ",H=" + str.toHexByte(DH) + ",S=" + str.toHexByte(CL) + ",N=" + str.toHexByte(AL) + ") at " + str.toHexAddr(addr - this.cpu.segCS.base, this.cpu.segCS.sel));
|
||||
this.dbg.message("\nFDC.intBIOS(AH=" + str.toHexByte(AH) + ",D=" + str.toHexByte(DL) + ",C=" + str.toHexByte(CH) + ",H=" + str.toHexByte(DH) + ",S=" + str.toHexByte(CL) + ",N=" + str.toHexByte(AL) + ") at " + str.toHexAddr(addr - this.cpu.segCS.base, this.cpu.segCS.sel));
|
||||
// this.cpu.haltCPU();
|
||||
this.cpu.addInterruptReturn(addr, function (fdc, nCycles) {
|
||||
this.cpu.addInterruptReturn(addr, function(fdc, nCycles) {
|
||||
return function onBIOSDisketteReturn(nLevel) {
|
||||
nCycles = fdc.cpu.getCycles() - nCycles;
|
||||
fdc.messageDebugger("FDC.intBIOS(" + nLevel + "): C=" + (fdc.cpu.getCF()? 1 : 0) + " (cycles=" + nCycles + ")");
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -74,8 +74,8 @@ if (typeof module !== 'undefined') {
|
|||
* supported in theory, but in practice, they're not.
|
||||
*
|
||||
* NOTE: Since Memory blocks are low-level objects that have no UI requirements, they do not
|
||||
* inherit from the Component class; so, if you want to use print(), for example, you must
|
||||
* rely on class methods like Component.println() rather than object methods like this.println().
|
||||
* inherit from the Component class; so, if you want to use println(), for example, you must
|
||||
* use the methods in the Debugger class.
|
||||
*
|
||||
* Because Memory blocks now allow us to have a "sparse" address space, we could choose to
|
||||
* take the memory hit of allocating 4K arrays per block, where each element stores only one byte,
|
||||
|
|
@ -160,10 +160,6 @@ Memory.prototype = {
|
|||
* @return {number}
|
||||
*/
|
||||
readNone: function(off) {
|
||||
/*
|
||||
* This can happen so frequently that the browser can't come up for air, so it's best to do this only under special circumstances...
|
||||
*/
|
||||
// if (DEBUG) Component.println("readNone(" + str.toHexWord(this.addr + off) + ")");
|
||||
return 0;
|
||||
},
|
||||
/**
|
||||
|
|
@ -174,10 +170,6 @@ Memory.prototype = {
|
|||
* @param {number} v (could be either a byte or word value, since we use the same handler for both kinds of accesses)
|
||||
*/
|
||||
writeNone: function(off, v) {
|
||||
/*
|
||||
* This can happen so frequently that the browser can't come up for air, so it's best to do this only under special circumstances...
|
||||
*/
|
||||
// if (DEBUG) Component.println("writeNone(" + str.toHexWord(this.addr + off) + "): " + str.toHexWord(v));
|
||||
},
|
||||
/**
|
||||
* readByteTArray(off)
|
||||
|
|
@ -537,13 +529,13 @@ Memory.prototype = {
|
|||
if (this.cReadBreakpoints++ === 0) {
|
||||
this.setReadAccess(Memory.afnVerify);
|
||||
}
|
||||
if (DEBUG) Component.println("read breakpoint added to memory block " + str.toHex(this.addr));
|
||||
if (DEBUG) this.dbg.println("read breakpoint added to memory block " + str.toHex(this.addr));
|
||||
}
|
||||
else {
|
||||
if (this.cWriteBreakpoints++ === 0) {
|
||||
this.setWriteAccess(Memory.afnVerify);
|
||||
}
|
||||
if (DEBUG) Component.println("write breakpoint added to memory block " + str.toHex(this.addr));
|
||||
if (DEBUG) this.dbg.println("write breakpoint added to memory block " + str.toHex(this.addr));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -559,14 +551,14 @@ Memory.prototype = {
|
|||
if (!fWrite) {
|
||||
if (--this.cReadBreakpoints === 0) {
|
||||
this.resetReadAccess();
|
||||
if (DEBUG) Component.println("all read breakpoints removed from memory block " + str.toHex(this.addr));
|
||||
if (DEBUG) this.dbg.println("all read breakpoints removed from memory block " + str.toHex(this.addr));
|
||||
}
|
||||
Component.assert(this.cReadBreakpoints >= 0);
|
||||
}
|
||||
else {
|
||||
if (--this.cWriteBreakpoints === 0) {
|
||||
this.resetWriteAccess();
|
||||
if (DEBUG) Component.println("all write breakpoints removed from memory block " + str.toHex(this.addr));
|
||||
if (DEBUG) this.dbg.println("all write breakpoints removed from memory block " + str.toHex(this.addr));
|
||||
}
|
||||
Component.assert(this.cWriteBreakpoints >= 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ Mouse.prototype.powerUp = function(data, fRepower) {
|
|||
var componentScreen = this.cmp.getComponentByType("Video");
|
||||
if (componentScreen) this.canvasScreen = componentScreen.getCanvas();
|
||||
} else {
|
||||
this.warning(this.id + ": " + this.sAdapterType + " " + this.idAdapter + " unavailable");
|
||||
Component.warning(this.id + ": " + this.sAdapterType + " " + this.idAdapter + " unavailable");
|
||||
}
|
||||
}
|
||||
if (this.fActive) {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ Component.subclass(Component, Panel);
|
|||
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
|
||||
* @return {boolean} true if binding was successful, false if unrecognized binding request
|
||||
*/
|
||||
Panel.prototype.setBinding = function(sHTMLClass, sHTMLType, sBinding, control) {
|
||||
Panel.prototype.setBinding = function(sHTMLClass, sHTMLType, sBinding, control)
|
||||
{
|
||||
if (this.cmp && this.cmp.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
||||
if (this.cpu && this.cpu.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
||||
if (this.kbd && this.kbd.setBinding(sHTMLClass, sHTMLType, sBinding, control)) return true;
|
||||
|
|
@ -84,7 +85,8 @@ Panel.prototype.setBinding = function(sHTMLClass, sHTMLType, sBinding, control)
|
|||
* @param {X86CPU} cpu
|
||||
* @param {Debugger} dbg
|
||||
*/
|
||||
Panel.prototype.initBus = function(cmp, bus, cpu, dbg) {
|
||||
Panel.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||
{
|
||||
this.cmp = cmp;
|
||||
this.cpu = cpu;
|
||||
this.dbg = dbg;
|
||||
|
|
@ -99,7 +101,8 @@ Panel.prototype.initBus = function(cmp, bus, cpu, dbg) {
|
|||
* @param {boolean} [fRepower]
|
||||
* @return {boolean} true if successful, false if failure
|
||||
*/
|
||||
Panel.prototype.powerUp = function(data, fRepower) {
|
||||
Panel.prototype.powerUp = function(data, fRepower)
|
||||
{
|
||||
if (!fRepower) {
|
||||
Panel.init();
|
||||
}
|
||||
|
|
@ -113,7 +116,8 @@ Panel.prototype.powerUp = function(data, fRepower) {
|
|||
* @param {boolean} fSave
|
||||
* @return {Object|boolean}
|
||||
*/
|
||||
Panel.prototype.powerDown = function(fSave) {
|
||||
Panel.prototype.powerDown = function(fSave)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ RAM.prototype.reset = function() {
|
|||
}
|
||||
if (this.chipset) this.chipset.addCMOSMemory(this.addrRAM, this.sizeRAM);
|
||||
} else {
|
||||
this.error("No RAM allocated");
|
||||
Component.error("No RAM allocated");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -221,11 +221,11 @@ ROM.prototype.onLoadROM = function(sROMFile, sROMData, nErrorCode)
|
|||
this.aSymbols = rom['symbols'];
|
||||
|
||||
if (!this.abROM.length) {
|
||||
this.error("Empty ROM: " + sROMFile);
|
||||
Component.error("Empty ROM: " + sROMFile);
|
||||
return;
|
||||
}
|
||||
else if (this.abROM.length == 1) {
|
||||
this.error(this.abROM[0]);
|
||||
Component.error(this.abROM[0]);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -2478,11 +2478,11 @@ Video.prototype.onLoadSetFonts = function(sFontFile, sFontData, nErrorCode)
|
|||
var abFontData = eval("(" + sFontData + ")");
|
||||
|
||||
if (!abFontData.length) {
|
||||
this.error("Empty font ROM image: " + sFontFile);
|
||||
Component.error("Empty font ROM image: " + sFontFile);
|
||||
return;
|
||||
}
|
||||
else if (abFontData.length == 1) {
|
||||
this.error(abFontData[0]);
|
||||
Component.error(abFontData[0]);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -37,15 +37,15 @@ var X86 = {
|
|||
/*
|
||||
* CPU model numbers
|
||||
*/
|
||||
MODEL_8086: 8086,
|
||||
MODEL_8088: 8088,
|
||||
MODEL_80186: 80186,
|
||||
MODEL_80188: 80188,
|
||||
MODEL_80286: 80286,
|
||||
MODEL_8086: 8086,
|
||||
MODEL_8088: 8088,
|
||||
MODEL_80186: 80186,
|
||||
MODEL_80188: 80188,
|
||||
MODEL_80286: 80286,
|
||||
/*
|
||||
* Processor Status flag definitions (stored in regPS)
|
||||
*/
|
||||
PS: {
|
||||
PS: {
|
||||
CF: 0x0001, // bit 0: Carry flag
|
||||
BIT1: 0x0002, // bit 1: reserved, always set
|
||||
PF: 0x0004, // bit 2: Parity flag
|
||||
|
|
@ -124,23 +124,23 @@ var X86 = {
|
|||
},
|
||||
/*
|
||||
* Processor Exception Interrupts
|
||||
*
|
||||
*
|
||||
* Of the following exceptions, all are designed to be restartable, except for 0x08 and 0x09 (and 0x0D
|
||||
* after an attempt to write to a read-only segment).
|
||||
*
|
||||
*
|
||||
* Error codes are pushed onto the stack for 0x08 (always 0) and 0x0A through 0x0D.
|
||||
*
|
||||
*
|
||||
* Priority: Instruction exception, TRAP, NMI, Processor Extension Segment Overrun, and finally INTR.
|
||||
*
|
||||
*
|
||||
* All exceptions can also occur in real-mode, except where noted. A GP_FAULT in real-mode can be triggered
|
||||
* by "any memory reference instruction that attempts to reference [a] 16-bit word at offset 0FFFFH".
|
||||
*
|
||||
* Interrupts beyond 0x10 (up through 0x1F) are reserved for future exceptions.
|
||||
*
|
||||
*
|
||||
* Implementation Detail: For any opcode we know must generate a UD_FAULT interrupt, we invoke opInvalid().
|
||||
* We reserve the term "undefined" for opcodes that require further investigation, and we invoke opUndefined()
|
||||
* in those cases until an opcode's behavior has been defined; at that point, it's either valid or invalid.
|
||||
*
|
||||
*
|
||||
* As for "illegal", that's a silly (and redundant) term in this context, so we don't use it. Similarly,
|
||||
* the term "undocumented" should be limited to operations that are valid but that Intel did not document.
|
||||
*/
|
||||
|
|
@ -195,7 +195,7 @@ var X86 = {
|
|||
/*
|
||||
* Bit values for opFlags, which are all reset to zero prior to each instruction
|
||||
*/
|
||||
OPFLAG: {
|
||||
OPFLAG: {
|
||||
NOREAD: 0x0001,
|
||||
NOWRITE: 0x0002,
|
||||
NOINTR: 0x0004, // indicates a segreg has been set, or a prefix, or an STI (delay INTR acknowledgement)
|
||||
|
|
@ -221,9 +221,9 @@ var X86 = {
|
|||
*/
|
||||
OPCODE: {
|
||||
ES: 0x26, // opES()
|
||||
CS: 0x2E, // opCS()
|
||||
SS: 0x36, // opSS()
|
||||
DS: 0x3E, // opDS()
|
||||
CS: 0x2E, // opCS()
|
||||
SS: 0x36, // opSS()
|
||||
DS: 0x3E, // opDS()
|
||||
PUSHSP: 0x54,
|
||||
PUSHA: 0x60,
|
||||
POPA: 0x61,
|
||||
|
|
@ -239,31 +239,31 @@ var X86 = {
|
|||
OUTSW: 0x6F,
|
||||
ENTER: 0xC8,
|
||||
LEAVE: 0xC9,
|
||||
CALLF: 0x9A, // opCALLf()
|
||||
MOVSB: 0xA4, // opMOVSb()
|
||||
MOVSW: 0xA5, // opMOVSw()
|
||||
CMPSB: 0xA6,
|
||||
CMPSW: 0xA7,
|
||||
STOSB: 0xAA,
|
||||
STOSW: 0xAB,
|
||||
LODSB: 0xAC,
|
||||
LODSW: 0xAD,
|
||||
SCASB: 0xAE,
|
||||
SCASW: 0xAF,
|
||||
INT3: 0xCC,
|
||||
INTn: 0xCD,
|
||||
INTO: 0xCE,
|
||||
CALLF: 0x9A, // opCALLf()
|
||||
MOVSB: 0xA4, // opMOVSb()
|
||||
MOVSW: 0xA5, // opMOVSw()
|
||||
CMPSB: 0xA6,
|
||||
CMPSW: 0xA7,
|
||||
STOSB: 0xAA,
|
||||
STOSW: 0xAB,
|
||||
LODSB: 0xAC,
|
||||
LODSW: 0xAD,
|
||||
SCASB: 0xAE,
|
||||
SCASW: 0xAF,
|
||||
INT3: 0xCC,
|
||||
INTn: 0xCD,
|
||||
INTO: 0xCE,
|
||||
LOOPNZ: 0xE0,
|
||||
LOOPZ: 0xE1,
|
||||
LOOP: 0xE2,
|
||||
CALL: 0xE8,
|
||||
CALL: 0xE8,
|
||||
JMP: 0xE9, // JMP opcode (2-byte displacement)
|
||||
JMPS: 0xEB, // JMP opcode (1-byte displacement)
|
||||
LOCK: 0xF0,
|
||||
REPNZ: 0xF2,
|
||||
REPZ: 0xF3,
|
||||
CALLW: 0x10FF,
|
||||
CALLDW: 0x18FF,
|
||||
LOCK: 0xF0,
|
||||
REPNZ: 0xF2,
|
||||
REPZ: 0xF3,
|
||||
CALLW: 0x10FF,
|
||||
CALLDW: 0x18FF,
|
||||
UD2: 0x0B0F // UD2 (invalid opcode guaranteed to generate UD_FAULT on all post-8086 processors)
|
||||
}
|
||||
};
|
||||
|
|
@ -288,9 +288,9 @@ X86.PS.SET = (X86.PS.BIT1 | X86.PS.IOPL | X86.PS.NT | X86.PS.BIT15);
|
|||
/*
|
||||
* getPS() brings all the direct and indirect flags together, and setPS() performs the
|
||||
* reverse, setting all the corresponding "result registers" to match the indirect flags.
|
||||
*
|
||||
*
|
||||
* These "result registers" are created/reset by an initial call to setPS(0); they include:
|
||||
*
|
||||
*
|
||||
* this.resultSize (must be set to one of: SIZE_BYTE or SIZE_WORD)
|
||||
* this.resultValue
|
||||
* this.resultParitySign
|
||||
|
|
|
|||
|
|
@ -122,21 +122,20 @@ function X86CPU(parmsCPU) {
|
|||
* "INT 0x00" generated by a divide-by-zero or any other kind of interrupt (nor any interrupt simulated
|
||||
* with "PUSHF/CALLF").
|
||||
*
|
||||
* aInterruptReturn is a stack of return address notifications set up by software interrupt notification
|
||||
* aInterruptReturn is a hash of return address notifications set up by software interrupt notification
|
||||
* functions that want to receive return notifications. A software interrupt function must call
|
||||
* cpu.addInterruptReturn(fn).
|
||||
*
|
||||
* WARNING: There's no specific mechanism in place to insure that software interrupt return notifications
|
||||
* don't get "orphaned" and stack up if an interrupt handler bypasses the normal return path (INT 0x24 is
|
||||
* one example of an "evil" software interrupt). So use this feature sparingly, avoid "evil" software
|
||||
* interrupts, and/or add a mechanism to detect and clean up orphans.
|
||||
* WARNING: There's no mechanism in place to insure that software interrupt return notifications don't
|
||||
* get "orphaned" if an interrupt handler bypasses the normal return path (INT 0x24 is one example of an
|
||||
* "evil" software interrupt).
|
||||
*/
|
||||
this.aInterruptNotify = [];
|
||||
this.aInterruptReturn = [];
|
||||
|
||||
/*
|
||||
* Since aReturnNotify is a "sparse array", this global count gives the CPU a quick way of knowing whether
|
||||
* or not RETF or IRET instructions need to bother checking the array.
|
||||
* or not RETF or IRET instructions need to bother calling checkInterruptReturn().
|
||||
*/
|
||||
this.cInterruptReturn = 0;
|
||||
|
||||
|
|
@ -931,27 +930,27 @@ X86CPU.prototype.checkInterruptNotify = function(nInt)
|
|||
X86CPU.prototype.addInterruptReturn = function(addr, fn)
|
||||
{
|
||||
if (fn !== undefined) {
|
||||
if (this.aInterruptReturn[addr] === undefined)
|
||||
this.aInterruptReturn[addr] = [];
|
||||
this.aInterruptReturn[addr].push(fn);
|
||||
this.cInterruptReturn++;
|
||||
if (this.aInterruptReturn[addr] == null) {
|
||||
this.cInterruptReturn++;
|
||||
}
|
||||
this.aInterruptReturn[addr] = fn;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* checkInterruptReturn(addr)
|
||||
*
|
||||
* It is expected (though not required) that callers will check cInterruptReturn and avoid calling
|
||||
* this function if the count is zero.
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} addr is a physical (non-segmented) address
|
||||
*/
|
||||
X86CPU.prototype.checkInterruptReturn = function(addr)
|
||||
{
|
||||
var aNotify = this.aInterruptReturn[addr];
|
||||
if (aNotify !== undefined) {
|
||||
while (aNotify.length > 0) {
|
||||
var fn = aNotify.pop();
|
||||
fn(--this.cInterruptReturn);
|
||||
}
|
||||
var fn = this.aInterruptReturn[addr];
|
||||
if (fn != null) {
|
||||
fn(--this.cInterruptReturn);
|
||||
delete this.aInterruptReturn[addr];
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2329,8 +2329,8 @@ var X86OpXX = {
|
|||
}
|
||||
if (nReps--) {
|
||||
/*
|
||||
* NOTE: Storing a word imposes another 4-cycle penalty on the 8088, so consider that if you think the
|
||||
* cycle times here are too high.
|
||||
* NOTE: Storing a word imposes another 4-cycle penalty on the 8088, so consider that
|
||||
* if you think the cycle times here are too high.
|
||||
*/
|
||||
this.setSOWord(this.segES, this.regDI, this.regAX);
|
||||
this.regDI = (this.regDI + ((this.regPS & X86.PS.DF)? -2 : 2)) & 0xffff;
|
||||
|
|
|
|||
|
|
@ -118,8 +118,8 @@ X86Seg.loadProt = function loadProt(sel, fSuppress)
|
|||
|
||||
/*
|
||||
* TODO: This is only the first of many steps toward accurately counting cycles in protected mode;
|
||||
* I simply noticed that "POP segreg" takes 5 cycles in real mode and 20 in protected mode, so I'm
|
||||
* starting with a 15-cycle penalty. Obviously the penalty will be much greater when the load fails.
|
||||
* I simply noted that "POP segreg" takes 5 cycles in real mode and 20 in protected mode, so I'm
|
||||
* starting with a 15-cycle difference. Obviously the difference will be much greater when the load fails.
|
||||
*/
|
||||
this.cpu.nStepCycles -= 15;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue