Enhanced INT return handling, and reorganized some disks.

This commit is contained in:
Jeff Parsons 2014-12-13 10:09:12 -08:00 committed by jeffpar
commit 27359de735
140 changed files with 701 additions and 503 deletions

View file

@ -199,8 +199,9 @@ function loadMachine(sFile)
* do with "package.json". Also note that require() assumes the same path as that of the
* requiring file, whereas fs.readFileSync() assumes the path reported by process.cwd().
*
* TODO: Actually, I removed the comments from my sample "machine.json" file, so we should
* try to reinstate this code now.
* TODO: I've since removed the comments from my sample "machine.json" file, so we could
* try to reinstate this code; however, there are still hex constants, which I find *much*
* preferable to the decimal equivalents. JSON's restrictions continue to infuriate me.
*
* var machine = require(lib + "../bin/" +sFile);
*/

View file

@ -1333,17 +1333,17 @@ ChipSet.prototype.getRTCCycleLimit = function(nCycles)
if (nCyclesUpdate > 0) {
if (nCycles > nCyclesUpdate) {
if (DEBUG && this.messageEnabled(Messages.RTC)) {
this.messageDebugger("getRTCCycleLimit(" + nCycles + "): reduced to " + nCyclesUpdate + " cycles", true);
this.messagePrint("getRTCCycleLimit(" + nCycles + "): reduced to " + nCyclesUpdate + " cycles", true);
}
nCycles = nCyclesUpdate;
} else {
if (DEBUG && this.messageEnabled(Messages.RTC)) {
this.messageDebugger("getRTCCycleLimit(" + nCycles + "): already less than " + nCyclesUpdate + " cycles", true);
this.messagePrint("getRTCCycleLimit(" + nCycles + "): already less than " + nCyclesUpdate + " cycles", true);
}
}
} else {
if (DEBUG && this.messageEnabled(Messages.RTC)) {
this.messageDebugger("RTC next update has passed by " + nCyclesUpdate + " cycles", true);
this.messagePrint("RTC next update has passed by " + nCyclesUpdate + " cycles", true);
}
}
}
@ -1402,9 +1402,9 @@ ChipSet.prototype.updateRTCTime = function()
if (DEBUG) {
if (nCyclesUpdate - this.nRTCCyclesNextUpdate > this.nRTCCyclesPerPeriod) {
if (bPrev & ChipSet.CMOS.STATUSC.PF) {
this.messageDebugger("RTC interrupt handler failed to clear STATUSC", Messages.RTC);
this.messagePrint("RTC interrupt handler failed to clear STATUSC", Messages.RTC);
} else {
this.messageDebugger("CPU took too long trigger new RTC periodic interrupt", Messages.RTC);
this.messagePrint("CPU took too long trigger new RTC periodic interrupt", Messages.RTC);
}
}
}
@ -2714,7 +2714,7 @@ ChipSet.prototype.requestDMA = function(iDMAChannel, done)
if (!channel.component || !channel.fnTransfer || !channel.obj) {
if (DEBUG && this.messageEnabled(Messages.DMA | Messages.DATA)) {
this.messageDebugger("requestDMA(" + iDMAChannel + "): not connected to a component", true);
this.messagePrint("requestDMA(" + iDMAChannel + "): not connected to a component", true);
}
if (done) done(true);
return;
@ -2731,7 +2731,7 @@ ChipSet.prototype.requestDMA = function(iDMAChannel, done)
if (channel.masked) {
if (DEBUG && this.messageEnabled(Messages.DMA | Messages.DATA)) {
this.messageDebugger("requestDMA(" + iDMAChannel + "): channel masked, request queued", true);
this.messagePrint("requestDMA(" + iDMAChannel + "): channel masked, request queued", true);
}
return;
}
@ -2784,7 +2784,7 @@ ChipSet.prototype.advanceDMA = function(channel, fInit)
if (DEBUG && DEBUGGER && channel.sAddrDebug === null) {
channel.sAddrDebug = str.toHex(addr >> 4, 4) + ":" + str.toHex(addr & 0xf, 4);
if (this.messageEnabled(this.messageBitsDMA(iDMAChannel)) && channel.xfer != ChipSet.DMA_MODE.XFER_WRITE) {
this.messageDebugger("advanceDMA(" + iDMAChannel + ") transferring " + channel.cbDebug + " bytes from " + channel.sAddrDebug, true);
this.messagePrint("advanceDMA(" + iDMAChannel + ") transferring " + channel.cbDebug + " bytes from " + channel.sAddrDebug, true);
this.dbg.doDump("db", channel.sAddrDebug, "l" + Math.floor((channel.cbDebug + 15) / 16));
}
}
@ -2795,7 +2795,7 @@ ChipSet.prototype.advanceDMA = function(channel, fInit)
if (b < 0) {
if (!channel.fWarning) {
if (DEBUG && obj.messageEnabled(Messages.DMA)) {
obj.messageDebugger("advanceDMA(" + iDMAChannel + ") ran out of data, assuming 0xff", true);
obj.messagePrint("advanceDMA(" + iDMAChannel + ") ran out of data, assuming 0xff", true);
}
channel.fWarning = true;
}
@ -2844,7 +2844,7 @@ ChipSet.prototype.advanceDMA = function(channel, fInit)
}
else {
if (DEBUG && this.messageEnabled(Messages.DMA | Messages.WARN)) {
this.messageDebugger("advanceDMA(" + iDMAChannel + ") unsupported xfer mode: " + str.toHexWord(channel.xfer), true);
this.messagePrint("advanceDMA(" + iDMAChannel + ") unsupported xfer mode: " + str.toHexWord(channel.xfer), true);
}
channel.fError = true;
}
@ -2898,7 +2898,7 @@ ChipSet.prototype.updateDMA = function(channel)
}
if (DEBUG && this.messageEnabled(this.messageBitsDMA(iDMAChannel)) && channel.xfer == ChipSet.DMA_MODE.XFER_WRITE && channel.sAddrDebug) {
this.messageDebugger("updateDMA(" + iDMAChannel + ") transferred " + channel.cbDebug + " bytes to " + channel.sAddrDebug, true);
this.messagePrint("updateDMA(" + iDMAChannel + ") transferred " + channel.cbDebug + " bytes to " + channel.sAddrDebug, true);
this.dbg.doDump("db", channel.sAddrDebug, "l" + Math.floor((channel.cbDebug + 15) / 16));
}
@ -3041,22 +3041,22 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
var nIRQ = (nIRL == null? undefined : pic.nIRQBase + nIRL);
if (pic.bISR & bIREnd) {
if (DEBUG && this.messageEnabled(this.messageBitsIRQ(nIRQ))) {
this.messageDebugger("outPIC" + iPIC + "(0x" + str.toHexByte(pic.port) + "): IRQ " + nIRQ + " going out of service", true);
this.messagePrint("outPIC" + iPIC + "(0x" + str.toHexByte(pic.port) + "): IRQ " + nIRQ + " going out of service", true);
}
pic.bISR &= ~bIREnd;
this.checkIRR();
} else {
if (DEBUG && this.messageEnabled(Messages.PIC | Messages.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(0x" + str.toHexByte(pic.port) + "): unexpected EOI command, IRQ " + nIRQ + " not in service", true);
this.messagePrint("outPIC" + iPIC + "(0x" + str.toHexByte(pic.port) + "): unexpected EOI command, IRQ " + nIRQ + " not in service", true);
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)
*/
if (DEBUG && (bOCW2 & ChipSet.PIC_LO.OCW2_SET_ROTAUTO) && this.messageEnabled(Messages.PIC | Messages.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(0x" + str.toHexByte(pic.port) + "): unsupported OCW2 rotate command: " + str.toHexByte(bOut), true);
this.dbg.stopCPU();
if (bOCW2 & ChipSet.PIC_LO.OCW2_SET_ROTAUTO) {
this.notice("PIC" + iPIC + "(0x" + str.toHexByte(pic.port) + "): unsupported OCW2 rotate command: " + str.toHexByte(bOut));
this.cpu.stopCPU();
}
}
else if (bOCW2 == ChipSet.PIC_LO.OCW2_SET_PRI) {
@ -3069,10 +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
*/
if (DEBUG && this.messageEnabled(Messages.PIC | Messages.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(0x" + str.toHexByte(pic.port) + "): unsupported OCW2 automatic EOI command: " + str.toHexByte(bOut), true);
this.dbg.stopCPU();
}
this.notice("PIC" + iPIC + "(0x" + str.toHexByte(pic.port) + "): unsupported OCW2 automatic EOI command: " + str.toHexByte(bOut));
this.cpu.stopCPU();
}
} else {
/*
@ -3082,9 +3080,8 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
* that's unfortunate, because I don't support them yet.
*/
if (bOut & (ChipSet.PIC_LO.OCW3_POLL_CMD | ChipSet.PIC_LO.OCW3_SMM_CMD)) {
if (DEBUG && this.messageEnabled(Messages.PIC | Messages.WARN)) {
this.messageDebugger("outPIC" + iPIC + "(0x" + str.toHexByte(pic.port) + "): unsupported OCW3 command: " + str.toHexByte(bOut), true);
}
this.notice("PIC" + iPIC + "(0x" + str.toHexByte(pic.port) + "): unsupported OCW3 command: " + str.toHexByte(bOut));
this.cpu.stopCPU();
}
pic.bOCW3 = bOut;
}
@ -3179,7 +3176,7 @@ ChipSet.prototype.setIRR = function(nIRQ, nDelay)
if (!(pic.bIRR & bIRR)) {
pic.bIRR |= bIRR;
if (DEBUG && this.messageEnabled(this.messageBitsIRQ(nIRQ) | Messages.CHIPSET)) {
this.messageDebugger("setIRR(" + nIRQ + ")", true);
this.messagePrint("setIRR(" + nIRQ + ")", true);
}
pic.nDelay = nDelay || 0;
this.checkIRR();
@ -3201,7 +3198,7 @@ ChipSet.prototype.clearIRR = function(nIRQ)
if (pic.bIRR & bIRR) {
pic.bIRR &= ~bIRR;
if (DEBUG && this.messageEnabled(this.messageBitsIRQ(nIRQ) | Messages.CHIPSET)) {
this.messageDebugger("clearIRR(" + nIRQ + ")", true);
this.messagePrint("clearIRR(" + nIRQ + ")", true);
}
this.checkIRR();
}
@ -3328,7 +3325,7 @@ ChipSet.prototype.getIRRVector = function(iPIC)
var nIRQ = pic.nIRQBase + nIRL;
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), true);
this.messagePrint("getIRRVector(): IRQ " + nIRQ + " interrupting @" + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel) + " stack=" + str.toHexAddr(this.cpu.regSP, this.cpu.segSS.sel), true);
}
if (MAXDEBUG && DEBUGGER) {
this.acInterrupts[nIRQ]++;
@ -3444,7 +3441,7 @@ ChipSet.prototype.outTimer = function(iTimer, bOut, addrFrom)
ChipSet.prototype.inTimerCtrl = function(port, addrFrom)
{
this.messagePort(port, null, addrFrom, "TIMER_CTRL", null, Messages.TIMER);
if (DEBUG) this.messageDebugger("TIMER_CTRL: Read-Back command not supported (yet)", Messages.TIMER);
if (DEBUG) this.messagePrint("TIMER_CTRL: Read-Back command not supported (yet)", Messages.TIMER);
return null;
};
@ -3465,7 +3462,7 @@ ChipSet.prototype.outTimerCtrl = function(port, bOut, addrFrom)
*/
var iTimer = (bOut & ChipSet.TIMER_CTRL.SC) >> 6;
if (iTimer == 0x3) {
if (DEBUG) this.messageDebugger("TIMER_CTRL: Read-Back command not supported (yet)", Messages.TIMER);
if (DEBUG) this.messagePrint("TIMER_CTRL: Read-Back command not supported (yet)", Messages.TIMER);
return;
}
/*
@ -3517,7 +3514,7 @@ ChipSet.prototype.outTimerCtrl = function(port, bOut, addrFrom)
timer.countStart[1] = timer.countInit[1];
timer.nCyclesStart = this.cpu.getCycles(this.fScaleTimers);
if (DEBUG && this.messageEnabled(Messages.TIMER)) {
this.messageDebugger("TIMER0 count reset @" + timer.nCyclesStart + " cycles", true);
this.messagePrint("TIMER0 count reset @" + timer.nCyclesStart + " cycles", true);
}
}
}
@ -3720,7 +3717,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
if (ticksElapsed < 0) {
if (DEBUG && this.messageEnabled(Messages.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): negative tick count (" + ticksElapsed + ")", true);
this.messagePrint("updateTimer(" + iTimer + "): negative tick count (" + ticksElapsed + ")", true);
}
timer.nCyclesStart = nCycles;
ticksElapsed = 0;
@ -3740,7 +3737,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
if (timer.mode == ChipSet.TIMER_CTRL.MODE0) {
if (count <= 0) count = 0;
if (DEBUG && this.messageEnabled(Messages.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): MODE0 timer count=" + count, true);
this.messagePrint("updateTimer(" + iTimer + "): MODE0 timer count=" + count, true);
}
if (!count) {
timer.fOUT = true;
@ -3775,7 +3772,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
count = countInit + count;
if (count <= 0) {
if (DEBUG && this.messageEnabled(Messages.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): underflow=" + count, true);
this.messagePrint("updateTimer(" + iTimer + "): underflow=" + count, true);
}
count = countInit;
}
@ -3807,7 +3804,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
count = countInit + count;
if (count <= 0) {
if (DEBUG && this.messageEnabled(Messages.TIMER)) {
this.messageDebugger("updateTimer(" + iTimer + "): underflow=" + count, true);
this.messagePrint("updateTimer(" + iTimer + "): underflow=" + count, true);
}
count = countInit;
}
@ -4290,7 +4287,7 @@ ChipSet.prototype.out8042InBuffCmd = function(port, bOut, addrFrom)
case ChipSet.KBC.CMD.DISABLE_KBD: // 0xAD
this.set8042CmdData(this.b8042CmdData | ChipSet.KBC.DATA.CMD.NO_CLOCK);
if (DEBUG) this.messageDebugger("keyboard disabled", Messages.KEYBOARD | Messages.PORT);
if (DEBUG) this.messagePrint("keyboard disabled", Messages.KEYBOARD | Messages.PORT);
/*
* NOTE: The MODEL_5170 BIOS calls "KBD_RESET" (F000:17D2) while the keyboard interface is disabled,
* yet we must still deliver the Keyboard's CMDRES.BAT_OK response code? Seems like an odd thing for
@ -4301,13 +4298,13 @@ ChipSet.prototype.out8042InBuffCmd = function(port, bOut, addrFrom)
case ChipSet.KBC.CMD.ENABLE_KBD: // 0xAE
this.set8042CmdData(this.b8042CmdData & ~ChipSet.KBC.DATA.CMD.NO_CLOCK);
if (this.kbd) this.kbd.checkScanCode();
if (DEBUG) this.messageDebugger("keyboard re-enabled", Messages.KEYBOARD | Messages.PORT);
if (DEBUG) this.messagePrint("keyboard re-enabled", Messages.KEYBOARD | Messages.PORT);
break;
case ChipSet.KBC.CMD.SELF_TEST: // 0xAA
if (this.kbd) this.kbd.flushScanCode();
this.set8042CmdData(this.b8042CmdData | ChipSet.KBC.DATA.CMD.NO_CLOCK);
if (DEBUG) this.messageDebugger("keyboard disabled on reset", Messages.KEYBOARD | Messages.PORT);
if (DEBUG) this.messagePrint("keyboard disabled on reset", Messages.KEYBOARD | Messages.PORT);
this.set8042OutBuff(ChipSet.KBC.DATA.SELF_TEST.OK);
this.set8042OutPort(ChipSet.KBC.OUTPORT.NO_RESET | ChipSet.KBC.OUTPORT.A20_ON);
break;
@ -4329,7 +4326,7 @@ ChipSet.prototype.out8042InBuffCmd = function(port, bOut, addrFrom)
default:
if (DEBUG && this.messageEnabled(Messages.C8042)) {
this.messageDebugger("unrecognized 8042 command: " + str.toHexByte(this.b8042InBuff), true);
this.messagePrint("unrecognized 8042 command: " + str.toHexByte(this.b8042InBuff), true);
this.dbg.stopCPU();
}
break;
@ -4382,7 +4379,7 @@ ChipSet.prototype.set8042OutBuff = function(b)
this.b8042Status &= ~ChipSet.KBC.STATUS.OUTBUFF_FULL;
this.b8042Status |= ChipSet.KBC.STATUS.OUTBUFF_DELAY;
if (DEBUG && this.messageEnabled(Messages.KEYBOARD | Messages.PORT)) {
this.messageDebugger("set8042OutBuff(0x" + str.toHexByte(b) + ")", true);
this.messagePrint("set8042OutBuff(0x" + str.toHexByte(b) + ")", true);
}
}
};
@ -4404,7 +4401,7 @@ ChipSet.prototype.set8042OutPort = function(b)
* determine if that's what the caller intended.
*/
if (DEBUG && this.messageEnabled(Messages.C8042)) {
this.messageDebugger("unexpected 8042 output port reset: " + str.toHexByte(b), true);
this.messagePrint("unexpected 8042 output port reset: " + str.toHexByte(b), true);
this.dbg.stopCPU();
}
this.cpu.resetRegs();
@ -4514,12 +4511,12 @@ ChipSet.prototype.notifyKbdData = function(b)
}
else {
if (DEBUG && this.messageEnabled(Messages.KEYBOARD | Messages.PORT)) {
this.messageDebugger("notifyKbdData(0x" + str.toHexByte(b) + "): output buffer full", true);
this.messagePrint("notifyKbdData(0x" + str.toHexByte(b) + "): output buffer full", true);
}
}
} else {
if (DEBUG && this.messageEnabled(Messages.KEYBOARD | Messages.PORT)) {
this.messageDebugger("notifyKbdData(0x" + str.toHexByte(b) + "): disabled", true);
this.messagePrint("notifyKbdData(0x" + str.toHexByte(b) + "): disabled", true);
}
}
}
@ -4582,7 +4579,7 @@ ChipSet.prototype.inCMOSData = function(port, addrFrom)
* occurs in a timely manner, too.
*/
if ((bIn & ChipSet.CMOS.STATUSC.PF) && (this.abCMOSData[ChipSet.CMOS.ADDR.STATUSB] & ChipSet.CMOS.STATUSB.PIE)) {
if (DEBUG) this.messageDebugger("RTC periodic interrupt cleared", Messages.RTC);
if (DEBUG) this.messagePrint("RTC periodic interrupt cleared", Messages.RTC);
this.setRTCCycleLimit();
}
}
@ -4608,10 +4605,10 @@ ChipSet.prototype.outCMOSData = function(port, bOut, addrFrom)
this.abCMOSData[bAddr] = (bAddr <= ChipSet.CMOS.ADDR.STATUSD? this.setRTCByte(bAddr, bOut) : bOut);
if (bAddr == ChipSet.CMOS.ADDR.STATUSB && (bDelta & ChipSet.CMOS.STATUSB.PIE)) {
if (bOut & ChipSet.CMOS.STATUSB.PIE) {
if (DEBUG) this.messageDebugger("RTC periodic interrupts enabled", Messages.RTC);
if (DEBUG) this.messagePrint("RTC periodic interrupts enabled", Messages.RTC);
this.setRTCCycleLimit();
} else {
if (DEBUG) this.messageDebugger("RTC periodic interrupts disabled", Messages.RTC);
if (DEBUG) this.messagePrint("RTC periodic interrupts disabled", Messages.RTC);
}
}
};
@ -4791,13 +4788,13 @@ ChipSet.prototype.setSpeaker = function(fOn)
if (fOn) {
if (this.sourceAudio) {
this.sourceAudio['frequency']['value'] = freq;
if (this.messageEnabled(Messages.SPEAKER)) this.messageDebugger("speaker set to " + freq + "hz", true);
if (this.messageEnabled(Messages.SPEAKER)) this.messagePrint("speaker set to " + freq + "hz", true);
} else {
this.sourceAudio = this.contextAudio['createOscillator']();
this.sourceAudio['type'] = 1; // 0: sine wave, 1: square wave, 2: sawtooth wave, 3: triangle wave
this.sourceAudio['connect'](this.contextAudio['destination']);
this.sourceAudio['frequency']['value'] = freq;
if (this.messageEnabled(Messages.SPEAKER)) this.messageDebugger("speaker on at " + freq + "hz", true);
if (this.messageEnabled(Messages.SPEAKER)) this.messagePrint("speaker on at " + freq + "hz", true);
this.sourceAudio['noteOn'](0); // aka start()
}
} else {
@ -4805,11 +4802,11 @@ ChipSet.prototype.setSpeaker = function(fOn)
this.sourceAudio['noteOff'](0); // aka stop()
this.sourceAudio['disconnect'](); // QUESTION: is this automatic following a stop(), since this particular source cannot be started again?
delete this.sourceAudio; // QUESTION: ditto?
if (this.messageEnabled(Messages.SPEAKER)) this.messageDebugger("speaker off at " + freq + "hz", true);
if (this.messageEnabled(Messages.SPEAKER)) this.messagePrint("speaker off at " + freq + "hz", true);
}
}
} else if (fOn) {
this.messageDebugger("BEEP", Messages.SPEAKER);
this.messagePrint("BEEP", Messages.SPEAKER);
}
};

View file

@ -174,7 +174,7 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
}
}
if (DEBUG && this.messageEnabled()) this.messageDebugger("PREFETCH: " + PREFETCH + ", TYPEDARRAYS: " + TYPEDARRAYS);
if (DEBUG && this.messageEnabled()) this.messagePrint("PREFETCH: " + PREFETCH + ", TYPEDARRAYS: " + TYPEDARRAYS);
/*
* Iterate through all the components again and call their initBus() handler, if any
@ -320,7 +320,7 @@ Computer.prototype.onLoadSetReady = function(sStateFile, sStateData, nErrorCode)
if (!nErrorCode) {
this.sStateData = sStateData;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("loaded state file " + sStateFile.replace(this.sUserID || "xxx", "xxx"));
this.messagePrint("loaded state file " + sStateFile.replace(this.sUserID || "xxx", "xxx"));
}
} else {
this.sResumePath = null;
@ -362,7 +362,7 @@ Computer.prototype.wait = function(fn, parms)
return;
}
}
if (DEBUG && this.messageEnabled()) this.messageDebugger("Computer.wait(ready)");
if (DEBUG && this.messageEnabled()) this.messagePrint("Computer.wait(ready)");
fn.call(this, parms);
};
@ -388,7 +388,7 @@ Computer.prototype.validateState = function(stateComputer)
if (!stateComputer) stateValidate.clear();
} else {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Last state: " + sTimestampComputer + " (validate: " + sTimestampValidate + ")");
this.messagePrint("Last state: " + sTimestampComputer + " (validate: " + sTimestampValidate + ")");
}
}
}
@ -410,7 +410,7 @@ Computer.prototype.powerOn = function(resume)
}
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Computer.powerOn(" + (resume == Computer.RESUME_REPOWER ? "repower" : (resume ? "resume" : "")) + ")");
this.messagePrint("Computer.powerOn(" + (resume == Computer.RESUME_REPOWER ? "repower" : (resume ? "resume" : "")) + ")");
}
var fRepower = false;
@ -649,7 +649,7 @@ Computer.prototype.donePowerOn = function(aParms)
var fRestore = aParms[2];
if (DEBUG && this.aFlags.fPowered && this.messageEnabled()) {
this.messageDebugger("Computer.donePowerOn(): redundant");
this.messagePrint("Computer.donePowerOn(): redundant");
}
this.aFlags.fPowered = true;
@ -735,7 +735,7 @@ Computer.prototype.powerOff = function(fSave, fShutdown)
var sState = "none";
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Computer.powerOff(" + (fSave ? "save" : "nosave") + (fShutdown ? ",shutdown" : "") + ")");
this.messagePrint("Computer.powerOff(" + (fSave ? "save" : "nosave") + (fShutdown ? ",shutdown" : "") + ")");
}
var stateComputer = new State(this, Computer.sAppVer);
@ -842,14 +842,14 @@ Computer.prototype.powerOff = function(fSave, fShutdown)
Computer.prototype.reset = function()
{
if (this.bus && this.bus.reset) {
this.messageDebugger("Resetting " + this.bus.type);
this.messagePrint("Resetting " + this.bus.type);
this.bus.reset();
}
var aComponents = Component.getComponents(this.id);
for (var iComponent = 0; iComponent < aComponents.length; iComponent++) {
var component = aComponents[iComponent];
if (component !== this && component !== this.bus && component.reset) {
this.messageDebugger("Resetting " + component.type);
this.messagePrint("Resetting " + component.type);
component.reset();
}
}
@ -989,7 +989,7 @@ Computer.prototype.verifyUserID = function(sUserID)
{
this.sUserID = null;
var fMessages = DEBUG && this.messageEnabled();
if (fMessages) this.messageDebugger("verifyUserID(" + sUserID + ")");
if (fMessages) this.messagePrint("verifyUserID(" + sUserID + ")");
var sRequest = web.getHost() + UserAPI.ENDPOINT + '?' + UserAPI.QUERY.REQ + '=' + UserAPI.REQ.VERIFY + '&' + UserAPI.QUERY.USER + '=' + sUserID;
var response = web.loadResource(sRequest);
var nErrorCode = response[0];
@ -999,16 +999,16 @@ Computer.prototype.verifyUserID = function(sUserID)
response = eval("(" + sResponse + ")");
if (response.code && response.code == UserAPI.CODE.OK) {
web.setLocalStorageItem(Computer.STATE_USERID, response.data);
if (fMessages) this.messageDebugger(Computer.STATE_USERID + " updated: " + response.data);
if (fMessages) this.messagePrint(Computer.STATE_USERID + " updated: " + response.data);
this.sUserID = response.data;
} else {
if (fMessages) this.messageDebugger(response.code + ": " + response.data);
if (fMessages) this.messagePrint(response.code + ": " + response.data);
}
} catch (e) {
Component.error(e.message + " (" + sResponse + ")");
}
} else {
if (fMessages) this.messageDebugger("invalid response (error " + nErrorCode + ")");
if (fMessages) this.messagePrint("invalid response (error " + nErrorCode + ")");
}
return this.sUserID;
};
@ -1024,12 +1024,12 @@ Computer.prototype.getServerStatePath = function()
var sStatePath = null;
if (this.sUserID) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger(Computer.STATE_USERID + " for load: " + this.sUserID);
this.messagePrint(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);
} else {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger(Computer.STATE_USERID + " unavailable");
this.messagePrint(Computer.STATE_USERID + " unavailable");
}
}
return sStatePath;
@ -1051,7 +1051,7 @@ Computer.prototype.saveServerState = function(sUserID, sState)
*/
if (sState) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("size of server state: " + sState.length + " bytes");
this.messagePrint("size of server state: " + sState.length + " bytes");
}
var response = this.storeServerState(sUserID, sState, true);
if (response && response[UserAPI.RES.CODE] == UserAPI.CODE.OK) {
@ -1068,7 +1068,7 @@ Computer.prototype.saveServerState = function(sUserID, sState)
}
} else {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("no state to store");
this.messagePrint("no state to store");
}
}
};
@ -1085,7 +1085,7 @@ Computer.prototype.saveServerState = function(sUserID, sState)
Computer.prototype.storeServerState = function(sUserID, sState, fSync)
{
if (DEBUG && this.messageEnabled()) {
this.messageDebugger(Computer.STATE_USERID + " for store: " + sUserID);
this.messagePrint(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,
@ -1110,7 +1110,7 @@ Computer.prototype.storeServerState = function(sUserID, sState, fSync)
}
sResponse = '{"' + UserAPI.RES.CODE + '":' + response[0] + ',"' + UserAPI.RES.DATA + '":"' + sResponse + '"}';
}
if (DEBUG && this.messageEnabled()) this.messageDebugger(sResponse);
if (DEBUG && this.messageEnabled()) this.messagePrint(sResponse);
return JSON.parse(sResponse);
}
return null;
@ -1219,7 +1219,7 @@ Computer.init = function()
var computer = new Computer(parmsComputer, parmsMachine, true);
if (DEBUG && computer.messageEnabled()) {
computer.messageDebugger("onInit(" + computer.aFlags.fPowered + ")");
computer.messagePrint("onInit(" + computer.aFlags.fPowered + ")");
}
/*
@ -1251,7 +1251,7 @@ Computer.show = function()
if (computer) {
if (DEBUG && computer.messageEnabled()) {
computer.messageDebugger("onShow(" + computer.fInitialized + "," + computer.aFlags.fPowered + ")");
computer.messagePrint("onShow(" + computer.fInitialized + "," + computer.aFlags.fPowered + ")");
}
if (computer.fInitialized && !computer.aFlags.fPowered) {
@ -1300,7 +1300,7 @@ Computer.exit = function()
if (computer) {
if (DEBUG && computer.messageEnabled()) {
computer.messageDebugger("onExit(" + computer.aFlags.fPowered + ")");
computer.messagePrint("onExit(" + computer.aFlags.fPowered + ")");
}
if (computer.aFlags.fPowered) {

View file

@ -1583,6 +1583,41 @@ if (DEBUGGER) {
this.aMessageRegs[asRegs[20]] = str.toHexWord(cpu.regIP);
};
/**
* message(sMessage, fAddress)
*
* @this {Debugger}
* @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, fAddress)
{
if (fAddress) {
sMessage += " @" + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel);
}
if (this.sMessagePrev && sMessage == this.sMessagePrev) return;
if (!SAMPLER) this.println(sMessage); // + " (" + this.cpu.getCycles() + " cycles)"
this.sMessagePrev = sMessage;
if (this.cpu) {
if (this.bitsMessage & Messages.HALT) {
this.cpu.stopCPU();
}
/*
* We have no idea what the frequency of println() calls might be; all we know is that they easily
* screw up the CPU's careful assumptions about cycles per burst. So we call yieldCPU() after every
* message, to effectively end the current burst and start fresh.
*
* TODO: See CPU.calcStartTime() for a discussion of why we might want to call yieldCPU() *before*
* we display the message.
*/
this.cpu.yieldCPU();
}
};
/**
* messageInt(nInt, addr)
*
@ -1668,41 +1703,6 @@ if (DEBUGGER) {
}
};
/**
* message(sMessage, fAddress)
*
* @this {Debugger}
* @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, fAddress)
{
if (fAddress) {
sMessage += " @" + str.toHexAddr(this.cpu.regIP, this.cpu.segCS.sel);
}
if (this.sMessagePrev && sMessage == this.sMessagePrev) return;
if (!SAMPLER) this.println(sMessage); // + " (" + this.cpu.getCycles() + " cycles)"
this.sMessagePrev = sMessage;
if (this.cpu) {
if (this.bitsMessage & Messages.HALT) {
this.cpu.stopCPU();
}
/*
* We have no idea what the frequency of println() calls might be; all we know is that they easily
* screw up the CPU's careful assumptions about cycles per burst. So we call yieldCPU() after every
* message, to effectively end the current burst and start fresh.
*
* TODO: See CPU.calcStartTime() for a discussion of why we might want to call yieldCPU() *before*
* we display the message.
*/
this.cpu.yieldCPU();
}
};
/**
* traceInit()
*

View file

@ -445,7 +445,7 @@ Disk.prototype.create = function(mode, nCylinders, nHeads, nSectors, cbSector)
*/
if (this.mode != DiskAPI.MODE.PRELOAD) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("blank disk for \"" + this.sDiskName + "\": " + this.nCylinders + " cylinders, " + this.nHeads + " head(s)");
this.messagePrint("blank disk for \"" + this.sDiskName + "\": " + this.nCylinders + " cylinders, " + this.nHeads + " head(s)");
}
var aCylinders = new Array(this.nCylinders);
for (var iCylinder = 0; iCylinder < aCylinders.length; iCylinder++) {
@ -506,7 +506,7 @@ Disk.prototype.load = function(sDiskName, sDiskPath, file, fnNotify, controller)
if (DEBUG) {
var sMessage = 'Disk.load("' + sDiskName + '","' + sDiskPath + '")';
this.controller.log(sMessage);
this.messageDebugger(sMessage);
this.messagePrint(sMessage);
}
if (this.fnNotify) {
@ -659,7 +659,7 @@ Disk.prototype.doneLoad = function(sDiskFile, sDiskData, nErrorCode, sDiskPath)
if (this.fOnDemand) {
if (!nErrorCode) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger('Disk.doneLoad("' + sDiskFile + '","' + sDiskPath + '")');
this.messagePrint('Disk.doneLoad("' + sDiskFile + '","' + sDiskPath + '")');
}
this.fRemote = true;
disk = this;
@ -678,7 +678,7 @@ Disk.prototype.doneLoad = function(sDiskFile, sDiskData, nErrorCode, sDiskPath)
this.controller.notice("Unable to load disk \"" + this.sDiskName + "\" (error " + nErrorCode + ")", fPrintOnly);
} else {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger('Disk.doneLoad("' + sDiskFile + '","' + sDiskPath + '")');
this.messagePrint('Disk.doneLoad("' + sDiskFile + '","' + sDiskPath + '")');
}
try {
/*
@ -776,7 +776,7 @@ Disk.prototype.doneLoad = function(sDiskFile, sDiskData, nErrorCode, sDiskPath)
var sHeads = nHeads + " head" + (nHeads > 1 ? "s" : "");
var nSectorsPerTrack = aDiskData[0][0].length;
var sSectorsPerTrack = nSectorsPerTrack + " sector" + (nSectorsPerTrack > 1 ? "s" : "") + "/track";
this.messageDebugger(sCylinders + ", " + sHeads + ", " + sSectorsPerTrack);
this.messagePrint(sCylinders + ", " + sHeads + ", " + sSectorsPerTrack);
}
/*
* Before the image is usable, we must "normalize" all the sectors. In the past, this meant
@ -920,7 +920,7 @@ Disk.prototype.onLoadParseSectors = function(sURLName, sURLData, nErrorCode, sec
fAsync = sectorInfo[4];
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.onLoadParseSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + ")");
this.messagePrint("Disk.onLoadParseSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + ")");
}
var abData = JSON.parse(sURLData);
@ -938,7 +938,7 @@ Disk.prototype.onLoadParseSectors = function(sURLName, sURLData, nErrorCode, sec
var sector = this.seek(iCylinder, iHead, iSector, true);
if (!sector) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.onLoadParseSectors(): seek(" + iCylinder + "," + iHead + "," + iSector + ") failed");
this.messagePrint("Disk.onLoadParseSectors(): seek(" + iCylinder + "," + iHead + "," + iSector + ") failed");
}
break;
}
@ -990,7 +990,7 @@ Disk.prototype.connectRemoteDisk = function(sDiskPath)
Disk.prototype.readRemoteSectors = function(iCylinder, iHead, iSector, cbSector, nSectors, done)
{
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.readRemoteSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + "," + cbSector + ")");
this.messagePrint("Disk.readRemoteSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + "," + cbSector + ")");
}
if (this.fRemote) {
@ -1030,7 +1030,7 @@ Disk.prototype.readRemoteSectors = function(iCylinder, iHead, iSector, cbSector,
Disk.prototype.writeRemoteSectors = function(iCylinder, iHead, iSector, nSectors, abSectors, fAsync)
{
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.writeRemoteSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + ")");
this.messagePrint("Disk.writeRemoteSectors(" + iCylinder + ":" + iHead + ":" + iSector + ":" + nSectors + ")");
}
if (this.fRemote) {
@ -1099,7 +1099,7 @@ Disk.prototype.queueDirtySector = function(sector, fAsync)
this.aDirtyTimestamps.push(usr.getTime());
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.queueDirtySector(" + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + "): " + this.aDirtySectors.length + " dirty");
this.messagePrint("Disk.queueDirtySector(" + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + "): " + this.aDirtySectors.length + " dirty");
}
return fAsync && this.updateWriteTimer();
@ -1170,7 +1170,7 @@ Disk.prototype.findDirtySectors = function(fAsync)
var j = this.aDirtySectors.indexOf(sectorNext);
this.assert(j >= 0, "dirty sector (" + iCylinder + ":" + iHead + ":" + sectorNext['sector'] + ") missing from aDirtySectors");
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.findDirtySectors(" + iCylinder + ":" + iHead + ":" + sectorNext['sector'] + ")");
this.messagePrint("Disk.findDirtySectors(" + iCylinder + ":" + iHead + ":" + sectorNext['sector'] + ")");
}
this.aDirtySectors.splice(j, 1);
this.aDirtyTimestamps.splice(j, 1);
@ -1207,7 +1207,7 @@ Disk.prototype.onWriteCleanSectors = function(sURLName, sURLData, nErrorCode, se
var sector = this.aDiskData[iCylinder][iHead][i];
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("Disk.onWriteCleanSectors(" + iCylinder + ":" + iHead + ":" + sector['sector'] + ")");
this.messagePrint("Disk.onWriteCleanSectors(" + iCylinder + ":" + iHead + ":" + sector['sector'] + ")");
}
if (!nErrorCode) {
@ -1306,7 +1306,7 @@ Disk.prototype.seek = function(iCylinder, iHead, iSector, fWrite, done)
return null;
} else {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger('Disk.seek("' + this.sDiskName + '"): uninitialized sector ' + iCylinder + ':' + iHead + ':' + iSector);
this.messagePrint('Disk.seek("' + this.sDiskName + '"): uninitialized sector ' + iCylinder + ':' + iHead + ':' + iSector);
}
}
}
@ -1385,7 +1385,7 @@ Disk.prototype.read = function(sector, ibSector, fCompare)
var b = -1;
if (DEBUG && !ibSector && !fCompare && this.messageEnabled()) {
this.messageDebugger("Disk.read(" + this.controller.id + ":" + this.drive.iDrive + "," + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + ")");
this.messagePrint("Disk.read(" + this.controller.id + ":" + this.drive.iDrive + "," + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + ")");
}
if (ibSector < sector['length']) {
@ -1412,7 +1412,7 @@ Disk.prototype.write = function(sector, ibSector, b)
return false;
if (DEBUG && !ibSector && this.messageEnabled()) {
this.messageDebugger("Disk.write(" + this.controller.id + ":" + this.drive.iDrive + "," + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + ")");
this.messagePrint("Disk.write(" + this.controller.id + ":" + this.drive.iDrive + "," + sector.iCylinder + ":" + sector.iHead + ":" + sector['sector'] + ")");
}
if (ibSector < sector['length']) {
@ -1484,7 +1484,7 @@ Disk.prototype.save = function()
}
}
if (DEBUG && this.messageEnabled()) {
this.messageDebugger('Disk.save("' + this.sDiskName + '"): saved ' + (deltas.length - 1) + ' change(s)');
this.messagePrint('Disk.save("' + this.sDiskName + '"): saved ' + (deltas.length - 1) + ' change(s)');
}
return deltas;
};
@ -1614,7 +1614,7 @@ Disk.prototype.restore = function(deltas)
this.controller.notice("unable to restore disk '" + this.sDiskName + ": " + sReason);
} else {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger('Disk.restore("' + this.sDiskName + '"): restored ' + nChanges + ' change(s)');
this.messagePrint('Disk.restore("' + this.sDiskName + '"): restored ' + nChanges + ' change(s)');
}
}
return nChanges;

View file

@ -776,7 +776,7 @@ FDC.prototype.initController = function(data)
this.regControl = data[i] || FDC.REG_CONTROL.RATE500K; // default to maximum data rate
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("FDC initialized for " + this.aDrives.length + " drive(s)");
this.messagePrint("FDC initialized for " + this.aDrives.length + " drive(s)");
}
return fSuccess;
};
@ -1282,7 +1282,7 @@ FDC.prototype.loadDiskette = function(iDrive, sDisketteName, sDiskettePath, fAut
if (fAutoMount) {
drive.fAutoMount = true;
this.cAutoMount++;
if (this.messageEnabled()) this.messageDebugger("loading diskette '" + sDisketteName + "'");
if (this.messageEnabled()) this.messagePrint("loading diskette '" + sDisketteName + "'");
}
drive.fLocal = !!file;
var disk = new Disk(this, drive, DiskAPI.MODE.PRELOAD);
@ -1531,13 +1531,13 @@ FDC.prototype.addDiskHistory = function(sDisketteName, sDiskettePath, disk)
if (this.aDiskHistory[i][1] == sDiskettePath) {
var nChanges = disk.restore(this.aDiskHistory[i][2]);
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("disk '" + sDisketteName + "' restored from history (" + nChanges + " changes)");
this.messagePrint("disk '" + sDisketteName + "' restored from history (" + nChanges + " changes)");
}
return;
}
}
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("disk '" + sDisketteName + "' added to history (nothing to restore)");
this.messagePrint("disk '" + sDisketteName + "' added to history (nothing to restore)");
}
this.aDiskHistory[i] = [sDisketteName, sDiskettePath, []];
};
@ -1556,13 +1556,13 @@ FDC.prototype.removeDiskHistory = function(sDisketteName, sDiskettePath)
if (this.aDiskHistory[i][1] == sDiskettePath) {
this.aDiskHistory.splice(i, 1);
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("disk '" + sDisketteName + "' removed from history");
this.messagePrint("disk '" + sDisketteName + "' removed from history");
}
return;
}
}
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("unable to remove disk '" + sDisketteName + "' from history (" + sDiskettePath + ")");
this.messagePrint("unable to remove disk '" + sDisketteName + "' from history (" + sDiskettePath + ")");
}
};
@ -1581,7 +1581,7 @@ FDC.prototype.updateDiskHistory = function(sDisketteName, sDiskettePath, disk)
if (this.aDiskHistory[i][1] == sDiskettePath) {
this.aDiskHistory[i][2] = disk.save();
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("disk '" + sDisketteName + "' updated in history");
this.messagePrint("disk '" + sDisketteName + "' updated in history");
}
return;
}
@ -1593,7 +1593,7 @@ FDC.prototype.updateDiskHistory = function(sDisketteName, sDiskettePath, disk)
* before unloading, the fact that the disk is no longer listed here can't be treated as an error.
*/
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("unable to update disk '" + sDisketteName + "' in history (" + sDiskettePath + ")");
this.messagePrint("unable to update disk '" + sDisketteName + "' in history (" + sDiskettePath + ")");
}
};
@ -1719,7 +1719,7 @@ FDC.prototype.outFDCData = function(port, bOut, addrFrom)
return;
}
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("unsupported FDC command: " + str.toHexByte(bCmd));
this.messagePrint("unsupported FDC command: " + str.toHexByte(bCmd));
this.dbg.stopCPU();
}
};
@ -1948,7 +1948,7 @@ FDC.prototype.doCmd = function()
default:
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("FDC operation unsupported (command=0x: " + str.toHexByte(bCmd) + ")");
this.messagePrint("FDC operation unsupported (command=0x: " + str.toHexByte(bCmd) + ")");
this.dbg.stopCPU();
}
break;
@ -2029,7 +2029,7 @@ FDC.prototype.popCmd = function(name)
if (DEBUG && this.messageEnabled(Messages.PORT | Messages.FDC)) {
var bCmdMasked = bCmd & FDC.REG_DATA.CMD.MASK;
if (!name && !this.regDataIndex && FDC.aCmdInfo[bCmdMasked]) name = FDC.aCmdInfo[bCmdMasked].name;
this.messageDebugger("FDC.CMD[" + (name || this.regDataIndex) + "]: 0x" + str.toHexByte(bCmd), true);
this.messagePrint("FDC.CMD[" + (name || this.regDataIndex) + "]: 0x" + str.toHexByte(bCmd), true);
}
this.regDataIndex++;
return bCmd;
@ -2081,7 +2081,7 @@ FDC.prototype.beginResult = function()
FDC.prototype.pushResult = function(bResult, name)
{
if (DEBUG && this.messageEnabled(Messages.PORT | Messages.FDC)) {
this.messageDebugger("FDC.RES[" + (name || this.regDataTotal) + "]: 0x" + str.toHexByte(bResult), true);
this.messagePrint("FDC.RES[" + (name || this.regDataTotal) + "]: 0x" + str.toHexByte(bResult), true);
}
this.regDataArray[this.regDataTotal++] = bResult;
};
@ -2147,7 +2147,7 @@ FDC.prototype.dmaRead = function(drive, b, done)
/*
* The DMA controller should be ASKING for data, not GIVING us data; this suggests an internal DMA miscommunication
*/
if (DEBUG) this.messageDebugger("dmaRead(): invalid DMA acknowledgement");
if (DEBUG) this.messagePrint("dmaRead(): invalid DMA acknowledgement");
done(-1, false);
};
@ -2166,7 +2166,7 @@ FDC.prototype.dmaWrite = function(drive, b)
/*
* The DMA controller should be GIVING us data, not ASKING for data; this suggests an internal DMA miscommunication
*/
if (DEBUG) this.messageDebugger("dmaWrite(): invalid DMA acknowledgement");
if (DEBUG) this.messagePrint("dmaWrite(): invalid DMA acknowledgement");
return -1;
};
@ -2185,7 +2185,7 @@ FDC.prototype.dmaFormat = function(drive, b)
/*
* The DMA controller should be GIVING us data, not ASKING for data; this suggests an internal DMA miscommunication
*/
if (DEBUG) this.messageDebugger("dmaFormat(): invalid DMA acknowledgement");
if (DEBUG) this.messagePrint("dmaFormat(): invalid DMA acknowledgement");
return -1;
};
@ -2205,7 +2205,7 @@ FDC.prototype.doRead = function(drive)
drive.resCode = FDC.REG_DATA.RES.NOT_READY | FDC.REG_DATA.RES.INCOMPLETE;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("FDC.doRead(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")");
this.messagePrint("FDC.doRead(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")");
}
if (drive.disk) {
@ -2229,7 +2229,7 @@ FDC.prototype.doWrite = function(drive)
drive.resCode = FDC.REG_DATA.RES.NOT_READY | FDC.REG_DATA.RES.INCOMPLETE;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("FDC.doWrite(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")");
this.messagePrint("FDC.doWrite(" + drive.bCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")");
}
if (drive.disk) {
@ -2429,7 +2429,7 @@ FDC.prototype.writeFormat = function(drive, b)
drive.nBytes = 128 << drive.abFormat[3];// N (0 => 128, 1 => 256, 2 => 512, 3 => 1024)
drive.cbFormat = 0;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("writeFormat(head=" + str.toHexByte(drive.bHead) + ",cyl=" + str.toHexByte(drive.bCylinder) + ",sec=" + str.toHexByte(drive.bSector) + ",len=" + str.toHexWord(drive.nBytes) + ")");
this.messagePrint("writeFormat(head=" + str.toHexByte(drive.bHead) + ",cyl=" + str.toHexByte(drive.bCylinder) + ",sec=" + str.toHexByte(drive.bSector) + ",len=" + str.toHexWord(drive.nBytes) + ")");
}
for (var i = 0; i < drive.nBytes; i++) {
if (this.writeByte(drive, drive.bFiller) < 0) {

View file

@ -139,7 +139,7 @@ HDC.aDriveTypes = [
0x00: [306, 2],
0x01: [375, 8],
0x02: [306, 6],
0x03: [306, 4] // <= default 'xt' drive type (10Mb)
0x03: [306, 4] // 10Mb (default XTC drive type)
},
/*
* Sadly, drive types differ across controller models (XTC drive types don't match ATC drive types),
@ -167,8 +167,8 @@ HDC.aDriveTypes = [
* 15 (reserved--all zeros)
*/
{
0x01: [306, 4],
0x02: [615, 4], // <= default 'at' drive type (20Mb)
0x01: [306, 4], // 10Mb
0x02: [615, 4], // 20Mb (default ATC drive type)
0x03: [615, 6],
0x04: [940, 8],
0x05: [940, 6],
@ -748,7 +748,7 @@ HDC.prototype.initController = function(data, fHard)
}
}
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC initialized for " + this.aDrives.length + " drive(s)");
this.messagePrint("HDC initialized for " + this.aDrives.length + " drive(s)");
}
return fSuccess;
};
@ -1149,7 +1149,7 @@ HDC.prototype.loadDisk = function(iDrive, sDiskName, sDiskPath, fAutoMount)
if (fAutoMount) {
drive.fAutoMount = true;
this.cAutoMount++;
if (this.messageEnabled()) this.messageDebugger("loading " + sDiskName);
if (this.messageEnabled()) this.messagePrint("loading " + sDiskName);
}
var disk = drive.disk || new Disk(this, drive, drive.mode);
disk.load(sDiskName, sDiskPath, null, this.doneLoadDisk);
@ -1437,7 +1437,7 @@ HDC.prototype.inATCData = function(port, addrFrom)
*/
hdc.regStatus = HDC.ATC.STATUS.ERROR;
hdc.regError = HDC.ATC.ERROR.NO_CHS;
if (DEBUG) hdc.messageDebugger("HDC.inATCData(): read failed");
if (DEBUG) hdc.messagePrint("HDC.inATCData(): read failed");
}
}, false);
} else {
@ -1469,7 +1469,7 @@ HDC.prototype.outATCData = function(port, bOut, addrFrom)
this.regStatus = HDC.ATC.STATUS.ERROR;
this.regError = HDC.ATC.ERROR.NO_CHS;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.outATCData(" + str.toHexByte(bOut) + "): write failed");
this.messagePrint("HDC.outATCData(" + str.toHexByte(bOut) + "): write failed");
}
}
else if (this.drive.ibSector == 1) {
@ -1503,7 +1503,7 @@ HDC.prototype.outATCData = function(port, bOut, addrFrom)
* TODO: What to do about unexpected writes? The number of bytes has exceeded what the command specified.
*/
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.outATCData(" + str.toHexByte(bOut) + "): write exceeds count (" + this.drive.nBytes + ")");
this.messagePrint("HDC.outATCData(" + str.toHexByte(bOut) + "): write exceeds count (" + this.drive.nBytes + ")");
}
}
} else {
@ -1511,7 +1511,7 @@ HDC.prototype.outATCData = function(port, bOut, addrFrom)
* TODO: What to do about unexpected writes? No command was specified.
*/
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.outATCData(" + str.toHexByte(bOut) + "): write without command");
this.messagePrint("HDC.outATCData(" + str.toHexByte(bOut) + "): write without command");
}
}
};
@ -1832,14 +1832,14 @@ HDC.prototype.doATC = function()
}
if (DEBUG && this.messageEnabled(Messages.HDC)) {
this.messageDebugger("HDC.doATC(0x" + str.toHexByte(bCmd) + "): " + HDC.aATCCommands[bCmd], true);
this.messagePrint("HDC.doATC(0x" + str.toHexByte(bCmd) + "): " + HDC.aATCCommands[bCmd], true);
}
switch (bCmd & HDC.ATC.COMMAND.MASK) {
case HDC.ATC.COMMAND.READ_DATA:
if (DEBUG && this.messageEnabled(Messages.HDC)) {
this.messageDebugger("HDC.doRead(" + iDrive + ',' + drive.wCylinder + ':' + drive.bHead + ':' + drive.bSector + ',' + nSectors + ")", true);
this.messagePrint("HDC.doRead(" + iDrive + ',' + drive.wCylinder + ':' + drive.bHead + ':' + drive.bSector + ',' + nSectors + ")", true);
}
/*
* We're using a call to readByte() that disables auto-increment, so that once we've got the first
@ -1868,7 +1868,7 @@ HDC.prototype.doATC = function()
case HDC.ATC.COMMAND.WRITE_DATA:
if (DEBUG && this.messageEnabled(Messages.HDC)) {
this.messageDebugger("HDC.doWrite(" + iDrive + ',' + drive.wCylinder + ':' + drive.bHead + ':' + drive.bSector + ',' + nSectors + ")", true);
this.messagePrint("HDC.doWrite(" + iDrive + ',' + drive.wCylinder + ':' + drive.bHead + ':' + drive.bSector + ',' + nSectors + ")", true);
}
this.regStatus = HDC.ATC.STATUS.DATA_REQ;
break;
@ -1917,7 +1917,7 @@ HDC.prototype.doATC = function()
default:
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.doATC(0x" + str.toHexByte(this.regCommand) + "): " + (bCmd < 0? ("invalid drive (" + iDrive + ")") : "unsupported operation"));
this.messagePrint("HDC.doATC(0x" + str.toHexByte(this.regCommand) + "): " + (bCmd < 0? ("invalid drive (" + iDrive + ")") : "unsupported operation"));
if (bCmd >= 0) this.dbg.stopCPU();
}
break;
@ -1961,9 +1961,9 @@ HDC.prototype.setATCIRR = function(fWrite)
* has a low tolerance for fast controller interrupts during multi-sector operations.
*/
this.chipset.setIRR(ChipSet.IRQ.ATC, 120);
if (DEBUG) this.messageDebugger("HDC.setATCIRR(): enabled", Messages.PIC | Messages.HDC);
if (DEBUG) this.messagePrint("HDC.setATCIRR(): enabled", Messages.PIC | Messages.HDC);
} else {
if (DEBUG) this.messageDebugger("HDC.setATCIRR(): disabled", Messages.PIC | Messages.HDC);
if (DEBUG) this.messagePrint("HDC.setATCIRR(): disabled", Messages.PIC | Messages.HDC);
}
}
};
@ -2045,7 +2045,7 @@ HDC.prototype.doXTC = function()
bDataStatus = HDC.XTC.DATA.STATUS_OK;
if (!drive && this.iDriveAllowFail == iDrive) {
this.iDriveAllowFail = -1;
if (DEBUG) this.messageDebugger("HDC.doXTC(): fake failure triggered");
if (DEBUG) this.messagePrint("HDC.doXTC(): fake failure triggered");
bDataStatus = HDC.XTC.DATA.STATUS_ERROR;
}
this.beginResult(bDataStatus | bDrive);
@ -2082,7 +2082,7 @@ HDC.prototype.doXTC = function()
case HDC.XTC.DATA.CMD.RECALIBRATE: // 0x01
drive.bControl = bControl;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.doXTC(): drive " + iDrive + " control byte: 0x" + str.toHexByte(bControl));
this.messagePrint("HDC.doXTC(): drive " + iDrive + " control byte: 0x" + str.toHexByte(bControl));
}
this.beginResult(HDC.XTC.DATA.STATUS_OK | bDrive);
break;
@ -2120,7 +2120,7 @@ HDC.prototype.doXTC = function()
default:
this.beginResult(HDC.XTC.DATA.STATUS_ERROR | bDrive);
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.doXTC(0x" + str.toHexByte(bCmdOrig) + "): " + (bCmd < 0? ("invalid drive (" + iDrive + ")") : "unsupported operation"));
this.messagePrint("HDC.doXTC(0x" + str.toHexByte(bCmdOrig) + "): " + (bCmd < 0? ("invalid drive (" + iDrive + ")") : "unsupported operation"));
if (bCmd >= 0) this.dbg.stopCPU();
}
break;
@ -2141,7 +2141,7 @@ HDC.prototype.popCmd = function()
if (bCmdIndex < this.regDataTotal) {
bCmd = this.regDataArray[this.regDataIndex++];
if (DEBUG && this.messageEnabled((bCmdIndex > 0? Messages.PORT : 0) | Messages.HDC)) {
this.messageDebugger("HDC.CMD[" + bCmdIndex + "]: 0x" + str.toHexByte(bCmd) + (!bCmdIndex && HDC.aXTCCommands[bCmd]? (" (" + HDC.aXTCCommands[bCmd] + ")") : ""), true);
this.messagePrint("HDC.CMD[" + bCmdIndex + "]: 0x" + str.toHexByte(bCmd) + (!bCmdIndex && HDC.aXTCCommands[bCmd]? (" (" + HDC.aXTCCommands[bCmd] + ")") : ""), true);
}
}
return bCmd;
@ -2159,7 +2159,7 @@ HDC.prototype.beginResult = function(bResult)
if (bResult !== undefined) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.beginResult(0x" + str.toHexByte(bResult) + ")");
this.messagePrint("HDC.beginResult(0x" + str.toHexByte(bResult) + ")");
}
this.pushResult(bResult);
}
@ -2181,7 +2181,7 @@ HDC.prototype.beginResult = function(bResult)
HDC.prototype.pushResult = function(bResult)
{
if (DEBUG && this.messageEnabled((this.regDataTotal > 0? Messages.PORT : 0) | Messages.HDC)) {
this.messageDebugger("HDC.RES[" + this.regDataTotal + "]: 0x" + str.toHexByte(bResult), true);
this.messagePrint("HDC.RES[" + this.regDataTotal + "]: 0x" + str.toHexByte(bResult), true);
}
this.regDataArray[this.regDataTotal++] = bResult;
};
@ -2203,7 +2203,7 @@ HDC.prototype.dmaRead = function(drive, b, done)
/*
* The DMA controller should be ASKING for data, not GIVING us data; this suggests an internal DMA miscommunication
*/
if (DEBUG) this.messageDebugger("dmaRead(): invalid DMA acknowledgement");
if (DEBUG) this.messagePrint("dmaRead(): invalid DMA acknowledgement");
done(-1, false);
};
@ -2222,7 +2222,7 @@ HDC.prototype.dmaWrite = function(drive, b)
/*
* The DMA controller should be GIVING us data, not ASKING for data; this suggests an internal DMA miscommunication
*/
if (DEBUG) this.messageDebugger("dmaWrite(): invalid DMA acknowledgement");
if (DEBUG) this.messagePrint("dmaWrite(): invalid DMA acknowledgement");
return -1;
};
@ -2241,7 +2241,7 @@ HDC.prototype.dmaWriteBuffer = function(drive, b)
/*
* The DMA controller should be GIVING us data, not ASKING for data; this suggests an internal DMA miscommunication
*/
if (DEBUG) this.messageDebugger("dmaWriteBuffer(): invalid DMA acknowledgement");
if (DEBUG) this.messagePrint("dmaWriteBuffer(): invalid DMA acknowledgement");
return -1;
};
@ -2260,7 +2260,7 @@ HDC.prototype.dmaWriteFormat = function(drive, b)
/*
* The DMA controller should be GIVING us data, not ASKING for data; this suggests an internal DMA miscommunication
*/
if (DEBUG) this.messageDebugger("dmaWriteFormat(): invalid DMA acknowledgement");
if (DEBUG) this.messagePrint("dmaWriteFormat(): invalid DMA acknowledgement");
return -1;
};
@ -2276,7 +2276,7 @@ HDC.prototype.doDMARead = function(drive, done)
drive.errorCode = HDC.XTC.DATA.ERR.NOT_READY;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.doDMARead(" + drive.iDrive + ',' + drive.wCylinder + ':' + drive.bHead + ':' + drive.bSector + ',' + ((drive.nBytes / drive.cbSector)|0) + ")");
this.messagePrint("HDC.doDMARead(" + drive.iDrive + ',' + drive.wCylinder + ':' + drive.bHead + ':' + drive.bSector + ',' + ((drive.nBytes / drive.cbSector)|0) + ")");
}
if (drive.disk) {
@ -2320,7 +2320,7 @@ HDC.prototype.doDMAWrite = function(drive, done)
drive.errorCode = HDC.XTC.DATA.ERR.NOT_READY;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.doDMAWrite(" + drive.iDrive + ',' + drive.wCylinder + ':' + drive.bHead + ':' + drive.bSector + ',' + ((drive.nBytes / drive.cbSector)|0) + ")");
this.messagePrint("HDC.doDMAWrite(" + drive.iDrive + ',' + drive.wCylinder + ':' + drive.bHead + ':' + drive.bSector + ',' + ((drive.nBytes / drive.cbSector)|0) + ")");
}
if (drive.disk) {
@ -2370,7 +2370,7 @@ HDC.prototype.doDMAWriteBuffer = function(drive, done)
{
drive.errorCode = HDC.XTC.DATA.ERR.NOT_READY;
if (DEBUG) this.messageDebugger("HDC.doDMAWriteBuffer()");
if (DEBUG) this.messagePrint("HDC.doDMAWriteBuffer()");
if (!drive.abSector || drive.abSector.length != drive.nBytes) {
drive.abSector = new Array(drive.nBytes);
@ -2669,7 +2669,7 @@ HDC.prototype.writeFormat = function(drive, b)
drive.cbFormat = 0;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("HDC.writeFormat(" + drive.wCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")");
this.messagePrint("HDC.writeFormat(" + drive.wCylinder + ":" + drive.bHead + ":" + drive.bSector + ":" + drive.nBytes + ")");
}
for (var i = 0; i < drive.nBytes; i++) {
@ -2754,7 +2754,7 @@ HDC.prototype.intBIOSDiskette = function(addr)
{
var AH = this.cpu.regAX >> 8;
if ((!AH && this.chipset && this.chipset.checkIMR(ChipSet.IRQ.FDC))) {
if (DEBUG) this.messageDebugger("HDC.intBIOSDiskette(): skipping useless INT 0x40 diskette reset");
if (DEBUG) this.messagePrint("HDC.intBIOSDiskette(): skipping useless INT 0x40 diskette reset");
return false;
}
return true;

View file

@ -68,7 +68,7 @@ function Keyboard(parmsKbd)
this.fMobile = web.isMobile();
this.fMSIE = web.isUserAgent("MSIE");
this.messageDebugger("mobile keyboard support: " + (this.fMobile? "true" : "false"));
this.messagePrint("mobile keyboard support: " + (this.fMobile? "true" : "false"));
/*
* This is count of the number of "soft keyboard" keys present. At the moment, its only
@ -115,9 +115,17 @@ function Keyboard(parmsKbd)
* nRepeat: > 0 if timer should generate more "make" scan code(s), -1 for "break" scan code(s)
* timer: timer for next key operation, if any
*
* Keys are inserted into aKeysActive using splice(0, 0, key), but not before zeroing nRepeat
* of any repeating key that already occupies index 0, so that at most only one key (ie, the most
* recent) can ever be in a repeating state.
* Keys are inserted at the head of aKeysActive, using splice(0, 0, key), but not before zeroing
* nRepeat of any repeating key that already occupies the head (index 0), so that at most only one
* key (ie, the most recent) will ever be in a repeating state.
*
* IBM PC keyboard repeat behavior: when pressing CTRL, then C, and then releasing CTRL while still
* holding C, the repeated CTRL_C characters turn into 'c' characters. We emulate that behavior.
* However, when pressing C, then CTRL, all repeating stops: not a single CTRL_C is generated, and
* even if the CTRL is released before the C, no more more 'c' characters are generated either.
* We do NOT fully emulate that behavior -- we DO stop the repeating, but we also generate one CTRL_C.
* More investigation is required, because I need to confirm whether the IBM keyboard automatically
* "breaks" all non-shift keys before it "makes" the CTRL.
*/
this.aKeysActive = [];
@ -252,7 +260,7 @@ Keyboard.KEYCODE = {
// Technically, that makes it DCO (Decimal Coded Octal), but then again, BCD should have really
// been called HCD (Hexadecimal Coded Decimal), so if "they" can take liberties, so can I.
//
// ONDOWN is a bias we add to browser keyCodes that we want to handle on "down" rather than "press".
// ONDOWN is a bias we add to browser keyCodes that we want to handle on "down" rather than on "press".
//
ONDOWN: 1000,
//
@ -475,11 +483,16 @@ Keyboard.LOCATION = {
* and the simulated shift-key states (in bitsStateSim). The LOCK keys are problematic in both cases: the
* browsers give us no way to query the LOCK key states, so we can only infer them, and because they are "soft"
* locks, the machine's notion of their state is subject to change at any time as well. Granted, the IBM PC
* ROM BIOS will store its LOCK states in the ROM BIOS Data Area (@0040:0017), but that's purely a convention.
* ROM BIOS will store its LOCK states in the ROM BIOS Data Area (@0040:0017), but that's just a BIOS convention.
*
* TODO: Consider taking notice of the ROM BIOS Data Area state anyway, although I'm not keen on the idea.
* Also, because this is purely for internal use, don't make the mistake of thinking that these bits have any
* connection to the ROM BIOS bits @0040:0017 (they don't). We emulate hardware, not ROMs.
*
* Note that right-hand state bits match the left-hand state bits shifted right 1 bit; makes sense, "right"? ;-)
* TODO: Consider taking notice of the ROM BIOS Data Area state anyway, even though I'd rather remain ROM-agnostic;
* at the very least, it would help us keep our LOCK LEDs in sync with the machine's LOCK states. However, the LED
* issue will be largely moot (at least for MODEL_5170 machines) once we add support for PC AT keyboard LED commands.
*
* Note that right-hand state bits are equal to the left-hand bits shifted right 1 bit; makes sense, "right"? ;-)
*
* @enum {number}
*/
@ -496,7 +509,7 @@ Keyboard.STATE = {
CMD: 0x0080, // 101-key keyboard only
CMDS: 0x00c0,
SHIFTS: 0x00ff, // SHIFT | RSHIFT | CTRL | RCTRL | ALT | RALT | CMD | RCMD
INSERT: 0x0100, // TODO: Placeholder
INSERT: 0x0100, // TODO: Placeholder (we currently have no notion of any "insert" states)
CAPS_LOCK: 0x0200,
NUM_LOCK: 0x0400,
SCROLL_LOCK: 0x0800,
@ -1006,7 +1019,7 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control)
this.bindings[id] = control;
control.onclick = function(kbd, sKey, simCode) {
return function onClickKeyboard(event) {
if (!COMPILED && kbd.messageEnabled()) kbd.messageDebugger(sKey + " clicked", Messages.KEYS);
if (!COMPILED && kbd.messageEnabled()) kbd.messagePrint(sKey + " clicked", Messages.KEYS);
if (kbd.cpu) kbd.cpu.setFocus();
kbd.updateShiftState(simCode, true); // future-proofing if/when any LOCK keys are added to CLICKCODES
kbd.addActiveKey(simCode, true);
@ -1138,7 +1151,7 @@ Keyboard.prototype.resetDevice = function(fNotify)
/*
* TODO: There's more to reset, like LED indicators, default type rate, and emptying the scan code buffer.
*/
this.messageDebugger("keyboard reset", Messages.KEYBOARD | Messages.PORT);
this.messagePrint("keyboard reset", Messages.KEYBOARD | Messages.PORT);
this.abScanBuffer = [Keyboard.CMDRES.BAT_OK];
if (fNotify && this.chipset) this.chipset.notifyKbdData(this.abScanBuffer[0]);
};
@ -1161,7 +1174,7 @@ Keyboard.prototype.setEnable = function(fData, fClock)
var fReset = false;
if (this.fClock !== fClock) {
if (!COMPILED && this.messageEnabled(Messages.KEYBOARD | Messages.PORT)) {
this.messageDebugger("keyboard clock line changing to " + fClock, true);
this.messagePrint("keyboard clock line changing to " + fClock, true);
}
/*
* Toggling the clock line low and then high signals a "reset", which we acknowledge once the
@ -1171,7 +1184,7 @@ Keyboard.prototype.setEnable = function(fData, fClock)
}
if (this.fData !== fData) {
if (!COMPILED && this.messageEnabled(Messages.KEYBOARD | Messages.PORT)) {
this.messageDebugger("keyboard data line changing to " + fData, true);
this.messagePrint("keyboard data line changing to " + fData, true);
}
this.fData = fData;
/*
@ -1229,7 +1242,7 @@ Keyboard.prototype.checkScanCode = function()
b = this.abScanBuffer[0];
if (this.chipset) this.chipset.notifyKbdData(b);
}
if (this.messageEnabled()) this.messageDebugger("scan code 0x" + str.toHexByte(b) + " available");
if (this.messageEnabled()) this.messagePrint("scan code 0x" + str.toHexByte(b) + " available");
return b;
};
@ -1247,7 +1260,7 @@ Keyboard.prototype.readScanCode = function()
if (this.abScanBuffer.length) {
b = this.abScanBuffer[0];
}
if (this.messageEnabled()) this.messageDebugger("scan code 0x" + str.toHexByte(b) + " delivered");
if (this.messageEnabled()) this.messagePrint("scan code 0x" + str.toHexByte(b) + " delivered");
return b;
};
@ -1261,7 +1274,7 @@ Keyboard.prototype.readScanCode = function()
Keyboard.prototype.flushScanCode = function()
{
this.abScanBuffer = [];
if (this.messageEnabled()) this.messageDebugger("scan codes flushed");
if (this.messageEnabled()) this.messagePrint("scan codes flushed");
};
/**
@ -1288,7 +1301,7 @@ Keyboard.prototype.shiftScanCode = function(fNotify)
this.chipset.notifyKbdData(this.abScanBuffer[0]);
}
}
if (this.messageEnabled()) this.messageDebugger("scan codes shifted, notify " + (fNotify? "true" : "false"));
if (this.messageEnabled()) this.messagePrint("scan codes shifted, notify " + (fNotify? "true" : "false"));
}
};
@ -1455,7 +1468,7 @@ Keyboard.prototype.addScanCode = function(bScan)
*/
if (this.abScanBuffer) {
if (this.abScanBuffer.length < Keyboard.LIMIT.MAX_SCANCODES) {
if (this.messageEnabled()) this.messageDebugger("scan code 0x" + str.toHexByte(bScan) + " buffered");
if (this.messageEnabled()) this.messagePrint("scan code 0x" + str.toHexByte(bScan) + " buffered");
this.abScanBuffer.push(bScan);
if (this.abScanBuffer.length == 1) {
if (this.chipset) this.chipset.notifyKbdData(bScan);
@ -1465,7 +1478,7 @@ Keyboard.prototype.addScanCode = function(bScan)
if (this.abScanBuffer.length == Keyboard.LIMIT.MAX_SCANCODES) {
this.abScanBuffer.push(Keyboard.CMDRES.BUFF_FULL);
}
this.messageDebugger("scan code buffer overflow");
this.messagePrint("scan code buffer overflow");
}
};
@ -1624,7 +1637,7 @@ Keyboard.prototype.addActiveKey = function(simCode, fPress)
{
if (!Keyboard.SIMCODES[simCode]) {
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
this.messageDebugger("addActiveKey(" + simCode + "," + (fPress? "press" : "down") + "): unrecognized", true);
this.messagePrint("addActiveKey(" + simCode + "," + (fPress? "press" : "down") + "): unrecognized", true);
}
return;
}
@ -1634,6 +1647,13 @@ Keyboard.prototype.addActiveKey = function(simCode, fPress)
*/
if (!this.cpu || !this.cpu.isRunning()) return;
/*
* If this simCode is in the KEYSTATE table, then stop all repeating.
*/
if (Keyboard.KEYSTATES[simCode] && this.aKeysActive.length) {
if (this.aKeysActive[0].nRepeat > 0) this.aKeysActive[0].nRepeat = 0;
}
var key;
for (var i = 0; i < this.aKeysActive.length; i++) {
key = this.aKeysActive[i];
@ -1655,7 +1675,7 @@ Keyboard.prototype.addActiveKey = function(simCode, fPress)
}
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
this.messageDebugger("addActiveKey(" + simCode + "," + (fPress? "press" : "down") + "): " + (i < 0? "already active" : (i == this.aKeysActive.length? "adding" : "updating")), true);
this.messagePrint("addActiveKey(" + simCode + "," + (fPress? "press" : "down") + "): " + (i < 0? "already active" : (i == this.aKeysActive.length? "adding" : "updating")), true);
}
if (i < 0) return;
@ -1756,7 +1776,7 @@ Keyboard.prototype.removeActiveKey = function(simCode, fFlush)
{
if (!Keyboard.SIMCODES[simCode]) {
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
this.messageDebugger("removeActiveKey(" + simCode + "): unrecognized", true);
this.messagePrint("removeActiveKey(" + simCode + "): unrecognized", true);
}
return false;
}
@ -1770,7 +1790,6 @@ Keyboard.prototype.removeActiveKey = function(simCode, fFlush)
for (var i = 0; i < this.aKeysActive.length; i++) {
var key = this.aKeysActive[i];
if (key.simCode == simCode || key.simCode == Keyboard.SHIFTED_KEYCODES[simCode]) {
if (this.aKeysActive[0].nRepeat > 0) this.aKeysActive[0].nRepeat = 0;
this.aKeysActive.splice(i, 1);
if (key.timer) clearTimeout(key.timer);
if (key.fDown && !fFlush) this.keySimulate(key.simCode, false);
@ -1780,10 +1799,10 @@ Keyboard.prototype.removeActiveKey = function(simCode, fFlush)
}
}
if (!COMPILED && !fFlush && this.messageEnabled(Messages.KEYS)) {
this.messageDebugger("removeActiveKey(" + simCode + "): " + (fRemoved? "removed" : "not active"), true);
this.messagePrint("removeActiveKey(" + simCode + "): " + (fRemoved? "removed" : "not active"), true);
}
if (!this.aKeysActive.length && this.fToggleCapsLock) {
if (!COMPILED) this.messageDebugger("removeActiveKey(): inverting caps-lock now", Messages.KEYS);
if (!COMPILED) this.messagePrint("removeActiveKey(): inverting caps-lock now", Messages.KEYS);
this.updateShiftState(Keyboard.SIMCODE.CAPS_LOCK);
this.fToggleCapsLock = false;
}
@ -1807,7 +1826,7 @@ Keyboard.prototype.updateActiveKey = function(key, msTimer)
}
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
this.messageDebugger((msTimer? '\n' : "") + "updateActiveKey(" + key.simCode + (msTimer? "," + msTimer + "ms" : "") + "): " + (key.fDown? "down" : "up"), true);
this.messagePrint((msTimer? '\n' : "") + "updateActiveKey(" + key.simCode + (msTimer? "," + msTimer + "ms" : "") + "): " + (key.fDown? "down" : "up"), true);
}
this.keySimulate(key.simCode, key.fDown);
@ -1878,7 +1897,7 @@ Keyboard.prototype.getSimCode = function(keyCode, fShifted)
Keyboard.prototype.onFocusChange = function(fFocus)
{
if (this.fHasFocus != fFocus && !COMPILED && this.messageEnabled(Messages.KEYS)) {
this.messageDebugger("onFocusChange(" + (fFocus? "true" : "false") + ")", true);
this.messagePrint("onFocusChange(" + (fFocus? "true" : "false") + ")", true);
}
this.fHasFocus = fFocus;
/*
@ -2005,7 +2024,7 @@ Keyboard.prototype.onKeyDown = function(event, fDown)
}
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
this.messageDebugger("\nonKey" + (fDown? "Down" : "Up") + "(" + keyCode + "): " + (fIgnore? "ignore" : (fPass? "true" : "false")), true);
this.messagePrint("\nonKey" + (fDown? "Down" : "Up") + "(" + keyCode + "): " + (fIgnore? "ignore" : (fPass? "true" : "false")), true);
}
/*
@ -2045,7 +2064,7 @@ Keyboard.prototype.onKeyPress = function(event)
var simCode = this.checkActiveKey();
if (simCode && this.isAlphaKey(simCode) && this.isAlphaKey(keyCode) && simCode != keyCode) {
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
this.messageDebugger("onKeyPress(" + keyCode + ") out of sync with " + simCode + ", invert caps-lock", true);
this.messagePrint("onKeyPress(" + keyCode + ") out of sync with " + simCode + ", invert caps-lock", true);
}
this.fToggleCapsLock = true;
keyCode = simCode;
@ -2059,7 +2078,7 @@ Keyboard.prototype.onKeyPress = function(event)
var fPass = !Keyboard.SIMCODES[keyCode] || !!(this.bitsState & Keyboard.STATE.CMD);
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
this.messageDebugger("\nonKeyPress(" + keyCode + "): " + (fPass? "true" : "false"), true);
this.messagePrint("\nonKeyPress(" + keyCode + "): " + (fPass? "true" : "false"), true);
}
if (!fPass) {
@ -2149,7 +2168,7 @@ Keyboard.prototype.keySimulate = function(simCode, fDown)
}
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
this.messageDebugger("keySimulate(" + simCode + "," + (fDown? "down" : "up") + "): " + (fSimulated? "true" : "false"), true);
this.messagePrint("keySimulate(" + simCode + "," + (fDown? "down" : "up") + "): " + (fSimulated? "true" : "false"), true);
}
return fSimulated;

View file

@ -544,7 +544,7 @@ Mouse.prototype.sendPacket = function(sDiag, xDiag, yDiag)
var b2 = this.xDelta & 0x3F;
var b3 = this.yDelta & 0x3F;
if (this.messageEnabled(Messages.SERIAL)) {
this.messageDebugger((sDiag? (sDiag + ": ") : "") + (yDiag !== undefined? ("mouse (" + xDiag + "," + yDiag + "): ") : "") + "serial packet [" + str.toHexByte(b1) + "," + str.toHexByte(b2) + "," + str.toHexByte(b3) + "]", 0, true);
this.messagePrint((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.xDelta = this.yDelta = 0;
@ -576,11 +576,11 @@ Mouse.prototype.notifyMCR = function(bMCR)
var fIdentify = false;
if (!(this.bMCR & SerialPort.MCR.RTS)) {
this.reset();
this.messageDebugger("serial mouse reset");
this.messagePrint("serial mouse reset");
fIdentify = true;
}
if (!(this.bMCR & SerialPort.MCR.DTR)) {
this.messageDebugger("serial mouse ID requested");
this.messagePrint("serial mouse ID requested");
fIdentify = true;
}
if (fIdentify) {
@ -605,7 +605,7 @@ Mouse.prototype.notifyMCR = function(bMCR)
* I'm calling this good enough for now.
*/
this.componentAdapter.sendRBR([Mouse.ID_SERIAL, Mouse.ID_SERIAL]);
this.messageDebugger("serial mouse ID sent");
this.messagePrint("serial mouse ID sent");
}
this.captureMouse(this.inputScreen);
this.setActive(fActive);
@ -624,7 +624,7 @@ Mouse.prototype.notifyMCR = function(bMCR)
* a mouse device that's still powered may still send event data to the serial port, and if there was software
* polling the serial port, it might expect to see that data. Unlikely, but not impossible.
*/
this.messageDebugger("serial mouse inactive");
this.messagePrint("serial mouse inactive");
this.releaseMouse(this.inputScreen);
this.setActive(fActive);
}

View file

@ -279,7 +279,7 @@ State.prototype = {
this[this.id] = s;
this.fLoaded = true;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("localStorage(" + this.key + "): " + s.length + " bytes loaded");
this.messagePrint("localStorage(" + this.key + "): " + s.length + " bytes loaded");
}
return true;
}
@ -318,7 +318,7 @@ State.prototype = {
var s = JSON.stringify(this[this.id]);
if (web.setLocalStorageItem(this.key, s)) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("localStorage(" + this.key + "): " + s.length + " bytes stored");
this.messagePrint("localStorage(" + this.key + "): " + s.length + " bytes stored");
}
} else {
/*
@ -378,7 +378,7 @@ State.prototype = {
if (sKey && (fAll || sKey.substr(0, this.key.length) == this.key)) {
web.removeLocalStorageItem(sKey);
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("localStorage(" + sKey + ") removed");
this.messagePrint("localStorage(" + sKey + ") removed");
}
aKeys.splice(i, 1);
i = 0;
@ -404,12 +404,12 @@ State.prototype = {
return false;
},
/**
* messageDebugger(sMessage)
* messagePrint(sMessage)
*
* @this {State}
* @param {string} sMessage is any caller-defined message string
*/
messageDebugger: function(sMessage) {
messagePrint: function(sMessage) {
if (DEBUGGER && this.dbg) this.dbg.message(sMessage);
}
};

View file

@ -2013,7 +2013,7 @@ Video.prototype.setBinding = function(sHTMLType, sBinding, control)
this.sLockMessage = control.textContent;
if (this.inputScreen && this.inputScreen.lockPointer) {
control.onclick = function onClickLockPointer() {
if (DEBUG) video.messageDebugger("lockPointer()");
if (DEBUG) video.messagePrint("lockPointer()");
video.lockPointer(true);
};
} else {
@ -2024,7 +2024,7 @@ Video.prototype.setBinding = function(sHTMLType, sBinding, control)
case "refresh":
control.onclick = function onClickRefresh() {
if (DEBUG) video.messageDebugger("refreshScreen()");
if (DEBUG) video.messagePrint("refreshScreen()");
video.updateScreen(true);
};
return true;
@ -2183,7 +2183,7 @@ Video.prototype.captureTouch = function()
Video.prototype.onFocusChange = function(fFocus)
{
if (this.fHasFocus != fFocus && DEBUG && this.messageEnabled()) {
this.messageDebugger("onFocusChange(" + (fFocus? "true" : "false") + ")", true);
this.messagePrint("onFocusChange(" + (fFocus? "true" : "false") + ")", true);
}
/*
* As per http://stackoverflow.com/questions/6740253/disable-scrolling-when-changing-focus-form-elements-ipad-web-app,
@ -2216,7 +2216,7 @@ Video.prototype.releaseTouch = function()
*/
Video.prototype.onTouchStart = function(event)
{
if (DEBUG) this.messageDebugger("onTouchStart()");
if (DEBUG) this.messagePrint("onTouchStart()");
this.processTouchEvent(event, true);
};
@ -2228,7 +2228,7 @@ Video.prototype.onTouchStart = function(event)
*/
Video.prototype.onTouchMove = function(event)
{
if (DEBUG) this.messageDebugger("onTouchMove()");
if (DEBUG) this.messagePrint("onTouchMove()");
this.processTouchEvent(event, false);
};
@ -2240,7 +2240,7 @@ Video.prototype.onTouchMove = function(event)
*/
Video.prototype.onTouchEnd = function(event)
{
if (DEBUG) this.messageDebugger("onTouchEnd()");
if (DEBUG) this.messagePrint("onTouchEnd()");
};
/**
@ -2703,7 +2703,7 @@ Video.prototype.onROMLoad = function(abROM)
* TODO: Unlike the MDA/CGA font data, we may want to hang onto this data, so that we can regenerate
* the color font(s) whenever the foreground and/or background colors have been changed.
*/
if (DEBUG) this.messageDebugger("onROMLoad(): EGA fonts loaded");
if (DEBUG) this.messagePrint("onROMLoad(): EGA fonts loaded");
this.setFontData(abROM, [0x2230, 0x3160], 8);
}
this.setReady();
@ -2886,7 +2886,7 @@ Video.prototype.buildFont = function(nFont, offData, offSplit, cxChar, cyChar, a
var fChanges = false;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("buildFont(" + nFont + "): building " + Video.cardSpecs[nFont][0] + " font");
this.messagePrint("buildFont(" + nFont + "): building " + Video.cardSpecs[nFont][0] + " font");
}
if (this.createFont(nFont, offData, offSplit, cxChar, cyChar, abFontData, aRGBColors, aColorMap)) fChanges = true;
@ -2898,7 +2898,7 @@ Video.prototype.buildFont = function(nFont, offData, offSplit, cxChar, cyChar, a
if (this.fDoubleFont) {
nFont <<= 1;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("buildFont(" + nFont + "): building " + Video.cardSpecs[nFont >> 1][0] + " double-size font");
this.messagePrint("buildFont(" + nFont + "): building " + Video.cardSpecs[nFont >> 1][0] + " double-size font");
}
if (this.createFont(nFont, offData, offSplit, cxChar, cyChar, abFontData, aRGBColors, aColorMap)) fChanges = true;
}
@ -2947,7 +2947,7 @@ Video.prototype.createFont = function(nFont, offData, offSplit, cxChar, cyChar,
var rgbColorOrig = font.aCSSColors[iColor]? font.aRGBColors[iColor] : [];
if (rgbColor[0] !== rgbColorOrig[0] || rgbColor[1] !== rgbColorOrig[1] || rgbColor[2] !== rgbColorOrig[2]) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("creating font color " + iColor + " for font " + nFont);
this.messagePrint("creating font color " + iColor + " for font " + nFont);
}
this.createFontColor(font, iColor, rgbColor, nDouble, offData, offSplit, cxChar, cyChar, abFontData);
fChanges = true;
@ -3179,7 +3179,7 @@ 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));
if (this.iCellCursor != iCellCursor) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("checkCursor(): cursor moved from " + this.iCellCursor + " to " + iCellCursor);
this.messagePrint("checkCursor(): cursor moved from " + this.iCellCursor + " to " + iCellCursor);
}
this.removeCursor();
this.iCellCursor = iCellCursor;
@ -3234,7 +3234,7 @@ Video.prototype.removeCursor = function()
this.updateChar(col, row, data);
}
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("removeCursor(): removed from " + row + "," + col);
this.messagePrint("removeCursor(): removed from " + row + "," + col);
}
this.aCellCache[this.iCellCursor] = data;
}
@ -3301,7 +3301,7 @@ Video.prototype.getAccess = function()
break;
default:
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("getAccess(): invalid GRC mode (" + str.toHexByte(regGRCMode) + ")");
this.messagePrint("getAccess(): invalid GRC mode (" + str.toHexByte(regGRCMode) + ")");
}
break;
}
@ -3329,7 +3329,7 @@ Video.prototype.setAccess = function(nAccess)
if (nAccess != null && card && nAccess != card.nAccess) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("setAccess(0x" + str.toHexWord(nAccess) + ")");
this.messagePrint("setAccess(0x" + str.toHexWord(nAccess) + ")");
}
card.setMemoryAccess(nAccess);
@ -3666,7 +3666,7 @@ Video.prototype.setMode = function(nMode, fForce)
if (nMode != null && (nMode != this.nMode || fForce)) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("setMode(0x" + str.toHexWord(nMode) + (fForce? ",force" : "") + ")");
this.messagePrint("setMode(0x" + str.toHexWord(nMode) + (fForce? ",force" : "") + ")");
}
this.cUpdates = 0; // count updateScreen() calls as a means of driving blink updates
@ -3692,7 +3692,7 @@ Video.prototype.setMode = function(nMode, fForce)
if (this.addrBuffer) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("setMode(" + nMode + "): removing 0x" + str.toHex(this.sizeBuffer) + " bytes from 0x" + str.toHex(this.addrBuffer));
this.messagePrint("setMode(" + nMode + "): removing 0x" + str.toHex(this.sizeBuffer) + " bytes from 0x" + str.toHex(this.addrBuffer));
}
if (!this.bus.removeMemory(this.addrBuffer, this.sizeBuffer)) {
@ -3711,7 +3711,7 @@ Video.prototype.setMode = function(nMode, fForce)
this.sizeBuffer = card.sizeBuffer;
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("setMode(" + nMode + "): adding 0x" + str.toHex(this.sizeBuffer) + " bytes to 0x" + str.toHex(this.addrBuffer));
this.messagePrint("setMode(" + nMode + "): adding 0x" + str.toHex(this.sizeBuffer) + " bytes to 0x" + str.toHex(this.addrBuffer));
}
var controller = (card === this.cardEGA? card : null);
@ -4418,11 +4418,11 @@ Video.prototype.outATC = function(port, bOut, addrFrom)
if ((bOut & Card.ATC.INDX_PAL_ENABLE) && !fPalEnabled) {
if (!this.buildFonts()) {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("outATC(" + str.toHexByte(bOut) + "): no font changes required");
this.messagePrint("outATC(" + str.toHexByte(bOut) + "): no font changes required");
}
} else {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("outATC(" + str.toHexByte(bOut) + "): redraw screen for font changes");
this.messagePrint("outATC(" + str.toHexByte(bOut) + "): redraw screen for font changes");
}
this.updateScreen(true);
}
@ -4917,7 +4917,7 @@ Video.prototype.outCRTCData = function(card, bOut, addrFrom)
this.checkCursor();
} else {
if (DEBUG && this.messageEnabled()) {
this.messageDebugger("outCRTCData(): ignoring unexpected write to CRTC[" + str.toHexByte(card.iCRTCReg) + "]: " + str.toHexByte(bOut));
this.messagePrint("outCRTCData(): ignoring unexpected write to CRTC[" + str.toHexByte(card.iCRTCReg) + "]: " + str.toHexByte(bOut));
}
}
};

View file

@ -56,30 +56,29 @@ if (typeof module !== 'undefined') {
*
* model: a number (eg, 8088) that should match one of the X86.MODEL values
*
* This extends the CPU class and passes any remaining parmsCPU properties to the
* CPU class constructor, along with a default speed (cycles per second) based on the
* specified (or default) CPU model number.
* This extends the CPU class and passes any remaining parmsCPU properties to the CPU class
* constructor, along with a default speed (cycles per second) based on the specified (or default)
* CPU model number.
*
* The X86CPU class was initially written to simulate a 8086/8088 microprocessor, although
* over time it is evolving to support newer microprocessors (for example, limited
* support for 80186/80188 instructions can already be conditionally enabled).
* The X86CPU class was initially written to simulate a 8086/8088 microprocessor, although over time
* it has evolved to support later microprocessors (eg, the 80186/80188 and the 80286, including
* protected-mode support).
*
* This is a logical simulation, not a physical simulation, and performance is critical,
* second only to the accuracy of the simulation when running real-world x86 software.
* Consequently, it takes liberties that do not reflect exactly how actual hardware
* operated, especially with regard to external components.
* This is a logical simulation, not a physical simulation, and performance is critical, second only
* to the accuracy of the simulation when running real-world x86 software. Consequently, it takes a
* few liberties with the operation of the simulated hardware, especially with regard to timings,
* little-used features, etc. We do make an effort to maintain accurate instruction cycle counts,
* but there are many other obstacles (eg, prefetch queue, wait states) to achieving perfect timings.
*
* For example, our 8237 DMA controller performs all DMA transfers immediately,
* since internally they are all memory-to-memory, and attempting to interleave DMA
* cycles with instruction execution cycles would only hurt overall performance.
* Similarly, the 8254 timer counters are updated only on-demand.
* For example, our 8237 DMA controller performs all DMA transfers immediately, since internally
* they are all memory-to-memory, and attempting to interleave DMA cycles with instruction execution
* cycles would hurt overall performance. Similarly, 8254 timer counters are updated only on-demand.
*
* The 8237 and 8254, along with several "chips", are combined into a single convenient
* "Chipset" component, to keep the number of components we must juggle to a minimum.
* The 8237 and 8254, along with the 8259 interrupt controller and several other "chips", are combined
* into a single "Chipset" component, to keep the number of components we juggle to a minimum.
*
* All that being said, this does not change the primary goal: to produce as accurate
* a simulation as possible, within the limits of what JavaScript allows and how
* precisely/predictably it behaves.
* All that being said, this does not change the overall goal: to produce as accurate a simulation as
* possible, within the limits of what JavaScript allows and how precisely/predictably it behaves.
*
* @constructor
* @extends CPU
@ -1006,8 +1005,14 @@ X86CPU.prototype.addIntReturn = function(addr, fn)
/**
* checkIntReturn(addr)
*
* It is expected (though not required) that callers will check cIntReturn and avoid calling
* this function if the count is zero.
* We check for possible "INT n" software interrupt returns in the cases of "IRET" (opHelpIRET), "RETF 2"
* (opHelpRETF) and "JMPF [DWORD]" (opGrpJMPFdw).
*
* "JMPF [DWORD]" is an unfortunate choice that newer versions of DOS (as of at least 3.20, and probably
* earlier) employed in their INT 0x13 hooks; I would have preferred not making this call for that opcode.
*
* It is expected (though not required) that callers will check cIntReturn and avoid calling this function
* if the count is zero, for maximum performance.
*
* @this {X86CPU}
* @param {number} addr is a physical (non-segmented) address
@ -1039,7 +1044,7 @@ X86CPU.prototype.setProtMode = function(fProt)
fProt = !!(this.regMSW & X86.MSW.PE);
}
if (!fProt) {
this.messageDebugger("returning to real-mode");
this.messagePrint("returning to real-mode");
}
this.aOpGrp6 = (fProt? X86Op0F.aOpGrp6Prot : X86Op0F.aOpGrp6Real);
this.segCS.updateMode(fProt);
@ -2083,7 +2088,7 @@ X86CPU.prototype.getBytePrefetch = function(addr)
*/
}
b = this.aPrefetch[this.iPrefetchTail] & 0xff;
if (MAXDEBUG) this.messageDebugger(" getBytePrefetch[" + this.iPrefetchTail + "]: " + str.toHex(addr) + ":" + str.toHexByte(b));
if (MAXDEBUG) this.messagePrint(" getBytePrefetch[" + this.iPrefetchTail + "]: " + str.toHex(addr) + ":" + str.toHexByte(b));
if (MAXDEBUG) this.assert(addr == (this.aPrefetch[this.iPrefetchTail] >> 8), "X86CPU.getBytePrefetch(" + str.toHex(addr) + "): invalid tail address (" + str.toHex(this.aPrefetch[this.iPrefetchTail] >> 8) + ")");
this.iPrefetchTail = (this.iPrefetchTail + 1) & X86CPU.PREFETCH.MASK;
this.cbPrefetchQueued--;
@ -2125,7 +2130,7 @@ X86CPU.prototype.fillPrefetch = function(n)
var addr = this.addrPrefetchHead;
var b = this.aMemBlocks[(addr & this.addrMemMask) >> this.blockShift].readByte(addr & this.blockLimit);
this.aPrefetch[this.iPrefetchHead] = b | (addr << 8);
if (MAXDEBUG) this.messageDebugger(" fillPrefetch[" + this.iPrefetchHead + "]: " + str.toHex(addr) + ":" + str.toHexByte(b));
if (MAXDEBUG) this.messagePrint(" fillPrefetch[" + this.iPrefetchHead + "]: " + str.toHex(addr) + ":" + str.toHexByte(b));
this.addrPrefetchHead = (addr + 1) & this.addrMemMask;
this.iPrefetchHead = (this.iPrefetchHead + 1) & X86CPU.PREFETCH.MASK;
this.cbPrefetchQueued++;
@ -2150,7 +2155,7 @@ X86CPU.prototype.flushPrefetch = function(addr)
{
this.addrPrefetchHead = addr;
this.iPrefetchTail = this.iPrefetchHead = this.cbPrefetchQueued = this.cbPrefetchValid = 0;
if (MAXDEBUG && addr !== undefined) this.messageDebugger(" flushPrefetch[-]: " + str.toHex(addr));
if (MAXDEBUG && addr !== undefined) this.messagePrint(" flushPrefetch[-]: " + str.toHex(addr));
};
/**
@ -2173,7 +2178,7 @@ X86CPU.prototype.advancePrefetch = function(inc)
this.cbPrefetchQueued -= inc;
} else {
this.flushPrefetch(this.regEIP);
if (MAXDEBUG) this.messageDebugger("advancePrefetch(" + inc + "): flushed");
if (MAXDEBUG) this.messagePrint("advancePrefetch(" + inc + "): flushed");
}
};

View file

@ -1122,7 +1122,7 @@ var X86Grps = {
* @param {number} src (null)
* @return {number}
*/
opGrpCALLdw: function(dst, src) {
opGrpCALLFdw: function(dst, src) {
if (this.regEA < 0) {
return X86Grps.opGrpUndefined.call(this, dst, src);
}
@ -1149,11 +1149,12 @@ var X86Grps = {
* @param {number} src (null)
* @return {number}
*/
opGrpJMPdw: function(dst, src) {
opGrpJMPFdw: function(dst, src) {
if (this.regEA < 0) {
return X86Grps.opGrpUndefined.call(this, dst, src);
}
this.setCSIP(dst, this.getWord(this.regEA + 2));
if (this.cIntReturn) this.checkIntReturn(this.regEIP);
this.nStepCycles -= this.CYCLES.nOpCyclesJmpDM;
if (EAFUNCS) this.setEAWord = this.setEAWordDisabled; else this.opFlags |= X86.OPFLAG.NOWRITE;
return dst;
@ -1324,8 +1325,8 @@ X86Grps.aOpGrp4b = [
];
X86Grps.aOpGrp4w = [
X86Grps.opGrpINCw, X86Grps.opGrpDECw, X86Grps.opGrpCALLw, X86Grps.opGrpCALLdw, // 0xFF(reg=0x0-0x3)
X86Grps.opGrpJMPw, X86Grps.opGrpJMPdw, X86Grps.opGrpPUSHw, X86Grps.opGrpFault // 0xFF(reg=0x4-0x7)
X86Grps.opGrpINCw, X86Grps.opGrpDECw, X86Grps.opGrpCALLw, X86Grps.opGrpCALLFdw, // 0xFF(reg=0x0-0x3)
X86Grps.opGrpJMPw, X86Grps.opGrpJMPFdw, X86Grps.opGrpPUSHw, X86Grps.opGrpFault // 0xFF(reg=0x4-0x7)
];
/*

View file

@ -484,9 +484,6 @@ var X86Help = {
this.segES.load(0);
}
}
/*
* We check for possible "INT n" software interrupt returns only in the cases of "IRET" and "RETF 2".
*/
if (n == 2 && this.cIntReturn) this.checkIntReturn(this.regEIP);
},
/**
@ -576,7 +573,7 @@ var X86Help = {
opHelpFault: function(nFault, nError, fHalt)
{
if (!this.aFlags.fComplete) {
this.messageDebugger("Fault " + str.toHexByte(nFault) + " blocked by Debugger", Messages.WARN);
this.messagePrint("Fault " + str.toHexByte(nFault) + " blocked by Debugger", Messages.WARN);
this.setIP(this.opEA - this.segCS.base);
return;
}
@ -689,22 +686,22 @@ var X86Help = {
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 fRunning = this.aFlags.fRunning;
if (this.messageDebugger(sMessage, bitsMessage)) {
if (this.messagePrint(sMessage, bitsMessage)) {
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.
*
* Note that we had to capture fRunning before calling messageDebugger(), because if MESSAGE.HALT
* is set, messageDebugger() will have already halted the CPU.
* Note that we had to capture fRunning before calling messagePrint(), because if MESSAGE.HALT
* is set, messagePrint() will have already halted the CPU.
*/
fHalt = fRunning;
this.dbg.stopCPU();
}
} else {
/*
* If messageDebugger() returned false, then messageEnabled() must have returned false as well, which
* If messagePrint() 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);

View file

@ -1981,7 +1981,7 @@ var X86OpXX = {
* op=0x9B (wait)
*/
opWAIT: function() {
this.messageDebugger("WAIT not implemented", Messages.CPU);
this.messagePrint("WAIT not implemented", Messages.CPU);
this.nStepCycles--;
},
/**

View file

@ -938,7 +938,7 @@ Component.prototype = {
* If bitsMessage is not specified, the component's MESSAGE category is used.
*
* @this {Component}
* @param {number} [bitsMessage] is zero or more Debugger MESSAGE_* category flag(s)
* @param {number} [bitsMessage] is zero or more MESSAGE_* category flag(s)
* @return {boolean} true if all specified message enabled, false if not
*/
messageEnabled: function(bitsMessage) {
@ -954,18 +954,18 @@ Component.prototype = {
return false;
},
/**
* messageDebugger(sMessage, bitsMessage, fAddress)
* messagePrint(sMessage, bitsMessage, fAddress)
*
* If bitsMessage is not specified, the component's MESSAGE category is used.
* If bitsMessage is true, the message is displayed regardless.
*
* @this {Component}
* @param {string} sMessage is any caller-defined message string
* @param {number|boolean} [bitsMessage] is zero or more Debugger MESSAGE_* category flag(s)
* @param {number|boolean} [bitsMessage] is zero or more 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) {
messagePrint: function(sMessage, bitsMessage, fAddress) {
if (DEBUGGER && this.dbg) {
if (bitsMessage === true || this.messageEnabled(bitsMessage | 0)) {
this.dbg.message(sMessage, fAddress);
@ -986,7 +986,7 @@ Component.prototype = {
* @param {number|null} [addrFrom]
* @param {string|null} [name] of the port, if any
* @param {number|null} [bIn] is the input value, if known, on an input operation
* @param {number|boolean} [bitsMessage] is zero or more Debugger MESSAGE_* category flag(s)
* @param {number|boolean} [bitsMessage] is zero or more MESSAGE_* category flag(s)
*/
messagePort: function(port, bOut, addrFrom, name, bIn, bitsMessage) {
if (DEBUGGER && this.dbg) {

View file

@ -393,6 +393,14 @@ web.promptUser = function(sPrompt, sDefault)
*/
web.fLocalStorage = null;
/**
* TODO: Is there any way to get the Closure Compiler to stop inlining this string? This
* isn't cutting it.
*
* @const {string}
*/
web.sLocalStorageTest = "PCjs.localStorage";
/**
* hasLocalStorage
*
@ -404,11 +412,10 @@ web.hasLocalStorage = function() {
if (web.fLocalStorage == null) {
var f = false;
if (window) {
var sTest = 'PCjs.localStorage';
try {
window.localStorage.setItem(sTest, sTest);
f = (window.localStorage.getItem(sTest) === sTest);
window.localStorage.removeItem(sTest);
window.localStorage.setItem(web.sLocalStorageTest, web.sLocalStorageTest);
f = (window.localStorage.getItem(web.sLocalStorageTest) == web.sLocalStorageTest);
window.localStorage.removeItem(web.sLocalStorageTest);
} catch(e) {
web.logLocalStorageError(e);
f = false;