Added more demos and support for mixed-case properties (including a new 'debugger' property in Markdown files)

This commit is contained in:
Jeff Parsons 2016-03-05 18:09:41 -08:00
commit 7ca64fcea5
162 changed files with 84341 additions and 345 deletions

View file

@ -328,6 +328,7 @@ MarkOut.aHTMLEntities = {
* 'id' (eg, "ibm5150")
* 'name' (eg, "IBM PC (Model 5150) with Monochrome Display")
* 'type' (eg, "pc" or "pc-dbg")
* 'debugger' (eg, true)
* 'config' (eg, "machine.xml")
* 'template' (eg, "machine.xsl")
* 'uncompiled' (eg, true)
@ -355,7 +356,7 @@ MarkOut.aHTMLEntities = {
MarkOut.aFMBooleanMachineProps = {
'autopower': "autoPower"
};
MarkOut.aFMReservedMachineProps = ['id', 'name', 'type', 'config', 'template', 'uncompiled', 'automount', 'parms'];
MarkOut.aFMReservedMachineProps = ['id', 'name', 'type', 'debugger', 'config', 'template', 'uncompiled', 'automount', 'parms'];
/**
* convertMD()
@ -1121,11 +1122,11 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock)
if (!this.fMachineXML && this.aMachineDefs[sMachineID]) {
var machine = this.aMachineDefs[sMachineID];
sMachine = machine['type'] || "pc";
sMachineOptions = (sMachine.indexOf("-dbg") > 0? "debugger" : "");
sMachineOptions = ((sMachine.indexOf("-dbg") > 0 || machine['debugger'] == "true")? "debugger" : "");
sMachine = sMachine.replace("-dbg", "").toUpperCase();
sMachineXMLFile = machine['config'] || "machine.xml";
sMachineXSLFile = machine['template'] || "";
sMachineVersion = (machine['uncompiled'] && machine['uncompiled'] == "true"? "uncompiled" : "");
sMachineVersion = ((machine['uncompiled'] == "true")? "uncompiled" : "");
sMachineParms = machine['parms'] || "";
sReplacement = machine['name'] || "Embedded PC";
sReplacement = "[" + sReplacement + "](" + sMachineXMLFile + ' "' + sMachine + 'js!' + sMachineID + '!' + sMachineXSLFile + '!!' + sMachineOptions + '!' + sMachineParms + '")';

View file

@ -1091,6 +1091,10 @@ Computer.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
return true;
case "save":
if (str.endsWith(web.getHost(), "pcjs.org")) {
control.style.display = "none";
return false;
}
this.bindings[sBinding] = control;
control.onclick = function onClickSave() {
var sUserID = computer.queryUserID(true);
@ -1154,6 +1158,11 @@ Computer.prototype.queryUserID = function(fPrompt)
sUserID = web.getLocalStorageItem(Computer.STATE_USERID);
if (sUserID !== undefined) {
if (!sUserID && fPrompt) {
/*
* NOTE: Warning the user here that "Save" operations are not currently supported by pcjs.org is
* merely a precaution, because ordinarily, setBinding() should have already determined if we are
* running from pcjs.org and disabled any "Save" button.
*/
sUserID = web.promptUser("Saving machine states on the pcjs.org server is currently unsupported.\n\nIf you're running your own server, enter your user ID below.");
if (sUserID) {
sUserID = this.verifyUserID(sUserID);

View file

@ -109,11 +109,11 @@ function CPU(parmsCPU, nCyclesDefault)
this.aFlags.fDisplayLiveRegs = false;
/*
* Provide a power-saving URL-based way of overriding the 'autostart' setting;
* if an "autostart" parameter is specified on the URL, anything other than "true"
* Provide a power-saving URL-based way of overriding the 'autoStart' setting;
* if an "autoStart" parameter is specified on the URL, anything other than "true"
* or "false" is treated as the null setting (see above for details).
*/
var sAutoStart = Component.parmsURL['autostart'];
var sAutoStart = Component.parmsURL['autostart'] || Component.parmsURL['autoStart'];
if (sAutoStart !== undefined) {
this.aFlags.fAutoStart = (sAutoStart == "true"? true : (sAutoStart == "false"? false : null));
}
@ -320,8 +320,15 @@ CPU.prototype.powerDown = function(fSave, fShutdown)
*/
CPU.prototype.autoStart = function()
{
/*
* Start running automatically on power-up, assuming there's no Debugger and no "Run" button
*/
if (this.aFlags.fAutoStart === true || this.aFlags.fAutoStart === null && (!DEBUGGER || !this.dbg) && this.bindings["run"] === undefined) {
this.runCPU(); // start running automatically on power-up, assuming there's no Debugger and no "Run" button
/*
* Now we ALSO set fSetFocus 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);
return true;
}
return false;
@ -385,7 +392,10 @@ CPU.prototype.resetChecksum = function()
if (this.aFlags.fChecksum) {
this.aCounts.nChecksum = 0;
this.aCounts.nCyclesChecksumNext = this.aCounts.nCyclesChecksumStart - this.nTotalCycles;
// this.aCounts.nCyclesChecksumNext = this.aCounts.nCyclesChecksumStart + this.aCounts.nCyclesChecksumInterval - (this.nTotalCycles % this.aCounts.nCyclesChecksumInterval);
/*
* this.aCounts.nCyclesChecksumNext = this.aCounts.nCyclesChecksumStart + this.aCounts.nCyclesChecksumInterval -
* (this.nTotalCycles % this.aCounts.nCyclesChecksumInterval);
*/
return true;
}
return false;
@ -513,7 +523,16 @@ CPU.prototype.updateVideo = function(fForce)
*/
CPU.prototype.setFocus = function()
{
if (this.aVideo.length) this.aVideo[0].setFocus();
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 = window.scrollX, y = window.scrollY;
this.aVideo[0].setFocus();
window.scrollTo(x, y);
}
};
/**
@ -530,6 +549,7 @@ CPU.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
{
var cpu = this;
var fBound = false;
switch (sBinding) {
case "power":
case "reset":
@ -795,19 +815,20 @@ CPU.prototype.getSpeedTarget = function()
};
/**
* setSpeed(nMultiplier, fOnClick)
* setSpeed(nMultiplier, fSetFocus)
*
* 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} [fOnClick] is true if called from a click handler that might have stolen focus
* @param {boolean} [fSetFocus] is true to give the CPU 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, fOnClick)
CPU.prototype.setSpeed = function(nMultiplier, fSetFocus)
{
var fSuccess = false;
if (nMultiplier !== undefined) {
@ -828,7 +849,7 @@ CPU.prototype.setSpeed = function(nMultiplier, fOnClick)
if (controlSpeed) controlSpeed.textContent = sSpeed;
this.println("target speed: " + sSpeed);
}
if (fOnClick) this.setFocus();
if (fSetFocus) this.setFocus();
}
this.addCycles(this.nRunCycles);
this.nRunCycles = 0;
@ -985,12 +1006,12 @@ CPU.prototype.calcRemainingTime = function()
};
/**
* runCPU(fOnClick)
* runCPU(fSetFocus)
*
* @this {CPU}
* @param {boolean} [fOnClick] is true if called from a click handler that might have stolen focus
* @param {boolean} [fSetFocus] is true to give the CPU focus
*/
CPU.prototype.runCPU = function(fOnClick)
CPU.prototype.runCPU = function(fSetFocus)
{
if (!this.setBusy(true)) {
this.updateCPU();
@ -998,7 +1019,7 @@ CPU.prototype.runCPU = function(fOnClick)
return;
}
this.startCPU(fOnClick);
this.startCPU(fSetFocus);
/*
* calcStartTime() initializes the cycle counter and timestamp for this runCPU() invocation, and optionally

View file

@ -3899,16 +3899,16 @@ if (DEBUGGER) {
};
/**
* runCPU(fOnClick)
* runCPU(fSetFocus)
*
* @this {Debugger}
* @param {boolean} [fOnClick] is true if called from a click handler that might have stolen focus
* @param {boolean} [fSetFocus] is true to give the CPU focus
* @return {boolean} true if run request successful, false if not
*/
Debugger.prototype.runCPU = function(fOnClick)
Debugger.prototype.runCPU = function(fSetFocus)
{
if (!this.isCPUAvail()) return false;
this.cpu.runCPU(fOnClick);
this.cpu.runCPU(fSetFocus);
return true;
};

View file

@ -557,17 +557,20 @@ Mouse.prototype.clickMouse = function(iButton, fDown)
if (this.fButton1 != fDown) {
this.fButton1 = fDown;
this.sendPacket(sDiag);
return;
}
break;
case Mouse.BUTTON.RIGHT:
if (this.fButton2 != fDown) {
this.fButton2 = fDown;
this.sendPacket(sDiag);
return;
}
break;
default:
break;
}
this.printMessage(sDiag + ": ignored");
}
};

View file

@ -3172,15 +3172,16 @@ Video.prototype.captureTouch = function(nTouchConfig)
function onTouchEnd(event) { video.onTouchEnd(event); },
false // we'll specify false for the 'useCapture' parameter for now...
);
/*
* Using desktop mouse events to simulate touch events should only be enabled as needed.
*
if (DEBUG) {
/*
*/
control.addEventListener(
'mousedown',
function onMouseDown(event) { video.onTouchStart(event); },
false // we'll specify false for the 'useCapture' parameter for now...
);
/*
control.addEventListener(
'mousemove',
function onMouseMove(event) { video.onTouchMove(event); },
@ -3191,17 +3192,21 @@ Video.prototype.captureTouch = function(nTouchConfig)
function onMouseUp(event) { video.onTouchEnd(event); },
false // we'll specify false for the 'useCapture' parameter for now...
);
*/
}
*/
// this.log("touch events captured");
this.nTouchConfig = nTouchConfig;
this.xTouch = this.yTouch = this.timeTouch = -1;
/*
* As long as fTouchDefault is false, we call preventDefault() on every touch event, to prevent
* the page from moving/scrolling while the canvas is processing touch events. However, there must
* also be exceptions to permit the soft keyboard to activate; see processTouchEvent() for details.
*/
this.fTouchDefault = false;
/*
* I also need to come up with some rules for when the simulated mouse's primary button stays down.
* Let's try setting a timeout handler whenever a touchstart is received, which we'll immediately cancel

View file

@ -1589,7 +1589,18 @@ X86Seg.prototype.messageSeg = function(sel, base, limit, type, ext)
if (this.id == X86Seg.ID.CODE) sDPL += " cpl=" + this.cpl;
this.dbg.message("loadSeg(" + this.sName + "):" + ch + "sel=" + str.toHexWord(sel) + " base=" + str.toHex(base) + " limit=" + str.toHexWord(limit) + " type=" + str.toHexWord(type) + sDPL, true);
}
this.cpu.assert(/* base !== X86.ADDR_INVALID && */ (this.cpu.model >= X86.MODEL_80386 || !ext || ext == X86.DESC.EXT.AVAIL));
/*
* Unless I've got a bug that's causing descriptor corruption, it appears that Windows 3.0 may be setting the
* EXT field of descriptors, even when the processor is an 80286; eg, the EXT field below has been set to 0x000F:
*
* ## ds 1bd
* dumpSel(0x01BD): %1101B8
* %001101B8 FFFF C090 B317 000F
*
* So I've disabled this assert (I had already disabled the "base !== X86.ADDR_INVALID" check).
*
* this.cpu.assert(base !== X86.ADDR_INVALID && (this.cpu.model >= X86.MODEL_80386 || !ext || ext == X86.DESC.EXT.AVAIL));
*/
}
};

View file

@ -183,7 +183,7 @@
<xsl:choose>
<xsl:when test="@pos = 'left'">float:left;</xsl:when>
<xsl:when test="@pos = 'right'">float:right;</xsl:when>
<xsl:when test="@pos = 'center'">margin:0 auto;</xsl:when>
<xsl:when test="@pos = 'center'">margin:0 auto;clear:both;</xsl:when>
<xsl:when test="@pos">position:<xsl:value-of select="@pos"/>;</xsl:when>
<xsl:when test="$left != '' or $top != ''">position:relative;</xsl:when>
<xsl:otherwise/>
@ -349,11 +349,16 @@
<xsl:if test="@label"><xsl:text> </xsl:text><xsl:value-of select="$APPCLASS"/><xsl:text>-label</xsl:text></xsl:if>
</xsl:variable>
<xsl:variable name="labelWidth">
<xsl:if test="@labelwidth">width:<xsl:value-of select="@labelwidth"/>;</xsl:if>
<xsl:choose>
<xsl:when test="@labelwidth">width:<xsl:value-of select="@labelwidth"/>;</xsl:when>
<xsl:when test="@labelWidth">width:<xsl:value-of select="@labelWidth"/>;</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:variable name="labelStyle">
<xsl:choose>
<xsl:when test="@labelstyle"><xsl:value-of select="@labelstyle"/></xsl:when>
<xsl:when test="@labelStyle"><xsl:value-of select="@labelStyle"/></xsl:when>
<xsl:otherwise>text-align:right;</xsl:otherwise>
</xsl:choose>
</xsl:variable>
@ -559,24 +564,28 @@
<xsl:variable name="autoStart">
<xsl:choose>
<xsl:when test="@autostart"><xsl:value-of select="@autostart"/></xsl:when>
<xsl:when test="@autoStart"><xsl:value-of select="@autoStart"/></xsl:when>
<xsl:otherwise>null</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="csStart">
<xsl:choose>
<xsl:when test="@csstart"><xsl:value-of select="@csstart"/></xsl:when>
<xsl:when test="@csStart"><xsl:value-of select="@csStart"/></xsl:when>
<xsl:otherwise>-1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="csInterval">
<xsl:choose>
<xsl:when test="@csinterval"><xsl:value-of select="@csinterval"/></xsl:when>
<xsl:when test="@csInterval"><xsl:value-of select="@csInterval"/></xsl:when>
<xsl:otherwise>-1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="csStop">
<xsl:choose>
<xsl:when test="@csstop"><xsl:value-of select="@csstop"/></xsl:when>
<xsl:when test="@csStop"><xsl:value-of select="@csStop"/></xsl:when>
<xsl:otherwise>-1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
@ -748,12 +757,14 @@
<xsl:variable name="charBOL">
<xsl:choose>
<xsl:when test="@charbol"><xsl:value-of select="@charbol"/></xsl:when>
<xsl:when test="@charBOL"><xsl:value-of select="@charBOL"/></xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="tabSize">
<xsl:choose>
<xsl:when test="@tabsize"><xsl:value-of select="@tabsize"/></xsl:when>
<xsl:when test="@tabSize"><xsl:value-of select="@tabSize"/></xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:variable>
@ -938,12 +949,14 @@
<xsl:variable name="screenWidth">
<xsl:choose>
<xsl:when test="@screenwidth"><xsl:value-of select="@screenwidth"/></xsl:when>
<xsl:when test="@screenWidth"><xsl:value-of select="@screenWidth"/></xsl:when>
<xsl:otherwise>256</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="screenHeight">
<xsl:choose>
<xsl:when test="@screenheight"><xsl:value-of select="@screenheight"/></xsl:when>
<xsl:when test="@screenHeight"><xsl:value-of select="@screenHeight"/></xsl:when>
<xsl:otherwise>224</xsl:otherwise>
</xsl:choose>
</xsl:variable>
@ -968,12 +981,14 @@
<xsl:variable name="charCols">
<xsl:choose>
<xsl:when test="@cols"><xsl:value-of select="@cols"/></xsl:when>
<xsl:when test="@charCols"><xsl:value-of select="@charCols"/></xsl:when>
<xsl:otherwise>80</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="charRows">
<xsl:choose>
<xsl:when test="@rows"><xsl:value-of select="@rows"/></xsl:when>
<xsl:when test="@charRows"><xsl:value-of select="@charRows"/></xsl:when>
<xsl:otherwise>25</xsl:otherwise>
</xsl:choose>
</xsl:variable>
@ -981,24 +996,28 @@
<xsl:choose>
<xsl:when test="@charset"><xsl:value-of select="@charset"/></xsl:when>
<xsl:when test="@fontrom"><xsl:value-of select="@fontrom"/></xsl:when>
<xsl:when test="@fontROM"><xsl:value-of select="@fontROM"/></xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:variable name="screenColor">
<xsl:choose>
<xsl:when test="@screencolor"><xsl:value-of select="@screencolor"/></xsl:when>
<xsl:when test="@screenColor"><xsl:value-of select="@screenColor"/></xsl:when>
<xsl:otherwise>black</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="touchScreen">
<xsl:choose>
<xsl:when test="@touchscreen"><xsl:value-of select="@touchscreen"/></xsl:when>
<xsl:when test="@touchScreen"><xsl:value-of select="@touchScreen"/></xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
<xsl:variable name="autoLock">
<xsl:choose>
<xsl:when test="@autolock"><xsl:value-of select="@autolock"/></xsl:when>
<xsl:when test="@autoLock"><xsl:value-of select="@autoLock"/></xsl:when>
<xsl:otherwise>false</xsl:otherwise>
</xsl:choose>
</xsl:variable>
@ -1066,12 +1085,14 @@
<xsl:variable name="autoPower">
<xsl:choose>
<xsl:when test="@autopower"><xsl:value-of select="@autopower"/></xsl:when>
<xsl:when test="@autoPower"><xsl:value-of select="@autoPower"/></xsl:when>
<xsl:otherwise>true</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="busWidth">
<xsl:choose>
<xsl:when test="@buswidth"><xsl:value-of select="@buswidth"/></xsl:when>
<xsl:when test="@busWidth"><xsl:value-of select="@busWidth"/></xsl:when>
<xsl:otherwise>20</xsl:otherwise>
</xsl:choose>
</xsl:variable>

View file

@ -125,6 +125,16 @@ function Component(type, parms, constructor, bitsMessage)
this.dbg = null; // by default, no connection to a Debugger
this.bitsMessage = bitsMessage || 0;
/*
* TODO: Consider adding another parameter to the Component() constructor that allows components to tell
* us if they support single or multiple instances per machine. For example, there can be multiple SerialPort
* components per machine, but only one CPU component (well, OK, an FPU is also supported, but that's considered
* a different component).
*
* It's not critical, but it would help catch machine configuration errors; for example, a machine that mistakenly
* includes two CPU components may, aside from wasting memory, end up with odd side-effects, like unresponsive
* CPU controls.
*/
Component.add(this);
}
@ -262,7 +272,6 @@ Component.addMachineResource = function(idMachine, sName, data)
* so addMachine() is never called, so resources do not need to be recorded.
*/
if (Component.machines[idMachine] && sName) {
Component.assert(Component.machines[idMachine][sName] === undefined);
Component.machines[idMachine][sName] = data;
}
};