Added support for automatic scripts (ie, autoScript)
This commit is contained in:
parent
1b987df6e2
commit
30df38738c
34 changed files with 3895 additions and 3580 deletions
|
|
@ -114,7 +114,7 @@ function MarkOut(sMD, sIndent, req, aParms, fDebug, sMachineFile, fAutoHeading)
|
|||
this.aMachines = []; // this keeps track of embedded machines on the page
|
||||
this.buildOptions = {}; // this keeps track of any build options specified on the page
|
||||
this.aMachineDefs = {}; // this keeps track of any machine definitions at the top of the file (as part of any Jekyll "Front Matter")
|
||||
this.aCommandDefs = {}; // this keeps track of any command definitions at the top of the file (as part of any Jekyll "Front Matter")
|
||||
this.aScriptDefs = {}; // this keeps track of any script definitions at the top of the file (as part of any Jekyll "Front Matter")
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -439,6 +439,24 @@ MarkOut.prototype.convertMD = function(sIndent)
|
|||
*/
|
||||
sMD = sMD.replace(aMatch[0], "");
|
||||
|
||||
/*
|
||||
* Extract script definitions first, if any, from the Front Matter.
|
||||
*/
|
||||
var aScriptDefs = aMatch[1].match(/\nscripts:([\s\S]*?)\n([^\s]|$)/);
|
||||
if (aScriptDefs) {
|
||||
var reScript = /[ \t]+([a-z0-9$@_-]+):\s*\|/gi;
|
||||
var aScripts = aScriptDefs[1].split(reScript);
|
||||
/*
|
||||
* Since the preceding RegExp contains a capture group (representing the name of the script),
|
||||
* it will be "spliced" into the split results. So, aScripts[0] will be whatever characters precede
|
||||
* the first command (which we can ignore), followed by the first script name, followed by one or more
|
||||
* command lines, followed by the second script name, followed by one or more command lines, and so on.
|
||||
*/
|
||||
for (var iScript = 1; iScript < aScripts.length; iScript += 2) {
|
||||
this.aScriptDefs[aScripts[iScript]] = aScripts[iScript+1].replace(/\n[ \t]*/g, " ").trim().replace(/"/g, """);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract machine definitions, if any, from the Front Matter.
|
||||
*/
|
||||
|
|
@ -448,7 +466,7 @@ MarkOut.prototype.convertMD = function(sIndent)
|
|||
var asMachines = aMachineDefs[1].split(/\n[ \t]+-\s*/);
|
||||
for (var iMachine = 0; iMachine < asMachines.length; iMachine++) {
|
||||
if (!asMachines[iMachine]) continue;
|
||||
var id = null, iProp, sProp;
|
||||
var id = null, iProp, sProp, sValue;
|
||||
var aOptions, aaOptions = [], machine = {};
|
||||
var reOption = /([ \t]*)([^\s]+):[ \t]*([^\n]*)/g;
|
||||
while (aOptions = reOption.exec(asMachines[iMachine])) {
|
||||
|
|
@ -456,15 +474,16 @@ MarkOut.prototype.convertMD = function(sIndent)
|
|||
}
|
||||
for (var iOption = 0; iOption < aaOptions.length; iOption++) {
|
||||
aOptions = aaOptions[iOption];
|
||||
var sSpace = aOptions[1], sName = aOptions[2].toLowerCase(), sValue = aOptions[3];
|
||||
if (sName == 'automount') sName = 'autoMount'; // for backward compatibility
|
||||
if (sName == 'autotype') {
|
||||
sName = 'autoType';
|
||||
var sSpace = aOptions[1];
|
||||
sProp = aOptions[2];
|
||||
sValue = aOptions[3];
|
||||
if (sProp == 'automount') sProp = 'autoMount'; // for backward compatibility
|
||||
if (sProp == 'autoType' || sProp == 'autoScript') {
|
||||
sValue = sValue.replace(/\\/g, "\"); // automatically "double" any backslashes
|
||||
}
|
||||
if (!id && sName == 'id') {
|
||||
if (!id && sProp == 'id') {
|
||||
id = sValue;
|
||||
} else if (sName == 'autoMount') {
|
||||
} else if (sProp == 'autoMount') {
|
||||
/*
|
||||
* I take a simplistic approach to parsing the object definition associated with "autoMount",
|
||||
* because I know it only consists of 1 or more drive letters, each of which may be followed
|
||||
|
|
@ -501,7 +520,7 @@ MarkOut.prototype.convertMD = function(sIndent)
|
|||
sValue += '}';
|
||||
iOption = iProp - 1;
|
||||
}
|
||||
machine[sName] = sValue;
|
||||
machine[sProp] = sValue;
|
||||
}
|
||||
/*
|
||||
* Any "non-reserved" properties are now merged into the 'parms' property; 'autoMount'
|
||||
|
|
@ -515,7 +534,17 @@ MarkOut.prototype.convertMD = function(sIndent)
|
|||
machine['parms'] += MarkOut.aFMBooleanMachineProps[sProp] + ':' + machine[sProp] + ',';
|
||||
continue;
|
||||
}
|
||||
machine['parms'] += sProp + ':"' + machine[sProp] + '",';
|
||||
sValue = machine[sProp];
|
||||
if (sProp == "autoScript") {
|
||||
sValue = this.aScriptDefs[sValue] || sValue;
|
||||
/*
|
||||
* Don't try to optimize out the second replace(); it's not there simply to replace
|
||||
* the single backslashes that were added to all " entities. It's there to escape
|
||||
* ALL backslashes in the string (ie, the ones we just added, and any others).
|
||||
*/
|
||||
sValue = sValue.replace(/(")/g, "\\$1").replace(/\\/g, "\\\\");
|
||||
}
|
||||
machine['parms'] += sProp + ':"' + sValue + '",';
|
||||
}
|
||||
}
|
||||
var sDrives = machine['drives'];
|
||||
|
|
@ -535,21 +564,6 @@ MarkOut.prototype.convertMD = function(sIndent)
|
|||
}
|
||||
}
|
||||
|
||||
var aCommandDefs = aMatch[1].match(/\ncommands:([\s\S]*?)\n([^\s]|$)/);
|
||||
if (aCommandDefs) {
|
||||
var reCommand = /[ \t]+([a-z0-9$@_-]+):\s*\|/gi;
|
||||
var aCommands = aCommandDefs[1].split(reCommand);
|
||||
/*
|
||||
* Since the preceding RegExp contains a capture group (representing the name of the command),
|
||||
* it will be "spliced" into the split results. So, aCommands[0] will be whatever characters precede
|
||||
* the first command (which we can ignore), followed by the first command name, followed by one or more
|
||||
* command lines, followed by the second command name, followed by one or more command lines, and so on.
|
||||
*/
|
||||
for (var iCommand = 1; iCommand < aCommands.length; iCommand += 2) {
|
||||
this.aCommandDefs[aCommands[iCommand]] = aCommands[iCommand+1].replace(/\n[ \t]*/g, " ").trim().replace(/"/g, """);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If a "title" element existed in the Front Matter, this code auto-generates a top-level heading
|
||||
* with the same value.
|
||||
|
|
@ -1331,8 +1345,8 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock)
|
|||
if (this.aMachineDefs[sMachineID]) {
|
||||
var sCommand = findParm(aParms, 'command');
|
||||
var sValue = findParm(aParms, 'value');
|
||||
if (this.aCommandDefs[sCommand]) {
|
||||
sValue = this.aCommandDefs[sCommand];
|
||||
if (this.aScriptDefs[sCommand]) {
|
||||
sValue = this.aScriptDefs[sCommand];
|
||||
sCommand = "script";
|
||||
} else if (sValue) {
|
||||
sValue = sValue.replace(/"/g, """);
|
||||
|
|
|
|||
|
|
@ -900,6 +900,8 @@ class Computer extends Component {
|
|||
}
|
||||
|
||||
this.nPowerChange = 0;
|
||||
|
||||
Component.processScript(this.idMachine, this.getMachineParm('autoScript'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -149,6 +149,8 @@ class Keyboard extends Component {
|
|||
*/
|
||||
this.autoInject = null;
|
||||
this.autoType = parmsKbd['autoType'];
|
||||
this.fDOSReady = false;
|
||||
this.fnDOSReady = this.fnInjectReady = null;
|
||||
|
||||
/*
|
||||
* HACK: We set fAllDown to false to ignore all down/up events for keys not explicitly marked as ONDOWN;
|
||||
|
|
@ -385,7 +387,15 @@ class Keyboard extends Component {
|
|||
intDOS(addr)
|
||||
{
|
||||
var AH = (this.cpu.regEAX >> 8) & 0xff;
|
||||
if (AH == 0x0A) this.injectInit(this.autoType);
|
||||
if (AH == 0x0A) {
|
||||
this.fDOSReady = true;
|
||||
if (this.fnDOSReady) {
|
||||
this.fnDOSReady();
|
||||
this.fnDOSReady = null;
|
||||
} else {
|
||||
this.injectInit(this.autoType);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -891,7 +901,6 @@ class Keyboard extends Component {
|
|||
* Make sure the auto-injection buffer is empty (an injection could have been in progress on any reset after the first).
|
||||
*/
|
||||
this.sInjectBuffer = "";
|
||||
this.fnCallReady = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1026,9 +1035,9 @@ class Keyboard extends Component {
|
|||
this.addActiveKey(charCode, true);
|
||||
}
|
||||
if (!this.sInjectBuffer.length) {
|
||||
if (this.fnCallReady) {
|
||||
this.fnCallReady();
|
||||
this.fnCallReady = null;
|
||||
if (this.fnInjectReady) {
|
||||
this.fnInjectReady();
|
||||
this.fnInjectReady = null;
|
||||
}
|
||||
} else {
|
||||
setTimeout(function(kbd) {
|
||||
|
|
@ -1040,19 +1049,35 @@ class Keyboard extends Component {
|
|||
}
|
||||
|
||||
/**
|
||||
* waitReady(fnCallReady)
|
||||
* waitReady(fnCallReady, sOption)
|
||||
*
|
||||
* @this {Keyboard}
|
||||
* @param {function()|null} fnCallReady
|
||||
* @param {string} [sOption]
|
||||
* @return {boolean} false if wait required, true otherwise
|
||||
*/
|
||||
waitReady(fnCallReady)
|
||||
waitReady(fnCallReady, sOption)
|
||||
{
|
||||
if (this.sInjectBuffer.length > 0) {
|
||||
if (!this.fnCallReady) this.fnCallReady = fnCallReady;
|
||||
return false;
|
||||
var fReady = false;
|
||||
|
||||
switch(sOption) {
|
||||
case "DOS":
|
||||
if (this.fDOSReady) {
|
||||
fReady = true;
|
||||
} else {
|
||||
this.fnDOSReady = fnCallReady;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!this.sInjectBuffer.length) {
|
||||
fReady = true;
|
||||
} else {
|
||||
this.fnInjectReady = fnCallReady;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
return fReady;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -848,7 +848,7 @@ class Component {
|
|||
}
|
||||
|
||||
if (!fSuccess) {
|
||||
Component.alertUser("Script error: '" + sCommand + "' command " + (fnCommand? " failed" : " unrecognized"));
|
||||
Component.alertUser("Script error: '" + sCommand + (fnCommand? " failed" : " unrecognized"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue