// Take a JavaScript date and convert it to DOS like `DIR` date function dirDate(date) { var month = ('0' + (date.getMonth() + 1)).slice(-2), day = ('0' + (date.getDate())).slice(-2), year = (date.getFullYear().toString().slice(-2)), timeString = date.toLocaleString( 'en-US', {minute: 'numeric', hour: 'numeric', hour12: true } ).replace(" AM", "a").replace(" PM", "p"); return `${month}-${day}-${year}\t${timeString}`; } // Used for slowing down output to feel more "real" function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // Used when getJSON fails function createFailedTerminal(termElement, error) { $(termElement).terminal({}, { greetings: null, onInit: async function typeMessage(term) { await sleep(1); term.set_prompt(''); term.echo("Starting WEB-DOS", {newline: false}); var i; for(i = 1; i <= 3; i++) { await sleep(200); term.echo(".", {newline: false}); } await sleep(200); term.echo("\n"); term.echo("ERROR: Failed to start WEB-DOS.\n"); term.echo("[[;red;]"+error.toString()); term.set_prompt(''); }, } ); } // Create a jsquery.terminal in a given element with a set of commands function createTerminal(termElement, commands) { $(termElement).terminal( function(command) { var upcaseCommand = command.toUpperCase(); comFunc = commands[upcaseCommand]; if(typeof comFunc !== 'undefined') { comFunc(this); } else { this.echo("Bad command or file name (Try HELP)\n"); } }, { greetings: null, onInit: async function typeMessage(term) { function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } await sleep(1); term.set_prompt(''); term.echo("Starting WEB-DOS", {newline: false}); var i; for(i = 1; i <= 3; i++) { await sleep(200); term.echo(".", {newline: false}); }; await sleep(200); term.echo("\n"); term.set_prompt('C:\>'); }, } ); } // Takes in a 'game' object and returns a function to run it in js-dos function createGameCommand(game, canvas, termElement) { return function() { canvas.style.display = ""; termElement.style.display = "none"; Dos(canvas, { wdosboxUrl: "https://js-dos.com/6.22/current/wdosbox.js", cycles: game.cycles, autolock: true, }).ready(function (fs, main) { fs.extract(game.url, "/" + game.dataFolder).then(function () { var runCommand = []; if(typeof game.runCommand == 'undefined') { runCommand = ["-c", "cd " + game.dataFolder, "-c", game.executable]; } else { runCommand = game.runCommand; } main(runCommand).then(function (ci) { window.ci = ci; document.title = game.executable; }); }); }); }; } // Given data from a config.json, create commands for a jsquery.template function createCommands(data, canvas, termElement) { var commands = {}; // Load commands from JSON data.games.forEach(function(game) { gameCommand = createGameCommand(game, canvas, termElement); commands[game.executable] = gameCommand; commands[game.executable + "." + game.extension] = gameCommand; }); commands["DIR"] = function(term){ var largestSizeLen = 0; data.games.forEach(function(game) { var localeStringLength = game.size.toLocaleString().length; if(localeStringLength > largestSizeLen) { largestSizeLen = localeStringLength; } }); var totalSize = 0; data.games.forEach(function(game) { totalSize = totalSize + game.size; var exe = game.executable.padEnd(8); var ext = game.extension; var size = game.size.toLocaleString().padStart(largestSizeLen); var date = dirDate(new Date(game.dateAdded)); term.echo(`${exe}\t${ext}\t\t\t${size}\t${date}`); }); var gameCount = data.games.length; var localeSize = totalSize.toLocaleString(); term.echo(`\t\t${gameCount} file(s)\t\t ${localeSize} bytes`); term.echo(`\t\t\t\t\t\t 42,821,632 bytes free`); }; commands["HELP"] = function(term){ term.echo("Supported commands:"); term.echo("\tDIR List all \"executables\" you can run"); term.echo("\tHELP You're reading it"); term.echo("\n"); term.echo("Or, just run one of these:"); data.games.forEach(function(game) { term.echo("\t" + game.executable); }); }; return commands; } // Load config.json, create commands, then launch jsquery.terminal function initTerminal(dataJSONPath, canvas, termElement) { var commands = {}; $.getJSON( dataJSONPath, function(data) { commands = createCommands(data, canvas, termElement); } ).fail( function(_, _, error) { terminal = createFailedTerminal(termElement, error); } ).done( function() { terminal = createTerminal(termElement, commands); } ); }