Move non-CPU-related update functions to the Computer component
This commit is contained in:
parent
8eaa56990c
commit
e02706ab08
18 changed files with 2557 additions and 2553 deletions
|
|
@ -124,7 +124,7 @@
|
|||
<disk path="/disks/pc/os2/ibm/1.0/OS210-DISK1.json">IBM OS/2 1.0 (1.44M Disk 1)</disk>
|
||||
<disk path="/disks/pc/os2/ibm/1.0/OS210-DISK2.json">IBM OS/2 1.0 (1.44M Disk 2)</disk>
|
||||
<disk path="/disks/pc/os2/ibm/1.0/OS210-DISK3.json">IBM OS/2 1.0 (1.44M Disk 3)</disk>
|
||||
<disk path="/disks/pc/os2/ibm/1.1/OS211-INSTALLATION.json">IBM OS/2 1.1 (1.44M Install)</disk>
|
||||
<disk path="/disks/pc/os2/ibm/1.1/OS211-INSTALL.json">IBM OS/2 1.1 (1.44M Install)</disk>
|
||||
<disk path="/disks/pc/os2/ibm/1.1/OS211-DISK01.json">IBM OS/2 1.1 (1.44M Disk 1)</disk>
|
||||
<disk path="/disks/pc/os2/ibm/1.1/OS211-DISK02.json">IBM OS/2 1.1 (1.44M Disk 2)</disk>
|
||||
<disk path="/disks/pc/os2/ibm/1.1/OS211-DISK03.json">IBM OS/2 1.1 (1.44M Disk 3)</disk>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<?xml-stylesheet type="text/xsl" href="/versions/pcjs/1.21.4/manifest.xsl"?>
|
||||
<manifest type="software">
|
||||
<title>IBM OS/2 1.1</title>
|
||||
<disk id="disk00" size="1474560" chs="80:2:18" img="archive/OS211-INSTALLATION.img" href="/disks/pc/os2/ibm/1.1/OS211-INSTALLATION.json" md5="64b1a50f35385f326e7b59b17b417769" md5json="6510aede5a434ae794a3ee9e8d09d6c9">
|
||||
<disk id="disk00" size="1474560" chs="80:2:18" img="archive/OS211-INSTALL.img" href="/disks/pc/os2/ibm/1.1/OS211-INSTALL.json" md5="64b1a50f35385f326e7b59b17b417769" md5json="6510aede5a434ae794a3ee9e8d09d6c9">
|
||||
<name>IBM OS/2 1.1 (1.44M Install)</name>
|
||||
</disk>
|
||||
<disk id="disk01" size="1474560" chs="80:2:18" img="archive/OS211-DISK01.img" href="/disks/pc/os2/ibm/1.1/OS211-DISK01.json" md5="5b0526049c097e7afa54073f13cf87d1" md5json="f74cb91702c9a502418139601269280d">
|
||||
|
|
|
|||
|
|
@ -1114,4 +1114,7 @@
|
|||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="comment">
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -338,7 +338,7 @@ function DiskDump(sDiskPath, asExclude, sFormat, fComments, sSize, sServerRoot,
|
|||
this.sDiskPath = path.join(this.sServerRoot, sDiskPath);
|
||||
}
|
||||
this.asExclude = asExclude || DiskDump.asExclusions;
|
||||
this.kbTarget = +sSize || 0;
|
||||
this.kbTarget = sSize|0; // convert the numeric string to a 32-bit number (or 0 if invalid)
|
||||
this.sFormat = (sFormat || DumpAPI.FORMAT.JSON);
|
||||
this.fJSONNative = (this.sFormat == DumpAPI.FORMAT.JSON && !fComments);
|
||||
this.nJSONIndent = 0;
|
||||
|
|
|
|||
|
|
@ -184,6 +184,14 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
|
|||
}
|
||||
this.dbg = /** @type {Debugger} */ (Component.getComponentByType("Debugger", this.id));
|
||||
|
||||
/*
|
||||
* Enumerate all Video components for future updateVideo() calls.
|
||||
*/
|
||||
this.aVideo = [];
|
||||
for (var video = null; (video = this.getMachineComponent("Video", video));) {
|
||||
this.aVideo.push(video);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the Bus component
|
||||
*/
|
||||
|
|
@ -1437,6 +1445,65 @@ Computer.prototype.getMachineComponent = function(sType, componentPrev)
|
|||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* updateFocus(fScroll)
|
||||
*
|
||||
* NOTE: When soft keyboard buttons call us to return focus to the machine (and away from the button),
|
||||
* the scroll feature has annoying effect on iOS, so we no longer do it by default (fScroll must be true).
|
||||
*
|
||||
* @this {Computer}
|
||||
* @param {boolean} [fScroll]
|
||||
*/
|
||||
Computer.prototype.updateFocus = function(fScroll)
|
||||
{
|
||||
if (this.aVideo.length) {
|
||||
/*
|
||||
* This seems to be recommended work-around to prevent the browser from scrolling the focused element
|
||||
* into view. The CPU is not a visual component, so when the CPU wants to set focus, the primary intent
|
||||
* is to ensure that keyboard input is fielded properly.
|
||||
*/
|
||||
var x = 0, y = 0;
|
||||
if (fScroll && window) {
|
||||
x = window.scrollX;
|
||||
y = window.scrollY;
|
||||
}
|
||||
/*
|
||||
* TODO: We need a mechanism to determine the "active" display, instead of hard-coding this to aVideo[0].
|
||||
*/
|
||||
this.aVideo[0].setFocus();
|
||||
if (fScroll && window) {
|
||||
window.scrollTo(x, y);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* updateStatus()
|
||||
*
|
||||
* @this {Computer}
|
||||
*/
|
||||
Computer.prototype.updateStatus = function()
|
||||
{
|
||||
if (this.panel) this.panel.updateStatus();
|
||||
};
|
||||
|
||||
/**
|
||||
* updateVideo(fForce)
|
||||
*
|
||||
* Any high-frequency updates should be performed here. Avoid DOM updates, since updateVideo() can be called up to
|
||||
* 60 times per second (see VIDEO_UPDATES_PER_SECOND).
|
||||
*
|
||||
* @this {Computer}
|
||||
* @param {boolean} [fForce] (true to force a video update)
|
||||
*/
|
||||
Computer.prototype.updateVideo = function(fForce)
|
||||
{
|
||||
for (var i = 0; i < this.aVideo.length; i++) {
|
||||
this.aVideo[i].updateScreen(fForce);
|
||||
}
|
||||
if (this.panel) this.panel.updateAnimation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Computer.init()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -122,11 +122,6 @@ function CPU(parmsCPU, nCyclesDefault)
|
|||
this.aCounts.nCyclesChecksumInterval = parmsCPU["csInterval"];
|
||||
this.aCounts.nCyclesChecksumStop = parmsCPU["csStop"];
|
||||
|
||||
/*
|
||||
* Initially, no video devices are attached that require CPU-driven updates. initBus() will update this.
|
||||
*/
|
||||
this.aVideo = [];
|
||||
|
||||
this.onRunTimeout = this.runCPU.bind(this); // function onRunTimeout() { cpu.runCPU(); };
|
||||
|
||||
this.setReady();
|
||||
|
|
@ -180,14 +175,6 @@ CPU.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
|
||||
this.fpu = cmp.getMachineComponent("FPU");
|
||||
|
||||
/*
|
||||
* Attach the Video component to the CPU, so that the CPU can periodically update
|
||||
* the video display via updateVideo(), as cycles permit.
|
||||
*/
|
||||
for (var video = null; (video = cmp.getMachineComponent("Video", video));) {
|
||||
this.aVideo.push(video);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach the ChipSet component to the CPU so that it can obtain the IDT vector number
|
||||
* of pending hardware interrupts in response to the ChipSet's updateINTR() notifications.
|
||||
|
|
@ -323,7 +310,7 @@ CPU.prototype.autoStart = function()
|
|||
*/
|
||||
if (this.flags.fAutoStart || (!DEBUGGER || !this.dbg) && this.bindings["run"] === undefined) {
|
||||
/*
|
||||
* Now we ALSO set fSetFocus when calling runCPU(), on the assumption that in the "auto-starting" context,
|
||||
* Now we ALSO set fUpdateFocus when calling runCPU(), on the assumption that in the "auto-starting" context,
|
||||
* a machine without focus is like a day without sunshine.
|
||||
*/
|
||||
this.runCPU(true);
|
||||
|
|
@ -483,66 +470,6 @@ CPU.prototype.displayValue = function(sLabel, nValue, cch)
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* updateStatus(fForce)
|
||||
*
|
||||
* This provides periodic Control Panel updates (eg, a few times per second; see STATUS_UPDATES_PER_SECOND).
|
||||
* The X86CPU subclasses updateStatus() to take care of any DOM updates (eg, register values) while the CPU is running.
|
||||
*
|
||||
* @this {CPU}
|
||||
* @param {boolean} [fForce]
|
||||
*/
|
||||
CPU.prototype.updateStatus = function(fForce)
|
||||
{
|
||||
if (this.cmp && this.cmp.panel) this.cmp.panel.updateStatus();
|
||||
};
|
||||
|
||||
/**
|
||||
* updateVideo(fForce)
|
||||
*
|
||||
* Any high-frequency updates should be performed here. Avoid DOM updates, since updateVideo() can be called up to
|
||||
* 60 times per second (see VIDEO_UPDATES_PER_SECOND).
|
||||
*
|
||||
* @this {CPU}
|
||||
* @param {boolean} [fForce] (true to force a video update)
|
||||
*/
|
||||
CPU.prototype.updateVideo = function(fForce)
|
||||
{
|
||||
for (var i = 0; i < this.aVideo.length; i++) {
|
||||
this.aVideo[i].updateScreen(fForce);
|
||||
}
|
||||
if (this.cmp && this.cmp.panel) this.cmp.panel.updateAnimation();
|
||||
};
|
||||
|
||||
/**
|
||||
* setFocus(fScroll)
|
||||
*
|
||||
* NOTE: When soft keyboard buttons call us to return focus to the machine (and away from the button),
|
||||
* the scroll feature has annoying effect on iOS, so we no longer do it by default (fScroll must be true).
|
||||
*
|
||||
* @this {CPU}
|
||||
* @param {boolean} [fScroll]
|
||||
*/
|
||||
CPU.prototype.setFocus = function(fScroll)
|
||||
{
|
||||
if (this.aVideo.length) {
|
||||
/*
|
||||
* This seems to be recommended work-around to prevent the browser from scrolling the focused element
|
||||
* into view. The CPU is not a visual component, so when the CPU wants to set focus, the primary intent
|
||||
* is to ensure that keyboard input is fielded properly.
|
||||
*/
|
||||
var x = 0, y = 0;
|
||||
if (fScroll && window) {
|
||||
x = window.scrollX;
|
||||
y = window.scrollY;
|
||||
}
|
||||
this.aVideo[0].setFocus();
|
||||
if (fScroll && window) {
|
||||
window.scrollTo(x, y);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* setBinding(sHTMLType, sBinding, control, sValue)
|
||||
*
|
||||
|
|
@ -823,20 +750,20 @@ CPU.prototype.getSpeedTarget = function()
|
|||
};
|
||||
|
||||
/**
|
||||
* setSpeed(nMultiplier, fSetFocus)
|
||||
* setSpeed(nMultiplier, fUpdateFocus)
|
||||
*
|
||||
* NOTE: This used to return the target speed, in mhz, but no callers appear to care at this point.
|
||||
*
|
||||
* @this {CPU}
|
||||
* @param {number} [nMultiplier] is the new proposed multiplier (reverts to 1 if the target was too high)
|
||||
* @param {boolean} [fSetFocus] is true to give the CPU focus
|
||||
* @param {boolean} [fUpdateFocus] is true to give the Computer focus
|
||||
* @return {boolean} true if successful, false if not
|
||||
*
|
||||
* @desc Whenever the speed is changed, the running cycle count and corresponding start time must be reset,
|
||||
* so that the next effective speed calculation obtains sensible results. In fact, when runCPU() initially calls
|
||||
* setSpeed() with no parameters, that's all this function does (it doesn't change the current speed setting).
|
||||
*/
|
||||
CPU.prototype.setSpeed = function(nMultiplier, fSetFocus)
|
||||
CPU.prototype.setSpeed = function(nMultiplier, fUpdateFocus)
|
||||
{
|
||||
var fSuccess = false;
|
||||
if (nMultiplier !== undefined) {
|
||||
|
|
@ -857,7 +784,7 @@ CPU.prototype.setSpeed = function(nMultiplier, fSetFocus)
|
|||
if (controlSpeed) controlSpeed.textContent = sSpeed;
|
||||
this.println("target speed: " + sSpeed);
|
||||
}
|
||||
if (fSetFocus) this.setFocus();
|
||||
if (fUpdateFocus && this.cmp) this.cmp.updateFocus();
|
||||
}
|
||||
this.addCycles(this.nRunCycles);
|
||||
this.nRunCycles = 0;
|
||||
|
|
@ -1014,12 +941,12 @@ CPU.prototype.calcRemainingTime = function()
|
|||
};
|
||||
|
||||
/**
|
||||
* runCPU(fSetFocus)
|
||||
* runCPU(fUpdateFocus)
|
||||
*
|
||||
* @this {CPU}
|
||||
* @param {boolean} [fSetFocus] is true to give the CPU focus
|
||||
* @param {boolean} [fUpdateFocus] is true to update Computer focus
|
||||
*/
|
||||
CPU.prototype.runCPU = function(fSetFocus)
|
||||
CPU.prototype.runCPU = function(fUpdateFocus)
|
||||
{
|
||||
if (!this.setBusy(true)) {
|
||||
this.updateCPU();
|
||||
|
|
@ -1027,7 +954,7 @@ CPU.prototype.runCPU = function(fSetFocus)
|
|||
return;
|
||||
}
|
||||
|
||||
this.startCPU(fSetFocus);
|
||||
this.startCPU(fUpdateFocus);
|
||||
|
||||
/*
|
||||
* calcStartTime() initializes the cycle counter and timestamp for this runCPU() invocation, and optionally
|
||||
|
|
@ -1078,13 +1005,13 @@ CPU.prototype.runCPU = function(fSetFocus)
|
|||
this.aCounts.nCyclesNextVideoUpdate -= nCycles;
|
||||
if (this.aCounts.nCyclesNextVideoUpdate <= 0) {
|
||||
this.aCounts.nCyclesNextVideoUpdate += this.aCounts.nCyclesPerVideoUpdate;
|
||||
this.updateVideo();
|
||||
if (this.cmp) this.cmp.updateVideo();
|
||||
}
|
||||
|
||||
this.aCounts.nCyclesNextStatusUpdate -= nCycles;
|
||||
if (this.aCounts.nCyclesNextStatusUpdate <= 0) {
|
||||
this.aCounts.nCyclesNextStatusUpdate += this.aCounts.nCyclesPerStatusUpdate;
|
||||
this.updateStatus();
|
||||
if (this.cmp) this.cmp.updateStatus();
|
||||
}
|
||||
|
||||
this.aCounts.nCyclesNextYield -= nCycles;
|
||||
|
|
@ -1106,13 +1033,13 @@ CPU.prototype.runCPU = function(fSetFocus)
|
|||
};
|
||||
|
||||
/**
|
||||
* startCPU(fSetFocus)
|
||||
* startCPU(fUpdateFocus)
|
||||
*
|
||||
* WARNING: Other components must use runCPU() to get the CPU running; this is a runCPU() helper function only.
|
||||
*
|
||||
* @param {boolean} [fSetFocus]
|
||||
* @param {boolean} [fUpdateFocus]
|
||||
*/
|
||||
CPU.prototype.startCPU = function(fSetFocus)
|
||||
CPU.prototype.startCPU = function(fUpdateFocus)
|
||||
{
|
||||
if (!this.flags.fRunning) {
|
||||
/*
|
||||
|
|
@ -1128,8 +1055,10 @@ CPU.prototype.startCPU = function(fSetFocus)
|
|||
if (this.chipset) this.chipset.setSpeaker();
|
||||
var controlRun = this.bindings["run"];
|
||||
if (controlRun) controlRun.textContent = "Halt";
|
||||
this.updateStatus(true);
|
||||
if (fSetFocus) this.setFocus(true);
|
||||
if (this.cmp) {
|
||||
this.cmp.updateStatus();
|
||||
if (fUpdateFocus) this.cmp.updateFocus(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1187,8 +1116,10 @@ CPU.prototype.stopCPU = function(fComplete)
|
|||
*/
|
||||
CPU.prototype.updateCPU = function(fForce)
|
||||
{
|
||||
this.updateVideo(fForce);
|
||||
this.updateStatus();
|
||||
if (this.cmp) {
|
||||
this.cmp.updateVideo(fForce);
|
||||
this.cmp.updateStatus();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2182,11 +2182,11 @@ if (DEBUGGER) {
|
|||
};
|
||||
|
||||
/**
|
||||
* setFocus()
|
||||
* updateFocus()
|
||||
*
|
||||
* @this {Debugger}
|
||||
*/
|
||||
Debugger.prototype.setFocus = function()
|
||||
Debugger.prototype.updateFocus = function()
|
||||
{
|
||||
if (this.controlDebug) this.controlDebug.focus();
|
||||
};
|
||||
|
|
@ -3945,16 +3945,16 @@ if (DEBUGGER) {
|
|||
};
|
||||
|
||||
/**
|
||||
* runCPU(fSetFocus)
|
||||
* runCPU(fUpdateFocus)
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {boolean} [fSetFocus] is true to give the CPU focus
|
||||
* @param {boolean} [fUpdateFocus] is true to update focus
|
||||
* @return {boolean} true if run request successful, false if not
|
||||
*/
|
||||
Debugger.prototype.runCPU = function(fSetFocus)
|
||||
Debugger.prototype.runCPU = function(fUpdateFocus)
|
||||
{
|
||||
if (!this.isCPUAvail()) return false;
|
||||
this.cpu.runCPU(fSetFocus);
|
||||
this.cpu.runCPU(fUpdateFocus);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
@ -4258,7 +4258,7 @@ if (DEBUGGER) {
|
|||
this.println(sStopped);
|
||||
}
|
||||
this.updateStatus(true);
|
||||
this.setFocus();
|
||||
this.updateFocus();
|
||||
this.clearTempBreakpoint(this.cpu.regLIP);
|
||||
}
|
||||
};
|
||||
|
|
@ -7618,7 +7618,7 @@ if (DEBUGGER) {
|
|||
if (this.nStep) {
|
||||
this.setTempBreakpoint(dbgAddr);
|
||||
if (!this.runCPU()) {
|
||||
this.cpu.setFocus();
|
||||
if (this.cmp) this.cmp.updateFocus();
|
||||
this.nStep = 0;
|
||||
}
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1438,7 +1438,11 @@ FDC.prototype.doneLoadDiskette = function onFDCLoadNotify(drive, disk, sDiskette
|
|||
drive.nDiskHeads = aDiskInfo[1];
|
||||
drive.nDiskSectors = aDiskInfo[2];
|
||||
|
||||
if (this.cpu) this.cpu.setFocus();
|
||||
/*
|
||||
* Since you usually want the Computer to have focus again after loading a new diskette, let's try automatically
|
||||
* updating the focus after a successful load.
|
||||
*/
|
||||
if (this.cmp) this.cmp.updateFocus();
|
||||
}
|
||||
else {
|
||||
drive.fLocal = false;
|
||||
|
|
|
|||
|
|
@ -1187,7 +1187,7 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
case "caps-lock":
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickCapsLock(event) {
|
||||
if (kbd.cpu) kbd.cpu.setFocus();
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.toggleCapsLock();
|
||||
};
|
||||
return true;
|
||||
|
|
@ -1195,7 +1195,7 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
case "num-lock":
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickNumLock(event) {
|
||||
if (kbd.cpu) kbd.cpu.setFocus();
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.toggleNumLock();
|
||||
};
|
||||
return true;
|
||||
|
|
@ -1203,7 +1203,7 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
case "scroll-lock":
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickScrollLock(event) {
|
||||
if (kbd.cpu) kbd.cpu.setFocus();
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.toggleScrollLock();
|
||||
};
|
||||
return true;
|
||||
|
|
@ -1218,7 +1218,7 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
control.onclick = function(kbd, sKey, simCode) {
|
||||
return function onClickKeyboard(event) {
|
||||
if (!COMPILED && kbd.messageEnabled()) kbd.printMessage(sKey + " clicked", Messages.KEYS);
|
||||
if (kbd.cpu) kbd.cpu.setFocus();
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
kbd.updateShiftState(simCode, true); // future-proofing if/when any LOCK keys are added to CLICKCODES
|
||||
kbd.addActiveKey(simCode, true);
|
||||
};
|
||||
|
|
@ -1255,7 +1255,7 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
*/
|
||||
this.bindings[id] = control;
|
||||
control.onclick = function onClickTest(event) {
|
||||
if (kbd.cpu) kbd.cpu.setFocus();
|
||||
if (kbd.cmp) kbd.cmp.updateFocus();
|
||||
return kbd.injectKeys(sValue);
|
||||
};
|
||||
return true;
|
||||
|
|
@ -1323,6 +1323,7 @@ Keyboard.prototype.findBinding = function(simCode, sType, fDown)
|
|||
*/
|
||||
Keyboard.prototype.initBus = function(cmp, bus, cpu, dbg)
|
||||
{
|
||||
this.cmp = cmp;
|
||||
this.bus = bus;
|
||||
this.cpu = cpu;
|
||||
this.dbg = dbg;
|
||||
|
|
|
|||
|
|
@ -5758,28 +5758,20 @@ Video.prototype.updateScreenGraphicsEGA = function(addrBuffer, addrScreen, addrS
|
|||
if (x < xDirty) xDirty = x;
|
||||
for (iPixel = 0; iPixel < nPixels; iPixel++) {
|
||||
/*
|
||||
* We must follow the golden JavaScript rule of appending "|0" to all hex constants with bit 31 set.
|
||||
* The innocuous use of the bit-wise OR operator has the side-effect of producing a negative value,
|
||||
* matching how entries in Video.aEGADWToByte are initialized (eg, "Video.aEGADWToByte[0x80000000|0]").
|
||||
*/
|
||||
var dwPixel = data & (0x80808080|0);
|
||||
/*
|
||||
* This was the old approach to dealing with negative hex values, by converting them to positive
|
||||
* values that didn't alter the low 32 bits. But it's not ideal, because it requires using values here
|
||||
* and in the array that are outside the signed 32-bit range, potentially triggering floating-point.
|
||||
*
|
||||
* if (dwPixel < 0) dwPixel += 0x100000000;
|
||||
*
|
||||
* An even simpler solution would be to use the unsigned right-shift operator:
|
||||
*
|
||||
* dwPixel >>> 0
|
||||
*
|
||||
* but again, all that does is produce a value outside the signed 32-bit range, which is sub-optimal.
|
||||
* 0x80808080 may LOOK like a 32-bit value, but it is not, because JavaScript treats it as a POSITIVE
|
||||
* number, and therefore outside the normal 32-bit integer range; however, the AND operator guarantees
|
||||
* that the result will be a 32-bit value, so it doesn't matter.
|
||||
*/
|
||||
var dwPixel = data & 0x80808080;
|
||||
this.assert(Video.aEGADWToByte[dwPixel] !== undefined);
|
||||
/*
|
||||
* Since assertions don't fix problems (only catch them, and only in DEBUG builds), I'm also ensuring
|
||||
* that bPixel will always default to 0 if an undefined value ever slips through again.
|
||||
* that bPixel will default to 0 if an undefined value ever slips through again.
|
||||
*
|
||||
* How did an undefined value slip through? We had (incorrectly) initialized entries in aEGADWToByte;
|
||||
* for example, we used to set aEGADWToByte[0x80808080] instead of aEGADWToByte[0x80808080|0]. The
|
||||
* former is a POSITIVE index that is outside the 32-bit integer range, whereas the latter is a NEGATIVE
|
||||
* index, which is what this code requires.
|
||||
*/
|
||||
var bPixel = Video.aEGADWToByte[dwPixel] || 0;
|
||||
this.setPixel(this.imageScreenBuffer, x++, y, aPixelColors[bPixel]);
|
||||
|
|
@ -5923,8 +5915,8 @@ Video.prototype.getRetraceBits = function(card)
|
|||
|
||||
/*
|
||||
* NOTE: The CGA bits CGA.STATUS.RETRACE (0x01) and CGA.STATUS.VRETRACE (0x08) match the EGA definitions,
|
||||
* and they also correspond to the MDA bits MDA.STATUS.HDRIVE (0x01) and MDA.STATUS.BWVIDEO (0x08); I'm not sure why
|
||||
* the MDA uses different designations, but the bits appear to serve the same purpose.
|
||||
* and they also correspond to the MDA bits MDA.STATUS.HDRIVE (0x01) and MDA.STATUS.BWVIDEO (0x08); I'm not sure
|
||||
* why the MDA uses different designations, but the bits appear to serve the same purpose.
|
||||
*
|
||||
* TODO: Decide whether this more faithful emulation of the retrace bits should be extended to the MDA/CGA, too;
|
||||
* doing so might slow down the BIOS scroll code a bit, though.
|
||||
|
|
|
|||
|
|
@ -1116,4 +1116,7 @@
|
|||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="comment">
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
|
|
|||
|
|
@ -624,21 +624,21 @@ web.downloadFile = function(sData, sType, fBase64, sFileName)
|
|||
sURI += (fBase64? sData : encodeURI(sData));
|
||||
} else {
|
||||
sURI += (fBase64? sData : encodeURIComponent(sData));
|
||||
if (sFileName) {
|
||||
link = document.createElement('a');
|
||||
if (typeof link.download != 'string') link = null;
|
||||
}
|
||||
}
|
||||
if (sFileName) {
|
||||
link = document.createElement('a');
|
||||
if (typeof link.download != 'string') link = null;
|
||||
}
|
||||
if (link) {
|
||||
link.href = sURI;
|
||||
link.download = sFileName;
|
||||
document.body.appendChild(link); // Firefox requires the link to be in the body
|
||||
document.body.appendChild(link); // Firefox allegedly requires the link to be in the body
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
sAlert = 'Check your Downloads folder for "' + sFileName + '"';
|
||||
sAlert = 'Check your Downloads folder for ' + sFileName + '.';
|
||||
} else {
|
||||
window.open(sURI);
|
||||
sAlert = 'Check your browser for a new window/tab containing the requested data';
|
||||
sAlert = 'Check your browser for a new window/tab containing the requested data (' + sFileName + ').';
|
||||
}
|
||||
return sAlert;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1114,4 +1114,7 @@
|
|||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="comment">
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue