Cleanup and refactoring.

This commit is contained in:
Will Scullin 2016-11-21 21:17:34 -08:00
parent 1dfbc0b61b
commit f9f0239d86
40 changed files with 4487 additions and 3964 deletions

14
.editorconfig Normal file
View File

@ -0,0 +1,14 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.js]
indent_size = 4
[*.md]
trim_trailing_whitespace = true

25
.eslintrc.json Normal file
View File

@ -0,0 +1,25 @@
{
"rules": {
"indent": [
2,
4
],
"quotes": [
2,
"single"
],
"linebreak-style": [
2,
"unix"
],
"semi": [
2,
"always"
]
},
"env": {
"browser": true,
"jquery": true
},
"extends": "eslint:recommended"
}

View File

@ -1,6 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<!-- -*- mode: HTML; indent-tabs-mode: nil -*- --> <!-- -*- mode: HTML; indent-tabs-mode: nil -*- -->
<!-- Copyright 2010 Will Scullin --> <!-- Copyright 2010-2016 Will Scullin -->
<html> <html>
<head> <head>
<base href="/apple" /> <base href="/apple" />
@ -10,17 +10,17 @@
<link rel="stylesheet" type="text/css" href="css/apple2.css" /> <link rel="stylesheet" type="text/css" href="css/apple2.css" />
<title>About Apple ][js/Apple //jse</title> <title>About Apple ][js/Apple //jse</title>
<script type="text/javascript"> <script type="text/javascript">
var _gaq = _gaq || []; var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-19205057-1']); _gaq.push(['_setAccount', 'UA-19205057-1']);
_gaq.push(['_trackPageview']); _gaq.push(['_trackPageview']);
(function() { (function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})(); })();
</script> </script>
<meta property="og:title" content="About Apple ][js" /> <meta property="og:title" content="About Apple ][js" />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
@ -35,7 +35,7 @@
</div> </div>
<div style="max-width: 800px; margin: auto"> <div style="max-width: 800px; margin: auto">
<h2>What is this?</h2> <h2>What is this?</h2>
<span class="motter"><a href="../apple2/">Apple ][js</a></span> and <span class="motter"><a href="../apple2/">Apple ][js</a></span> and
<span class="motter"><a href="../apple//e">Apple //jse</a></span> <span class="motter"><a href="../apple//e">Apple //jse</a></span>
are Apple ][ and Apple //e emulators written entirely in JavaScript are Apple ][ and Apple //e emulators written entirely in JavaScript
and HTML5. and HTML5.
@ -45,10 +45,10 @@
I now simulate having a 1 Megabyte RAMFactor card in slot 2. I now simulate having a 1 Megabyte RAMFactor card in slot 2.
<li><h3>Thunderclock Emulation (//jse)</h3> <li><h3>Thunderclock Emulation (//jse)</h3>
There is cursory emulation of the Thunderclock card, enough There is cursory emulation of the Thunderclock card, enough
to keep ProDOS applications from asking you to enter the date to keep ProDOS applications from asking you to enter the date
all the time. ProDOS attempts to guess the year from the month, all the time. ProDOS attempts to guess the year from the month,
the day and the day of the week, something that needs to be the day and the day of the week, something that needs to be
patched every 6 years. This means newer versions think it's 1996, patched every 6 years. This means newer versions think it's 1996,
older versions are stuck in the 80s. older versions are stuck in the 80s.
<li><h3>Firefox Nightly Joystick Support</h3> <li><h3>Firefox Nightly Joystick Support</h3>
Joystick support has yet to officially land, but the latest Joystick support has yet to officially land, but the latest
@ -95,7 +95,7 @@
score. score.
</li> </li>
<li><h3>Competition</h3> <li><h3>Competition</h3>
Now in addition to Now in addition to
<a href="http://www.megidish.net/apple2js/">Gil Megidish's</a> <a href="http://www.megidish.net/apple2js/">Gil Megidish's</a>
Apple2JS, there's a couple of new kids on the block, including Apple2JS, there's a couple of new kids on the block, including
<a href="http://porkrind.org/a2/">David Caldwell's</a> Apple II+ <a href="http://porkrind.org/a2/">David Caldwell's</a> Apple II+
@ -157,7 +157,7 @@
<a href="http://jqueryui.com">jQuery UI</a> <a href="http://jqueryui.com">jQuery UI</a>
</li> </li>
<li> <li>
Base64 Utilities via Base64 Utilities via
<a href="http://kevin.vanzonneveld.net/">KvZ</a> <a href="http://kevin.vanzonneveld.net/">KvZ</a>
</li> </li>
<li> <li>
@ -173,7 +173,7 @@
<i>Beneath Apple DOS</i> <i>Beneath Apple DOS</i>
</a> </a>
by Don Worth and Pieter Lechner by Don Worth and Pieter Lechner
</li> </li>
<li> <li>
<i>Inside the Apple //e</i> by Gary B. Little <i>Inside the Apple //e</i> by Gary B. Little
</li> </li>
@ -224,7 +224,7 @@
realized there was, in fact, another apple2js in the world. realized there was, in fact, another apple2js in the world.
</li> </li>
</ul> </ul>
</li> </li>
<h2>Contact</h2> <h2>Contact</h2>
<ul> <ul>
<li> <li>

View File

@ -1,6 +1,6 @@
<!DOCTYPE html><!-- -*- mode: HTML; indent-tabs-mode: nil -*- --> <!DOCTYPE html><!-- -*- mode: HTML; indent-tabs-mode: nil -*- -->
<!-- <!--
Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com> Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
Permission to use, copy, modify, distribute, and sell this software and its Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that documentation for any purpose is hereby granted without fee, provided that
@ -50,6 +50,7 @@
<script type="text/javascript" src="js/langcard.js"></script> <script type="text/javascript" src="js/langcard.js"></script>
<script type="text/javascript" src="js/fpbasic.js"></script> <script type="text/javascript" src="js/fpbasic.js"></script>
<script type="text/javascript" src="js/apple2char.js"></script> <script type="text/javascript" src="js/apple2char.js"></script>
<script type="text/javascript" src="js/applesoft/decompiler.js"></script>
<script type="text/javascript" src="js/canvas2.js"></script> <script type="text/javascript" src="js/canvas2.js"></script>
<script type="text/javascript" src="js/apple2io.js"></script> <script type="text/javascript" src="js/apple2io.js"></script>
<script type="text/javascript" src="js/parallel.js"></script> <script type="text/javascript" src="js/parallel.js"></script>
@ -66,772 +67,8 @@
<!-- Disk Index --> <!-- Disk Index -->
<script type="text/javascript" src="json/disks/index.js"></script> <script type="text/javascript" src="json/disks/index.js"></script>
<script type="text/javascript"> <script type="text/javascript" src="js/main2.js"></script>
var kHz = 1023;
var focused = false;
var startTime = Date.now();
var lastCycles = 0;
var frames = 0, lastFrames = 0;
var paused = false;
var sound = true;
var hashtag;
var disk_categories = {'Local Saves': []};
var disk_sets = {}
var disk_cur_name = [];
var disk_cur_cat = [];
function DriveLights()
{
return {
driveLight: function(drive, on) {
$("#disk" + drive).css("background-image",
on ? "url(css/red-on-16.png)" :
"url(css/red-off-16.png)");
},
dirty: function(drive, dirty) {
},
label: function(drive, label) {
$("#disklabel" + drive).text(label);
}
}
}
var DISK_TYPES = ['dsk','do','po','raw','nib','2mg'];
var TAPE_TYPES = ['wav','aiff','aif','mp3'];
var _saveDrive = 1;
var _loadDrive = 1;
function openLoad(drive, event)
{
_loadDrive = drive;
if (disk_cur_cat[drive]) {
$("#category_select").val(disk_cur_cat[drive]).change();
}
$("#load").dialog("open");
}
function openSave(drive, event)
{
_saveDrive = drive;
$("#save_name").val($("#disklabel" + drive).text());
$("#save").dialog("open");
}
var loading = false;
function loadAjax(url) {
loading = true;
$("#loading").dialog("open");
$.ajax({ url: url,
cache: false,
dataType: "jsonp",
jsonp: false,
global: false
});
}
function doLoad() {
var urls = $("#disk_select").val(), url;
if (urls && urls.length) {
if (typeof(urls) == "string") {
url = urls;
} else {
url = urls[0];
}
}
var files = $("#local_file").prop("files");
if (files.length == 1) {
doLoadLocal();
} else if (url) {
var filename;
$("#load").dialog("close");
if (url.substr(0,6) == "local:") {
filename = url.substr(6);
if (filename == "__manage") {
openManage();
} else {
loadLocalStorage(_loadDrive, filename);
}
} else {
var r1 = /json\/disks\/(.*).json$/.exec(url);
if (r1 && _loadDrive == 1) {
filename = r1[1];
document.location.hash = filename;
}
loadAjax(url);
}
}
}
function doSave() {
var name = $("#save_name").val();
saveLocalStorage(_saveDrive, name);
$("#save").dialog("close");
}
function doDelete(name) {
if (confirm("Delete " + name + "?")) {
deleteLocalStorage(name);
}
}
function doLoadLocal() {
var files = $("#local_file").prop("files")
if (files.length == 1) {
var file = files[0];
var parts = file.name.split(".");
var ext = parts[parts.length - 1].toLowerCase();
if ($.inArray(ext, DISK_TYPES) >= 0) {
doLoadLocalDisk(file);
} else if ($.inArray(ext, TAPE_TYPES) >= 0) {
doLoadLocalTape(file);
} else {
alert('Unknown file type: ' + ext);
$("#load").dialog("close");
}
}
}
function doLoadLocalDisk(file) {
var fileReader = new FileReader();
fileReader.onload = function(event) {
var parts = file.name.split(".");
var name = parts[0], ext = parts[parts.length - 1].toLowerCase();
if (disk2.setBinary(_saveDrive, name, ext, this.result)) {
$("#disklabel" + _saveDrive).text(name);
$("#load").dialog("close");
initGamepad();
}
}
fileReader.readAsArrayBuffer(file);
}
function doLoadLocalTape(file) {
// Audio Buffer Source
if (typeof webkitAudioContext != "undefined") {
var context = new webkitAudioContext();
} else {
alert("Not supported by your browser");
$("#load").dialog("close");
return;
}
var fileReader = new FileReader();
fileReader.onload = function(ev) {
context.decodeAudioData(ev.target.result, function(buffer) {
var buf = [];
var data = buffer.getChannelData(0), datum = data[0];
var old = (datum > 0.0), current;
var last = 0, delta, ival;
debug('Sample Count: ' + data.length);
debug('Sample rate: ' + buffer.sampleRate);
for (var idx = 1; idx < data.length; idx++) {
datum = data[idx];
if ((datum > 0.1) || (datum < -0.1)) {
current = (datum > 0.0);
if (current != old) {
delta = idx - last;
if (delta > 2000000) {
delta = 2000000;
}
ival = delta / buffer.sampleRate * 1000;
if (ival >= 0.550 && ival < 0.750) {
ival = 0.650; // Header
} else if (ival >= 0.175 && ival < 0.225) {
ival = 0.200; // sync 1
} else if (ival >= 0.225 && ival < 0.275) {
ival = 0.250; // 0 / sync 2
} else if (ival >= 0.450 && ival < 0.550) {
ival = 0.500; // 1
} else {
// debug(idx + ' ' + buf.length + ' ' + ival);
}
buf.push(parseInt(ival * kHz));
old = current;
last = idx;
}
}
}
io.setTape(buf);
$("#load").dialog("close");
});
};
fileReader.readAsArrayBuffer(file);
}
function openManage() {
$("#manage").dialog("open");
}
function loadHTTP(url) {
loading = true;
$("#loading").dialog("open");
var req = new XMLHttpRequest();
req.open("GET", url, true);
req.responseType = "arraybuffer";
req.onload = function(event) {
var parts = url.split(/[\/\.]/);
var name = decodeURIComponent(parts[parts.length - 2]);
var ext = parts[parts.length - 1].toLowerCase();
if (disk2.setBinary(_saveDrive, name, ext, req.response)) {
$("#disklabel" + _saveDrive).text(name);
$("#loading").dialog("close");
loading = false;
}
}
req.send(null);
}
var prefs = new Prefs();
var runTimer = null;
var cpu = new CPU6502();
var ram1 = new RAM(0x00, 0x03),
ram2 = new RAM(0x0C, 0x1F),
ram3 = new RAM(0x60, 0xBF);
var hgr = new HiresPage(1);
var hgr2 = new HiresPage(2);
var gr = new LoresPage(1);
var gr2 = new LoresPage(2);
var rom = new Apple2ROM();
var vm = new VideoModes(gr, hgr, gr2, hgr2);
var mmu = {
auxRom: function(slot, rom) {
cpu.addPageHandler(rom);
}
};
var drivelights = new DriveLights();
var io = new Apple2IO(cpu, vm);
var keyboard = new KeyBoard(io);
var parallel = new Parallel(io, new Printer(), 1);
var disk2 = new DiskII(io, drivelights, 6);
var slinky = new RAMFactor(mmu, io, 2, 1024 * 1024);
var clock = new Thunderclock(mmu, io, 7);
var lc = new LanguageCard(io, rom);
cpu.addPageHandler(ram1);
cpu.addPageHandler(gr);
cpu.addPageHandler(gr2);
cpu.addPageHandler(ram2);
cpu.addPageHandler(hgr);
cpu.addPageHandler(hgr2);
cpu.addPageHandler(ram3);
cpu.addPageHandler(lc);
cpu.addPageHandler(io);
cpu.addPageHandler(parallel);
cpu.addPageHandler(slinky);
cpu.addPageHandler(disk2);
cpu.addPageHandler(clock);
var showFPS = false;
function updateKHz() {
var now = Date.now();
var ms = now - startTime;
var cycles = cpu.cycles();
var delta;
if (showFPS) {
delta = frames - lastFrames;
var fps = parseInt(delta/(ms/1000), 10);
$("#khz").html( fps + "fps");
} else {
delta = cycles - lastCycles;
khz = parseInt(delta/ms);
$("#khz").html( khz + "KHz");
}
startTime = now;
lastCycles = cycles;
lastFrames = frames;
}
/* Audio Handling */
initAudio(io);
function updateSound()
{
enableSound($("#enable_sound").attr("checked"));
}
function dumpDisk(drive) {
var wind = window.open("", "_blank");
wind.document.title = $("#disklabel" + drive).text();
wind.document.write("<pre>");
wind.document.write(disk2.getJSON(drive, true));
wind.document.write("</pre>");
wind.document.close();
}
function step()
{
if (runTimer) {
clearInterval(runTimer);
}
runTimer = null;
cpu.step(function() {
debug(cpu.dumpRegisters());
debug(cpu.dumpPC());
});
}
var running = false;
var accelerated = false;
function updateSpeed()
{
accelerated = $("#accelerator_toggle").prop("checked");
kHz = accelerated ? 4092 : 1023;
io.updateHz(kHz * 1000);
if (runTimer) {
run();
}
}
var _requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
function run(pc) {
if (runTimer) {
clearInterval(runTimer);
}
if (pc) {
cpu.setPC(pc);
}
var ival = 30;
var now, last = Date.now();
var runFn = function() {
now = Date.now();
frames++;
var step = (now - last) * kHz, stepMax = kHz * ival;
last = now;
if (step > stepMax) {
step = stepMax;
}
if (document.location.hash != hashtag) {
hashtag = document.location.hash;
filename = hup()
if (filename) {
if (filename.indexOf("://") > 0) {
loadHTTP(disk);
} else {
loadAjax("json/disks/" + filename + ".json");
}
}
}
if (!loading) {
running = true;
cpu.stepCycles(step);
running = false;
vm.blit();
io.sampleTick();
}
processGamepad(io);
if (!paused && _requestAnimationFrame) {
_requestAnimationFrame(runFn);
}
};
if (_requestAnimationFrame) {
_requestAnimationFrame(runFn);
} else {
runTimer = setInterval(runFn, ival);
}
}
function stop() {
if (runTimer) {
clearInterval(runTimer);
}
runTimer = null;
}
function reset()
{
cpu.reset();
}
function loadBinary(bin) {
stop();
for (var idx = 0; idx < bin.length; idx++) {
var pos = bin.start + idx;
cpu.write(pos >> 8, pos & 0xff, bin.data[idx]);
}
run(bin.start);
}
function selectCategory(event) {
$("#disk_select").empty();
var cat = disk_categories[$("#category_select").val()];
if (cat) {
for (var idx = 0; idx < cat.length; idx++) {
var file = cat[idx], name = file.name;
if (file.disk) {
name += " - " + file.disk;
}
var option = $("<option />").val(file.filename).text(name)
.appendTo("#disk_select");
if (disk_cur_name[_loadDrive] == name) {
option.attr("selected", "selected");
}
}
}
}
function selectDisk(event) {
// Maybe display some info.
}
function clickDisk(event) {
doLoad();
}
function loadDisk(data) {
var name = data.name;
var category = data.category;
if (data.disk) {
name += " - " + data.disk;
}
disk_cur_cat[_loadDrive] = category;
disk_cur_name[_loadDrive] = name;
$("#disklabel" + _loadDrive).text(name);
disk2.setDisk(_loadDrive, data);
initGamepad(data.gamepad);
}
function loadJSON(data) {
if (data.type == "binary") {
loadBinary(data);
} else if ($.inArray(data.type, DISK_TYPES) >= 0) {
loadDisk(data);
}
initGamepad(data.gamepad);
$("#loading").dialog("close");
loading = false;
}
/*
* LocalStorage Disk Storage
*/
function updateLocalStorage() {
var diskIndex = JSON.parse(window.localStorage.diskIndex || "{}");
var names = [], name, cat;
for (name in diskIndex) {
if (diskIndex.hasOwnProperty(name)) {
names.push(name);
}
}
cat = disk_categories['Local Saves'] = [];
$("#manage").empty();
names.forEach(function(name) {
cat.push({'category': 'Local Saves',
'name': name,
'filename': 'local:' + name});
$("#manage").append("<span class='local_save'>" +
name +
" <a href='#' onclick='doDelete(\"" +
name +
"\")'>Delete</a><br /></span>");
});
cat.push({'category': 'Local Saves',
'name': 'Manage Saves...',
'filename': 'local:__manage'});
}
function saveLocalStorage(drive, name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || "{}");
var json = disk2.getJSON(drive);
diskIndex[name] = json;
window.localStorage.diskIndex = JSON.stringify(diskIndex);
window.alert("Saved");
drivelights.label(drive, name);
drivelights.dirty(drive, false);
updateLocalStorage();
}
function deleteLocalStorage(name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || "{}");
if (diskIndex[name]) {
delete diskIndex[name];
window.alert("Deleted");
}
window.localStorage.diskIndex = JSON.stringify(diskIndex);
updateLocalStorage();
}
function loadLocalStorage(drive, name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || "{}");
if (diskIndex[name]) {
disk2.setJSON(drive, diskIndex[name]);
drivelights.label(drive, name);
drivelights.dirty(drive, false);
}
}
/*
* Keyboard/Gamepad routines
*/
var _key;
function _keydown(evt) {
if (evt.keyCode === 112) { // F1 - Reset
cpu.reset();
} else if (evt.keyCode === 113) { // F2 - Full Screen
var elem = document.getElementById("screen");
if (document.webkitCancelFullScreen) {
if (document.webkitIsFullScreen) {
document.webkitCancelFullScreen();
} else {
if (Element.ALLOW_KEYBOARD_INPUT) {
elem.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
} else {
elem.webkitRequestFullScreen();
}
}
} else if (document.mozCancelFullScreen) {
if (document.mozIsFullScreen) {
document.mozCancelFullScreen();
} else {
elem.mozRequestFullScreen();
}
}
} else if (evt.keyCode == 16) { // Shift
keyboard.shiftKey(true);
io.buttonDown(2);
} else if (evt.keyCode == 17) { // Control
keyboard.controlKey(true);
} else if (!focused && (!evt.metaKey || evt.ctrlKey)) {
evt.preventDefault();
var key = keyboard.mapKeyEvent(evt);
if (key != 0xff) {
io.keyDown(key);
_key = key;
}
}
}
function _keyup(evt) {
_key = 0xff;
if (evt.keyCode == 16) { // Shift
keyboard.shiftKey(false);
io.buttonUp(2);
} else if (evt.keyCode == 17) { // Control
keyboard.controlKey(false);
} else {
if (!focused) {
io.keyUp();
}
}
}
function updateScreen() {
var green = $("#green_screen").prop("checked");
scanlines = $("#show_scanlines").prop("checked");
vm.green(green);
}
var flipX = false;
var flipY = false;
var swapXY = false;
function updateJoystick() {
flipX = $("#flip_x").prop("checked");
flipY = $("#flip_y").prop("checked");
swapXY = $("#swap_x_y").prop("checked");
}
function _mousemove(evt) {
if (gamepad) {
return;
}
var s = $("#screen");
var offset = s.offset();
var x = (evt.pageX - offset.left) / s.width(),
y = (evt.pageY - offset.top) / s.height(),
z = x;
if (swapXY) {
x = y;
y = z;
}
io.paddle(0, flipX ? 1 - x : x);
io.paddle(1, flipY ? 1 - y : y);
}
var paused = false;
function pauseRun(b) {
if (paused) {
run();
b.value = "Pause";
} else {
stop();
b.value = "Run";
}
paused = !paused;
}
$(function() {
hashtag = document.location.hash;
$("button,input[type=button],a.button").button().focus(function() {
// Crazy hack required by Chrome
var self = this;
window.setTimeout(function() {
self.blur();
}, 1)
});
var canvas = document.getElementById("screen");
var context = canvas.getContext('2d');
vm.setContext(context);
/*
* Input Handling
*/
$(window).keydown(_keydown);
$(window).keyup(_keyup);
$("canvas").mousedown(function(evt) {
if (!gamepad) {
io.buttonDown(evt.which == 1 ? 0 : 1);
}
evt.preventDefault();
})
.mouseup(function(evt) {
if (!gamepad) {
io.buttonUp(evt.which == 1 ? 0 : 1);
}
})
.bind("contextmenu", function(e) { e.preventDefault(); });
$('body').mousemove(_mousemove);
$("input,textarea").focus(function() { focused = true; });
$("input,textarea").blur(function() { focused = false; });
keyboard.create($("#keyboard"));
if (prefs.havePrefs()) {
$("input[type=checkbox]").each(function() {
var val = prefs.readPref(this.id);
if (val != null)
this.checked = JSON.parse(val);
});
$("input[type=checkbox]").change(function() {
prefs.writePref(this.id, JSON.stringify(this.checked));
});
}
reset();
run();
setInterval(updateKHz, 1000);
updateSound();
updateScreen();
updateSpeed();
var cancel = function() { $(this).dialog("close"); };
$("#loading").dialog({ autoOpen: false, modal: true });
$("#options").dialog({ autoOpen: false,
modal: true,
width: 320,
height: 400,
buttons: {"Close": cancel }});
$("#load").dialog({ autoOpen: false,
modal: true,
width: 540,
buttons: {"Cancel": cancel, "Load": doLoad }});
$("#save").dialog({ autoOpen: false,
modal: true,
width: 320,
buttons: {"Cancel": cancel, "Save": doSave }});
$("#manage").dialog({ autoOpen: false,
modal: true,
width: 320,
buttons: {"Close": cancel }});
if (window.localStorage !== undefined) {
$("button.disksave").show();
}
var oldcat = "";
for (var idx = 0; idx < disk_index.length; idx++) {
var file = disk_index[idx];
var cat = file.category;
var name = file.name, disk = file.disk;
if (cat != oldcat) {
$("<option />").val(cat).text(cat).appendTo("#category_select");
disk_categories[cat] = [];
oldcat = cat;
}
disk_categories[cat].push(file);
if (disk) {
if (!disk_sets[name]) {
disk_sets[name] = []
}
disk_sets[name].push(file);
}
}
$("<option/>").text("Local Saves").appendTo("#category_select");
updateLocalStorage();
initGamepad();
// Check for disks in hashtag
var filename = gup("disk") || hup();
if (filename) {
if (filename.indexOf("://") > 0) {
loadHTTP(filename);
} else {
loadAjax("json/disks/" + filename + ".json");
}
}
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
$("select").removeAttr("multiple").css("height", "auto");
}
});
</script>
</head> </head>
<body> <body>
<div style="margin: auto; width: 604px"> <div style="margin: auto; width: 604px">

View File

@ -1,6 +1,6 @@
<!DOCTYPE html><!-- -*- mode: HTML; indent-tabs-mode: nil -*- --> <!DOCTYPE html><!-- -*- mode: HTML; indent-tabs-mode: nil -*- -->
<!-- <!--
Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com> Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
Permission to use, copy, modify, distribute, and sell this software and its Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that documentation for any purpose is hereby granted without fee, provided that
@ -51,6 +51,7 @@
<script type="text/javascript" src="js/apple2e.js"></script> <script type="text/javascript" src="js/apple2e.js"></script>
<script type="text/javascript" src="js/apple2e-enhanced.js"></script> <script type="text/javascript" src="js/apple2e-enhanced.js"></script>
<script type="text/javascript" src="js/apple2echar.js"></script> <script type="text/javascript" src="js/apple2echar.js"></script>
<script type="text/javascript" src="js/applesoft/decompiler.js"></script>
<script type="text/javascript" src="js/canvas2e.js"></script> <script type="text/javascript" src="js/canvas2e.js"></script>
<script type="text/javascript" src="js/slot3.js"></script> <script type="text/javascript" src="js/slot3.js"></script>
<script type="text/javascript" src="js/apple2io.js"></script> <script type="text/javascript" src="js/apple2io.js"></script>
@ -68,774 +69,7 @@
<!-- Disk Index --> <!-- Disk Index -->
<script type="text/javascript" src="json/disks/index.js"></script> <script type="text/javascript" src="json/disks/index.js"></script>
<script type="text/javascript"> <script type="text/javascript" src="js/main2e.js"></script>
var enhanced = true;
var focused = false;
var startTime = Date.now();
var lastCycles = 0;
var frames = 0, lastFrames = 0;
var paused = false;
var sound = true;
var hashtag;
var disk_categories = {'Local Saves': []};
var disk_sets = {}
var disk_cur_name = [];
var disk_cur_cat = [];
function DriveLights()
{
return {
driveLight: function(drive, on) {
$("#disk" + drive).css("background-image",
on ? "url(css/red-on-16.png)" :
"url(css/red-off-16.png)");
},
dirty: function(drive, dirty) {
},
label: function(drive, label) {
$("#disklabel" + drive).text(label);
}
}
}
var DISK_TYPES = ['dsk','do','po','raw','nib','2mg'];
var TAPE_TYPES = ['wav','aiff','aif','mp3'];
var _saveDrive = 1;
var _loadDrive = 1;
function openLoad(drive, event)
{
_loadDrive = drive;
if (disk_cur_cat[drive]) {
$("#category_select").val(disk_cur_cat[drive]).change();
}
$("#load").dialog("open");
}
function openSave(drive, event)
{
_saveDrive = drive;
$("#save_name").val($("#disklabel" + drive).text());
$("#save").dialog("open");
}
var loading = false;
function loadAjax(url) {
loading = true;
$("#loading").dialog("open");
$.ajax({ url: url,
cache: false,
dataType: "jsonp",
jsonp: false,
global: false
});
}
function doLoad() {
var urls = $("#disk_select").val(), url;
if (urls && urls.length) {
if (typeof(urls) == "string") {
url = urls;
} else {
url = urls[0];
}
}
var files = $("#local_file").prop("files");
if (files.length == 1) {
doLoadLocal();
} else if (url) {
var filename;
$("#load").dialog("close");
if (url.substr(0,6) == "local:") {
filename = url.substr(6);
if (filename == "__manage") {
openManage();
} else {
loadLocalStorage(_loadDrive, filename);
}
} else {
var r1 = /json\/disks\/(.*).json$/.exec(url);
if (r1 && _loadDrive == 1) {
filename = r1[1];
document.location.hash = filename;
}
loadAjax(url);
}
}
}
function doSave() {
var name = $("#save_name").val();
saveLocalStorage(_saveDrive, name);
$("#save").dialog("close");
}
function doDelete(name) {
if (confirm("Delete " + name + "?")) {
deleteLocalStorage(name);
}
}
function doLoadLocal() {
var files = $("#local_file").prop("files")
if (files.length == 1) {
var file = files[0];
var parts = file.name.split(".");
var ext = parts[parts.length - 1].toLowerCase();
if ($.inArray(ext, DISK_TYPES) >= 0) {
doLoadLocalDisk(file);
} else if ($.inArray(ext, TAPE_TYPES) >= 0) {
doLoadLocalTape(file);
} else {
alert('Unknown file type: ' + ext);
$("#load").dialog("close");
}
}
}
function doLoadLocalDisk(file) {
var fileReader = new FileReader();
fileReader.onload = function(event) {
var parts = file.name.split(".");
var name = parts[0], ext = parts[parts.length - 1].toLowerCase();
if (disk2.setBinary(_saveDrive, name, ext, this.result)) {
$("#disklabel" + _saveDrive).text(name);
$("#load").dialog("close");
initGamepad();
}
}
fileReader.readAsArrayBuffer(file);
}
function doLoadLocalTape(file) {
// Audio Buffer Source
if (typeof webkitAudioContext != "undefined") {
var context = new webkitAudioContext();
} else {
alert("Not supported by your browser");
$("#load").dialog("close");
return;
}
var fileReader = new FileReader();
fileReader.onload = function(ev) {
context.decodeAudioData(ev.target.result, function(buffer) {
var buf = [];
var data = buffer.getChannelData(0), datum = data[0];
var old = (datum > 0.0), current;
var last = 0, delta, ival;
debug('Sample Count: ' + data.length);
debug('Sample rate: ' + buffer.sampleRate);
for (var idx = 1; idx < data.length; idx++) {
datum = data[idx];
if ((datum > 0.1) || (datum < -0.1)) {
current = (datum > 0.0);
if (current != old) {
delta = idx - last;
if (delta > 2000000) {
delta = 2000000;
}
ival = delta / buffer.sampleRate * 1000;
if (ival >= 0.550 && ival < 0.750) {
ival = 0.650; // Header
} else if (ival >= 0.175 && ival < 0.225) {
ival = 0.200; // sync 1
} else if (ival >= 0.225 && ival < 0.275) {
ival = 0.250; // 0 / sync 2
} else if (ival >= 0.450 && ival < 0.550) {
ival = 0.500; // 1
} else {
// debug(idx + ' ' + buf.length + ' ' + ival);
}
buf.push(parseInt(ival * kHz));
old = current;
last = idx;
}
}
}
io.setTape(buf);
$("#load").dialog("close");
});
};
fileReader.readAsArrayBuffer(file);
}
function openManage() {
$("#manage").dialog("open");
}
function loadHTTP(url) {
loading = true;
$("#loading").dialog("open");
var req = new XMLHttpRequest();
req.open("GET", url, true);
req.responseType = "arraybuffer";
req.onload = function(event) {
var parts = url.split(/[\/\.]/);
var name = decodeURIComponent(parts[parts.length - 2]);
var ext = parts[parts.length - 1].toLowerCase();
if (disk2.setBinary(_saveDrive, name, ext, req.response)) {
$("#disklabel" + _saveDrive).text(name);
$("#loading").dialog("close");
loading = false;
}
}
req.send(null);
}
var prefs = new Prefs();
var runTimer = null;
var cpu = new CPU6502({"65C02": enhanced});
var hgr = new HiresPage(1);
var hgr2 = new HiresPage(2);
var gr = new LoresPage(1);
var gr2 = new LoresPage(2);
var rom;
if (enhanced) {
rom = new Apple2eEnhancedROM();
} else {
rom = new Apple2eROM();
}
var vm = new VideoModes(gr, hgr, gr2, hgr2);
var drivelights = new DriveLights();
var io = new Apple2IO(cpu, vm);
var keyboard = new KeyBoard(io);
var mmu = new MMU(cpu, gr, gr2, hgr, hgr2, io, rom);
var parallel = new Parallel(io, new Printer(), 1);
var disk2 = new DiskII(io, drivelights, 6);
var slot3 = new Slot3(mmu, rom);
var slinky = new RAMFactor(mmu, io, 2, 1024 * 1024);
var clock = new Thunderclock(mmu, io, 7);
mmu.addSlot(1, parallel);
mmu.addSlot(2, slinky);
mmu.addSlot(3, slot3);
mmu.addSlot(6, disk2);
mmu.addSlot(7, clock);
cpu.addPageHandler(mmu);
var showFPS = false;
function updateKHz() {
var now = Date.now();
var ms = now - startTime;
var cycles = cpu.cycles();
var delta;
if (showFPS) {
delta = frames - lastFrames;
var fps = parseInt(delta/(ms/1000), 10);
$("#khz").html( fps + "fps");
} else {
delta = cycles - lastCycles;
khz = parseInt(delta/ms);
$("#khz").html( khz + "KHz");
}
startTime = now;
lastCycles = cycles;
lastFrames = frames;
}
/* Audio Handling */
initAudio(io);
function updateSound()
{
enableSound($("#enable_sound").attr("checked"));
}
function dumpDisk(drive) {
var wind = window.open("", "_blank");
wind.document.title = $("#disklabel" + drive).text();
wind.document.write("<pre>");
wind.document.write(disk2.getJSON(drive, true));
wind.document.write("</pre>");
wind.document.close();
}
function step()
{
if (runTimer) {
clearInterval(runTimer);
}
runTimer = null;
cpu.step(function() {
debug(cpu.dumpRegisters());
debug(cpu.dumpPC());
});
}
var running = false;
var accelerated = false;
function updateSpeed()
{
accelerated = $("#accelerator_toggle").prop("checked");
kHz = accelerated ? 4092 : 1023;
io.updateHz(kHz * 1000);
if (runTimer) {
run();
}
}
var _requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
function run(pc) {
if (runTimer) {
clearInterval(runTimer);
}
if (pc) {
cpu.setPC(pc);
}
var ival = 30;
var now, last = Date.now();
var runFn = function() {
now = Date.now();
frames++;
var step = (now - last) * kHz, stepMax = kHz * ival;
last = now;
if (step > stepMax) {
step = stepMax;
}
if (document.location.hash != hashtag) {
hashtag = document.location.hash;
filename = hup()
if (filename) {
if (filename.indexOf("://") > 0) {
loadHTTP(disk);
} else {
loadAjax("json/disks/" + filename + ".json");
}
}
}
if (!loading) {
mmu.resetVB();
running = true;
cpu.stepCycles(step);
running = false;
vm.blit();
io.sampleTick();
}
processGamepad(io);
if (!paused && _requestAnimationFrame) {
_requestAnimationFrame(runFn);
}
};
if (_requestAnimationFrame) {
_requestAnimationFrame(runFn);
} else {
runTimer = setInterval(runFn, ival);
}
}
function stop() {
if (runTimer) {
clearInterval(runTimer);
}
runTimer = null;
}
function reset()
{
cpu.reset();
}
function loadBinary(bin) {
stop();
for (var idx = 0; idx < bin.length; idx++) {
var pos = bin.start + idx;
cpu.write(pos >> 8, pos & 0xff, bin.data[idx]);
}
run(bin.start);
}
function selectCategory(event) {
$("#disk_select").empty();
var cat = disk_categories[$("#category_select").val()];
if (cat) {
for (var idx = 0; idx < cat.length; idx++) {
var file = cat[idx], name = file.name;
if (file.disk) {
name += " - " + file.disk;
}
var option = $("<option />").val(file.filename).text(name)
.appendTo("#disk_select");
if (disk_cur_name[_loadDrive] == name) {
option.attr("selected", "selected");
}
}
}
}
function selectDisk(event) {
// Maybe display some info.
}
function clickDisk(event) {
doLoad();
}
function loadDisk(data) {
var name = data.name;
var category = data.category;
if (data.disk) {
name += " - " + data.disk;
}
disk_cur_cat[_loadDrive] = category;
disk_cur_name[_loadDrive] = name;
$("#disklabel" + _loadDrive).text(name);
disk2.setDisk(_loadDrive, data);
initGamepad(data.gamepad);
}
function loadJSON(data) {
if (data.type == "binary") {
loadBinary(data);
} else if ($.inArray(data.type, DISK_TYPES) >= 0) {
loadDisk(data);
}
initGamepad(data.gamepad);
$("#loading").dialog("close");
loading = false;
}
/*
* LocalStorage Disk Storage
*/
function updateLocalStorage() {
var diskIndex = JSON.parse(window.localStorage.diskIndex || "{}");
var names = [], name, cat;
for (name in diskIndex) {
if (diskIndex.hasOwnProperty(name)) {
names.push(name);
}
}
cat = disk_categories['Local Saves'] = [];
$("#manage").empty();
names.forEach(function(name) {
cat.push({'category': 'Local Saves',
'name': name,
'filename': 'local:' + name});
$("#manage").append("<span class='local_save'>" +
name +
" <a href='#' onclick='doDelete(\"" +
name +
"\")'>Delete</a><br /></span>");
});
cat.push({'category': 'Local Saves',
'name': 'Manage Saves...',
'filename': 'local:__manage'});
}
function saveLocalStorage(drive, name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || "{}");
var json = disk2.getJSON(drive);
diskIndex[name] = json;
window.localStorage.diskIndex = JSON.stringify(diskIndex);
window.alert("Saved");
drivelights.label(drive, name);
drivelights.dirty(drive, false);
updateLocalStorage();
}
function deleteLocalStorage(name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || "{}");
if (diskIndex[name]) {
delete diskIndex[name];
window.alert("Deleted");
}
window.localStorage.diskIndex = JSON.stringify(diskIndex);
updateLocalStorage();
}
function loadLocalStorage(drive, name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || "{}");
if (diskIndex[name]) {
disk2.setJSON(drive, diskIndex[name]);
drivelights.label(drive, name);
drivelights.dirty(drive, false);
}
}
/*
* Keyboard/Gamepad routines
*/
var _key;
function _keydown(evt) {
if (evt.keyCode === 112) { // F1 - Reset
cpu.reset();
} else if (evt.keyCode === 113) { // F2 - Full Screen
var elem = document.getElementById("screen");
if (document.webkitCancelFullScreen) {
if (document.webkitIsFullScreen) {
document.webkitCancelFullScreen();
} else {
if (Element.ALLOW_KEYBOARD_INPUT) {
elem.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
} else {
elem.webkitRequestFullScreen();
}
}
} else if (document.mozCancelFullScreen) {
if (document.mozIsFullScreen) {
document.mozCancelFullScreen();
} else {
elem.mozRequestFullScreen();
}
}
} else if (evt.keyCode == 16) { // Shift
keyboard.shiftKey(true);
io.buttonDown(2);
} else if (evt.keyCode == 17) { // Control
keyboard.controlKey(true);
} else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command
keyboard.commandKey(true);
} else if (evt.keyCode == 18) { // Alt
keyboard.optionKey(true);
} else if (!focused) {
evt.preventDefault();
var key = keyboard.mapKeyEvent(evt);
if (key != 0xff) {
io.keyDown(key);
_key = key;
}
}
}
function _keyup(evt) {
_key = 0xff;
if (evt.keyCode == 16) { // Shift
keyboard.shiftKey(false);
io.buttonUp(2);
} else if (evt.keyCode == 17) { // Control
keyboard.controlKey(false);
} else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command
keyboard.commandKey(false);
} else if (evt.keyCode == 18) { // Alt
keyboard.optionKey(false);
} else {
if (!focused) {
io.keyUp();
}
}
}
function updateScreen() {
var green = $("#green_screen").prop("checked");
scanlines = $("#show_scanlines").prop("checked");
vm.green(green);
}
var flipX = false;
var flipY = false;
var swapXY = false;
function updateJoystick() {
flipX = $("#flip_x").prop("checked");
flipY = $("#flip_y").prop("checked");
swapXY = $("#swap_x_y").prop("checked");
}
function _mousemove(evt) {
if (gamepad) {
return;
}
var s = $("#screen");
var offset = s.offset();
var x = (evt.pageX - offset.left) / s.width(),
y = (evt.pageY - offset.top) / s.height(),
z = x;
if (swapXY) {
x = y;
y = z;
}
io.paddle(0, flipX ? 1 - x : x);
io.paddle(1, flipY ? 1 - y : y);
}
var paused = false;
function pauseRun(b) {
if (paused) {
run();
b.value = "Pause";
} else {
stop();
b.value = "Run";
}
paused = !paused;
}
$(function() {
hashtag = document.location.hash;
$("button,input[type=button],a.button").button().focus(function() {
// Crazy hack required by Chrome
var self = this;
window.setTimeout(function() {
self.blur();
}, 1)
});
var canvas = document.getElementById("screen");
var context = canvas.getContext('2d');
vm.setContext(context);
/*
* Input Handling
*/
$(window).keydown(_keydown);
$(window).keyup(_keyup);
$("canvas").mousedown(function(evt) {
if (!gamepad) {
io.buttonDown(evt.which == 1 ? 0 : 1);
}
evt.preventDefault();
})
.mouseup(function(evt) {
if (!gamepad) {
io.buttonUp(evt.which == 1 ? 0 : 1);
}
})
.mousemove(_mousemove)
.bind("contextmenu", function(e) { e.preventDefault(); });
$("input,textarea").focus(function() { focused = true; })
.blur(function() { focused = false; });
$("body > div").hover(function() { focused = false; },
function() { focused = true; });
keyboard.create($("#keyboard"));
if (prefs.havePrefs()) {
$("input[type=checkbox]").each(function() {
var val = prefs.readPref(this.id);
if (val != null)
this.checked = JSON.parse(val);
});
$("input[type=checkbox]").change(function() {
prefs.writePref(this.id, JSON.stringify(this.checked));
});
}
reset();
run();
setInterval(updateKHz, 1000);
updateSound();
updateScreen();
updateSpeed();
var cancel = function() { $(this).dialog("close"); };
$("#loading").dialog({ autoOpen: false, modal: true });
$("#options").dialog({ autoOpen: false,
modal: true,
width: 320,
height: 400,
buttons: {"Close": cancel }});
$("#load").dialog({ autoOpen: false,
modal: true,
width: 540,
buttons: {"Cancel": cancel, "Load": doLoad }});
$("#save").dialog({ autoOpen: false,
modal: true,
width: 320,
buttons: {"Cancel": cancel, "Save": doSave }});
$("#manage").dialog({ autoOpen: false,
modal: true,
width: 320,
buttons: {"Close": cancel }});
if (window.localStorage !== undefined) {
$("button.disksave").show();
}
var oldcat = "";
for (var idx = 0; idx < disk_index.length; idx++) {
var file = disk_index[idx];
var cat = file.category;
var name = file.name, disk = file.disk;
if (cat != oldcat) {
$("<option />").val(cat).text(cat).appendTo("#category_select");
disk_categories[cat] = [];
oldcat = cat;
}
disk_categories[cat].push(file);
if (disk) {
if (!disk_sets[name]) {
disk_sets[name] = []
}
disk_sets[name].push(file);
}
}
$("<option/>").text("Local Saves").appendTo("#category_select");
updateLocalStorage();
// Check for disks in hashtag
var filename = gup("disk") || hup();
if (filename) {
if (filename.indexOf("://") > 0) {
loadHTTP(filename);
} else {
loadAjax("json/disks/" + filename + ".json");
}
}
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
$("select").removeAttr("multiple").css("height", "auto");
}
});
</script>
</head> </head>
<body class="apple2e"> <body class="apple2e">
<div style="margin: auto; width: 604px"> <div style="margin: auto; width: 604px">

View File

@ -1,4 +1,4 @@
/* Copyright 2010-2013 Will Scullin */ /* Copyright 2010-2016 Will Scullin */
.disklabel { .disklabel {
color: #000; color: #000;

View File

@ -1,265 +1,260 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /*exported apple2_charset */
/*global bytify */ var apple2_charset = [
/*exported charset */ 0x00,0x1c,0x22,0x2a,0x2e,0x2c,0x20,0x1e,
0x00,0x08,0x14,0x22,0x22,0x3e,0x22,0x22,
var charset = [ 0x00,0x3c,0x22,0x22,0x3c,0x22,0x22,0x3c,
0x00,0x1c,0x22,0x2a,0x2e,0x2c,0x20,0x1e, 0x00,0x1c,0x22,0x20,0x20,0x20,0x22,0x1c,
0x00,0x08,0x14,0x22,0x22,0x3e,0x22,0x22, 0x00,0x3c,0x22,0x22,0x22,0x22,0x22,0x3c,
0x00,0x3c,0x22,0x22,0x3c,0x22,0x22,0x3c, 0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x3e,
0x00,0x1c,0x22,0x20,0x20,0x20,0x22,0x1c, 0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x20,
0x00,0x3c,0x22,0x22,0x22,0x22,0x22,0x3c, 0x00,0x1e,0x20,0x20,0x20,0x26,0x22,0x1e,
0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x3e, 0x00,0x22,0x22,0x22,0x3e,0x22,0x22,0x22,
0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x20, 0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x1c,
0x00,0x1e,0x20,0x20,0x20,0x26,0x22,0x1e, 0x00,0x02,0x02,0x02,0x02,0x02,0x22,0x1c,
0x00,0x22,0x22,0x22,0x3e,0x22,0x22,0x22, 0x00,0x22,0x24,0x28,0x30,0x28,0x24,0x22,
0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x1c, 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x3e,
0x00,0x02,0x02,0x02,0x02,0x02,0x22,0x1c, 0x00,0x22,0x36,0x2a,0x2a,0x22,0x22,0x22,
0x00,0x22,0x24,0x28,0x30,0x28,0x24,0x22, 0x00,0x22,0x22,0x32,0x2a,0x26,0x22,0x22,
0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x3e, 0x00,0x1c,0x22,0x22,0x22,0x22,0x22,0x1c,
0x00,0x22,0x36,0x2a,0x2a,0x22,0x22,0x22, 0x00,0x3c,0x22,0x22,0x3c,0x20,0x20,0x20,
0x00,0x22,0x22,0x32,0x2a,0x26,0x22,0x22, 0x00,0x1c,0x22,0x22,0x22,0x2a,0x24,0x1a,
0x00,0x1c,0x22,0x22,0x22,0x22,0x22,0x1c, 0x00,0x3c,0x22,0x22,0x3c,0x28,0x24,0x22,
0x00,0x3c,0x22,0x22,0x3c,0x20,0x20,0x20, 0x00,0x1c,0x22,0x20,0x1c,0x02,0x22,0x1c,
0x00,0x1c,0x22,0x22,0x22,0x2a,0x24,0x1a, 0x00,0x3e,0x08,0x08,0x08,0x08,0x08,0x08,
0x00,0x3c,0x22,0x22,0x3c,0x28,0x24,0x22, 0x00,0x22,0x22,0x22,0x22,0x22,0x22,0x1c,
0x00,0x1c,0x22,0x20,0x1c,0x02,0x22,0x1c, 0x00,0x22,0x22,0x22,0x22,0x22,0x14,0x08,
0x00,0x3e,0x08,0x08,0x08,0x08,0x08,0x08, 0x00,0x22,0x22,0x22,0x2a,0x2a,0x36,0x22,
0x00,0x22,0x22,0x22,0x22,0x22,0x22,0x1c, 0x00,0x22,0x22,0x14,0x08,0x14,0x22,0x22,
0x00,0x22,0x22,0x22,0x22,0x22,0x14,0x08, 0x00,0x22,0x22,0x14,0x08,0x08,0x08,0x08,
0x00,0x22,0x22,0x22,0x2a,0x2a,0x36,0x22, 0x00,0x3e,0x02,0x04,0x08,0x10,0x20,0x3e,
0x00,0x22,0x22,0x14,0x08,0x14,0x22,0x22, 0x00,0x3e,0x30,0x30,0x30,0x30,0x30,0x3e,
0x00,0x22,0x22,0x14,0x08,0x08,0x08,0x08, 0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x00,
0x00,0x3e,0x02,0x04,0x08,0x10,0x20,0x3e, 0x00,0x3e,0x06,0x06,0x06,0x06,0x06,0x3e,
0x00,0x3e,0x30,0x30,0x30,0x30,0x30,0x3e, 0x00,0x00,0x00,0x08,0x14,0x22,0x00,0x00,
0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,
0x00,0x3e,0x06,0x06,0x06,0x06,0x06,0x3e, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x08,0x14,0x22,0x00,0x00, 0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x08,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e, 0x00,0x14,0x14,0x14,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x14,0x14,0x3e,0x14,0x3e,0x14,0x14,
0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x08, 0x00,0x08,0x1e,0x28,0x1c,0x0a,0x3c,0x08,
0x00,0x14,0x14,0x14,0x00,0x00,0x00,0x00, 0x00,0x30,0x32,0x04,0x08,0x10,0x26,0x06,
0x00,0x14,0x14,0x3e,0x14,0x3e,0x14,0x14, 0x00,0x10,0x28,0x28,0x10,0x2a,0x24,0x1a,
0x00,0x08,0x1e,0x28,0x1c,0x0a,0x3c,0x08, 0x00,0x08,0x08,0x08,0x00,0x00,0x00,0x00,
0x00,0x30,0x32,0x04,0x08,0x10,0x26,0x06, 0x00,0x08,0x10,0x20,0x20,0x20,0x10,0x08,
0x00,0x10,0x28,0x28,0x10,0x2a,0x24,0x1a, 0x00,0x08,0x04,0x02,0x02,0x02,0x04,0x08,
0x00,0x08,0x08,0x08,0x00,0x00,0x00,0x00, 0x00,0x08,0x2a,0x1c,0x08,0x1c,0x2a,0x08,
0x00,0x08,0x10,0x20,0x20,0x20,0x10,0x08, 0x00,0x00,0x08,0x08,0x3e,0x08,0x08,0x00,
0x00,0x08,0x04,0x02,0x02,0x02,0x04,0x08, 0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x10,
0x00,0x08,0x2a,0x1c,0x08,0x1c,0x2a,0x08, 0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,
0x00,0x00,0x08,0x08,0x3e,0x08,0x08,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x10, 0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x00,
0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00, 0x00,0x1c,0x22,0x26,0x2a,0x32,0x22,0x1c,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08, 0x00,0x08,0x18,0x08,0x08,0x08,0x08,0x1c,
0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x00, 0x00,0x1c,0x22,0x02,0x0c,0x10,0x20,0x3e,
0x00,0x1c,0x22,0x26,0x2a,0x32,0x22,0x1c, 0x00,0x3e,0x02,0x04,0x0c,0x02,0x22,0x1c,
0x00,0x08,0x18,0x08,0x08,0x08,0x08,0x1c, 0x00,0x04,0x0c,0x14,0x24,0x3e,0x04,0x04,
0x00,0x1c,0x22,0x02,0x0c,0x10,0x20,0x3e, 0x00,0x3e,0x20,0x3c,0x02,0x02,0x22,0x1c,
0x00,0x3e,0x02,0x04,0x0c,0x02,0x22,0x1c, 0x00,0x0e,0x10,0x20,0x3c,0x22,0x22,0x1c,
0x00,0x04,0x0c,0x14,0x24,0x3e,0x04,0x04, 0x00,0x3e,0x02,0x04,0x08,0x10,0x10,0x10,
0x00,0x3e,0x20,0x3c,0x02,0x02,0x22,0x1c, 0x00,0x1c,0x22,0x22,0x1c,0x22,0x22,0x1c,
0x00,0x0e,0x10,0x20,0x3c,0x22,0x22,0x1c, 0x00,0x1c,0x22,0x22,0x1e,0x02,0x04,0x38,
0x00,0x3e,0x02,0x04,0x08,0x10,0x10,0x10, 0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,
0x00,0x1c,0x22,0x22,0x1c,0x22,0x22,0x1c, 0x00,0x00,0x00,0x08,0x00,0x08,0x08,0x10,
0x00,0x1c,0x22,0x22,0x1e,0x02,0x04,0x38, 0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04,
0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00, 0x00,0x00,0x00,0x3e,0x00,0x3e,0x00,0x00,
0x00,0x00,0x00,0x08,0x00,0x08,0x08,0x10, 0x00,0x10,0x08,0x04,0x02,0x04,0x08,0x10,
0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04, 0x00,0x1c,0x22,0x04,0x08,0x08,0x00,0x08,
0x00,0x00,0x00,0x3e,0x00,0x3e,0x00,0x00, 0x80,0x9c,0xa2,0xaa,0xae,0xac,0xa0,0x9e,
0x00,0x10,0x08,0x04,0x02,0x04,0x08,0x10, 0x80,0x88,0x94,0xa2,0xa2,0xbe,0xa2,0xa2,
0x00,0x1c,0x22,0x04,0x08,0x08,0x00,0x08, 0x80,0xbc,0xa2,0xa2,0xbc,0xa2,0xa2,0xbc,
0x80,0x9c,0xa2,0xaa,0xae,0xac,0xa0,0x9e, 0x80,0x9c,0xa2,0xa0,0xa0,0xa0,0xa2,0x9c,
0x80,0x88,0x94,0xa2,0xa2,0xbe,0xa2,0xa2, 0x80,0xbc,0xa2,0xa2,0xa2,0xa2,0xa2,0xbc,
0x80,0xbc,0xa2,0xa2,0xbc,0xa2,0xa2,0xbc, 0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xbe,
0x80,0x9c,0xa2,0xa0,0xa0,0xa0,0xa2,0x9c, 0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xa0,
0x80,0xbc,0xa2,0xa2,0xa2,0xa2,0xa2,0xbc, 0x80,0x9e,0xa0,0xa0,0xa0,0xa6,0xa2,0x9e,
0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xbe, 0x80,0xa2,0xa2,0xa2,0xbe,0xa2,0xa2,0xa2,
0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xa0, 0x80,0x9c,0x88,0x88,0x88,0x88,0x88,0x9c,
0x80,0x9e,0xa0,0xa0,0xa0,0xa6,0xa2,0x9e, 0x80,0x82,0x82,0x82,0x82,0x82,0xa2,0x9c,
0x80,0xa2,0xa2,0xa2,0xbe,0xa2,0xa2,0xa2, 0x80,0xa2,0xa4,0xa8,0xb0,0xa8,0xa4,0xa2,
0x80,0x9c,0x88,0x88,0x88,0x88,0x88,0x9c, 0x80,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xbe,
0x80,0x82,0x82,0x82,0x82,0x82,0xa2,0x9c, 0x80,0xa2,0xb6,0xaa,0xaa,0xa2,0xa2,0xa2,
0x80,0xa2,0xa4,0xa8,0xb0,0xa8,0xa4,0xa2, 0x80,0xa2,0xa2,0xb2,0xaa,0xa6,0xa2,0xa2,
0x80,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xbe, 0x80,0x9c,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c,
0x80,0xa2,0xb6,0xaa,0xaa,0xa2,0xa2,0xa2, 0x80,0xbc,0xa2,0xa2,0xbc,0xa0,0xa0,0xa0,
0x80,0xa2,0xa2,0xb2,0xaa,0xa6,0xa2,0xa2, 0x80,0x9c,0xa2,0xa2,0xa2,0xaa,0xa4,0x9a,
0x80,0x9c,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c, 0x80,0xbc,0xa2,0xa2,0xbc,0xa8,0xa4,0xa2,
0x80,0xbc,0xa2,0xa2,0xbc,0xa0,0xa0,0xa0, 0x80,0x9c,0xa2,0xa0,0x9c,0x82,0xa2,0x9c,
0x80,0x9c,0xa2,0xa2,0xa2,0xaa,0xa4,0x9a, 0x80,0xbe,0x88,0x88,0x88,0x88,0x88,0x88,
0x80,0xbc,0xa2,0xa2,0xbc,0xa8,0xa4,0xa2, 0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c,
0x80,0x9c,0xa2,0xa0,0x9c,0x82,0xa2,0x9c, 0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0x94,0x88,
0x80,0xbe,0x88,0x88,0x88,0x88,0x88,0x88, 0x80,0xa2,0xa2,0xa2,0xaa,0xaa,0xb6,0xa2,
0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c, 0x80,0xa2,0xa2,0x94,0x88,0x94,0xa2,0xa2,
0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0x94,0x88, 0x80,0xa2,0xa2,0x94,0x88,0x88,0x88,0x88,
0x80,0xa2,0xa2,0xa2,0xaa,0xaa,0xb6,0xa2, 0x80,0xbe,0x82,0x84,0x88,0x90,0xa0,0xbe,
0x80,0xa2,0xa2,0x94,0x88,0x94,0xa2,0xa2, 0x80,0xbe,0xb0,0xb0,0xb0,0xb0,0xb0,0xbe,
0x80,0xa2,0xa2,0x94,0x88,0x88,0x88,0x88, 0x80,0x80,0xa0,0x90,0x88,0x84,0x82,0x80,
0x80,0xbe,0x82,0x84,0x88,0x90,0xa0,0xbe, 0x80,0xbe,0x86,0x86,0x86,0x86,0x86,0xbe,
0x80,0xbe,0xb0,0xb0,0xb0,0xb0,0xb0,0xbe, 0x80,0x80,0x80,0x88,0x94,0xa2,0x80,0x80,
0x80,0x80,0xa0,0x90,0x88,0x84,0x82,0x80, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xbe,
0x80,0xbe,0x86,0x86,0x86,0x86,0x86,0xbe, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x88,0x94,0xa2,0x80,0x80, 0x80,0x88,0x88,0x88,0x88,0x88,0x80,0x88,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xbe, 0x80,0x94,0x94,0x94,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 0x80,0x94,0x94,0xbe,0x94,0xbe,0x94,0x94,
0x80,0x88,0x88,0x88,0x88,0x88,0x80,0x88, 0x80,0x88,0x9e,0xa8,0x9c,0x8a,0xbc,0x88,
0x80,0x94,0x94,0x94,0x80,0x80,0x80,0x80, 0x80,0xb0,0xb2,0x84,0x88,0x90,0xa6,0x86,
0x80,0x94,0x94,0xbe,0x94,0xbe,0x94,0x94, 0x80,0x90,0xa8,0xa8,0x90,0xaa,0xa4,0x9a,
0x80,0x88,0x9e,0xa8,0x9c,0x8a,0xbc,0x88, 0x80,0x88,0x88,0x88,0x80,0x80,0x80,0x80,
0x80,0xb0,0xb2,0x84,0x88,0x90,0xa6,0x86, 0x80,0x88,0x90,0xa0,0xa0,0xa0,0x90,0x88,
0x80,0x90,0xa8,0xa8,0x90,0xaa,0xa4,0x9a, 0x80,0x88,0x84,0x82,0x82,0x82,0x84,0x88,
0x80,0x88,0x88,0x88,0x80,0x80,0x80,0x80, 0x80,0x88,0xaa,0x9c,0x88,0x9c,0xaa,0x88,
0x80,0x88,0x90,0xa0,0xa0,0xa0,0x90,0x88, 0x80,0x80,0x88,0x88,0xbe,0x88,0x88,0x80,
0x80,0x88,0x84,0x82,0x82,0x82,0x84,0x88, 0x80,0x80,0x80,0x80,0x80,0x88,0x88,0x90,
0x80,0x88,0xaa,0x9c,0x88,0x9c,0xaa,0x88, 0x80,0x80,0x80,0x80,0xbe,0x80,0x80,0x80,
0x80,0x80,0x88,0x88,0xbe,0x88,0x88,0x80, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x88,
0x80,0x80,0x80,0x80,0x80,0x88,0x88,0x90, 0x80,0x80,0x82,0x84,0x88,0x90,0xa0,0x80,
0x80,0x80,0x80,0x80,0xbe,0x80,0x80,0x80, 0x80,0x9c,0xa2,0xa6,0xaa,0xb2,0xa2,0x9c,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x88, 0x80,0x88,0x98,0x88,0x88,0x88,0x88,0x9c,
0x80,0x80,0x82,0x84,0x88,0x90,0xa0,0x80, 0x80,0x9c,0xa2,0x82,0x8c,0x90,0xa0,0xbe,
0x80,0x9c,0xa2,0xa6,0xaa,0xb2,0xa2,0x9c, 0x80,0xbe,0x82,0x84,0x8c,0x82,0xa2,0x9c,
0x80,0x88,0x98,0x88,0x88,0x88,0x88,0x9c, 0x80,0x84,0x8c,0x94,0xa4,0xbe,0x84,0x84,
0x80,0x9c,0xa2,0x82,0x8c,0x90,0xa0,0xbe, 0x80,0xbe,0xa0,0xbc,0x82,0x82,0xa2,0x9c,
0x80,0xbe,0x82,0x84,0x8c,0x82,0xa2,0x9c, 0x80,0x8e,0x90,0xa0,0xbc,0xa2,0xa2,0x9c,
0x80,0x84,0x8c,0x94,0xa4,0xbe,0x84,0x84, 0x80,0xbe,0x82,0x84,0x88,0x90,0x90,0x90,
0x80,0xbe,0xa0,0xbc,0x82,0x82,0xa2,0x9c, 0x80,0x9c,0xa2,0xa2,0x9c,0xa2,0xa2,0x9c,
0x80,0x8e,0x90,0xa0,0xbc,0xa2,0xa2,0x9c, 0x80,0x9c,0xa2,0xa2,0x9e,0x82,0x84,0xb8,
0x80,0xbe,0x82,0x84,0x88,0x90,0x90,0x90, 0x80,0x80,0x80,0x88,0x80,0x88,0x80,0x80,
0x80,0x9c,0xa2,0xa2,0x9c,0xa2,0xa2,0x9c, 0x80,0x80,0x80,0x88,0x80,0x88,0x88,0x90,
0x80,0x9c,0xa2,0xa2,0x9e,0x82,0x84,0xb8, 0x80,0x84,0x88,0x90,0xa0,0x90,0x88,0x84,
0x80,0x80,0x80,0x88,0x80,0x88,0x80,0x80, 0x80,0x80,0x80,0xbe,0x80,0xbe,0x80,0x80,
0x80,0x80,0x80,0x88,0x80,0x88,0x88,0x90, 0x80,0x90,0x88,0x84,0x82,0x84,0x88,0x90,
0x80,0x84,0x88,0x90,0xa0,0x90,0x88,0x84, 0x80,0x9c,0xa2,0x84,0x88,0x88,0x80,0x88,
0x80,0x80,0x80,0xbe,0x80,0xbe,0x80,0x80, 0x00,0x1c,0x22,0x2a,0x2e,0x2c,0x20,0x1e,
0x80,0x90,0x88,0x84,0x82,0x84,0x88,0x90, 0x00,0x08,0x14,0x22,0x22,0x3e,0x22,0x22,
0x80,0x9c,0xa2,0x84,0x88,0x88,0x80,0x88, 0x00,0x3c,0x22,0x22,0x3c,0x22,0x22,0x3c,
0x00,0x1c,0x22,0x2a,0x2e,0x2c,0x20,0x1e, 0x00,0x1c,0x22,0x20,0x20,0x20,0x22,0x1c,
0x00,0x08,0x14,0x22,0x22,0x3e,0x22,0x22, 0x00,0x3c,0x22,0x22,0x22,0x22,0x22,0x3c,
0x00,0x3c,0x22,0x22,0x3c,0x22,0x22,0x3c, 0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x3e,
0x00,0x1c,0x22,0x20,0x20,0x20,0x22,0x1c, 0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x20,
0x00,0x3c,0x22,0x22,0x22,0x22,0x22,0x3c, 0x00,0x1e,0x20,0x20,0x20,0x26,0x22,0x1e,
0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x3e, 0x00,0x22,0x22,0x22,0x3e,0x22,0x22,0x22,
0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x20, 0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x1c,
0x00,0x1e,0x20,0x20,0x20,0x26,0x22,0x1e, 0x00,0x02,0x02,0x02,0x02,0x02,0x22,0x1c,
0x00,0x22,0x22,0x22,0x3e,0x22,0x22,0x22, 0x00,0x22,0x24,0x28,0x30,0x28,0x24,0x22,
0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x1c, 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x3e,
0x00,0x02,0x02,0x02,0x02,0x02,0x22,0x1c, 0x00,0x22,0x36,0x2a,0x2a,0x22,0x22,0x22,
0x00,0x22,0x24,0x28,0x30,0x28,0x24,0x22, 0x00,0x22,0x22,0x32,0x2a,0x26,0x22,0x22,
0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x3e, 0x00,0x1c,0x22,0x22,0x22,0x22,0x22,0x1c,
0x00,0x22,0x36,0x2a,0x2a,0x22,0x22,0x22, 0x00,0x3c,0x22,0x22,0x3c,0x20,0x20,0x20,
0x00,0x22,0x22,0x32,0x2a,0x26,0x22,0x22, 0x00,0x1c,0x22,0x22,0x22,0x2a,0x24,0x1a,
0x00,0x1c,0x22,0x22,0x22,0x22,0x22,0x1c, 0x00,0x3c,0x22,0x22,0x3c,0x28,0x24,0x22,
0x00,0x3c,0x22,0x22,0x3c,0x20,0x20,0x20, 0x00,0x1c,0x22,0x20,0x1c,0x02,0x22,0x1c,
0x00,0x1c,0x22,0x22,0x22,0x2a,0x24,0x1a, 0x00,0x3e,0x08,0x08,0x08,0x08,0x08,0x08,
0x00,0x3c,0x22,0x22,0x3c,0x28,0x24,0x22, 0x00,0x22,0x22,0x22,0x22,0x22,0x22,0x1c,
0x00,0x1c,0x22,0x20,0x1c,0x02,0x22,0x1c, 0x00,0x22,0x22,0x22,0x22,0x22,0x14,0x08,
0x00,0x3e,0x08,0x08,0x08,0x08,0x08,0x08, 0x00,0x22,0x22,0x22,0x2a,0x2a,0x36,0x22,
0x00,0x22,0x22,0x22,0x22,0x22,0x22,0x1c, 0x00,0x22,0x22,0x14,0x08,0x14,0x22,0x22,
0x00,0x22,0x22,0x22,0x22,0x22,0x14,0x08, 0x00,0x22,0x22,0x14,0x08,0x08,0x08,0x08,
0x00,0x22,0x22,0x22,0x2a,0x2a,0x36,0x22, 0x00,0x3e,0x02,0x04,0x08,0x10,0x20,0x3e,
0x00,0x22,0x22,0x14,0x08,0x14,0x22,0x22, 0x00,0x3e,0x30,0x30,0x30,0x30,0x30,0x3e,
0x00,0x22,0x22,0x14,0x08,0x08,0x08,0x08, 0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x00,
0x00,0x3e,0x02,0x04,0x08,0x10,0x20,0x3e, 0x00,0x3e,0x06,0x06,0x06,0x06,0x06,0x3e,
0x00,0x3e,0x30,0x30,0x30,0x30,0x30,0x3e, 0x00,0x00,0x00,0x08,0x14,0x22,0x00,0x00,
0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,
0x00,0x3e,0x06,0x06,0x06,0x06,0x06,0x3e, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x08,0x14,0x22,0x00,0x00, 0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x08,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e, 0x00,0x14,0x14,0x14,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x14,0x14,0x3e,0x14,0x3e,0x14,0x14,
0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x08, 0x00,0x08,0x1e,0x28,0x1c,0x0a,0x3c,0x08,
0x00,0x14,0x14,0x14,0x00,0x00,0x00,0x00, 0x00,0x30,0x32,0x04,0x08,0x10,0x26,0x06,
0x00,0x14,0x14,0x3e,0x14,0x3e,0x14,0x14, 0x00,0x10,0x28,0x28,0x10,0x2a,0x24,0x1a,
0x00,0x08,0x1e,0x28,0x1c,0x0a,0x3c,0x08, 0x00,0x08,0x08,0x08,0x00,0x00,0x00,0x00,
0x00,0x30,0x32,0x04,0x08,0x10,0x26,0x06, 0x00,0x08,0x10,0x20,0x20,0x20,0x10,0x08,
0x00,0x10,0x28,0x28,0x10,0x2a,0x24,0x1a, 0x00,0x08,0x04,0x02,0x02,0x02,0x04,0x08,
0x00,0x08,0x08,0x08,0x00,0x00,0x00,0x00, 0x00,0x08,0x2a,0x1c,0x08,0x1c,0x2a,0x08,
0x00,0x08,0x10,0x20,0x20,0x20,0x10,0x08, 0x00,0x00,0x08,0x08,0x3e,0x08,0x08,0x00,
0x00,0x08,0x04,0x02,0x02,0x02,0x04,0x08, 0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x10,
0x00,0x08,0x2a,0x1c,0x08,0x1c,0x2a,0x08, 0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,
0x00,0x00,0x08,0x08,0x3e,0x08,0x08,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x10, 0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x00,
0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00, 0x00,0x1c,0x22,0x26,0x2a,0x32,0x22,0x1c,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08, 0x00,0x08,0x18,0x08,0x08,0x08,0x08,0x1c,
0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x00, 0x00,0x1c,0x22,0x02,0x0c,0x10,0x20,0x3e,
0x00,0x1c,0x22,0x26,0x2a,0x32,0x22,0x1c, 0x00,0x3e,0x02,0x04,0x0c,0x02,0x22,0x1c,
0x00,0x08,0x18,0x08,0x08,0x08,0x08,0x1c, 0x00,0x04,0x0c,0x14,0x24,0x3e,0x04,0x04,
0x00,0x1c,0x22,0x02,0x0c,0x10,0x20,0x3e, 0x00,0x3e,0x20,0x3c,0x02,0x02,0x22,0x1c,
0x00,0x3e,0x02,0x04,0x0c,0x02,0x22,0x1c, 0x00,0x0e,0x10,0x20,0x3c,0x22,0x22,0x1c,
0x00,0x04,0x0c,0x14,0x24,0x3e,0x04,0x04, 0x00,0x3e,0x02,0x04,0x08,0x10,0x10,0x10,
0x00,0x3e,0x20,0x3c,0x02,0x02,0x22,0x1c, 0x00,0x1c,0x22,0x22,0x1c,0x22,0x22,0x1c,
0x00,0x0e,0x10,0x20,0x3c,0x22,0x22,0x1c, 0x00,0x1c,0x22,0x22,0x1e,0x02,0x04,0x38,
0x00,0x3e,0x02,0x04,0x08,0x10,0x10,0x10, 0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,
0x00,0x1c,0x22,0x22,0x1c,0x22,0x22,0x1c, 0x00,0x00,0x00,0x08,0x00,0x08,0x08,0x10,
0x00,0x1c,0x22,0x22,0x1e,0x02,0x04,0x38, 0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04,
0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00, 0x00,0x00,0x00,0x3e,0x00,0x3e,0x00,0x00,
0x00,0x00,0x00,0x08,0x00,0x08,0x08,0x10, 0x00,0x10,0x08,0x04,0x02,0x04,0x08,0x10,
0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04, 0x00,0x1c,0x22,0x04,0x08,0x08,0x00,0x08,
0x00,0x00,0x00,0x3e,0x00,0x3e,0x00,0x00, 0x80,0x9c,0xa2,0xaa,0xae,0xac,0xa0,0x9e,
0x00,0x10,0x08,0x04,0x02,0x04,0x08,0x10, 0x80,0x88,0x94,0xa2,0xa2,0xbe,0xa2,0xa2,
0x00,0x1c,0x22,0x04,0x08,0x08,0x00,0x08, 0x80,0xbc,0xa2,0xa2,0xbc,0xa2,0xa2,0xbc,
0x80,0x9c,0xa2,0xaa,0xae,0xac,0xa0,0x9e, 0x80,0x9c,0xa2,0xa0,0xa0,0xa0,0xa2,0x9c,
0x80,0x88,0x94,0xa2,0xa2,0xbe,0xa2,0xa2, 0x80,0xbc,0xa2,0xa2,0xa2,0xa2,0xa2,0xbc,
0x80,0xbc,0xa2,0xa2,0xbc,0xa2,0xa2,0xbc, 0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xbe,
0x80,0x9c,0xa2,0xa0,0xa0,0xa0,0xa2,0x9c, 0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xa0,
0x80,0xbc,0xa2,0xa2,0xa2,0xa2,0xa2,0xbc, 0x80,0x9e,0xa0,0xa0,0xa0,0xa6,0xa2,0x9e,
0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xbe, 0x80,0xa2,0xa2,0xa2,0xbe,0xa2,0xa2,0xa2,
0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xa0, 0x80,0x9c,0x88,0x88,0x88,0x88,0x88,0x9c,
0x80,0x9e,0xa0,0xa0,0xa0,0xa6,0xa2,0x9e, 0x80,0x82,0x82,0x82,0x82,0x82,0xa2,0x9c,
0x80,0xa2,0xa2,0xa2,0xbe,0xa2,0xa2,0xa2, 0x80,0xa2,0xa4,0xa8,0xb0,0xa8,0xa4,0xa2,
0x80,0x9c,0x88,0x88,0x88,0x88,0x88,0x9c, 0x80,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xbe,
0x80,0x82,0x82,0x82,0x82,0x82,0xa2,0x9c, 0x80,0xa2,0xb6,0xaa,0xaa,0xa2,0xa2,0xa2,
0x80,0xa2,0xa4,0xa8,0xb0,0xa8,0xa4,0xa2, 0x80,0xa2,0xa2,0xb2,0xaa,0xa6,0xa2,0xa2,
0x80,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xbe, 0x80,0x9c,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c,
0x80,0xa2,0xb6,0xaa,0xaa,0xa2,0xa2,0xa2, 0x80,0xbc,0xa2,0xa2,0xbc,0xa0,0xa0,0xa0,
0x80,0xa2,0xa2,0xb2,0xaa,0xa6,0xa2,0xa2, 0x80,0x9c,0xa2,0xa2,0xa2,0xaa,0xa4,0x9a,
0x80,0x9c,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c, 0x80,0xbc,0xa2,0xa2,0xbc,0xa8,0xa4,0xa2,
0x80,0xbc,0xa2,0xa2,0xbc,0xa0,0xa0,0xa0, 0x80,0x9c,0xa2,0xa0,0x9c,0x82,0xa2,0x9c,
0x80,0x9c,0xa2,0xa2,0xa2,0xaa,0xa4,0x9a, 0x80,0xbe,0x88,0x88,0x88,0x88,0x88,0x88,
0x80,0xbc,0xa2,0xa2,0xbc,0xa8,0xa4,0xa2, 0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c,
0x80,0x9c,0xa2,0xa0,0x9c,0x82,0xa2,0x9c, 0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0x94,0x88,
0x80,0xbe,0x88,0x88,0x88,0x88,0x88,0x88, 0x80,0xa2,0xa2,0xa2,0xaa,0xaa,0xb6,0xa2,
0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c, 0x80,0xa2,0xa2,0x94,0x88,0x94,0xa2,0xa2,
0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0x94,0x88, 0x80,0xa2,0xa2,0x94,0x88,0x88,0x88,0x88,
0x80,0xa2,0xa2,0xa2,0xaa,0xaa,0xb6,0xa2, 0x80,0xbe,0x82,0x84,0x88,0x90,0xa0,0xbe,
0x80,0xa2,0xa2,0x94,0x88,0x94,0xa2,0xa2, 0x80,0xbe,0xb0,0xb0,0xb0,0xb0,0xb0,0xbe,
0x80,0xa2,0xa2,0x94,0x88,0x88,0x88,0x88, 0x80,0x80,0xa0,0x90,0x88,0x84,0x82,0x80,
0x80,0xbe,0x82,0x84,0x88,0x90,0xa0,0xbe, 0x80,0xbe,0x86,0x86,0x86,0x86,0x86,0xbe,
0x80,0xbe,0xb0,0xb0,0xb0,0xb0,0xb0,0xbe, 0x80,0x80,0x80,0x88,0x94,0xa2,0x80,0x80,
0x80,0x80,0xa0,0x90,0x88,0x84,0x82,0x80, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xbe,
0x80,0xbe,0x86,0x86,0x86,0x86,0x86,0xbe, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x88,0x94,0xa2,0x80,0x80, 0x80,0x88,0x88,0x88,0x88,0x88,0x80,0x88,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xbe, 0x80,0x94,0x94,0x94,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 0x80,0x94,0x94,0xbe,0x94,0xbe,0x94,0x94,
0x80,0x88,0x88,0x88,0x88,0x88,0x80,0x88, 0x80,0x88,0x9e,0xa8,0x9c,0x8a,0xbc,0x88,
0x80,0x94,0x94,0x94,0x80,0x80,0x80,0x80, 0x80,0xb0,0xb2,0x84,0x88,0x90,0xa6,0x86,
0x80,0x94,0x94,0xbe,0x94,0xbe,0x94,0x94, 0x80,0x90,0xa8,0xa8,0x90,0xaa,0xa4,0x9a,
0x80,0x88,0x9e,0xa8,0x9c,0x8a,0xbc,0x88, 0x80,0x88,0x88,0x88,0x80,0x80,0x80,0x80,
0x80,0xb0,0xb2,0x84,0x88,0x90,0xa6,0x86, 0x80,0x88,0x90,0xa0,0xa0,0xa0,0x90,0x88,
0x80,0x90,0xa8,0xa8,0x90,0xaa,0xa4,0x9a, 0x80,0x88,0x84,0x82,0x82,0x82,0x84,0x88,
0x80,0x88,0x88,0x88,0x80,0x80,0x80,0x80, 0x80,0x88,0xaa,0x9c,0x88,0x9c,0xaa,0x88,
0x80,0x88,0x90,0xa0,0xa0,0xa0,0x90,0x88, 0x80,0x80,0x88,0x88,0xbe,0x88,0x88,0x80,
0x80,0x88,0x84,0x82,0x82,0x82,0x84,0x88, 0x80,0x80,0x80,0x80,0x80,0x88,0x88,0x90,
0x80,0x88,0xaa,0x9c,0x88,0x9c,0xaa,0x88, 0x80,0x80,0x80,0x80,0xbe,0x80,0x80,0x80,
0x80,0x80,0x88,0x88,0xbe,0x88,0x88,0x80, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x88,
0x80,0x80,0x80,0x80,0x80,0x88,0x88,0x90, 0x80,0x80,0x82,0x84,0x88,0x90,0xa0,0x80,
0x80,0x80,0x80,0x80,0xbe,0x80,0x80,0x80, 0x80,0x9c,0xa2,0xa6,0xaa,0xb2,0xa2,0x9c,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x88, 0x80,0x88,0x98,0x88,0x88,0x88,0x88,0x9c,
0x80,0x80,0x82,0x84,0x88,0x90,0xa0,0x80, 0x80,0x9c,0xa2,0x82,0x8c,0x90,0xa0,0xbe,
0x80,0x9c,0xa2,0xa6,0xaa,0xb2,0xa2,0x9c, 0x80,0xbe,0x82,0x84,0x8c,0x82,0xa2,0x9c,
0x80,0x88,0x98,0x88,0x88,0x88,0x88,0x9c, 0x80,0x84,0x8c,0x94,0xa4,0xbe,0x84,0x84,
0x80,0x9c,0xa2,0x82,0x8c,0x90,0xa0,0xbe, 0x80,0xbe,0xa0,0xbc,0x82,0x82,0xa2,0x9c,
0x80,0xbe,0x82,0x84,0x8c,0x82,0xa2,0x9c, 0x80,0x8e,0x90,0xa0,0xbc,0xa2,0xa2,0x9c,
0x80,0x84,0x8c,0x94,0xa4,0xbe,0x84,0x84, 0x80,0xbe,0x82,0x84,0x88,0x90,0x90,0x90,
0x80,0xbe,0xa0,0xbc,0x82,0x82,0xa2,0x9c, 0x80,0x9c,0xa2,0xa2,0x9c,0xa2,0xa2,0x9c,
0x80,0x8e,0x90,0xa0,0xbc,0xa2,0xa2,0x9c, 0x80,0x9c,0xa2,0xa2,0x9e,0x82,0x84,0xb8,
0x80,0xbe,0x82,0x84,0x88,0x90,0x90,0x90, 0x80,0x80,0x80,0x88,0x80,0x88,0x80,0x80,
0x80,0x9c,0xa2,0xa2,0x9c,0xa2,0xa2,0x9c, 0x80,0x80,0x80,0x88,0x80,0x88,0x88,0x90,
0x80,0x9c,0xa2,0xa2,0x9e,0x82,0x84,0xb8, 0x80,0x84,0x88,0x90,0xa0,0x90,0x88,0x84,
0x80,0x80,0x80,0x88,0x80,0x88,0x80,0x80, 0x80,0x80,0x80,0xbe,0x80,0xbe,0x80,0x80,
0x80,0x80,0x80,0x88,0x80,0x88,0x88,0x90, 0x80,0x90,0x88,0x84,0x82,0x84,0x88,0x90,
0x80,0x84,0x88,0x90,0xa0,0x90,0x88,0x84, 0x80,0x9c,0xa2,0x84,0x88,0x88,0x80,0x88
0x80,0x80,0x80,0xbe,0x80,0xbe,0x80,0x80, ];
0x80,0x90,0x88,0x84,0x82,0x84,0x88,0x90,
0x80,0x9c,0xa2,0x84,0x88,0x88,0x80,0x88
];
charset = bytify(charset);

View File

@ -1,6 +1,3 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*global bytify:false */
/*exported Apple2eEnhancedROM */ /*exported Apple2eEnhancedROM */
function Apple2eEnhancedROM() function Apple2eEnhancedROM()
@ -2056,8 +2053,6 @@ function Apple2eEnhancedROM()
0xf5,0x03,0xfb,0x03,0x62,0xfa,0xfa,0xc3 0xf5,0x03,0xfb,0x03,0x62,0xfa,0xfa,0xc3
]; ];
rom = bytify(rom);
return { return {
start: function apple2e_start() { start: function apple2e_start() {
return 0xc1; return 0xc1;

View File

@ -1,5 +1,3 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*global bytify:false */
/*exported Apple2eROM*/ /*exported Apple2eROM*/
function Apple2eROM() function Apple2eROM()
@ -2057,8 +2055,6 @@ function Apple2eROM()
0xf5,0x03,0xfb,0x03,0x62,0xfa,0x40,0xfa 0xf5,0x03,0xfb,0x03,0x62,0xfa,0x40,0xfa
]; ];
rom = bytify(rom);
return { return {
start: function apple2e_start() { start: function apple2e_start() {
return 0xc1; return 0xc1;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2014 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -15,7 +14,7 @@
function Apple2IO(cpu, callbacks) function Apple2IO(cpu, callbacks)
{ {
"use strict"; 'use strict';
var _hz = 1023000; var _hz = 1023000;
var _rate = 44000; var _rate = 44000;
@ -36,7 +35,7 @@ function Apple2IO(cpu, callbacks)
var _low = -0.5; var _low = -0.5;
var _audioListener = null; var _audioListener = null;
var _trigger = 0; var _trigger = 0;
var _tape = []; var _tape = [];
@ -45,7 +44,7 @@ function Apple2IO(cpu, callbacks)
var _tapeFlip = false; var _tapeFlip = false;
var LOC = { var LOC = {
KEYBOARD: 0x00, // keyboard data (latched) (Read), KEYBOARD: 0x00, // keyboard data (latched) (Read),
CLR80VID: 0x0C, // clear 80 column mode CLR80VID: 0x0C, // clear 80 column mode
SET80VID: 0x0D, // set 80 column mode SET80VID: 0x0D, // set 80 column mode
CLRALTCH: 0x0E, // clear mousetext CLRALTCH: 0x0E, // clear mousetext
@ -89,7 +88,7 @@ function Apple2IO(cpu, callbacks)
SETIOUDIS:0x7E, // Enable double hires SETIOUDIS:0x7E, // Enable double hires
CLRIOUDIS:0x7F // Disable double hires CLRIOUDIS:0x7F // Disable double hires
}; };
function _debug() { function _debug() {
// debug.apply(arguments); // debug.apply(arguments);
} }
@ -116,43 +115,43 @@ function Apple2IO(cpu, callbacks)
var delta = now - _trigger; var delta = now - _trigger;
switch (off) { switch (off) {
case LOC.CLR80VID: case LOC.CLR80VID:
// _debug("80 Column Mode off"); // _debug('80 Column Mode off');
if ('_80col' in callbacks) callbacks._80col(false); if ('_80col' in callbacks) callbacks._80col(false);
break; break;
case LOC.SET80VID: case LOC.SET80VID:
// _debug("80 Column Mode on"); // _debug('80 Column Mode on');
if ('_80col' in callbacks) callbacks._80col(true); if ('_80col' in callbacks) callbacks._80col(true);
break; break;
case LOC.CLRALTCH: case LOC.CLRALTCH:
// _debug("Alt Char off"); // _debug('Alt Char off');
if ('altchar' in callbacks) callbacks.altchar(false); if ('altchar' in callbacks) callbacks.altchar(false);
break; break;
case LOC.SETALTCH: case LOC.SETALTCH:
// _debug("Alt Char on"); // _debug('Alt Char on');
if ('altchar' in callbacks) callbacks.altchar(true); if ('altchar' in callbacks) callbacks.altchar(true);
break; break;
case LOC.CLRTEXT: case LOC.CLRTEXT:
_debug("Graphics Mode"); _debug('Graphics Mode');
callbacks.text(false); callbacks.text(false);
break; break;
case LOC.SETTEXT: case LOC.SETTEXT:
_debug("Text Mode"); _debug('Text Mode');
callbacks.text(true); callbacks.text(true);
break; break;
case LOC.CLRMIXED: case LOC.CLRMIXED:
_debug("Mixed Mode off"); _debug('Mixed Mode off');
callbacks.mixed(false); callbacks.mixed(false);
break; break;
case LOC.SETMIXED: case LOC.SETMIXED:
_debug("Mixed Mode on"); _debug('Mixed Mode on');
callbacks.mixed(true); callbacks.mixed(true);
break; break;
case LOC.CLRHIRES: case LOC.CLRHIRES:
_debug("LoRes Mode"); _debug('LoRes Mode');
callbacks.hires(false); callbacks.hires(false);
break; break;
case LOC.SETHIRES: case LOC.SETHIRES:
_debug("HiRes Mode"); _debug('HiRes Mode');
callbacks.hires(true); callbacks.hires(true);
break; break;
case LOC.PAGE1: case LOC.PAGE1:
@ -162,27 +161,27 @@ function Apple2IO(cpu, callbacks)
callbacks.page(2); callbacks.page(2);
break; break;
case LOC.RDTEXT: case LOC.RDTEXT:
if ('isText' in callbacks) if ('isText' in callbacks)
result = callbacks.isText() ? 0x80 : 0x0; result = callbacks.isText() ? 0x80 : 0x0;
break; break;
case LOC.RDMIXED: case LOC.RDMIXED:
if ('isMixed' in callbacks) if ('isMixed' in callbacks)
result = callbacks.isMixed() ? 0x80 : 0x0; result = callbacks.isMixed() ? 0x80 : 0x0;
break; break;
case LOC.RDPAGE2: case LOC.RDPAGE2:
if ('isPage2' in callbacks) if ('isPage2' in callbacks)
result = callbacks.isPage2() ? 0x80 : 0x0; result = callbacks.isPage2() ? 0x80 : 0x0;
break; break;
case LOC.RDHIRES: case LOC.RDHIRES:
if ('isHires' in callbacks) if ('isHires' in callbacks)
result = callbacks.isHires() ? 0x80 : 0x0; result = callbacks.isHires() ? 0x80 : 0x0;
break; break;
case LOC.RD80VID: case LOC.RD80VID:
if ('is80Col' in callbacks) if ('is80Col' in callbacks)
result = callbacks.is80Col() ? 0x80 : 0x0; result = callbacks.is80Col() ? 0x80 : 0x0;
break; break;
case LOC.RDALTCH: case LOC.RDALTCH:
if ('isAltChar' in callbacks) if ('isAltChar' in callbacks)
result = callbacks.isAltChar() ? 0x80 : 0x0; result = callbacks.isAltChar() ? 0x80 : 0x0;
break; break;
case LOC.SETAN0: case LOC.SETAN0:
@ -262,7 +261,7 @@ function Apple2IO(cpu, callbacks)
_trigger = cpu.cycles(); _trigger = cpu.cycles();
break; break;
case LOC.TAPEIN: case LOC.TAPEIN:
var flipped = false; // var flipped = false;
if (_tapeOffset == -1) { if (_tapeOffset == -1) {
_tapeOffset = 0; _tapeOffset = 0;
_tapeNext = now; _tapeNext = now;
@ -270,22 +269,22 @@ function Apple2IO(cpu, callbacks)
if (_tapeOffset < _tape.length) { if (_tapeOffset < _tape.length) {
while (now >= _tapeNext) { while (now >= _tapeNext) {
if ((_tapeOffset % 1000) === 0) { if ((_tapeOffset % 1000) === 0) {
debug("Read " + (_tapeOffset / 1000)); debug('Read ' + (_tapeOffset / 1000));
} }
_tapeFlip = !_tapeFlip; _tapeFlip = !_tapeFlip;
flipped = true; // flipped = true;
_tapeNext += _tape[_tapeOffset++]; _tapeNext += _tape[_tapeOffset++];
} }
result = _tapeFlip ? 0x80 : 0x00; result = _tapeFlip ? 0x80 : 0x00;
} }
/* /*
if (flipped) { if (flipped) {
debug("now=" + now + " next=" + _tapeNext + " (" + (_tapeNext - now) + ")"); debug('now=' + now + ' next=' + _tapeNext + ' (' + (_tapeNext - now) + ')');
} }
*/ */
/* /*
var progress = var progress =
Math.round(_tapeOffset / _tapeBuffer.length * 100) / 100; Math.round(_tapeOffset / _tapeBuffer.length * 100) / 100;
if (_progress != progress) { if (_progress != progress) {
@ -294,9 +293,9 @@ function Apple2IO(cpu, callbacks)
} }
*/ */
} }
return result; return result;
} }
return { return {
registerSwitches: function apple2io_registerSwitches(a, locs) { registerSwitches: function apple2io_registerSwitches(a, locs) {
each(locs, function(key) { each(locs, function(key) {
@ -314,12 +313,12 @@ function Apple2IO(cpu, callbacks)
end: function apple2io_end() { end: function apple2io_end() {
return 0xc0; return 0xc0;
}, },
read: function apple2io_read(page, off) { read: function apple2io_read(page, off) {
var result = 0; var result = 0;
if (_locs[off]) { if (_locs[off]) {
result = _locs[off].ioSwitch(off); result = _locs[off].ioSwitch(off);
} else { } else {
debug("I/O read: C0" + toHex(off)); debug('I/O read: C0' + toHex(off));
} }
return result; return result;
}, },
@ -327,7 +326,7 @@ function Apple2IO(cpu, callbacks)
if (_locs[off]) { if (_locs[off]) {
_locs[off].ioSwitch(off, val); _locs[off].ioSwitch(off, val);
} else { } else {
debug("I/O write: C0" + toHex(off)); debug('I/O write: C0' + toHex(off));
} }
}, },
getState: function apple2io_getState() { return {}; }, getState: function apple2io_getState() { return {}; },
@ -339,7 +338,7 @@ function Apple2IO(cpu, callbacks)
_keyDown = true; _keyDown = true;
_key = ascii | 0x80; _key = ascii | 0x80;
}, },
keyUp: function apple2io_keyUp() { keyUp: function apple2io_keyUp() {
_keyDown = false; _keyDown = false;
_key = 0; _key = 0;
}, },
@ -353,10 +352,10 @@ function Apple2IO(cpu, callbacks)
paddle: function apple2io_paddle(p, v) { paddle: function apple2io_paddle(p, v) {
_paddle[p] = v; _paddle[p] = v;
}, },
updateHz: function apple2io_updateHz(hz) { updateHz: function apple2io_updateHz(hz) {
_hz = hz; _hz = hz;
_cycles_per_sample = _hz / _rate; _cycles_per_sample = _hz / _rate;
}, },
setKeyBuffer: function apple2io_setKeyBuffer(buffer) { setKeyBuffer: function apple2io_setKeyBuffer(buffer) {
@ -373,15 +372,15 @@ function Apple2IO(cpu, callbacks)
_tapeOffset = -1; _tapeOffset = -1;
}, },
sampleRate: function sampleRate(rate) { sampleRate: function sampleRate(rate) {
_rate = rate; _rate = rate;
_cycles_per_sample = _hz / _rate; _cycles_per_sample = _hz / _rate;
}, },
sampleTick: function sampleTick() { sampleTick: function sampleTick() {
_tick(); _tick();
}, },
addSampleListener: function addSampleListener(cb) { addSampleListener: function addSampleListener(cb) {
_audioListener = cb; _audioListener = cb;
} }

173
js/applesoft/decompiler.js Normal file
View File

@ -0,0 +1,173 @@
function ApplesoftDump(mem)
{
var _mem = mem;
var LETTERS =
" " +
" !\"#$%&'()*+,-./0123456789:;<=>?" +
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" +
"`abcdefghijklmnopqrstuvwxyz{|}~ ";
var TOKENS = {
0x80: "END",
0x81: "FOR",
0x82: "NEXT",
0x83: "DATA",
0x84: "INPUT",
0x85: "DEL",
0x86: "DIM",
0x87: "READ",
0x88: "GR",
0x89: "TEXT",
0x8a: "PR#",
0x8b: "IN#",
0x8c: "CALL",
0x8d: "PLOT",
0x8e: "HLIN",
0x8f: "VLIN",
0x90: "HGR2",
0x91: "HGR",
0x92: "HCOLOR=",
0x93: "HPLOT",
0x94: "DRAW",
0x95: "XDRAW",
0x96: "HTAB",
0x97: "HOME",
0x98: "ROT=",
0x99: "SCALE=",
0x9a: "SHLOAD",
0x9b: "TRACE",
0x9c: "NOTRACE",
0x9d: "NORMAL",
0x9e: "INVERSE",
0x9f: "FLASH",
0xa0: "COLOR=",
0xa1: "POP=",
0xa2: "VTAB",
0xa3: "HIMEM:",
0xa4: "LOMEM:",
0xa5: "ONERR",
0xa6: "RESUME",
0xa7: "RECALL",
0xa8: "STORE",
0xa9: "SPEED=",
0xaa: "LET",
0xab: "GOTO",
0xac: "RUN",
0xad: "IF",
0xae: "RESTORE",
0xaf: "&",
0xb0: "GOSUB",
0xb1: "RETURN",
0xb2: "REM",
0xb3: "STOP",
0xb4: "ON",
0xb5: "WAIT",
0xb6: "LOAD",
0xb7: "SAVE",
0xb8: "DEF",
0xb9: "POKE",
0xba: "PRINT",
0xbb: "CONT",
0xbc: "LIST",
0xbd: "CLEAR",
0xbe: "GET",
0xbf: "NEW",
0xc0: "TAB(",
0xc1: "TO",
0xc2: "FN",
0xc3: "SPC(",
0xc4: "THEN",
0xc5: "AT",
0xc6: "NOT",
0xc7: "STEP",
0xc8: "+",
0xc9: "-",
0xca: "*",
0xcb: "/",
0xcc: "^",
0xcd: "AND",
0xce: "OR",
0xcf: ">",
0xd0: "=",
0xd1: "<",
0xd2: "SGN",
0xd3: "INT",
0xd4: "ABS",
0xd5: "USR",
0xd6: "FRE",
0xd7: "SCRN(",
0xd8: "PDL",
0xd9: "POS",
0xda: "SQR",
0xdb: "RND",
0xdc: "LOG",
0xdd: "EXP",
0xde: "COS",
0xdf: "SIN",
0xe0: "TAN",
0xe1: "ATN",
0xe2: "PEEK",
0xe3: "LEN",
0xe4: "STR$",
0xe5: "VAL",
0xe6: "ASC",
0xe7: "CHR$",
0xe8: "LEFT$",
0xe9: "RIGHT$",
0xea: "MID$"
};
function readByte(addr) {
var page = addr >> 8,
off = addr & 0xff;
return _mem.read(page, off);
}
function readWord(addr) {
var lsb, msb;
lsb = readByte(addr, debug);
msb = readByte(addr + 1, debug);
return (msb << 8) | lsb;
}
return {
toString: function () {
var str = "";
var start = readWord(0x67); // Start
var end = readWord(0xaf); // End of program
var addr = start;
do {
var line = "";
var next = readWord(addr);
addr += 2;
var lineno = readWord(addr);
addr += 2;
line += lineno;
line += " ";
var val = false;
do {
if (addr < start || addr > end)
return str;
var val = readByte(addr++);
if (val > 0x80) {
line += " ";
line += TOKENS[val];
line += " ";
}
else
line += LETTERS[val];
} while (val);
line += "\n";
str += line;
addr = next;
} while (addr && addr >= start && addr < end);
return str;
}
};
}

View File

@ -2,7 +2,7 @@
function base64_encode (data) { function base64_encode (data) {
// Twacked by Will Scullin to handle arrays of "bytes" // Twacked by Will Scullin to handle arrays of "bytes"
// http://kevin.vanzonneveld.net // http://kevin.vanzonneveld.net
// + original by: Tyler Akins (http://rumkin.com) // + original by: Tyler Akins (http://rumkin.com)
// + improved by: Bayron Guevara // + improved by: Bayron Guevara
@ -19,9 +19,9 @@ function base64_encode (data) {
//if (typeof this.window['atob'] == 'function') { //if (typeof this.window['atob'] == 'function') {
// return atob(data); // return atob(data);
//} //}
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc="", tmp_arr = []; var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc='', tmp_arr = [];
if (!data) { if (!data) {
return data; return data;
@ -42,15 +42,15 @@ function base64_encode (data) {
// use hexets to index into b64, and append result to encoded string // use hexets to index into b64, and append result to encoded string
tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
} while (i < data.length); } while (i < data.length);
enc = tmp_arr.join(''); enc = tmp_arr.join('');
switch (data.length % 3) { switch (data.length % 3) {
case 1: case 1:
enc = enc.slice(0, -2) + '=='; enc = enc.slice(0, -2) + '==';
break; break;
case 2: case 2:
enc = enc.slice(0, -1) + '='; enc = enc.slice(0, -1) + '=';
break; break;
} }
@ -59,7 +59,7 @@ function base64_encode (data) {
function base64_decode(data) { function base64_decode(data) {
// Twacked by Will Scullin to handle arrays of "bytes" // Twacked by Will Scullin to handle arrays of "bytes"
// http://kevin.vanzonneveld.net // http://kevin.vanzonneveld.net
// + original by: Tyler Akins (http://rumkin.com) // + original by: Tyler Akins (http://rumkin.com)
// + improved by: Thunder.m // + improved by: Thunder.m
@ -80,7 +80,7 @@ function base64_decode(data) {
// return btoa(data); // return btoa(data);
//} //}
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, tmp_arr = []; var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, tmp_arr = [];
if (!data) { if (!data) {
@ -99,10 +99,10 @@ function base64_decode(data) {
o2 = bits>>8 & 0xff; o2 = bits>>8 & 0xff;
o3 = bits & 0xff; o3 = bits & 0xff;
tmp_arr[ac++] = o1; tmp_arr[ac++] = o1;
if (h3 != 64) { if (h3 != 64) {
tmp_arr[ac++] = o2; tmp_arr[ac++] = o2;
} }
if (h4 != 64) { if (h4 != 64) {
tmp_arr[ac++] = o3; tmp_arr[ac++] = o3;
} }

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2014 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -10,16 +9,14 @@
* implied warranty. * implied warranty.
*/ */
/*jshint browser:true */
/*globals allocMemPages: false,
charset: false,
base64_encode: false, base64_decode: false */
/*exported LoresPage, HiresPage, VideoModes*/
/* /*
* Text Page 1 Drawing * Text Page 1 Drawing
*/ */
/*globals allocMemPages: false,
base64_encode: false, base64_decode: false */
/*exported LoresPage, HiresPage, VideoModes*/
var textMode = true; var textMode = true;
var mixedMode = true; var mixedMode = true;
var hiresMode = false; var hiresMode = false;
@ -34,8 +31,10 @@ var scanlines = false;
* *
***************************************************************************/ ***************************************************************************/
function LoresPage(page) function LoresPage(page, charset)
{ {
'use strict';
// $00-$3F inverse // $00-$3F inverse
// $40-$7F flashing // $40-$7F flashing
// $80-$FF normal // $80-$FF normal
@ -108,16 +107,16 @@ function LoresPage(page)
data[off + 560 * 4 + 2] = c2 >> 1; data[off + 560 * 4 + 2] = c2 >> 1;
} }
} }
_init(); _init();
return { return {
start: function() { start: function() {
var self = this; var self = this;
window.setInterval(function() { window.setInterval(function() {
self.blink(); self.blink();
}, 267); }, 267);
return (0x04 * _page); return (0x04 * _page);
}, },
end: function() { return (0x04 * _page) + 0x03; }, end: function() { return (0x04 * _page) + 0x03; },
read: function(page, off) { read: function(page, off) {
@ -136,10 +135,10 @@ function LoresPage(page)
var col = (base % 0x80) % 0x28, var col = (base % 0x80) % 0x28,
adj = off - col; adj = off - col;
// 000001cd eabab000 -> 000abcde // 000001cd eabab000 -> 000abcde
var ab = (adj & 0x18), var ab = (adj & 0x18),
cd = (page & 0x03) << 1, cd = (page & 0x03) << 1,
e = adj >> 7; e = adj >> 7;
var row = ab | cd | e, color, idx, jdx, b; var row = ab | cd | e, color, idx, jdx, b;
@ -159,7 +158,7 @@ function LoresPage(page)
back = _greenMode ? _green : _white; back = _greenMode ? _green : _white;
} }
for (jdx = 0; jdx < 8; jdx++) { for (jdx = 0; jdx < 8; jdx++) {
b = charset[(val & 0x3f) * 8 + jdx]; b = charset[val * 8 + jdx];
b <<= 1; b <<= 1;
for (idx = 0; idx < 7; idx++) { for (idx = 0; idx < 7; idx++) {
color = (b & 0x80) ? fore : back; color = (b & 0x80) ? fore : back;
@ -177,7 +176,7 @@ function LoresPage(page)
b = (jdx < 4) ? (val & 0x0f) : (val >> 4); b = (jdx < 4) ? (val & 0x0f) : (val >> 4);
b |= (b << 4); b |= (b << 4);
b |= (b << 8); b |= (b << 8);
if (col & 0x1) { if ((col & 0x1) !== 0) {
b <<= 2; b <<= 2;
} }
for (idx = 0; idx < 14; idx++) { for (idx = 0; idx < 14; idx++) {
@ -187,7 +186,7 @@ function LoresPage(page)
off += 4; off += 4;
} }
off += 546 * 4 + 560 * 4; off += 546 * 4 + 560 * 4;
} }
} else { } else {
for (jdx = 0; jdx < 8; jdx++) { for (jdx = 0; jdx < 8; jdx++) {
b = (jdx < 4) ? (val & 0x0f) : (val >> 4); b = (jdx < 4) ? (val & 0x0f) : (val >> 4);
@ -212,7 +211,7 @@ function LoresPage(page)
}, },
blink: function() { blink: function() {
var addr = 0x400 * _page; var addr = 0x400 * _page;
_refreshing = true; _refreshing = true;
_blink = !_blink; _blink = !_blink;
for (var idx = 0; idx < 0x400; idx++, addr++) { for (var idx = 0; idx < 0x400; idx++, addr++) {
var b = _buffer[idx]; var b = _buffer[idx];
@ -247,14 +246,14 @@ function LoresPage(page)
} }
function HiresPage(page) function HiresPage(page)
{ {
var _page = page; var _page = page;
var orangeCol = [0xff, 0x65, 0x00]; var orangeCol = [0xff, 0x65, 0x00];
var greenCol = [0x00, 0xff, 0x00]; var greenCol = [0x00, 0xff, 0x00];
var blueCol = [0x09, 0x2a, 0xff]; var blueCol = [0x09, 0x2a, 0xff];
var violetCol = [0xc9, 0x39, 0xc7]; var violetCol = [0xc9, 0x39, 0xc7];
var whiteCol = [0xff, 0xff, 0xff]; var whiteCol = [0xff, 0xff, 0xff];
var blackCol = [0x00, 0x00, 0x00]; var blackCol = [0x00, 0x00, 0x00];
var _buffer = []; var _buffer = [];
@ -269,7 +268,7 @@ function HiresPage(page)
for (var idx = 0; idx < 0x2000; idx++) for (var idx = 0; idx < 0x2000; idx++)
_buffer[idx] = 0; // Math.floor(Math.random()*256); _buffer[idx] = 0; // Math.floor(Math.random()*256);
} }
function _drawPixel(data, off, color) { function _drawPixel(data, off, color) {
var c0 = color[0], c1 = color[1], c2 = color[2]; var c0 = color[0], c1 = color[1], c2 = color[2];
@ -286,7 +285,7 @@ function HiresPage(page)
data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2 >> 1; data[off + 560 * 4 + 2] = data[off + 560 * 4 + 6] = c2 >> 1;
} }
} }
_init(); _init();
return { return {
@ -306,17 +305,17 @@ function HiresPage(page)
if (_buffer[base] === val && !_refreshing) if (_buffer[base] === val && !_refreshing)
return; return;
_buffer[base] = val; _buffer[base] = val;
var hbs = val & 0x80; var hbs = val & 0x80;
val &= 0x7f; val &= 0x7f;
var col = (base % 0x80) % 0x28, var col = (base % 0x80) % 0x28,
adj = off - col; adj = off - col;
// 000001cd eabab000 -> 000abcde // 000001cd eabab000 -> 000abcde
var ab = (adj & 0x18), var ab = (adj & 0x18),
cd = (page & 0x03) << 1, cd = (page & 0x03) << 1,
e = adj >> 7; e = adj >> 7;
var rowa = ab | cd | e, var rowa = ab | cd | e,
rowb = base >> 10; rowb = base >> 10;
@ -324,18 +323,18 @@ function HiresPage(page)
if ((rowa < 24) && (col < 40)) { if ((rowa < 24) && (col < 40)) {
if (textMode || !hiresMode || (mixedMode && rowa > 19)) if (textMode || !hiresMode || (mixedMode && rowa > 19))
return; return;
var data = pages[_page].data, var data = pages[_page].data,
dy = rowa * 8 + rowb, dy = rowa * 8 + rowb,
dx = col * 14 - 2, dx = col * 14 - 2,
b0 = col > 0 ? _buffer[base - 1] : 0, b0 = col > 0 ? _buffer[base - 1] : 0,
b2 = col < 39 ? _buffer[base + 1] : 0; b2 = col < 39 ? _buffer[base + 1] : 0;
val |= (b2 & 0x3) << 7; val |= (b2 & 0x3) << 7;
var v0 = b0 & 0x20, v1 = b0 & 0x40, v2 = val & 0x1, var v0 = b0 & 0x20, v1 = b0 & 0x40, v2 = val & 0x1,
odd = !(col & 0x1), odd = (col & 0x1) === 0,
color, color,
oddCol = (hbs ? orangeCol : greenCol), oddCol = (hbs ? orangeCol : greenCol),
evenCol = (hbs ? blueCol : violetCol); evenCol = (hbs ? blueCol : violetCol);
off = dx * 4 + dy * 560 * 4 * 2; off = dx * 4 + dy * 560 * 4 * 2;
for (var idx = 0; idx < 9; idx++, off += 8) { for (var idx = 0; idx < 9; idx++, off += 8) {
@ -434,7 +433,7 @@ function VideoModes(gr,hgr,gr2,hgr2) {
_refresh(); _refresh();
} }
}, },
mixed: function(on) { mixed: function(on) {
var old = mixedMode; var old = mixedMode;
mixedMode = on; mixedMode = on;
if (old != on) { if (old != on) {
@ -490,4 +489,3 @@ function VideoModes(gr,hgr,gr2,hgr2) {
} }
}; };
} }

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -10,8 +9,9 @@
* implied warranty. * implied warranty.
*/ */
/*jshint browser:true */ /*globals allocMemPages: false, debug: false,
/*globals allocMemPages: false, charset: false, base64_encode: false, base64_decode: false, enhanced: false */ base64_encode: false, base64_decode: false,
enhanced: false */
/*exported LoresPage, HiresPage, VideoModes */ /*exported LoresPage, HiresPage, VideoModes */
@ -22,6 +22,12 @@ var pageMode = 1;
var _80colMode = false; var _80colMode = false;
var altCharMode = false; var altCharMode = false;
var doubleHiresMode = false; var doubleHiresMode = false;
var monoDHRMode = false;
var colorDHRMode = false;
var mixedDHRMode = false;
var highColorHGRMode = false;
var highColorTextMode = false;
var pages = []; var pages = [];
var context = null; var context = null;
var scanlines = false; var scanlines = false;
@ -32,9 +38,9 @@ var scanlines = false;
* *
***************************************************************************/ ***************************************************************************/
function LoresPage(page) function LoresPage(page, charset)
{ {
"use strict"; 'use strict';
// $00-$3F inverse // $00-$3F inverse
// $40-$7F flashing // $40-$7F flashing
@ -72,7 +78,7 @@ function LoresPage(page)
function _init() { function _init() {
_buffer[0] = allocMemPages(0x4); _buffer[0] = allocMemPages(0x4);
_buffer[1] = allocMemPages(0x4); _buffer[1] = allocMemPages(0x4);
for (var idx = 0; idx < 0x400; idx++) { for (var idx = 0; idx < 0x400; idx++) {
_buffer[0][idx] = 0; // idx & 0x2 ? 0xff : 0x00; _buffer[0][idx] = 0; // idx & 0x2 ? 0xff : 0x00;
_buffer[1][idx] = 0; // idx & 0x2 ? 0xff : 0x00; _buffer[1][idx] = 0; // idx & 0x2 ? 0xff : 0x00;
@ -110,7 +116,7 @@ function LoresPage(page)
data[off + 560 * 4 + 2] = c2 >> 1; data[off + 560 * 4 + 2] = c2 >> 1;
} }
} }
_init(); _init();
return { return {
@ -176,16 +182,13 @@ function LoresPage(page)
return; return;
_buffer[bank][base] = val; _buffer[bank][base] = val;
if (bank !== 0 && !_80colMode)
return;
var col = (base % 0x80) % 0x28, var col = (base % 0x80) % 0x28,
adj = off - col; adj = off - col;
// 000001cd eabab000 -> 000abcde // 000001cd eabab000 -> 000abcde
var ab = (adj & 0x18), var ab = (adj & 0x18),
cd = (page & 0x03) << 1, cd = (page & 0x03) << 1,
e = adj >> 7; e = adj >> 7;
var idx, jdx; var idx, jdx;
var row = ab | cd | e; var row = ab | cd | e;
var b; var b;
@ -197,19 +200,20 @@ function LoresPage(page)
var color; var color;
if (textMode || (mixedMode && row > 19)) { if (textMode || (mixedMode && row > 19)) {
var flash = ((val & 0xc0) == 0x40) && var flash = ((val & 0xc0) == 0x40) &&
_blink && !_80colMode && !altCharMode; _blink && !_80colMode && !altCharMode;
fore = flash ? _black : (_greenMode ? _green : _white); fore = flash ? _black : (_greenMode ? _green : _white);
back = flash ? (_greenMode ? _green : _white) : _black; back = flash ? (_greenMode ? _green : _white) : _black;
if (!enhanced) {
val = (val >= 0x40 && val < 0x60) ? val - 0x40 : val;
} else if (!altCharMode) {
val = (val >= 0x40 && val < 0x80) ? val - 0x40 : val;
}
if (_80colMode) { if (_80colMode) {
if (!enhanced) {
val = (val >= 0x40 && val < 0x60) ? val - 0x40 : val;
} else if (!altCharMode) {
val = (val >= 0x40 && val < 0x80) ? val - 0x40 : val;
}
off = (col * 14 + (bank ? 0 : 1) * 7 + row * 560 * 8 * 2) * 4; off = (col * 14 + (bank ? 0 : 1) * 7 + row * 560 * 8 * 2) * 4;
for (jdx = 0; jdx < 8; jdx++) { for (jdx = 0; jdx < 8; jdx++) {
b = charset[val * 8 + jdx]; b = charset[val * 8 + jdx];
for (idx = 0; idx < 7; idx++) { for (idx = 0; idx < 7; idx++) {
@ -221,8 +225,21 @@ function LoresPage(page)
off += 553 * 4 + 560 * 4; off += 553 * 4 + 560 * 4;
} }
} else { } else {
val = _buffer[0][base];
if (!enhanced) {
val = (val >= 0x40 && val < 0x60) ? val - 0x40 : val;
} else if (!altCharMode) {
val = (val >= 0x40 && val < 0x80) ? val - 0x40 : val;
}
off = (col * 14 + row * 560 * 8 * 2) * 4; off = (col * 14 + row * 560 * 8 * 2) * 4;
if (highColorTextMode) {
fore = _colors[_buffer[0][base] >> 4];
back = _colors[_buffer[0][base] & 0x0f];
}
for (jdx = 0; jdx < 8; jdx++) { for (jdx = 0; jdx < 8; jdx++) {
b = charset[val * 8 + jdx]; b = charset[val * 8 + jdx];
for (idx = 0; idx < 7; idx++) { for (idx = 0; idx < 7; idx++) {
@ -253,13 +270,13 @@ function LoresPage(page)
off += 4; off += 4;
} }
off += 553 * 4 + 560 * 4; off += 553 * 4 + 560 * 4;
} }
} else { } else {
if (bank & 0x1) { if (bank & 0x1) {
val = ((val & 0x77) << 1) | ((val & 0x88) >> 3); val = ((val & 0x77) << 1) | ((val & 0x88) >> 3);
} }
for (jdx = 0; jdx < 8; jdx++) { for (jdx = 0; jdx < 8; jdx++) {
color = _colors[(jdx < 4) ? color = _colors[(jdx < 4) ?
(val & 0x0f) : (val >> 4)]; (val & 0x0f) : (val >> 4)];
for (idx = 0; idx < 7; idx++) { for (idx = 0; idx < 7; idx++) {
_drawHalfPixel(data, off, color); _drawHalfPixel(data, off, color);
@ -288,12 +305,12 @@ function LoresPage(page)
off += 4; off += 4;
} }
off += 546 * 4 + 560 * 4; off += 546 * 4 + 560 * 4;
} }
} else { } else {
for (jdx = 0; jdx < 8; jdx++) { for (jdx = 0; jdx < 8; jdx++) {
color = _colors[(jdx < 4) ? color = _colors[(jdx < 4) ?
(val & 0x0f) : (val >> 4)]; (val & 0x0f) : (val >> 4)];
for (idx = 0; idx < 7; idx++) { for (idx = 0; idx < 7; idx++) {
_drawPixel(data, off, color); _drawPixel(data, off, color);
off += 8; off += 8;
} }
@ -305,11 +322,9 @@ function LoresPage(page)
} }
}, },
refresh: function() { refresh: function() {
var page, off, addr = 0x400 * _page; var addr = 0x400 * _page;
_refreshing = true; _refreshing = true;
for (var idx = 0; idx < 0x400; idx++, addr++) { for (var idx = 0; idx < 0x400; idx++, addr++) {
page = addr >> 8;
off = addr & 0xff;
this._write(addr >> 8, addr & 0xff, _buffer[0][idx], 0); this._write(addr >> 8, addr & 0xff, _buffer[0][idx], 0);
if (_80colMode) if (_80colMode)
this._write(addr >> 8, addr & 0xff, _buffer[1][idx], 1); this._write(addr >> 8, addr & 0xff, _buffer[1][idx], 1);
@ -318,7 +333,7 @@ function LoresPage(page)
}, },
blink: function() { blink: function() {
var addr = 0x400 * _page; var addr = 0x400 * _page;
_refreshing = true; _refreshing = true;
_blink = !_blink; _blink = !_blink;
for (var idx = 0; idx < 0x400; idx++, addr++) { for (var idx = 0; idx < 0x400; idx++, addr++) {
var b = _buffer[0][idx]; var b = _buffer[0][idx];
@ -361,8 +376,8 @@ function LoresPage(page)
***************************************************************************/ ***************************************************************************/
function HiresPage(page) function HiresPage(page)
{ {
"use strict"; 'use strict';
var _page = page; var _page = page;
@ -410,14 +425,14 @@ function HiresPage(page)
var greenCol = [0x00, 0xff, 0x00]; var greenCol = [0x00, 0xff, 0x00];
var blueCol = [0x09, 0x2a, 0xff]; var blueCol = [0x09, 0x2a, 0xff];
var violetCol = [0xc9, 0x39, 0xc7]; var violetCol = [0xc9, 0x39, 0xc7];
var whiteCol = [0xff, 0xff, 0xff]; var whiteCol = [0xff, 0xff, 0xff];
var blackCol = [0x00, 0x00, 0x00]; var blackCol = [0x00, 0x00, 0x00];
var _buffer = []; var _buffer = [];
var _refreshing = false; var _refreshing = false;
var _green = [0x00, 0xff, 0x80];
var _greenMode = false; var _greenMode = false;
var _green = [0x00, 0xff, 0x80];
function _init() { function _init() {
_buffer[0] = allocMemPages(0x20); _buffer[0] = allocMemPages(0x20);
@ -430,6 +445,7 @@ function HiresPage(page)
function _drawPixel(data, off, color) { function _drawPixel(data, off, color) {
var c0 = color[0], c1 = color[1], c2 = color[2]; var c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = data[off + 4] = c0; data[off + 0] = data[off + 4] = c0;
data[off + 1] = data[off + 5] = c1; data[off + 1] = data[off + 5] = c1;
data[off + 2] = data[off + 6] = c2; data[off + 2] = data[off + 6] = c2;
@ -459,7 +475,7 @@ function HiresPage(page)
data[off + 560 * 4 + 2] = c2 >> 1; data[off + 560 * 4 + 2] = c2 >> 1;
} }
} }
_init(); _init();
return { return {
@ -510,13 +526,10 @@ function HiresPage(page)
return [c[0] * 0.75, c[1] * 0.75, c[2] * 0.75]; return [c[0] * 0.75, c[1] * 0.75, c[2] * 0.75];
} }
var addr = (page << 8) | off, base = addr - 0x2000 * _page, var addr = (page << 8) | off, base = addr - 0x2000 * _page,
idx, jdx; idx, jdx;
if (_buffer[bank][base] == val && !_refreshing) if (_buffer[bank][base] == val && !_refreshing)
return; return;
_buffer[bank][base] = val; _buffer[bank][base] = val;
if (bank !== 0 && !doubleHiresMode)
return;
var hbs = val & 0x80; var hbs = val & 0x80;
val &= 0x7f; val &= 0x7f;
@ -524,10 +537,10 @@ function HiresPage(page)
var col = (base % 0x80) % 0x28, var col = (base % 0x80) % 0x28,
adj = off - col; adj = off - col;
// 000001cd eabab000 -> 000abcde // 000001cd eabab000 -> 000abcde
var ab = (adj & 0x18), var ab = (adj & 0x18),
cd = (page & 0x03) << 1, cd = (page & 0x03) << 1,
e = adj >> 7; e = adj >> 7;
var rowa = ab | cd | e, var rowa = ab | cd | e,
rowb = base >> 10; rowb = base >> 10;
@ -536,9 +549,9 @@ function HiresPage(page)
if ((rowa < 24) && (col < 40)) { if ((rowa < 24) && (col < 40)) {
if (textMode || !hiresMode || (mixedMode && rowa > 19)) if (textMode || !hiresMode || (mixedMode && rowa > 19))
return; return;
dy = rowa * 16 + rowb * 2; dy = rowa * 16 + rowb * 2;
var bz, b0, b1, b2, b3, b4, c; var bz, b0, b1, b2, b3, b4, c, hb;
if (doubleHiresMode) { if (doubleHiresMode) {
// Every 4 bytes is 7 pixels // Every 4 bytes is 7 pixels
// 2 bytes per bank // 2 bytes per bank
@ -557,26 +570,57 @@ function HiresPage(page)
((b2 & 0x3c) >> 2), // 4 ((b2 & 0x3c) >> 2), // 4
((b2 & 0x40) >> 6) | ((b3 & 0x07) << 1), // 5 ((b2 & 0x40) >> 6) | ((b3 & 0x07) << 1), // 5
((b3 & 0x78) >> 3), // 6 ((b3 & 0x78) >> 3), // 6
0], // 7
hb = [0,
b0 & 0x80, // 0
b0 & 0x80, // 1
b1 & 0x80, // 2
b2 & 0x80, // 3
b2 & 0x80, // 4
b3 & 0x80, // 5
b3 & 0x80, // 6
0]; // 7 0]; // 7
if (col > 0) { if (col > 0) {
c[0] = (bz & 0x78) >> 3; c[0] = (bz & 0x78) >> 3;
hb[0] = bz & 0x80;
} }
if (col < 39) { if (col < 39) {
c[8] = b4 & 0x0f; c[8] = b4 & 0x0f;
hb[8] = b4 & 0x80;
} }
dx = mcol * 14; dx = mcol * 14;
off = dx * 4 + dy * 280 * 4 * 2; off = dx * 4 + dy * 280 * 4 * 2;
var monoColor = null;
if (_greenMode) {
monoColor = _green;
} else if (monoDHRMode) {
monoColor = whiteCol;
}
for (idx = 1; idx < 8; idx++) { for (idx = 1; idx < 8; idx++) {
hbs = hb[idx];
var dcolor = dcolors[r4[c[idx]]]; var dcolor = dcolors[r4[c[idx]]];
var bits = c[idx-1] | (c[idx] << 4) | (c[idx+1] << 8); var bits = c[idx-1] | (c[idx] << 4) | (c[idx+1] << 8);
for (jdx = 0; jdx < 4; jdx++, off += 4) { for (jdx = 0; jdx < 4; jdx++, off += 4) {
if (_greenMode) { if (monoColor) {
if (bits & 0x10) { if (bits & 0x10) {
_drawHalfPixel(data, off, _green); _drawHalfPixel(data, off, monoColor);
} else { } else {
_drawHalfPixel(data, off, blackCol); _drawHalfPixel(data, off, blackCol);
} }
} else if (mixedDHRMode) {
if (hbs) {
_drawHalfPixel(data, off, dcolor);
} else {
if (bits & 0x10) {
_drawHalfPixel(data, off, whiteCol);
} else {
_drawHalfPixel(data, off, blackCol);
}
}
} else if (colorDHRMode) {
_drawHalfPixel(data, off, dcolor);
} else if (((bits & 0x3c) == 0x3c) || } else if (((bits & 0x3c) == 0x3c) ||
((bits & 0xf0) == 0xf0) || ((bits & 0xf0) == 0xf0) ||
((bits & 0x1e) == 0x1e) || ((bits & 0x1e) == 0x1e) ||
@ -590,7 +634,7 @@ function HiresPage(page)
_drawHalfPixel(data, off, dcolor); _drawHalfPixel(data, off, dcolor);
} else if ((bits & 0x28) == 0x28) { } else if ((bits & 0x28) == 0x28) {
_drawHalfPixel(data, off, dcolor); _drawHalfPixel(data, off, dcolor);
} else { } else {
_drawHalfPixel(data, off, blackCol); _drawHalfPixel(data, off, blackCol);
} }
bits >>= 1; bits >>= 1;
@ -607,22 +651,25 @@ function HiresPage(page)
_refreshing = false; _refreshing = false;
} }
} else { } else {
val = _buffer[0][base] & 0x7f;
dx = col * 14 - 2; dx = col * 14 - 2;
b0 = col > 0 ? _buffer[bank][base - 1] : 0; b0 = col > 0 ? _buffer[0][base - 1] : 0;
b2 = col < 39 ? _buffer[bank][base + 1] : 0; b2 = col < 39 ? _buffer[0][base + 1] : 0;
val |= (b2 & 0x3) << 7; val |= (b2 & 0x3) << 7;
var v0 = b0 & 0x20, v1 = b0 & 0x40, v2 = val & 0x1, var v0 = b0 & 0x20, v1 = b0 & 0x40, v2 = val & 0x1,
odd = !(col & 0x1), odd = !(col & 0x1),
color, color,
oddCol = (hbs ? orangeCol : greenCol), oddCol = (hbs ? orangeCol : greenCol),
evenCol = (hbs ? blueCol : violetCol); evenCol = (hbs ? blueCol : violetCol);
off = dx * 4 + dy * 280 * 4 * 2; off = dx * 4 + dy * 280 * 4 * 2;
for (idx = 0; idx < 9; idx++, off += 8) { for (idx = 0; idx < 9; idx++, off += 8) {
val >>= 1; val >>= 1;
if (v1) { if (v1) {
if (_greenMode) { if (_greenMode) {
color = _green; color = _green;
} else if (highColorHGRMode) {
color = dcolors[_buffer[1][base] >> 4];
} else if (v0 || v2) { } else if (v0 || v2) {
color = whiteCol; color = whiteCol;
} else { } else {
@ -631,6 +678,8 @@ function HiresPage(page)
} else { } else {
if (_greenMode) { if (_greenMode) {
color = blackCol; color = blackCol;
} else if (highColorHGRMode) {
color = dcolors[_buffer[1][base] & 0x0f];
} else if (odd && v2 && v0) { } else if (odd && v2 && v0) {
color = v0 ? dim(evenCol) : evenCol; color = v0 ? dim(evenCol) : evenCol;
} else if (!odd && v0 && v2) { } else if (!odd && v0 && v2) {
@ -644,7 +693,7 @@ function HiresPage(page)
_drawPixel(data, off, color); _drawPixel(data, off, color);
} }
dx += 2; dx += 2;
v0 = v1; v0 = v1;
v1 = v2; v1 = v2;
v2 = val & 0x01; v2 = val & 0x01;
@ -694,6 +743,7 @@ function HiresPage(page)
function VideoModes(gr,hgr,gr2,hgr2) { function VideoModes(gr,hgr,gr2,hgr2) {
var _grs = [gr, gr2]; var _grs = [gr, gr2];
var _hgrs = [hgr, hgr2]; var _hgrs = [hgr, hgr2];
var _seq = '';
function _refresh() { function _refresh() {
gr.refresh(); gr.refresh();
@ -711,15 +761,28 @@ function VideoModes(gr,hgr,gr2,hgr2) {
mixedMode = false; mixedMode = false;
hiresMode = true; hiresMode = true;
pageMode = 1; pageMode = 1;
_80colMode = false; _80colMode = false;
altCharMode = false; altCharMode = false;
doubleHiresMode = false; doubleHiresMode = false;
monoDHRMode = false;
colorDHRMode = false;
mixedDHRMode = false;
highColorHGRMode = false;
highColorTextMode = false;
_refresh(); _refresh();
}, },
text: function(on) { text: function(on) {
var old = textMode; var old = textMode;
textMode = on; textMode = on;
highColorTextMode = false;
_seq = on ? 'T+' : 'T-';
// debug('_seq=', _seq);
if (old != on) { if (old != on) {
_refresh(); _refresh();
} }
@ -727,6 +790,11 @@ function VideoModes(gr,hgr,gr2,hgr2) {
_80col: function(on) { _80col: function(on) {
var old = _80colMode; var old = _80colMode;
_80colMode = on; _80colMode = on;
_seq += on ? '8+' : '8-';
_seq = _seq.substr(0, 16);
// debug('_seq=', _seq);
if (old != on) { if (old != on) {
_refresh(); _refresh();
} }
@ -741,6 +809,11 @@ function VideoModes(gr,hgr,gr2,hgr2) {
hires: function(on) { hires: function(on) {
var old = hiresMode; var old = hiresMode;
hiresMode = on; hiresMode = on;
highColorHGRMode = false;
_seq = (on ? 'H+' : 'H-');
// debug('_seq=', _seq);
if (old != on) { if (old != on) {
_refresh(); _refresh();
} }
@ -748,6 +821,41 @@ function VideoModes(gr,hgr,gr2,hgr2) {
doublehires: function(on) { doublehires: function(on) {
var old = doubleHiresMode; var old = doubleHiresMode;
doubleHiresMode = on; doubleHiresMode = on;
_seq += on ? 'D+' : 'D-';
_seq = _seq.substr(0, 16);
// debug('_seq=', _seq);
if (on) {
if (_seq == 'T+D+') {
debug('High color text mode');
highColorTextMode = true;
doubleHiresMode = false;
} else if (_seq == 'H+8-D+') {
debug('High color hgr');
highColorHGRMode = true;
doubleHiresMode = false;
} else if (_seq == 'H+8+D+D-D+D-D+') {
debug('DoubleHires color');
colorDHRMode = true;
monoDHRMode = false;
mixedDHRMode = false;
_seq = '';
} else if (_seq == 'H+8-D+D-D+D-8+D+') {
debug('DoubleHires mono');
colorDHRMode = false;
monoDHRMode = true;
mixedDHRMode = false;
_seq = '';
} else if (_seq == 'H+8-D+D-8+D+D-D+') {
debug('DoubleHires mixed');
colorDHRMode = false;
monoDHRMode = false;
mixedDHRMode = true;
_seq = '';
}
}
if (old != on) { if (old != on) {
if (on) { if (on) {
this.page(1); this.page(1);
@ -755,7 +863,7 @@ function VideoModes(gr,hgr,gr2,hgr2) {
_refresh(); _refresh();
} }
}, },
mixed: function(on) { mixed: function(on) {
var old = mixedMode; var old = mixedMode;
mixedMode = on; mixedMode = on;
if (old != on) { if (old != on) {
@ -835,5 +943,3 @@ function VideoModes(gr,hgr,gr2,hgr2) {
} }
}; };
} }

View File

@ -1,11 +1,11 @@
/*! /*!
* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com> * Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that * the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting * copyright notice and this permission notice appear in supporting
* documentation. No representations are made about the suitability of this * documentation. No representations are made about the suitability of this
* software for any purpose. It is provided "as is" without express or * software for any purpose. It is provided "as is" without express or
* implied warranty. * implied warranty.
*/ */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -10,18 +9,20 @@
* implied warranty. * implied warranty.
*/ */
/*jshint browser: true */
/*globals extend: false, bytify: false, base64_encode: false, base64_decode: false, each: false */
/*exported DiskII */ /*exported DiskII */
/*globals bytify, each: false, extend: false
base64_encode, base64_decode
Uint8Array
*/
function DiskII(io, callbacks, slot) function DiskII(io, callbacks, slot)
{ {
"use strict"; 'use strict';
slot = slot || 6; slot = slot || 6;
var _drives = [ var _drives = [
{ // Drive 1 { // Drive 1
format: "dsk", format: 'dsk',
volume: 254, volume: 254,
tracks: [], tracks: [],
track: 0, track: 0,
@ -31,7 +32,7 @@ function DiskII(io, callbacks, slot)
dirty: false dirty: false
}, },
{ // Drive 2 { // Drive 2
format: "dsk", format: 'dsk',
volume: 254, volume: 254,
tracks: [], tracks: [],
track: 0, track: 0,
@ -68,12 +69,12 @@ function DiskII(io, callbacks, slot)
DRIVEREADMODE: 0x8E, // Q7L DRIVEREADMODE: 0x8E, // Q7L
DRIVEWRITEMODE: 0x8F // Q7H DRIVEWRITEMODE: 0x8F // Q7H
}; };
// var DO = [0x0,0x7,0xE,0x6,0xD,0x5,0xC,0x4, // var DO = [0x0,0x7,0xE,0x6,0xD,0x5,0xC,0x4,
// 0xB,0x3,0xA,0x2,0x9,0x1,0x8,0xF]; // 0xB,0x3,0xA,0x2,0x9,0x1,0x8,0xF];
var _DO = [0x0,0xD,0xB,0x9,0x7,0x5,0x3,0x1, var _DO = [0x0,0xD,0xB,0x9,0x7,0x5,0x3,0x1,
0xE,0xC,0xA,0x8,0x6,0x4,0x2,0xF]; 0xE,0xC,0xA,0x8,0x6,0x4,0x2,0xF];
// var PO = [0x0,0x8,0x1,0x9,0x2,0xa,0x3,0xb, // var PO = [0x0,0x8,0x1,0x9,0x2,0xa,0x3,0xb,
// 0x4,0xc,0x5,0xd,0x6,0xe,0x7,0xf]; // 0x4,0xc,0x5,0xd,0x6,0xe,0x7,0xf];
var _PO = [0x0,0x2,0x4,0x6,0x8,0xa,0xc,0xe, var _PO = [0x0,0x2,0x4,0x6,0x8,0xa,0xc,0xe,
@ -116,9 +117,9 @@ function DiskII(io, callbacks, slot)
} }
/** /**
* From Beneath Apple DOS * From Beneath Apple DOS
*/ */
function _fourXfour(val) { function _fourXfour(val) {
var xx = val & 0xaa; var xx = val & 0xaa;
var yy = val & 0x55; var yy = val & 0x55;
@ -170,7 +171,7 @@ function DiskII(io, callbacks, slot)
/* /*
* Gap 2 (5 bytes) * Gap 2 (5 bytes)
*/ */
for (idx = 0; idx < 0x05; idx++) { for (idx = 0; idx < 0x05; idx++) {
buf.push(0xff); buf.push(0xff);
} }
@ -180,33 +181,33 @@ function DiskII(io, callbacks, slot)
*/ */
extend(buf, [0xd5, 0xaa, 0xad]); // Data Prolog D5 AA AD extend(buf, [0xd5, 0xaa, 0xad]); // Data Prolog D5 AA AD
var nibbles = []; var nibbles = [];
var ptr2 = 0; var ptr2 = 0;
var ptr6 = 0x56; var ptr6 = 0x56;
var idx2, idx6; var idx2, idx6;
for (idx = 0; idx < 0x156; idx++) { for (idx = 0; idx < 0x156; idx++) {
nibbles[idx] = 0; nibbles[idx] = 0;
} }
idx2 = 0x55; idx2 = 0x55;
for (idx6 = 0x101; idx6 >= 0; idx6--) { for (idx6 = 0x101; idx6 >= 0; idx6--) {
var val6 = data[idx6 % 0x100]; var val6 = data[idx6 % 0x100];
var val2 = nibbles[ptr2 + idx2]; var val2 = nibbles[ptr2 + idx2];
val2 = (val2 << 1) | (val6 & 1); val2 = (val2 << 1) | (val6 & 1);
val6 >>= 1; val6 >>= 1;
val2 = (val2 << 1) | (val6 & 1); val2 = (val2 << 1) | (val6 & 1);
val6 >>= 1; val6 >>= 1;
nibbles[ptr6 + idx6] = val6; nibbles[ptr6 + idx6] = val6;
nibbles[ptr2 + idx2] = val2; nibbles[ptr2 + idx2] = val2;
if (--idx2 < 0) if (--idx2 < 0)
idx2 = 0x55; idx2 = 0x55;
} }
var last = 0; var last = 0;
for (idx = 0; idx < 0x156; idx++) { for (idx = 0; idx < 0x156; idx++) {
var val = nibbles[idx]; var val = nibbles[idx];
@ -214,13 +215,13 @@ function DiskII(io, callbacks, slot)
last = val; last = val;
} }
buf.push(_trans[last]); buf.push(_trans[last]);
extend(buf, [0xde, 0xaa, 0xeb]); // Epilog DE AA EB extend(buf, [0xde, 0xaa, 0xeb]); // Epilog DE AA EB
/* /*
* Gap 3 * Gap 3
*/ */
buf.push(0xff); buf.push(0xff);
return buf; return buf;
@ -229,11 +230,11 @@ function DiskII(io, callbacks, slot)
function _json_encode(drive, pretty) { function _json_encode(drive, pretty) {
var cur = _drives[drive - 1]; var cur = _drives[drive - 1];
var data = []; var data = [];
var format = "dsk"; var format = 'dsk';
for (var t = 0; t < cur.tracks.length; t++) { for (var t = 0; t < cur.tracks.length; t++) {
data[t] = []; data[t] = [];
if (cur.format === "nib") { if (cur.format === 'nib') {
format = "nib"; format = 'nib';
data[t] = base64_encode(cur.tracks[t]); data[t] = base64_encode(cur.tracks[t]);
} else { } else {
for (var s = 0; s < 0x10; s++) { for (var s = 0; s < 0x10; s++) {
@ -241,12 +242,12 @@ function DiskII(io, callbacks, slot)
} }
} }
} }
return JSON.stringify({"type": format, return JSON.stringify({'type': format,
"encoding": "base64", 'encoding': 'base64',
"volume": cur.volume, 'volume': cur.volume,
"data": data}, 'data': data},
null, null,
pretty ? " " : null); pretty ? ' ' : null);
} }
function _json_decode(drive, data) { function _json_decode(drive, data) {
@ -261,14 +262,14 @@ function DiskII(io, callbacks, slot)
var d = base64_decode(json.data[t][_s]); var d = base64_decode(json.data[t][_s]);
extend(track, _explodeSector(v, t, _DO[_s], d)); extend(track, _explodeSector(v, t, _DO[_s], d));
} }
tracks[t] = bytify(track); tracks[t] = bytify(track);
} }
_cur.volume = v; _cur.volume = v;
_cur.format = json.type; _cur.format = json.type;
_cur.tracks = tracks; _cur.tracks = tracks;
} }
function _readNext() { function _readNext() {
var result = 0; var result = 0;
if (_skip || _writeMode) { if (_skip || _writeMode) {
var t = _cur.tracks[_cur.track >> 1]; var t = _cur.tracks[_cur.track >> 1];
@ -283,8 +284,8 @@ function DiskII(io, callbacks, slot)
++_cur.head; ++_cur.head;
} }
} }
_skip = (++_skip % 4); _skip = (++_skip % 4);
return result; return result;
} }
@ -383,9 +384,9 @@ function DiskII(io, callbacks, slot)
[-1, 0, 1, 2], [-1, 0, 1, 2],
[-2,-1, 0, 1], [-2,-1, 0, 1],
[ 1,-2,-1, 0]]; [ 1,-2,-1, 0]];
function setPhase(phase, on) { function setPhase(phase, on) {
_debug("phase " + phase + (on ? " on" : " off")); _debug('phase ' + phase + (on ? ' on' : ' off'));
if (on) { if (on) {
_cur.track += _phase_delta[_cur.phase][phase]; _cur.track += _phase_delta[_cur.phase][phase];
_cur.phase = phase; _cur.phase = phase;
@ -395,10 +396,10 @@ function DiskII(io, callbacks, slot)
if (_cur.track < 0x0) if (_cur.track < 0x0)
_cur.track = 0x0; _cur.track = 0x0;
/* _debug("Drive " + _drive + /* _debug('Drive ' + _drive +
", track " + toHex(_cur.track >> 1) + ', track ' + toHex(_cur.track >> 1) +
" (" + toHex(_cur.track) + ")" + ' (' + toHex(_cur.track) + ')' +
" [" + (_cur.track % 4) + "/" + phase + "]"); */ ' [' + (_cur.track % 4) + '/' + phase + ']'); */
} }
} }
@ -429,20 +430,20 @@ function DiskII(io, callbacks, slot)
case LOC.PHASE3ON: case LOC.PHASE3ON:
setPhase(3, true); setPhase(3, true);
break; break;
case LOC.DRIVEOFF: case LOC.DRIVEOFF:
_debug("Drive Off"); _debug('Drive Off');
_on = false; _on = false;
if (callbacks.driveLight) { callbacks.driveLight(_drive, false); } if (callbacks.driveLight) { callbacks.driveLight(_drive, false); }
break; break;
case LOC.DRIVEON: case LOC.DRIVEON:
_debug("Drive On"); _debug('Drive On');
_on = true; _on = true;
if (callbacks.driveLight) { callbacks.driveLight(_drive, true); } if (callbacks.driveLight) { callbacks.driveLight(_drive, true); }
break; break;
case LOC.DRIVE1: case LOC.DRIVE1:
_debug("Disk 1"); _debug('Disk 1');
_drive = 1; _drive = 1;
_cur = _drives[_drive - 1]; _cur = _drives[_drive - 1];
if (_on && callbacks.driveLight) { if (_on && callbacks.driveLight) {
@ -451,7 +452,7 @@ function DiskII(io, callbacks, slot)
} }
break; break;
case LOC.DRIVE2: case LOC.DRIVE2:
_debug("Disk 2"); _debug('Disk 2');
_drive = 2; _drive = 2;
_cur = _drives[_drive - 1]; _cur = _drives[_drive - 1];
if (_on && callbacks.driveLight) { if (_on && callbacks.driveLight) {
@ -459,25 +460,25 @@ function DiskII(io, callbacks, slot)
callbacks.driveLight(2, true); callbacks.driveLight(2, true);
} }
break; break;
case LOC.DRIVEREAD: case LOC.DRIVEREAD:
result = _readNext(); result = _readNext();
// _debug("read: " + toHex(result)); // _debug('read: ' + toHex(result));
break; break;
case LOC.DRIVEWRITE: case LOC.DRIVEWRITE:
// _debug("write: " + toHex(val)); // _debug('write: ' + toHex(val));
if (val !== undefined) { if (val !== undefined) {
_writeNext(val); _writeNext(val);
} }
break; break;
case LOC.DRIVEREADMODE: case LOC.DRIVEREADMODE:
_debug("Read Mode"); _debug('Read Mode');
_writeMode = false; _writeMode = false;
result = (_readNext() & 0x7f) | (_cur.readOnly ? 0x80 : 0x00); result = (_readNext() & 0x7f) | (_cur.readOnly ? 0x80 : 0x00);
break; break;
case LOC.DRIVEWRITEMODE: case LOC.DRIVEWRITEMODE:
_debug("Write Mode"); _debug('Write Mode');
_writeMode = true; _writeMode = true;
break; break;
default: default:
@ -650,10 +651,10 @@ function DiskII(io, callbacks, slot)
var fmt = disk.type, readOnly = disk.readOnly; var fmt = disk.type, readOnly = disk.readOnly;
var data, t, s; var data, t, s;
if (disk.encoding == "base64") { if (disk.encoding == 'base64') {
data = []; data = [];
for (t = 0; t < disk.data.length; t++) { for (t = 0; t < disk.data.length; t++) {
if (fmt == "nib") { if (fmt == 'nib') {
data[t] = base64_decode(disk.data[t]); data[t] = base64_decode(disk.data[t]);
} else { } else {
data[t] = []; data[t] = [];
@ -667,7 +668,7 @@ function DiskII(io, callbacks, slot)
} }
var cur = _drives[drive - 1]; var cur = _drives[drive - 1];
// var v = (fmt === "dsk" ? data[0x11][0x00][0x06] : 0xfe); // var v = (fmt === 'dsk' ? data[0x11][0x00][0x06] : 0xfe);
// if (v == 0x00) { // if (v == 0x00) {
var v = disk.volume || 0xfe; var v = disk.volume || 0xfe;
// } // }
@ -679,19 +680,19 @@ function DiskII(io, callbacks, slot)
for (t = 0; t < data.length; t++) { for (t = 0; t < data.length; t++) {
var track = []; var track = [];
if (fmt === "nib") { if (fmt === 'nib') {
track = data[t]; track = data[t];
} else { } else {
for (s = 0; s < data[t].length; s++) { for (s = 0; s < data[t].length; s++) {
var _s = 15 - s; var _s = 15 - s;
if (fmt === "po") { // ProDOS Order if (fmt === 'po') { // ProDOS Order
extend(track, extend(track,
_explodeSector(v, t, _PO[s], data[t][s])); _explodeSector(v, t, _PO[s], data[t][s]));
} else if (fmt === "dsk") { // DOS Order } else if (fmt === 'dsk') { // DOS Order
extend(track, extend(track,
_explodeSector(v, t, _DO[_s], data[t][_s])); _explodeSector(v, t, _DO[_s], data[t][_s]));
} else { // flat } else { // flat
extend(track, extend(track,
_explodeSector(v, t, s, data[t][s])); _explodeSector(v, t, s, data[t][s]));
} }
} }
@ -712,32 +713,32 @@ function DiskII(io, callbacks, slot)
var _cur = _drives[drive - 1]; var _cur = _drives[drive - 1];
var tracks = []; var tracks = [];
var v = 254; var v = 254;
if (fmt === "do") { if (fmt === 'do') {
fmt = "dsk"; fmt = 'dsk';
} }
_cur.readOnly = false; _cur.readOnly = false;
if (fmt === "2mg") { if (fmt === '2mg') {
// Standard header size is 64 bytes. Make assumptions. // Standard header size is 64 bytes. Make assumptions.
var prefix = new Uint8Array(data.slice(0, 64)); var prefix = new Uint8Array(data.slice(0, 64));
data = data.slice(64); data = data.slice(64);
// Check image format. // Check image format.
// Sure, it's really 64 bits. But only 2 are actually used. // Sure, it's really 64 bits. But only 2 are actually used.
switch (prefix[0xc]) { switch (prefix[0xc]) {
case 0: case 0:
fmt = "dsk"; fmt = 'dsk';
break; break;
case 1: case 1:
fmt = "po"; fmt = 'po';
break; break;
case 2: case 2:
fmt = "nib"; fmt = 'nib';
break; break;
default: // Something hinky, assume "dsk" default: // Something hinky, assume 'dsk'
fmt = "dsk"; fmt = 'dsk';
break; break;
} }
var flags = var flags =
prefix[0x10] | (prefix[0x11] << 8) | prefix[0x10] | (prefix[0x11] << 8) |
(prefix[0x12] << 16) | (prefix[0x13] << 24); (prefix[0x12] << 16) | (prefix[0x13] << 24);
_cur.readOnly = (flags & 0x80000000) ? true : false; _cur.readOnly = (flags & 0x80000000) ? true : false;
@ -749,20 +750,20 @@ function DiskII(io, callbacks, slot)
} }
for (var t = 0; t < 35; t++) { for (var t = 0; t < 35; t++) {
var track, off, d; var track, off, d;
if (fmt === "nib") { if (fmt === 'nib') {
off = t * 0x1a00; off = t * 0x1a00;
track = new Uint8Array(data.slice(off, off + 0x1a00)); track = new Uint8Array(data.slice(off, off + 0x1a00));
} else { } else {
track = []; track = [];
for (var s = 0; s < 16; s++) { for (var s = 0; s < 16; s++) {
var _s = 15 - s; var _s = 15 - s;
if (fmt == "po") { // ProDOS Order if (fmt == 'po') { // ProDOS Order
off = (16 * t + s) * 256; off = (16 * t + s) * 256;
d = new Uint8Array(data.slice(off, off + 256)); d = new Uint8Array(data.slice(off, off + 256));
extend(track, extend(track,
_explodeSector(v, t, _PO[s], d)); _explodeSector(v, t, _PO[s], d));
} else if (fmt == "dsk") { // DOS Order } else if (fmt == 'dsk') { // DOS Order
off = (16 * t + _s) * 256; off = (16 * t + _s) * 256;
d = new Uint8Array(data.slice(off, off + 256)); d = new Uint8Array(data.slice(off, off + 256));
extend(track, extend(track,
_explodeSector(v, t, _DO[_s], d)); _explodeSector(v, t, _DO[_s], d));
@ -786,9 +787,9 @@ function DiskII(io, callbacks, slot)
var len = (16 * cur.tracks.length * 256); var len = (16 * cur.tracks.length * 256);
var data = new Uint8Array(len); var data = new Uint8Array(len);
var idx = 0; var idx = 0;
for (var t = 0; t < cur.tracks.length; t++) { for (var t = 0; t < cur.tracks.length; t++) {
if (cur.format === "nib") { if (cur.format === 'nib') {
data[idx++] = cur.tracks[t]; data[idx++] = cur.tracks[t];
} else { } else {
for (var s = 0; s < 0x10; s++) { for (var s = 0; s < 0x10; s++) {
@ -808,7 +809,7 @@ function DiskII(io, callbacks, slot)
var data = []; var data = [];
for (var t = 0; t < cur.tracks.length; t++) { for (var t = 0; t < cur.tracks.length; t++) {
data[t] = []; data[t] = [];
if (cur.format === "nib") { if (cur.format === 'nib') {
data += base64_encode(cur.tracks[t]); data += base64_encode(cur.tracks[t]);
} else { } else {
for (var s = 0; s < 0x10; s++) { for (var s = 0; s < 0x10; s++) {

View File

@ -1,5 +1,3 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*global bytify:false */
/*exported Apple2ROM */ /*exported Apple2ROM */
function Apple2ROM() function Apple2ROM()
{ {
@ -1542,8 +1540,6 @@ function Apple2ROM()
0xf5,0x03,0xfb,0x03,0x62,0xfa,0x59,0xff 0xf5,0x03,0xfb,0x03,0x62,0xfa,0x59,0xff
]; ];
rom = bytify(rom);
return { return {
start: function() { start: function() {
return 0xd0; return 0xd0;

View File

@ -1,10 +1,10 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /*exported IntBASIC */
function IntBASIC() function IntBASIC()
{ {
var rom = [ var rom = [
0xa9,0x20,0x8d,0x26,0x03,0xad,0x57,0xc0, 0xa9,0x20,0x8d,0x26,0x03,0xad,0x57,0xc0,
0xad,0x53,0xc0,0xad,0x50,0xc0,0xa9,0x00, 0xad,0x53,0xc0,0xad,0x50,0xc0,0xa9,0x00,
0x85,0x1c,0xad,0x26,0x03,0x85,0x1b,0xa0, 0x85,0x1c,0xad,0x26,0x03,0x85,0x1b,0xa0,
0x00,0x84,0x1a,0xa5,0x1c,0x91,0x1a,0x20, 0x00,0x84,0x1a,0xa5,0x1c,0x91,0x1a,0x20,
0xa2,0xd0,0xc8,0xd0,0xf6,0xe6,0x1b,0xa5, 0xa2,0xd0,0xc8,0xd0,0xf6,0xe6,0x1b,0xa5,
@ -1551,8 +1551,7 @@ function IntBASIC()
read: function(page, off) { read: function(page, off) {
return rom[((page - 0xD0) << 8) + off]; return rom[((page - 0xD0) << 8) + off];
}, },
write: function(page, off, val) { write: function() {
} }
}; };
} }

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -10,10 +9,12 @@
* implied warranty. * implied warranty.
*/ */
/*globals RAM */
/*exported LanguageCard */ /*exported LanguageCard */
/*globals RAM: false */
function LanguageCard(io, rom) { function LanguageCard(io, rom) {
'use strict';
var _io = io; var _io = io;
var _rom = rom; var _rom = rom;
var _bank1 = null; var _bank1 = null;
@ -88,28 +89,28 @@ function LanguageCard(io, rom) {
_readbsr = true; _readbsr = true;
_writebsr = false; _writebsr = false;
_bsr2 = true; _bsr2 = true;
_debug("Bank 2 Read"); _debug('Bank 2 Read');
break; break;
case LOC.WRITEBSR2: case LOC.WRITEBSR2:
case LOC._WRITEBSR2: case LOC._WRITEBSR2:
_readbsr = false; _readbsr = false;
_writebsr = ((_last & 0xF3) == (off & 0xF3)); _writebsr = ((_last & 0xF3) == (off & 0xF3));
_bsr2 = true; _bsr2 = true;
_debug("Bank 2 Write"); _debug('Bank 2 Write');
break; break;
case LOC.OFFBSR2: case LOC.OFFBSR2:
case LOC._OFFBSR2: case LOC._OFFBSR2:
_readbsr = false; _readbsr = false;
_writebsr = false; _writebsr = false;
_bsr2 = true; _bsr2 = true;
_debug("Bank 2 Off"); _debug('Bank 2 Off');
break; break;
case LOC.READWRBSR2: case LOC.READWRBSR2:
case LOC._READWRBSR2: case LOC._READWRBSR2:
_readbsr = true; _readbsr = true;
_writebsr = ((_last & 0xF3) == (off & 0xF3)); _writebsr = ((_last & 0xF3) == (off & 0xF3));
_bsr2 = true; _bsr2 = true;
_debug("Bank 2 Read/Write"); _debug('Bank 2 Read/Write');
break; break;
case LOC.READBSR1: case LOC.READBSR1:
@ -117,37 +118,37 @@ function LanguageCard(io, rom) {
_readbsr = true; _readbsr = true;
_writebsr = false; _writebsr = false;
_bsr2 = false; _bsr2 = false;
_debug("Bank 1 Read"); _debug('Bank 1 Read');
break; break;
case LOC.WRITEBSR1: case LOC.WRITEBSR1:
case LOC._WRITEBSR1: case LOC._WRITEBSR1:
_readbsr = false; _readbsr = false;
_writebsr = ((_last & 0xF3) == (off & 0xF3)); _writebsr = ((_last & 0xF3) == (off & 0xF3));
_bsr2 = false; _bsr2 = false;
_debug("Bank 1 Write"); _debug('Bank 1 Write');
break; break;
case LOC.OFFBSR1: case LOC.OFFBSR1:
case LOC._OFFBSR1: case LOC._OFFBSR1:
_readbsr = false; _readbsr = false;
_writebsr = false; _writebsr = false;
_bsr2 = false; _bsr2 = false;
_debug("Bank 1 Off"); _debug('Bank 1 Off');
break; break;
case LOC.READWRBSR1: case LOC.READWRBSR1:
case LOC._READWRBSR1: case LOC._READWRBSR1:
_readbsr = true; _readbsr = true;
_writebsr = ((_last & 0xF3) == (off & 0xF3)); _writebsr = ((_last & 0xF3) == (off & 0xF3));
_bsr2 = false; _bsr2 = false;
_debug("Bank 1 Read/Write"); _debug('Bank 1 Read/Write');
break; break;
case LOC.BSRBANK2: case LOC.BSRBANK2:
result = _bsr2 ? 0x80 : 0x00; result = _bsr2 ? 0x80 : 0x00;
_debug("Bank 2 Read " + _bsr2); _debug('Bank 2 Read ' + _bsr2);
break; break;
case LOC.BSRREADRAM: case LOC.BSRREADRAM:
result = _readbsr ? 0x80 : 0x00; result = _readbsr ? 0x80 : 0x00;
_debug("Bank SW RAM Read " + _readbsr); _debug('Bank SW RAM Read ' + _readbsr);
break; break;
default: default:
break; break;

876
js/main2.js Normal file
View File

@ -0,0 +1,876 @@
/* globals debug: false, gup: false, hup: false
CPU6502: false,
RAM: false,
Apple2ROM: false
apple2_charset: false,
Apple2IO: false
LoresPage: false, HiresPage: false, VideoModes: false
KeyBoard: false,
Parallel: false,
DiskII: false,
RAMFactor: false,
Printer: false,
LanguageCard: false,
Thunderclock: false,
Prefs: false,
disk_index: false,
initAudio: false, enableSound: false,
initGamepad: false, processGamepad: false, gamepad: false,
ApplesoftDump: false
*/
/* exported openLoad, openSave, doDelete,
selectCategory, selectDisk, clickDisk, loadJSON,
updateJoystick,
pauseRun, step
dumpProgram, PageDebug
*/
var kHz = 1023;
var focused = false;
var startTime = Date.now();
var lastCycles = 0;
var renderedFrames = 0, lastFrames = 0;
var paused = false;
var hashtag;
var disk_categories = {'Local Saves': []};
var disk_sets = {};
var disk_cur_name = [];
var disk_cur_cat = [];
function DriveLights()
{
return {
driveLight: function(drive, on) {
$('#disk' + drive).css('background-image',
on ? 'url(css/red-on-16.png)' :
'url(css/red-off-16.png)');
},
dirty: function(drive, dirty) {
$('#disksave' + drive).button('option', 'disabled', !dirty);
},
label: function(drive, label) {
if (label) {
$('#disklabel' + drive).text(label);
}
return $('#disklabel' + drive).text();
},
getState: function() {
return {
disks: [
this.label(1),
this.label(2)
]
};
},
setState: function(state) {
if (state && state.disks) {
this.label(1, state.disks[0].label);
this.label(2, state.disks[1].label);
}
}
};
}
var DISK_TYPES = ['dsk','do','po','raw','nib','2mg'];
var TAPE_TYPES = ['wav','aiff','aif','mp3'];
var _saveDrive = 1;
var _loadDrive = 1;
function openLoad(drive, event)
{
_loadDrive = drive;
if (event.metaKey) {
openLoadHTTP(drive);
} else {
if (disk_cur_cat[drive]) {
$('#category_select').val(disk_cur_cat[drive]).change();
}
$('#load').dialog('open');
}
}
function openSave(drive, event)
{
_saveDrive = drive;
if (event.metaKey) {
dumpDisk(drive);
} else if (event.altKey) {
openSaveLocal(drive);
} else {
$('#save_name').val(drivelights.label(drive));
$('#save').dialog('open');
}
}
var loading = false;
function loadAjax(url) {
loading = true;
$('#loading').dialog('open');
$.ajax({ url: url,
cache: false,
dataType: 'jsonp',
jsonp: false,
global: false
});
}
function doLoad() {
var urls = $('#disk_select').val(), url;
if (urls && urls.length) {
if (typeof(urls) == 'string') {
url = urls;
} else {
url = urls[0];
}
}
var files = $('#local_file').prop('files');
if (files.length == 1) {
doLoadLocal();
} else if (url) {
var filename;
$('#load').dialog('close');
if (url.substr(0,6) == 'local:') {
filename = url.substr(6);
if (filename == '__manage') {
openManage();
} else {
loadLocalStorage(_loadDrive, filename);
}
} else {
var r1 = /json\/disks\/(.*).json$/.exec(url);
if (r1 && _loadDrive == 1) {
filename = r1[1];
document.location.hash = filename;
}
loadAjax(url);
}
}
}
function doSave() {
var name = $('#save_name').val();
saveLocalStorage(_saveDrive, name);
$('#save').dialog('close');
}
function doDelete(name) {
if (window.confirm('Delete ' + name + '?')) {
deleteLocalStorage(name);
}
}
function doLoadLocal() {
var files = $('#local_file').prop('files');
if (files.length == 1) {
var file = files[0];
var parts = file.name.split('.');
var ext = parts[parts.length - 1].toLowerCase();
if ($.inArray(ext, DISK_TYPES) >= 0) {
doLoadLocalDisk(file);
} else if ($.inArray(ext, TAPE_TYPES) >= 0) {
doLoadLocalTape(file);
} else {
window.alert('Unknown file type: ' + ext);
$('#load').dialog('close');
}
}
}
function doLoadLocalDisk(file) {
var fileReader = new FileReader();
fileReader.onload = function() {
var parts = file.name.split('.');
var name = parts[0], ext = parts[parts.length - 1].toLowerCase();
if (disk2.setBinary(_saveDrive, name, ext, this.result)) {
drivelights.label(_saveDrive, name);
$('#load').dialog('close');
initGamepad();
}
};
fileReader.readAsArrayBuffer(file);
}
function doLoadLocalTape(file) {
// Audio Buffer Source
var context;
if (typeof window.AudioContext != 'undefined') {
context = new window.AudioContext();
} else {
window.alert('Not supported by your browser');
$('#load').dialog('close');
return;
}
var fileReader = new FileReader();
fileReader.onload = function(ev) {
context.decodeAudioData(ev.target.result, function(buffer) {
var buf = [];
var data = buffer.getChannelData(0), datum = data[0];
var old = (datum > 0.0), current;
var last = 0, delta, ival;
debug('Sample Count: ' + data.length);
debug('Sample rate: ' + buffer.sampleRate);
for (var idx = 1; idx < data.length; idx++) {
datum = data[idx];
if ((datum > 0.1) || (datum < -0.1)) {
current = (datum > 0.0);
if (current != old) {
delta = idx - last;
if (delta > 2000000) {
delta = 2000000;
}
ival = delta / buffer.sampleRate * 1000;
if (ival >= 0.550 && ival < 0.750) {
ival = 0.650; // Header
} else if (ival >= 0.175 && ival < 0.225) {
ival = 0.200; // sync 1
} else if (ival >= 0.225 && ival < 0.275) {
ival = 0.250; // 0 / sync 2
} else if (ival >= 0.450 && ival < 0.550) {
ival = 0.500; // 1
} else {
// debug(idx + ' ' + buf.length + ' ' + ival);
}
buf.push(parseInt(ival * kHz));
old = current;
last = idx;
}
}
}
io.setTape(buf);
$('#load').dialog('close');
});
};
fileReader.readAsArrayBuffer(file);
}
function doLoadHTTP(_url) {
var url = _url || $('#http_url').val();
if (url) {
var req = new XMLHttpRequest();
req.open('GET', url, true);
req.responseType = 'arraybuffer';
req.onload = function() {
var parts = url.split(/[\/\.]/);
var name = decodeURIComponent(parts[parts.length - 2]);
var ext = parts[parts.length - 1].toLowerCase();
if (disk2.setBinary(_saveDrive, name, ext, req.response)) {
drivelights.label(_saveDrive, name);
$('#http_load').dialog('close');
initGamepad();
}
};
req.send(null);
}
}
function openLoadHTTP(drive) {
_saveDrive = drive;
$('#http_load').dialog('open');
}
function openSaveLocal(drive) {
_saveDrive = drive;
var mimetype = 'application/octet-stream';
var data = disk2.getBinary(drive);
var a = $('#local_save_link');
var blob = new Blob([data], { 'type': mimetype });
a.attr('href', window.URL.createObjectURL(blob));
a.attr('download', drivelights.label(drive) + '.dsk');
$('#local_save').dialog('open');
}
function openManage() {
$('#manage').dialog('open');
}
var prefs = new Prefs();
var runTimer = null;
var cpu = new CPU6502();
var ram1 = new RAM(0x00, 0x03),
ram2 = new RAM(0x0C, 0x1F),
ram3 = new RAM(0x60, 0xBF);
var hgr = new HiresPage(1);
var hgr2 = new HiresPage(2);
var gr = new LoresPage(1, apple2_charset);
var gr2 = new LoresPage(2, apple2_charset);
var rom = new Apple2ROM();
var dumper = new ApplesoftDump(ram2);
var vm = new VideoModes(gr, hgr, gr2, hgr2);
var mmu = {
auxRom: function(slot, rom) {
cpu.addPageHandler(rom);
}
};
var drivelights = new DriveLights();
var io = new Apple2IO(cpu, vm);
var keyboard = new KeyBoard(io);
var parallel = new Parallel(io, new Printer(), 1);
var disk2 = new DiskII(io, drivelights, 6);
var slinky = new RAMFactor(mmu, io, 2, 1024 * 1024);
var clock = new Thunderclock(mmu, io, 7);
var lc = new LanguageCard(io, rom);
cpu.addPageHandler(ram1);
cpu.addPageHandler(gr);
cpu.addPageHandler(gr2);
cpu.addPageHandler(ram2);
cpu.addPageHandler(hgr);
cpu.addPageHandler(hgr2);
cpu.addPageHandler(ram3);
cpu.addPageHandler(lc);
cpu.addPageHandler(io);
cpu.addPageHandler(parallel);
cpu.addPageHandler(slinky);
cpu.addPageHandler(disk2);
cpu.addPageHandler(clock);
var showFPS = false;
function updateKHz() {
var now = Date.now();
var ms = now - startTime;
var cycles = cpu.cycles();
var delta;
if (showFPS) {
delta = renderedFrames - lastFrames;
var fps = parseInt(delta/(ms/1000), 10);
$('#khz').text( fps + 'fps');
} else {
delta = cycles - lastCycles;
var khz = parseInt(delta/ms);
$('#khz').text( khz + 'KHz');
}
startTime = now;
lastCycles = cycles;
lastFrames = renderedFrames;
}
/* Audio Handling */
initAudio(io);
function updateSound() {
enableSound($('#enable_sound').attr('checked'));
}
function dumpDisk(drive) {
var wind = window.open('', '_blank');
wind.document.title = drivelights.label(drive);
wind.document.write('<pre>');
wind.document.write(disk2.getJSON(drive, true));
wind.document.write('</pre>');
wind.document.close();
}
function dumpProgram() {
var wind = window.open('', '_blank');
wind.document.title = 'Program Listing';
wind.document.write('<pre>');
wind.document.write(dumper.toString());
wind.document.write('</pre>');
wind.document.close();
}
function step()
{
if (runTimer) {
clearInterval(runTimer);
}
runTimer = null;
cpu.step(function() {
debug(cpu.dumpRegisters());
debug(cpu.dumpPC());
});
}
var accelerated = false;
function updateSpeed()
{
accelerated = $('#accelerator_toggle').prop('checked');
kHz = accelerated ? 4092 : 1023;
io.updateHz(kHz * 1000);
if (runTimer) {
run();
}
}
var _requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
function run(pc) {
if (runTimer) {
clearInterval(runTimer);
}
if (pc) {
cpu.setPC(pc);
}
var ival = 30;
var now, last = Date.now();
var runFn = function() {
now = Date.now();
renderedFrames++;
var step = (now - last) * kHz, stepMax = kHz * ival;
last = now;
if (step > stepMax) {
step = stepMax;
}
if (document.location.hash != hashtag) {
hashtag = document.location.hash;
var hash = hup();
if (hash) {
processHash(hash);
}
}
if (!loading) {
cpu.stepCycles(step);
vm.blit();
io.sampleTick();
}
processGamepad(io);
if (!paused && _requestAnimationFrame) {
_requestAnimationFrame(runFn);
}
};
if (_requestAnimationFrame) {
_requestAnimationFrame(runFn);
} else {
runTimer = setInterval(runFn, ival);
}
}
function stop() {
if (runTimer) {
clearInterval(runTimer);
}
runTimer = null;
}
function reset()
{
cpu.reset();
}
function loadBinary(bin) {
stop();
for (var idx = 0; idx < bin.length; idx++) {
var pos = bin.start + idx;
cpu.write(pos >> 8, pos & 0xff, bin.data[idx]);
}
run(bin.start);
}
function selectCategory() {
$('#disk_select').empty();
var cat = disk_categories[$('#category_select').val()];
if (cat) {
for (var idx = 0; idx < cat.length; idx++) {
var file = cat[idx], name = file.name;
if (file.disk) {
name += ' - ' + file.disk;
}
var option = $('<option />').val(file.filename).text(name)
.appendTo('#disk_select');
if (disk_cur_name[_loadDrive] == name) {
option.attr('selected', 'selected');
}
}
}
}
function selectDisk() {
$('#local_file').val('');
}
function clickDisk() {
doLoad();
}
function loadDisk(disk) {
var name = disk.name;
var category = disk.category;
if (disk.disk) {
name += ' - ' + disk.disk;
}
disk_cur_cat[_loadDrive] = category;
disk_cur_name[_loadDrive] = name;
drivelights.label(_loadDrive, name);
disk2.setDisk(_loadDrive, disk);
initGamepad(disk.gamepad);
}
function loadJSON(data) {
if (data.type == 'binary') {
loadBinary(data);
} else if ($.inArray(data.type, DISK_TYPES) >= 0) {
loadDisk(data);
}
initGamepad(data.gamepad);
$('#loading').dialog('close');
loading = false;
}
/*
* LocalStorage Disk Storage
*/
function updateLocalStorage() {
var diskIndex = JSON.parse(window.localStorage.diskIndex || '{}');
var names = [], name, cat;
for (name in diskIndex) {
if (diskIndex.hasOwnProperty(name)) {
names.push(name);
}
}
cat = disk_categories['Local Saves'] = [];
$('#manage').empty();
names.forEach(function(name) {
cat.push({'category': 'Local Saves',
'name': name,
'filename': 'local:' + name});
$('#manage').append('<span class="local_save">' +
name +
' <a href="#" onclick="doDelete(\'' +
name +
'\')">Delete</a><br /></span>');
});
cat.push({'category': 'Local Saves',
'name': 'Manage Saves...',
'filename': 'local:__manage'});
}
function saveLocalStorage(drive, name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || '{}');
var json = disk2.getJSON(drive);
diskIndex[name] = json;
window.localStorage.diskIndex = JSON.stringify(diskIndex);
window.alert('Saved');
drivelights.label(drive, name);
drivelights.dirty(drive, false);
updateLocalStorage();
}
function deleteLocalStorage(name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || '{}');
if (diskIndex[name]) {
delete diskIndex[name];
window.alert('Deleted');
}
window.localStorage.diskIndex = JSON.stringify(diskIndex);
updateLocalStorage();
}
function loadLocalStorage(drive, name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || '{}');
if (diskIndex[name]) {
disk2.setJSON(drive, diskIndex[name]);
drivelights.label(drive, name);
drivelights.dirty(drive, false);
}
}
function processHash(hash) {
if (hash.indexOf('://') > 0) {
var parts = hash.split('.');
var ext = parts[parts.length - 1].toLowerCase();
if (ext == 'json') {
loadAjax(hash);
} else {
doLoadHTTP(hash);
}
} else {
loadAjax('json/disks/' + hash + '.json');
}
}
/*
* Keyboard/Gamepad routines
*/
function _keydown(evt) {
if (evt.keyCode === 112) { // F1 - Reset
cpu.reset();
} else if (evt.keyCode === 113) { // F2 - Full Screen
var elem = document.getElementById('screen');
if (document.webkitCancelFullScreen) {
if (document.webkitIsFullScreen) {
document.webkitCancelFullScreen();
} else {
if (Element.ALLOW_KEYBOARD_INPUT) {
elem.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
} else {
elem.webkitRequestFullScreen();
}
}
} else if (document.mozCancelFullScreen) {
if (document.mozIsFullScreen) {
document.mozCancelFullScreen();
} else {
elem.mozRequestFullScreen();
}
}
} else if (evt.keyCode == 16) { // Shift
keyboard.shiftKey(true);
io.buttonDown(2);
} else if (evt.keyCode == 17) { // Control
keyboard.controlKey(true);
} else if (!focused && (!evt.metaKey || evt.ctrlKey)) {
evt.preventDefault();
var key = keyboard.mapKeyEvent(evt);
if (key != 0xff) {
io.keyDown(key);
}
}
}
function _keyup(evt) {
if (evt.keyCode == 16) { // Shift
keyboard.shiftKey(false);
io.buttonUp(2);
} else if (evt.keyCode == 17) { // Control
keyboard.controlKey(false);
} else {
if (!focused) {
io.keyUp();
}
}
}
function updateScreen() {
var green = $('#green_screen').prop('checked');
vm.green(green);
}
var disableMouseJoystick = false;
var flipX = false;
var flipY = false;
var swapXY = false;
function updateJoystick() {
disableMouseJoystick = $('#disable_mouse').prop('checked');
flipX = $('#flip_x').prop('checked');
flipY = $('#flip_y').prop('checked');
swapXY = $('#swap_x_y').prop('checked');
if (disableMouseJoystick) {
io.paddle(0, 0.5);
io.paddle(1, 0.5);
return;
}
}
function _mousemove(evt) {
if (gamepad || disableMouseJoystick) {
return;
}
var s = $('#screen');
var offset = s.offset();
var x = (evt.pageX - offset.left) / s.width(),
y = (evt.pageY - offset.top) / s.height(),
z = x;
if (swapXY) {
x = y;
y = z;
}
io.paddle(0, flipX ? 1 - x : x);
io.paddle(1, flipY ? 1 - y : y);
}
function pauseRun(b) {
if (paused) {
run();
b.value = 'Pause';
} else {
stop();
b.value = 'Run';
}
paused = !paused;
}
$(function() {
hashtag = document.location.hash;
$('button,input[type=button],a.button').button().focus(function() {
// Crazy hack required by Chrome
var self = this;
window.setTimeout(function() {
self.blur();
}, 1);
});
var canvas = document.getElementById('screen');
var context = canvas.getContext('2d');
vm.setContext(context);
/*
* Input Handling
*/
$(window).keydown(_keydown);
$(window).keyup(_keyup);
$('canvas').mousedown(function(evt) {
if (!gamepad) {
io.buttonDown(evt.which == 1 ? 0 : 1);
}
evt.preventDefault();
})
.mouseup(function(evt) {
if (!gamepad) {
io.buttonUp(evt.which == 1 ? 0 : 1);
}
})
.bind('contextmenu', function(evt) { evt.preventDefault(); });
$('body').mousemove(_mousemove);
$('input,textarea').focus(function() { focused = true; })
.blur(function() { focused = false; });
keyboard.create($('#keyboard'));
if (prefs.havePrefs()) {
$('input[type=checkbox]').each(function() {
var val = prefs.readPref(this.id);
if (val)
this.checked = JSON.parse(val);
}).change(function() {
prefs.writePref(this.id, JSON.stringify(this.checked));
});
}
reset();
run();
setInterval(updateKHz, 1000);
updateSound();
updateScreen();
updateSpeed();
var cancel = function() { $(this).dialog('close'); };
$('#loading').dialog({ autoOpen: false, modal: true });
$('#options').dialog({ autoOpen: false,
modal: true,
width: 320,
height: 400,
buttons: {'Close': cancel }});
$('#load').dialog({ autoOpen: false,
modal: true,
width: 540,
buttons: {'Cancel': cancel, 'Load': doLoad }});
$('#save').dialog({ autoOpen: false,
modal: true,
width: 320,
buttons: {'Cancel': cancel, 'Save': doSave }});
$('#manage').dialog({ autoOpen: false,
modal: true,
width: 320,
buttons: {'Close': cancel }});
$('#local_save').dialog({ autoOpen: false,
modal: true,
width: 530,
buttons: {'OK': cancel }});
$('#http_load').dialog({ autoOpen: false,
modal: true,
width: 530,
buttons: {'Cancel': cancel, 'OK': doLoadHTTP }});
if (window.localStorage !== undefined) {
$('.disksave').show();
}
var oldcat = '';
for (var idx = 0; idx < disk_index.length; idx++) {
var file = disk_index[idx];
var cat = file.category;
var name = file.name, disk = file.disk;
if (file.e) {
continue;
}
if (cat != oldcat) {
$('<option />').val(cat).text(cat).appendTo('#category_select');
disk_categories[cat] = [];
oldcat = cat;
}
disk_categories[cat].push(file);
if (disk) {
if (!disk_sets[name]) {
disk_sets[name] = [];
}
disk_sets[name].push(file);
}
}
$('<option/>').text('Local Saves').appendTo('#category_select');
updateLocalStorage();
initGamepad();
// Check for disks in hashtag
var hash = gup('disk') || hup();
if (hash) {
processHash(hash);
}
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
$('select').removeAttr('multiple').css('height', 'auto');
}
if (navigator.standalone) {
$('body').addClass('standalone');
}
$('.key-REPT').click(function() {
$('#keyboard').hide();
$('#textarea').show();
$('#text_input').focus();
});
$('#text_input').keydown(function() {
focused = $('#buffering').prop('checked');
}).keyup(function() {
focused = $('#buffering').prop('checked');
});
});

877
js/main2e.js Normal file
View File

@ -0,0 +1,877 @@
/* globals debug: false, gup: false, hup: false,
CPU6502: false,
Apple2eROM: false, Apple2eEnhancedROM: false,
apple2e_charset: false,
Apple2IO: false
LoresPage: false, HiresPage: false, VideoModes: false
KeyBoard: false,
Parallel: false,
DiskII: false,
RAMFactor: false,
Printer: false,
MMU: false,
Slot3: false,
Thunderclock: false,
Prefs: false,
disk_index: false,
initAudio: false, enableSound: false,
initGamepad: false, processGamepad: false, gamepad: false,
ApplesoftDump: false
*/
/* exported openLoad, openSave, doDelete,
selectCategory, selectDisk, clickDisk, loadJSON,
updateJoystick,
pauseRun, step,
restoreState, saveState,
dumpProgram, PageDebug
*/
var kHz = 1023;
var focused = false;
var startTime = Date.now();
var lastCycles = 0;
var renderedFrames = 0, lastFrames = 0;
var paused = false;
var hashtag;
var disk_categories = {'Local Saves': []};
var disk_sets = {};
var disk_cur_name = [];
var disk_cur_cat = [];
function DriveLights()
{
return {
driveLight: function(drive, on) {
$('#disk' + drive).css('background-image',
on ? 'url(css/red-on-16.png)' :
'url(css/red-off-16.png)');
},
dirty: function(drive, dirty) {
$('#disksave' + drive).button('option', 'disabled', !dirty);
},
label: function(drive, label) {
if (label) {
$('#disklabel' + drive).text(label);
}
return $('#disklabel' + drive).text();
},
getState: function() {
return {
disks: [
this.label(1),
this.label(2)
]
};
},
setState: function(state) {
if (state && state.disks) {
this.label(1, state.disks[0].label);
this.label(2, state.disks[1].label);
}
}
};
}
var DISK_TYPES = ['dsk','do','po','raw','nib','2mg'];
var TAPE_TYPES = ['wav','aiff','aif','mp3'];
var _saveDrive = 1;
var _loadDrive = 1;
function openLoad(drive, event)
{
_loadDrive = drive;
if (event.metaKey) {
openLoadHTTP(drive);
} else {
if (disk_cur_cat[drive]) {
$('#category_select').val(disk_cur_cat[drive]).change();
}
$('#load').dialog('open');
}
}
function openSave(drive, event)
{
_saveDrive = drive;
if (event.metaKey) {
dumpDisk(drive);
} else if (event.altKey) {
openSaveLocal(drive);
} else {
$('#save_name').val(drivelights.label(drive));
$('#save').dialog('open');
}
}
var loading = false;
function loadAjax(url) {
loading = true;
$('#loading').dialog('open');
$.ajax({ url: url,
cache: false,
dataType: 'jsonp',
jsonp: false,
global: false
});
}
function doLoad() {
var urls = $('#disk_select').val(), url;
if (urls && urls.length) {
if (typeof(urls) == 'string') {
url = urls;
} else {
url = urls[0];
}
}
var files = $('#local_file').prop('files');
if (files.length == 1) {
doLoadLocal();
} else if (url) {
var filename;
$('#load').dialog('close');
if (url.substr(0,6) == 'local:') {
filename = url.substr(6);
if (filename == '__manage') {
openManage();
} else {
loadLocalStorage(_loadDrive, filename);
}
} else {
var r1 = /json\/disks\/(.*).json$/.exec(url);
if (r1 && _loadDrive == 1) {
filename = r1[1];
document.location.hash = filename;
}
loadAjax(url);
}
}
}
function doSave() {
var name = $('#save_name').val();
saveLocalStorage(_saveDrive, name);
$('#save').dialog('close');
}
function doDelete(name) {
if (window.confirm('Delete ' + name + '?')) {
deleteLocalStorage(name);
}
}
function doLoadLocal() {
var files = $('#local_file').prop('files');
if (files.length == 1) {
var file = files[0];
var parts = file.name.split('.');
var ext = parts[parts.length - 1].toLowerCase();
if ($.inArray(ext, DISK_TYPES) >= 0) {
doLoadLocalDisk(file);
} else if ($.inArray(ext, TAPE_TYPES) >= 0) {
doLoadLocalTape(file);
} else {
window.alert('Unknown file type: ' + ext);
$('#load').dialog('close');
}
}
}
function doLoadLocalDisk(file) {
var fileReader = new FileReader();
fileReader.onload = function() {
var parts = file.name.split('.');
var name = parts[0], ext = parts[parts.length - 1].toLowerCase();
if (disk2.setBinary(_saveDrive, name, ext, this.result)) {
drivelights.label(_saveDrive, name);
$('#load').dialog('close');
initGamepad();
}
};
fileReader.readAsArrayBuffer(file);
}
function doLoadLocalTape(file) {
// Audio Buffer Source
var context;
if (typeof window.AudioContext != 'undefined') {
context = new window.AudioContext();
} else {
window.alert('Not supported by your browser');
$('#load').dialog('close');
return;
}
var fileReader = new FileReader();
fileReader.onload = function(ev) {
context.decodeAudioData(ev.target.result, function(buffer) {
var buf = [];
var data = buffer.getChannelData(0), datum = data[0];
var old = (datum > 0.0), current;
var last = 0, delta, ival;
debug('Sample Count: ' + data.length);
debug('Sample rate: ' + buffer.sampleRate);
for (var idx = 1; idx < data.length; idx++) {
datum = data[idx];
if ((datum > 0.1) || (datum < -0.1)) {
current = (datum > 0.0);
if (current != old) {
delta = idx - last;
if (delta > 2000000) {
delta = 2000000;
}
ival = delta / buffer.sampleRate * 1000;
if (ival >= 0.550 && ival < 0.750) {
ival = 0.650; // Header
} else if (ival >= 0.175 && ival < 0.225) {
ival = 0.200; // sync 1
} else if (ival >= 0.225 && ival < 0.275) {
ival = 0.250; // 0 / sync 2
} else if (ival >= 0.450 && ival < 0.550) {
ival = 0.500; // 1
} else {
// debug(idx + ' ' + buf.length + ' ' + ival);
}
buf.push(parseInt(ival * kHz));
old = current;
last = idx;
}
}
}
io.setTape(buf);
$('#load').dialog('close');
});
};
fileReader.readAsArrayBuffer(file);
}
function doLoadHTTP(_url) {
var url = _url || $('#http_url').val();
if (url) {
var req = new XMLHttpRequest();
req.open('GET', url, true);
req.responseType = 'arraybuffer';
req.onload = function() {
var parts = url.split(/[\/\.]/);
var name = decodeURIComponent(parts[parts.length - 2]);
var ext = parts[parts.length - 1].toLowerCase();
if (disk2.setBinary(_saveDrive, name, ext, req.response)) {
drivelights.label(_saveDrive, name);
$('#http_load').dialog('close');
initGamepad();
}
};
req.send(null);
}
}
function openLoadHTTP(drive) {
_saveDrive = drive;
$('#http_load').dialog('open');
}
function openSaveLocal(drive) {
_saveDrive = drive;
var mimetype = 'application/octet-stream';
var data = disk2.getBinary(drive);
var a = $('#local_save_link');
var blob = new Blob([data], { 'type': mimetype });
a.attr('href', window.URL.createObjectURL(blob));
a.attr('download', drivelights.label(drive) + '.dsk');
$('#local_save').dialog('open');
}
function openManage() {
$('#manage').dialog('open');
}
var prefs = new Prefs();
var enhanced = true;
var runTimer = null;
var cpu = new CPU6502({'65C02': enhanced});
var hgr = new HiresPage(1);
var hgr2 = new HiresPage(2);
var gr = new LoresPage(1, apple2e_charset);
var gr2 = new LoresPage(2, apple2e_charset);
var rom;
if (enhanced) {
rom = new Apple2eEnhancedROM();
} else {
rom = new Apple2eROM();
}
var vm = new VideoModes(gr, hgr, gr2, hgr2);
var drivelights = new DriveLights();
var io = new Apple2IO(cpu, vm);
var keyboard = new KeyBoard(io);
var mmu = new MMU(cpu, gr, gr2, hgr, hgr2, io, rom);
var dumper = new ApplesoftDump(mmu);
var parallel = new Parallel(io, new Printer(), 1);
var disk2 = new DiskII(io, drivelights, 6);
var slot3 = new Slot3(mmu, rom);
var slinky = new RAMFactor(mmu, io, 2, 1024 * 1024);
var clock = new Thunderclock(mmu, io, 7);
mmu.addSlot(1, parallel);
mmu.addSlot(2, slinky);
mmu.addSlot(3, slot3);
mmu.addSlot(6, disk2);
mmu.addSlot(7, clock);
cpu.addPageHandler(mmu);
var showFPS = false;
function updateKHz() {
var now = Date.now();
var ms = now - startTime;
var cycles = cpu.cycles();
var delta;
if (showFPS) {
delta = renderedFrames - lastFrames;
var fps = parseInt(delta/(ms/1000), 10);
$('#khz').text( fps + 'fps');
} else {
delta = cycles - lastCycles;
var khz = parseInt(delta/ms);
$('#khz').text( khz + 'KHz');
}
startTime = now;
lastCycles = cycles;
lastFrames = renderedFrames;
}
/* Audio Handling */
initAudio(io);
function updateSound() {
enableSound($('#enable_sound').attr('checked'));
}
function dumpDisk(drive) {
var wind = window.open('', '_blank');
wind.document.title = drivelights.label(drive);
wind.document.write('<pre>');
wind.document.write(disk2.getJSON(drive, true));
wind.document.write('</pre>');
wind.document.close();
}
function dumpProgram() {
var wind = window.open('', '_blank');
wind.document.title = 'Program Listing';
wind.document.write('<pre>');
wind.document.write(dumper.toString());
wind.document.write('</pre>');
wind.document.close();
}
function step()
{
if (runTimer) {
clearInterval(runTimer);
}
runTimer = null;
cpu.step(function() {
debug(cpu.dumpRegisters());
debug(cpu.dumpPC());
});
}
var accelerated = false;
function updateSpeed()
{
accelerated = $('#accelerator_toggle').prop('checked');
kHz = accelerated ? 4092 : 1023;
io.updateHz(kHz * 1000);
if (runTimer) {
run();
}
}
var _requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
function run(pc) {
if (runTimer) {
clearInterval(runTimer);
}
if (pc) {
cpu.setPC(pc);
}
var ival = 30;
var now, last = Date.now();
var runFn = function() {
now = Date.now();
renderedFrames++;
var step = (now - last) * kHz, stepMax = kHz * ival;
last = now;
if (step > stepMax) {
step = stepMax;
}
if (document.location.hash != hashtag) {
hashtag = document.location.hash;
var hash = hup();
if (hash) {
processHash(hash);
}
}
if (!loading) {
mmu.resetVB();
cpu.stepCycles(step);
vm.blit();
io.sampleTick();
}
processGamepad(io);
if (!paused && _requestAnimationFrame) {
_requestAnimationFrame(runFn);
}
};
if (_requestAnimationFrame) {
_requestAnimationFrame(runFn);
} else {
runTimer = setInterval(runFn, ival);
}
}
function stop() {
if (runTimer) {
clearInterval(runTimer);
}
runTimer = null;
}
function reset()
{
cpu.reset();
}
function loadBinary(bin) {
stop();
for (var idx = 0; idx < bin.length; idx++) {
var pos = bin.start + idx;
cpu.write(pos >> 8, pos & 0xff, bin.data[idx]);
}
run(bin.start);
}
function selectCategory() {
$('#disk_select').empty();
var cat = disk_categories[$('#category_select').val()];
if (cat) {
for (var idx = 0; idx < cat.length; idx++) {
var file = cat[idx], name = file.name;
if (file.disk) {
name += ' - ' + file.disk;
}
var option = $('<option />').val(file.filename).text(name)
.appendTo('#disk_select');
if (disk_cur_name[_loadDrive] == name) {
option.attr('selected', 'selected');
}
}
}
}
function selectDisk() {
$('#local_file').val('');
}
function clickDisk() {
doLoad();
}
function loadDisk(disk) {
var name = disk.name;
var category = disk.category;
if (disk.disk) {
name += ' - ' + disk.disk;
}
disk_cur_cat[_loadDrive] = category;
disk_cur_name[_loadDrive] = name;
drivelights.label(_loadDrive, name);
disk2.setDisk(_loadDrive, disk);
initGamepad(disk.gamepad);
}
function loadJSON(data) {
if (data.type == 'binary') {
loadBinary(data);
} else if ($.inArray(data.type, DISK_TYPES) >= 0) {
loadDisk(data);
}
initGamepad(data.gamepad);
$('#loading').dialog('close');
loading = false;
}
/*
* LocalStorage Disk Storage
*/
function updateLocalStorage() {
var diskIndex = JSON.parse(window.localStorage.diskIndex || '{}');
var names = [], name, cat;
for (name in diskIndex) {
if (diskIndex.hasOwnProperty(name)) {
names.push(name);
}
}
cat = disk_categories['Local Saves'] = [];
$('#manage').empty();
names.forEach(function(name) {
cat.push({'category': 'Local Saves',
'name': name,
'filename': 'local:' + name});
$('#manage').append('<span class="local_save">' +
name +
' <a href="#" onclick="doDelete(\'' +
name +
'\')">Delete</a><br /></span>');
});
cat.push({'category': 'Local Saves',
'name': 'Manage Saves...',
'filename': 'local:__manage'});
}
function saveLocalStorage(drive, name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || '{}');
var json = disk2.getJSON(drive);
diskIndex[name] = json;
window.localStorage.diskIndex = JSON.stringify(diskIndex);
window.alert('Saved');
drivelights.label(drive, name);
drivelights.dirty(drive, false);
updateLocalStorage();
}
function deleteLocalStorage(name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || '{}');
if (diskIndex[name]) {
delete diskIndex[name];
window.alert('Deleted');
}
window.localStorage.diskIndex = JSON.stringify(diskIndex);
updateLocalStorage();
}
function loadLocalStorage(drive, name) {
var diskIndex = JSON.parse(window.localStorage.diskIndex || '{}');
if (diskIndex[name]) {
disk2.setJSON(drive, diskIndex[name]);
drivelights.label(drive, name);
drivelights.dirty(drive, false);
}
}
function processHash(hash) {
if (hash.indexOf('://') > 0) {
var parts = hash.split('.');
var ext = parts[parts.length - 1].toLowerCase();
if (ext == 'json') {
loadAjax(hash);
} else {
doLoadHTTP(hash);
}
} else {
loadAjax('json/disks/' + hash + '.json');
}
}
/*
* Keyboard/Gamepad routines
*/
var _key;
function _keydown(evt) {
if (!focused) {
evt.preventDefault();
var key = keyboard.mapKeyEvent(evt);
if (key != 0xff) {
if (_key != 0xff) io.keyUp();
io.keyDown(key, evt.shiftKey);
_key = key;
}
}
if (evt.keyCode === 112) {
cpu.reset();
} else if (evt.keyCode === 113) { // F2 - Full Screen
var elem = document.getElementById('screen');
if (document.webkitCancelFullScreen) {
if (document.webkitIsFullScreen) {
document.webkitCancelFullScreen();
} else {
if (Element.ALLOW_KEYBOARD_INPUT) {
elem.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
} else {
elem.webkitRequestFullScreen();
}
}
} else if (document.mozCancelFullScreen) {
if (document.mozIsFullScreen) {
document.mozCancelFullScreen();
} else {
elem.mozRequestFullScreen();
}
}
} else if (evt.keyCode === 114) {
io.keyDown(0x1b);
_key = 0x1b;
} else if (evt.keyCode == 16) { // Shift
keyboard.shiftKey(true);
io.buttonDown(2, true);
} else if (evt.keyCode == 17) { // Control
keyboard.controlKey(true);
} else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command
keyboard.commandKey(true);
} else if (evt.keyCode == 18) { // Alt
keyboard.optionKey(true);
}
}
function _keyup(evt) {
_key = 0xff;
if (!focused)
io.keyUp();
if (evt.keyCode == 16) { // Shift
keyboard.shiftKey(false);
io.buttonDown(2, false);
} else if (evt.keyCode == 17) { // Control
keyboard.controlKey(false);
} else if (evt.keyCode == 91 || evt.keyCode == 93) { // Command
keyboard.commandKey(false);
} else if (evt.keyCode == 18) { // Alt
keyboard.optionKey(false);
}
}
function updateScreen() {
var green = $('#green_screen').prop('checked');
vm.green(green);
}
var disableMouseJoystick = false;
var flipX = false;
var flipY = false;
var swapXY = false;
function updateJoystick() {
disableMouseJoystick = $('#disable_mouse').prop('checked');
flipX = $('#flip_x').prop('checked');
flipY = $('#flip_y').prop('checked');
swapXY = $('#swap_x_y').prop('checked');
if (disableMouseJoystick) {
io.paddle(0, 0.5);
io.paddle(1, 0.5);
return;
}
}
function _mousemove(evt) {
if (gamepad || disableMouseJoystick) {
return;
}
var s = $('#screen');
var offset = s.offset();
var x = (evt.pageX - offset.left) / s.width(),
y = (evt.pageY - offset.top) / s.height(),
z = x;
if (swapXY) {
x = y;
y = z;
}
io.paddle(0, flipX ? 1 - x : x);
io.paddle(1, flipY ? 1 - y : y);
}
function pauseRun(b) {
if (paused) {
run();
b.value = 'Pause';
} else {
stop();
b.value = 'Run';
}
paused = !paused;
}
$(function() {
hashtag = document.location.hash;
$('button,input[type=button],a.button').button().focus(function() {
// Crazy hack required by Chrome
var self = this;
window.setTimeout(function() {
self.blur();
}, 1);
});
var canvas = document.getElementById('screen');
var context = canvas.getContext('2d');
vm.setContext(context);
/*
* Input Handling
*/
$(window).keydown(_keydown);
$(window).keyup(_keyup);
$('canvas').mousedown(function(evt) {
if (!gamepad) {
io.buttonDown(evt.which == 1 ? 0 : 1);
}
evt.preventDefault();
})
.mouseup(function(evt) {
if (!gamepad) {
io.buttonUp(evt.which == 1 ? 0 : 1);
}
})
.bind('contextmenu', function(evt) { evt.preventDefault(); });
$('body').mousemove(_mousemove);
$('body > div').hover(function() { focused = false; },
function() { focused = true; });
$('input,textarea').focus(function() { focused = true; })
.blur(function() { focused = false; });
keyboard.create($('#keyboard'));
if (prefs.havePrefs()) {
$('input[type=checkbox]').each(function() {
var val = prefs.readPref(this.id);
if (val)
this.checked = JSON.parse(val);
}).change(function() {
prefs.writePref(this.id, JSON.stringify(this.checked));
});
}
reset();
run();
setInterval(updateKHz, 1000);
updateSound();
updateScreen();
updateSpeed();
var cancel = function() { $(this).dialog('close'); };
$('#loading').dialog({ autoOpen: false, modal: true });
$('#options').dialog({ autoOpen: false,
modal: true,
width: 320,
height: 400,
buttons: {'Close': cancel }});
$('#load').dialog({ autoOpen: false,
modal: true,
width: 540,
buttons: {'Cancel': cancel, 'Load': doLoad }});
$('#save').dialog({ autoOpen: false,
modal: true,
width: 320,
buttons: {'Cancel': cancel, 'Save': doSave }});
$('#manage').dialog({ autoOpen: false,
modal: true,
width: 320,
buttons: {'Close': cancel }});
$('#local_save').dialog({ autoOpen: false,
modal: true,
width: 530,
buttons: {'OK': cancel }});
$('#http_load').dialog({ autoOpen: false,
modal: true,
width: 530,
buttons: {'Cancel': cancel, 'OK': doLoadHTTP }});
if (window.localStorage !== undefined) {
$('.disksave').show();
}
var oldcat = '';
for (var idx = 0; idx < disk_index.length; idx++) {
var file = disk_index[idx];
var cat = file.category;
var name = file.name, disk = file.disk;
if (cat != oldcat) {
$('<option />').val(cat).text(cat).appendTo('#category_select');
disk_categories[cat] = [];
oldcat = cat;
}
disk_categories[cat].push(file);
if (disk) {
if (!disk_sets[name]) {
disk_sets[name] = [];
}
disk_sets[name].push(file);
}
}
$('<option/>').text('Local Saves').appendTo('#category_select');
updateLocalStorage();
initGamepad();
// Check for disks in hashtag
var hash = gup('disk') || hup();
if (hash) {
processHash(hash);
}
if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
$('select').removeAttr('multiple').css('height', 'auto');
}
if (navigator.standalone) {
$('body').addClass('standalone');
}
});

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -10,10 +9,16 @@
* implied warranty. * implied warranty.
*/ */
/*globals RAM: false, toHex: false, hiresMode: false, debug: false */
/*exported MMU */ /*exported MMU */
/*globals debug: false, toHex: false
hiresMode: false,
RAM: false
*/
function MMU(cpu, lores1, lores2, hires1, hires2, io, rom) function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
{ {
'use strict';
var idx; var idx;
var _auxRom = 0x00; var _auxRom = 0x00;
@ -28,14 +33,14 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
var _writebsr; var _writebsr;
// Auxilliary ROM // Auxilliary ROM
var _intcxrom; var _intcxrom;
var _slot3rom; var _slot3rom;
// Auxilliary RAM // Auxilliary RAM
var _auxRamRead; var _auxRamRead;
var _auxRamWrite; var _auxRamWrite;
var _altzp; var _altzp;
// Video // Video
var _80store = false; var _80store = false;
var _page2; var _page2;
@ -51,7 +56,7 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
_auxRamWrite = false; _auxRamWrite = false;
_altzp = false; _altzp = false;
_intcxrom = false; _intcxrom = false;
_slot3rom = false; _slot3rom = false;
_80store = false; _80store = false;
@ -93,7 +98,7 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
var memC0_C0 = [io]; var memC0_C0 = [io];
// var memC1_CF = [emptyslots, rom]; // var memC1_CF = [emptyslots, rom];
var memD0_DF = [rom, var memD0_DF = [rom,
new RAM(0xD0,0xDF), new RAM(0xD0,0xDF), new RAM(0xD0,0xDF), new RAM(0xD0,0xDF),
new RAM(0xD0,0xDF), new RAM(0xD0,0xDF)]; new RAM(0xD0,0xDF), new RAM(0xD0,0xDF)];
var memE0_FF = [rom, new RAM(0xE0,0xFF), new RAM(0xE0,0xFF)]; var memE0_FF = [rom, new RAM(0xE0,0xFF), new RAM(0xE0,0xFF)];
@ -172,7 +177,7 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
_readPages[idx] = _pages[idx][0]; _readPages[idx] = _pages[idx][0];
_writePages[idx] = _pages[idx][0]; _writePages[idx] = _pages[idx][0];
} }
/* /*
* I/O Switch locations * I/O Switch locations
*/ */
@ -235,7 +240,7 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
_OFFBSR1: 0x8e, _OFFBSR1: 0x8e,
_READWRBSR1: 0x8f _READWRBSR1: 0x8f
}; };
function _updateBanks() { function _updateBanks() {
if (_auxRamRead) { if (_auxRamRead) {
for (idx = 0x02; idx < 0xC0; idx++) { for (idx = 0x02; idx < 0xC0; idx++) {
@ -372,35 +377,35 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
if (typeof val != 'undefined') { if (typeof val != 'undefined') {
_80store = true; _80store = true;
// _debug("80 Store On"); // _debug("80 Store On");
} else } else
result = 0; result = 0;
break; break;
case LOC.RAMRDOFF: case LOC.RAMRDOFF:
if (typeof val != 'undefined') { if (typeof val != 'undefined') {
_auxRamRead = false; _auxRamRead = false;
_debug("Aux RAM Read Off"); _debug("Aux RAM Read Off");
} else } else
result = 0; result = 0;
break; break;
case LOC.RAMRDON: case LOC.RAMRDON:
if (typeof val != 'undefined') { if (typeof val != 'undefined') {
_auxRamRead = true; _auxRamRead = true;
_debug("Aux RAM Read On"); _debug("Aux RAM Read On");
} else } else
result = 0; result = 0;
break; break;
case LOC.RAMWROFF: case LOC.RAMWROFF:
if (typeof val != 'undefined') { if (typeof val != 'undefined') {
_auxRamWrite = false; _auxRamWrite = false;
_debug("Aux RAM Write Off"); _debug("Aux RAM Write Off");
} else } else
result = 0; result = 0;
break; break;
case LOC.RAMWRON: case LOC.RAMWRON:
if (typeof val != 'undefined') { if (typeof val != 'undefined') {
_auxRamWrite = true; _auxRamWrite = true;
_debug("Aux RAM Write On"); _debug("Aux RAM Write On");
} else } else
result = 0; result = 0;
break; break;
@ -416,7 +421,7 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
// _debug("Int CX ROM On"); // _debug("Int CX ROM On");
} }
break; break;
case LOC.ALTZPOFF: // 0x08 case LOC.ALTZPOFF: // 0x08
if (typeof val != 'undefined') { if (typeof val != 'undefined') {
_altzp = false; _altzp = false;
_debug("Alt ZP Off"); _debug("Alt ZP Off");
@ -515,7 +520,7 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
case LOC.BSRBANK2: case LOC.BSRBANK2:
_debug("Bank 2 Read " + !_bank1); _debug("Bank 2 Read " + !_bank1);
result = !_bank1 ? 0x80 : 0x00; result = !_bank1 ? 0x80 : 0x00;
break; break;
case LOC.BSRREADRAM: case LOC.BSRREADRAM:
_debug("Bank SW RAM Read " + _readbsr); _debug("Bank SW RAM Read " + _readbsr);
@ -571,10 +576,10 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
io.start(); io.start();
lores1.start(); lores1.start();
lores2.start(); lores2.start();
// Do us afterward because we override some of the above // Do us afterward because we override some of the above
io.registerSwitches(this, LOC); io.registerSwitches(this, LOC);
return 0x00; return 0x00;
}, },
end: function mmu_end() { end: function mmu_end() {
@ -632,7 +637,7 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
auxRamRead: _auxRamRead, auxRamRead: _auxRamRead,
auxRamWrite: _auxRamWrite, auxRamWrite: _auxRamWrite,
altzp: _altzp, altzp: _altzp,
_80store: _80store, _80store: _80store,
page2: _page2, page2: _page2,
@ -649,14 +654,14 @@ function MMU(cpu, lores1, lores2, hires1, hires2, io, rom)
_readbsr = state.readbsr; _readbsr = state.readbsr;
_writebsr = state.writebsr; _writebsr = state.writebsr;
_bank1 = state.bank1; _bank1 = state.bank1;
_auxRom = state.auxRom; _auxRom = state.auxRom;
_intcxrom = state.intcxrom; _intcxrom = state.intcxrom;
_slot3rom = state.slot3rom; _slot3rom = state.slot3rom;
_auxRamRead = state.auxRamRead; _auxRamRead = state.auxRamRead;
_auxRamWrite = state.auxRamWrite; _auxRamWrite = state.auxRamWrite;
_altzp = state.altzp; _altzp = state.altzp;
_80store = state._80store; _80store = state._80store;
_page2 = state.page2; _page2 = state.page2;

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -13,6 +12,8 @@
/*exported Parallel */ /*exported Parallel */
function Parallel(io, cbs, slot) { function Parallel(io, cbs, slot) {
'use strict';
slot = slot || 1; slot = slot || 1;
var LOC = { var LOC = {
@ -75,5 +76,3 @@ function Parallel(io, cbs, slot) {
write: function() {} write: function() {}
}; };
} }

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -10,23 +9,24 @@
* implied warranty. * implied warranty.
*/ */
/*jshint browser: true */
/*exported Prefs */ /*exported Prefs */
function Prefs() function Prefs()
{ {
'use strict';
return { return {
havePrefs: function() { havePrefs: function() {
return typeof(localStorage) != "undefined"; return typeof(localStorage) != 'undefined';
}, },
readPref: function(name) { readPref: function(name) {
if (localStorage) if (localStorage)
return localStorage.getItem(name); return localStorage.getItem(name);
return null; return null;
}, },
writePref: function(name, value) { writePref: function(name, value) {
if (localStorage) if (localStorage)
localStorage.setItem(name, value); localStorage.setItem(name, value);
} }
}; };
} }

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -10,10 +9,14 @@
* implied warranty. * implied warranty.
*/ */
/*globals allocMemPages, base64_encode, base64_decode */
/*exported RAM */ /*exported RAM */
/*globals allocMemPages: false
base64_encode: false, base64_decode: false
*/
function RAM(sp, ep) { function RAM(sp, ep) {
'use strict';
var mem; var mem;
var start_page = sp; var start_page = sp;
var end_page = ep; var end_page = ep;

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -10,10 +9,13 @@
* implied warranty. * implied warranty.
*/ */
/*globals allocMem:false, bytify, base64_encode, base64_decode, each: false */
/*exported RAMFactor*/ /*exported RAMFactor*/
/*globals allocMem: false, bytify: false, each: false,
base64_encode: false, base64_decode: false
*/
function RAMFactor(mmu, io, slot, size) { function RAMFactor(mmu, io, slot, size) {
'use strict';
var rom = [ var rom = [
0x43,0x4f,0x50,0x59,0x52,0x49,0x47,0x48, 0x43,0x4f,0x50,0x59,0x52,0x49,0x47,0x48,
0x54,0x20,0x28,0x43,0x29,0x20,0x31,0x39, 0x54,0x20,0x28,0x43,0x29,0x20,0x31,0x39,
@ -1079,14 +1081,14 @@ function RAMFactor(mmu, io, slot, size) {
} }
function _setmid(val) { function _setmid(val) {
if ((_rammid & 0x80) && !(val & 0x80)) { if (((_rammid & 0x80) !== 0) && ((val & 0x80) === 0)) {
_sethi(_ramhi + 1); _sethi(_ramhi + 1);
} }
_rammid = (val & 0xff); _rammid = (val & 0xff);
} }
function _setlo(val) { function _setlo(val) {
if ((_ramlo & 0x80) && !(val & 0x80)) { if (((_ramlo & 0x80) !== 0) && ((val & 0x80) === 0)) {
_setmid(_rammid + 1); _setmid(_rammid + 1);
} }
_ramlo = (val & 0xff); _ramlo = (val & 0xff);

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -14,6 +13,8 @@
function Slot3(mmu, rom) function Slot3(mmu, rom)
{ {
'use strict';
var auxRomFn = { var auxRomFn = {
start: function auxRom_start() { start: function auxRom_start() {
return 0xc8; return 0xc8;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -11,17 +10,19 @@
*/ */
/*exported Thunderclock */ /*exported Thunderclock */
/*global each */ /*global each: false */
function Thunderclock(mmu, io, slot) function Thunderclock(mmu, io, slot)
{ {
'use strict';
var rom = [ var rom = [
0x08,0x78,0x28,0x2c,0x58,0xff,0x70,0x05, // 00 0x08,0x78,0x28,0x2c,0x58,0xff,0x70,0x05, // 00
0x38,0xb0,0x01,0x18,0xb8,0x08,0x78,0x48, 0x38,0xb0,0x01,0x18,0xb8,0x08,0x78,0x48,
0x8a,0x48,0x98,0x48,0xad,0xff,0xcf,0x20, // 10 0x8a,0x48,0x98,0x48,0xad,0xff,0xcf,0x20, // 10
0x1a,0xc8,0x68,0x68,0xba,0x8d,0xf8,0x07, 0x1a,0xc8,0x68,0x68,0xba,0x8d,0xf8,0x07,
0x0a,0x0a,0x0a,0x0a,0x8d,0x78,0x07,0x68, // 20 0x0a,0x0a,0x0a,0x0a,0x8d,0x78,0x07,0x68, // 20
0x68,0x68,0xa8,0x68,0x9a,0x09,0x04,0x48, 0x68,0x68,0xa8,0x68,0x9a,0x09,0x04,0x48,
0x28,0x98,0xac,0x78,0x07,0xae,0xf8,0x07, // 30 0x28,0x98,0xac,0x78,0x07,0xae,0xf8,0x07, // 30
0x29,0x7f,0x48,0x50,0x0e,0xb8,0xa5,0x36, 0x29,0x7f,0x48,0x50,0x0e,0xb8,0xa5,0x36,
0xd0,0x04,0xe4,0x37,0xf0,0x0a,0xa9,0x08, // 40 0xd0,0x04,0xe4,0x37,0xf0,0x0a,0xa9,0x08, // 40
@ -340,7 +341,7 @@ function Thunderclock(mmu, io, slot)
switch (off) { switch (off) {
case LOC.CONTROL: case LOC.CONTROL:
if (val !== undefined) { if (val !== undefined) {
if (val & FLAGS.STROBE) { if ((val & FLAGS.STROBE) !== 0) {
if ((_command & 0x78) == 0x18) { if ((_command & 0x78) == 0x18) {
_calcbits(); _calcbits();
} }
@ -390,4 +391,3 @@ function Thunderclock(mmu, io, slot)
} }
}; };
} }

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2014 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -10,7 +9,6 @@
* implied warranty. * implied warranty.
*/ */
/*jshint jquery: true, browser: true */
/*globals debug: false */ /*globals debug: false */
/*exported enableSound, initAudio */ /*exported enableSound, initAudio */
@ -18,46 +16,46 @@
* Audio Handling * Audio Handling
*/ */
var sound = true; var sound = true;
var _samples = []; var _samples = [];
var audioContext; var audioContext;
var audioNode; var audioNode;
var AC = window.webkitAudioContext || window.AudioContext; var AC = window.AudioContext;
if (typeof AC !== 'undefined') { if (typeof AC !== 'undefined') {
audioContext = new AC(); audioContext = new AC();
audioNode = audioContext.createScriptProcessor(4096, 1, 1); audioNode = audioContext.createScriptProcessor(4096, 1, 1);
audioNode.onaudioprocess = function(event) { audioNode.onaudioprocess = function(event) {
var data = event.outputBuffer.getChannelData(0); var data = event.outputBuffer.getChannelData(0);
var sample = _samples.shift(); var sample = _samples.shift();
var idx = 0; var idx = 0;
var len = data.length; var len = data.length;
if (sample) { if (sample) {
len = Math.min(sample.length, len); len = Math.min(sample.length, len);
for (; idx < len; idx++) { for (; idx < len; idx++) {
data[idx] = sample[idx]; data[idx] = sample[idx];
} }
} }
for (; idx < data.length; idx++) {
data[idx] = 0.0;
}
};
/* for (; idx < data.length; idx++) {
// Create and specify parameters for the low-pass filter. data[idx] = 0.0;
var filter = audioContext.createBiquadFilter(); }
filter.type = 'lowpass'; };
filter.frequency.value = 11000;
filter.connect(audioContext.destination);
audioNode.connect(filter);
*/
audioNode.connect(audioContext.destination); /*
} // Create and specify parameters for the low-pass filter.
var filter = audioContext.createBiquadFilter();
filter.type = 'lowpass';
filter.frequency.value = 11000;
filter.connect(audioContext.destination);
audioNode.connect(filter);
*/
audioNode.connect(audioContext.destination);
}
function initAudio(io) { function initAudio(io) {
if (audioContext) { if (audioContext) {

View File

@ -1,11 +1,11 @@
/*! /*!
* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com> * Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that * the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting * copyright notice and this permission notice appear in supporting
* documentation. No representations are made about the suitability of this * documentation. No representations are made about the suitability of this
* software for any purpose. It is provided "as is" without express or * software for any purpose. It is provided "as is" without express or
* implied warranty. * implied warranty.
*/ */

View File

@ -1,5 +1,5 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* Copyright 2010-2014 Will Scullin <scullin@scullinsteel.com> /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -14,7 +14,7 @@
/*globals flipX: false, flipY: false */ /*globals flipX: false, flipY: false */
/*exported processGamepad, initGamepad, gamepad */ /*exported processGamepad, initGamepad, gamepad */
var gamepadSupportAvailable = !!navigator.webkitGetGamepads; var getGamepads = navigator.getGamepads || navigator.webkitGetGamepads;
var gamepad; var gamepad;
var gamepadMap = []; var gamepadMap = [];
var gamepadState = []; var gamepadState = [];
@ -54,17 +54,17 @@ var DEFAULT_GAMEPAD = {
'START': '\033' 'START': '\033'
}; };
window.addEventListener("gamepadconnected", function(e) { window.addEventListener('gamepadconnected', function(e) {
gamepad = e.gamepad; gamepad = e.gamepad;
}); });
function processGamepad(io) { function processGamepad(io) {
if (gamepadSupportAvailable) { if (getGamepads) {
gamepad = navigator.webkitGetGamepads()[0]; gamepad = getGamepads.call(navigator)[0];
} }
if (gamepad) { if (gamepad) {
var x = (gamepad.axes[0] * 1.414 + 1) / 2.0; var x = (gamepad.axes[0] * 1.414 + 1) / 2.0;
var y = (gamepad.axes[1] * 1.414 + 1) / 2.0; var y = (gamepad.axes[1] * 1.414 + 1) / 2.0;
io.paddle(0, flipX ? 1.0 - x : x); io.paddle(0, flipX ? 1.0 - x : x);
io.paddle(1, flipY ? 1.0 - y : y); io.paddle(1, flipY ? 1.0 - y : y);
var val; var val;
@ -74,12 +74,12 @@ function processGamepad(io) {
var old = gamepadState[idx]; var old = gamepadState[idx];
var button = gamepad.buttons[idx]; var button = gamepad.buttons[idx];
var pressed; var pressed;
if (typeof(button) == "object") { if (typeof(button) == 'object') {
pressed = button.pressed; pressed = button.pressed;
} else { } else {
pressed = (button == 1.0); pressed = (button == 1.0);
} }
if (pressed && !old) { if (pressed && !old) {
if (val <= 0) { if (val <= 0) {
io.buttonDown(-val); io.buttonDown(-val);
@ -117,5 +117,3 @@ function initGamepad(data) {
} }
}); });
} }

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -10,7 +9,6 @@
* implied warranty. * implied warranty.
*/ */
/*jshint jquery: true, browser: true */
/*globals debug: false, toHex: false, reset: false */ /*globals debug: false, toHex: false, reset: false */
/*exported KeyBoard */ /*exported KeyBoard */
@ -18,46 +16,46 @@ function KeyBoard(io) {
// keycode: [plain, cntl, shift] // keycode: [plain, cntl, shift]
var keymap = { var keymap = {
// Most of these won't happen // Most of these won't happen
0x00: [0x00, 0x00, 0x00], // 0x00: [0x00, 0x00, 0x00], //
0x01: [0x01, 0x01, 0x01], // 0x01: [0x01, 0x01, 0x01], //
0x02: [0x02, 0x02, 0x02], // 0x02: [0x02, 0x02, 0x02], //
0x03: [0x03, 0x03, 0x03], // 0x03: [0x03, 0x03, 0x03], //
0x04: [0x04, 0x04, 0x04], // 0x04: [0x04, 0x04, 0x04], //
0x05: [0x05, 0x05, 0x05], // 0x05: [0x05, 0x05, 0x05], //
0x06: [0x06, 0x06, 0x06], // 0x06: [0x06, 0x06, 0x06], //
0x07: [0x07, 0x07, 0x07], // 0x07: [0x07, 0x07, 0x07], //
0x08: [0x08, 0x08, 0x08], // BS 0x08: [0x08, 0x08, 0x08], // BS
0x09: [0x09, 0x09, 0x09], // TAB 0x09: [0x09, 0x09, 0x09], // TAB
0x0A: [0x0A, 0x0A, 0x0A], // 0x0A: [0x0A, 0x0A, 0x0A], //
0x0B: [0x0B, 0x0B, 0x0B], // 0x0B: [0x0B, 0x0B, 0x0B], //
0x0C: [0x0C, 0x0C, 0x0C], // 0x0C: [0x0C, 0x0C, 0x0C], //
0x0D: [0x0D, 0x0D, 0x0D], // CR 0x0D: [0x0D, 0x0D, 0x0D], // CR
0x0E: [0x0E, 0x0E, 0x0E], // 0x0E: [0x0E, 0x0E, 0x0E], //
0x0F: [0x0F, 0x0F, 0x0F], // 0x0F: [0x0F, 0x0F, 0x0F], //
0x10: [0xff, 0xff, 0xff], // SHIFT 0x10: [0xff, 0xff, 0xff], // SHIFT
0x11: [0xff, 0xff, 0xff], // CTRL 0x11: [0xff, 0xff, 0xff], // CTRL
0x12: [0xff, 0xff, 0xff], // OPTION 0x12: [0xff, 0xff, 0xff], // OPTION
0x13: [0x13, 0x13, 0x13], // 0x13: [0x13, 0x13, 0x13], //
0x14: [0x14, 0x14, 0x14], // 0x14: [0x14, 0x14, 0x14], //
0x15: [0x15, 0x15, 0x15], // 0x15: [0x15, 0x15, 0x15], //
0x16: [0x16, 0x16, 0x16], // 0x16: [0x16, 0x16, 0x16], //
0x17: [0x17, 0x17, 0x18], // 0x17: [0x17, 0x17, 0x18], //
0x18: [0x18, 0x18, 0x18], // 0x18: [0x18, 0x18, 0x18], //
0x19: [0x19, 0x19, 0x19], // 0x19: [0x19, 0x19, 0x19], //
0x1A: [0x1A, 0x1A, 0x1A], // 0x1A: [0x1A, 0x1A, 0x1A], //
0x1B: [0x1B, 0x1B, 0x1B], // ESC 0x1B: [0x1B, 0x1B, 0x1B], // ESC
0x1C: [0x1C, 0x1C, 0x1C], // 0x1C: [0x1C, 0x1C, 0x1C], //
0x1D: [0x1D, 0x1D, 0x1D], // 0x1D: [0x1D, 0x1D, 0x1D], //
0x1E: [0x1E, 0x1E, 0x1E], // 0x1E: [0x1E, 0x1E, 0x1E], //
0x1F: [0x1F, 0x1F, 0x1F], // 0x1F: [0x1F, 0x1F, 0x1F], //
// Most of these besides space won't happen // Most of these besides space won't happen
0x20: [0x20, 0x20, 0x20], // 0x20: [0x20, 0x20, 0x20], //
0x21: [0x21, 0x21, 0x21], // 0x21: [0x21, 0x21, 0x21], //
0x22: [0x22, 0x22, 0x22], // 0x22: [0x22, 0x22, 0x22], //
0x23: [0x23, 0x23, 0x23], // 0x23: [0x23, 0x23, 0x23], //
0x24: [0x24, 0x24, 0x24], // 0x24: [0x24, 0x24, 0x24], //
0x25: [0x08, 0x08, 0x08], // <- left 0x25: [0x08, 0x08, 0x08], // <- left
0x26: [0x0B, 0x0B, 0x0B], // ^ up 0x26: [0x0B, 0x0B, 0x0B], // ^ up
0x27: [0x15, 0x15, 0x15], // -> right 0x27: [0x15, 0x15, 0x15], // -> right
@ -69,7 +67,7 @@ function KeyBoard(io) {
0x2D: [0x2D, 0x2D, 0x5F], // - - _ 0x2D: [0x2D, 0x2D, 0x5F], // - - _
0x2E: [0x2E, 0x2E, 0x3E], // . - > 0x2E: [0x2E, 0x2E, 0x3E], // . - >
0x2F: [0x2F, 0x2F, 0x3F], // / - ? 0x2F: [0x2F, 0x2F, 0x3F], // / - ?
0x30: [0x30, 0x30, 0x29], // 0 - ) 0x30: [0x30, 0x30, 0x29], // 0 - )
0x31: [0x31, 0x31, 0x21], // 1 - ! 0x31: [0x31, 0x31, 0x21], // 1 - !
0x32: [0x32, 0x00, 0x40], // 2 - @ 0x32: [0x32, 0x00, 0x40], // 2 - @
@ -86,7 +84,7 @@ function KeyBoard(io) {
0x3D: [0x3D, 0x3D, 0x2B], // = - + 0x3D: [0x3D, 0x3D, 0x2B], // = - +
0x3E: [0x3E, 0x3E, 0x3E], // > 0x3E: [0x3E, 0x3E, 0x3E], // >
0x3F: [0x3F, 0x3F, 0x3F], // ? 0x3F: [0x3F, 0x3F, 0x3F], // ?
// Alpha and control // Alpha and control
0x40: [0x40, 0x00, 0x40], // @ 0x40: [0x40, 0x00, 0x40], // @
0x41: [0x41, 0x01, 0x41], // A 0x41: [0x41, 0x01, 0x41], // A
@ -99,12 +97,12 @@ function KeyBoard(io) {
0x48: [0x48, 0x08, 0x48], // H 0x48: [0x48, 0x08, 0x48], // H
0x49: [0x49, 0x09, 0x49], // I - TAB 0x49: [0x49, 0x09, 0x49], // I - TAB
0x4A: [0x4A, 0x0A, 0x4A], // J - NL 0x4A: [0x4A, 0x0A, 0x4A], // J - NL
0x4B: [0x4B, 0x0B, 0x4B], // K - VT 0x4B: [0x4B, 0x0B, 0x4B], // K - VT
0x4C: [0x4C, 0x0C, 0x4C], // L 0x4C: [0x4C, 0x0C, 0x4C], // L
0x4D: [0x4D, 0x0D, 0x4D], // M - CR 0x4D: [0x4D, 0x0D, 0x4D], // M - CR
0x4E: [0x4E, 0x0E, 0x4E], // N 0x4E: [0x4E, 0x0E, 0x4E], // N
0x4F: [0x4F, 0x0F, 0x4F], // O 0x4F: [0x4F, 0x0F, 0x4F], // O
0x50: [0x50, 0x10, 0x50], // P 0x50: [0x50, 0x10, 0x50], // P
0x51: [0x51, 0x11, 0x51], // Q 0x51: [0x51, 0x11, 0x51], // Q
0x52: [0x52, 0x12, 0x52], // R 0x52: [0x52, 0x12, 0x52], // R
@ -121,7 +119,7 @@ function KeyBoard(io) {
// 0x5D: [0x5D, 0x1D, 0x5D], // ] // 0x5D: [0x5D, 0x1D, 0x5D], // ]
0x5E: [0x5E, 0x1E, 0x5E], // ^ 0x5E: [0x5E, 0x1E, 0x5E], // ^
0x5F: [0x5F, 0x1F, 0x5F], // _ 0x5F: [0x5F, 0x1F, 0x5F], // _
// Stray keys // Stray keys
0xBA: [0x3B, 0x3B, 0x3A], // ; - : 0xBA: [0x3B, 0x3B, 0x3A], // ; - :
0xBB: [0x3D, 0x3D, 0x2B], // = - + 0xBB: [0x3D, 0x3D, 0x2B], // = - +
@ -132,35 +130,35 @@ function KeyBoard(io) {
0xDB: [0x5B, 0x5B, 0x5B], // [ 0xDB: [0x5B, 0x5B, 0x5B], // [
0xDC: [0x5C, 0x5C, 0x5C], // \ 0xDC: [0x5C, 0x5C, 0x5C], // \
0xDD: [0x5D, 0x5D, 0x5D], // ] 0xDD: [0x5D, 0x5D, 0x5D], // ]
0xDE: [0x27, 0x27, 0x22], // ' - " 0xDE: [0x27, 0x27, 0x22], // ' - '
0xFF: [0xFF, 0xFF, 0xFF] // No comma line 0xFF: [0xFF, 0xFF, 0xFF] // No comma line
}; };
var keys = var keys =
[[['1','2','3','4','5','6','7','8','9','0',':','-','RESET'], [[['1','2','3','4','5','6','7','8','9','0',':','-','RESET'],
['ESC','Q','W','E','R','T','Y','U','I','O','P','REPT','RETURN'], ['ESC','Q','W','E','R','T','Y','U','I','O','P','REPT','RETURN'],
['CTRL','A','S','D','F','G','H','J','K','L',';','&larr;','&rarr;'], ['CTRL','A','S','D','F','G','H','J','K','L',';','&larr;','&rarr;'],
['SHIFT','Z','X','C','V','B','N','M',',','.','/','SHIFT'], ['SHIFT','Z','X','C','V','B','N','M',',','.','/','SHIFT'],
['POWER', '&nbsp;']], ['POWER', '&nbsp;']],
[['!','"','#','$','%','&',"'",'(',')','0','*','=','RESET'], [['!','"','#','$','%','&','\'','(',')','0','*','=','RESET'],
['ESC','Q','W','E','R','T','Y','U','I','O','@','REPT','RETURN'], ['ESC','Q','W','E','R','T','Y','U','I','O','@','REPT','RETURN'],
['CTRL','A','S','D','F','BELL','H','J','K','L','+','&larr;','&rarr;'], ['CTRL','A','S','D','F','BELL','H','J','K','L','+','&larr;','&rarr;'],
['SHIFT','Z','X','C','V','B','^',']','<','>','?','SHIFT'], ['SHIFT','Z','X','C','V','B','^',']','<','>','?','SHIFT'],
['POWER', '&nbsp;']]]; ['POWER', '&nbsp;']]];
var shifted = false; var shifted = false;
var controlled = false; var controlled = false;
return { return {
mapKeyEvent: function keyboard_mapKeyEvent(evt) { mapKeyEvent: function keyboard_mapKeyEvent(evt) {
var code = evt.keyCode; var code = evt.keyCode;
if (code in keymap) { if (code in keymap) {
return keymap[code][evt.shiftKey ? 2 : (evt.ctrlKey ? 1 : 0)]; return keymap[code][evt.shiftKey ? 2 : (evt.ctrlKey ? 1 : 0)];
} }
debug("Unhandled key = " + toHex(code)); debug('Unhandled key = ' + toHex(code));
return 0xFF; return 0xFF;
}, },
@ -168,125 +166,125 @@ function KeyBoard(io) {
shifted = down; shifted = down;
if (down) { if (down) {
io.buttonDown(2); io.buttonDown(2);
$("#keyboard .key-SHIFT").addClass("active"); $('#keyboard .key-SHIFT').addClass('active');
} else { } else {
io.buttonUp(2); io.buttonUp(2);
$("#keyboard .key-SHIFT").removeClass("active"); $('#keyboard .key-SHIFT').removeClass('active');
} }
}, },
controlKey: function keyboard_controlKey(down) { controlKey: function keyboard_controlKey(down) {
controlled = down; controlled = down;
if (down) { if (down) {
$("#keyboard .key-CTRL").addClass("active"); $('#keyboard .key-CTRL').addClass('active');
} else { } else {
$("#keyboard .key-CTRL").removeClass("active"); $('#keyboard .key-CTRL').removeClass('active');
} }
}, },
create: function keyboard_create(kb) { create: function keyboard_create(kb) {
var x, y, row, key, key1, key2, label, label1, label2; var x, y, row, key, key1, key2, label, label1, label2;
kb.disableSelection(); kb.disableSelection();
function buildLabel(k) { function buildLabel(k) {
var span = $("<span>" + k + "</span>"); var span = $('<span>' + k + '</span>');
if (k.length > 1 && k.substr(0,1) != '&') if (k.length > 1 && k.substr(0,1) != '&')
span.addClass("small"); span.addClass('small');
return span; return span;
} }
function _mouseup(ev) { function _mouseup(ev) {
$(ev.currentTarget).removeClass("pressed"); $(ev.currentTarget).removeClass('pressed');
} }
function _mousedown(ev) { function _mousedown(ev) {
$(ev.currentTarget).addClass("pressed"); $(ev.currentTarget).addClass('pressed');
var key = $(ev.currentTarget).data(shifted ? "key2" : "key1"); var key = $(ev.currentTarget).data(shifted ? 'key2' : 'key1');
switch (key) { switch (key) {
case "BELL": case 'BELL':
key = "G"; key = 'G';
break; break;
case "RETURN": case 'RETURN':
key = "\r"; key = '\r';
break; break;
case "&larr;": case '&larr;':
key = "\010"; key = '\010';
break; break;
case "&rarr;": case '&rarr;':
key = "\025"; key = '\025';
break; break;
case "&nbsp;": case '&nbsp;':
key = " "; key = ' ';
break; break;
case "ESC": case 'ESC':
key = "\033"; key = '\033';
break; break;
default: default:
break; break;
} }
if (key.length > 1) { if (key.length > 1) {
switch (key) { switch (key) {
case "SHIFT": case 'SHIFT':
shifted = !shifted; shifted = !shifted;
$("#keyboard .key-SHIFT").toggleClass("active"); $('#keyboard .key-SHIFT').toggleClass('active');
break; break;
case "CTRL": case 'CTRL':
controlled = !controlled; controlled = !controlled;
$("#keyboard .key-CTRL").toggleClass("active"); $('#keyboard .key-CTRL').toggleClass('active');
break; break;
case "RESET": case 'RESET':
reset(); reset();
break; break;
case "POWER": case 'POWER':
if (window.confirm("Power Cycle?")) if (window.confirm('Power Cycle?'))
window.location.reload(); window.location.reload();
break; break;
default: default:
break; break;
} }
} else { } else {
if (controlled && key >= "@" && key <= "_") { if (controlled && key >= '@' && key <= '_') {
io.keyDown(key.charCodeAt(0) - 0x40); io.keyDown(key.charCodeAt(0) - 0x40);
} else { } else {
io.keyDown(key.charCodeAt(0)); io.keyDown(key.charCodeAt(0));
} }
} }
} }
for (y = 0; y < 5; y++) { for (y = 0; y < 5; y++) {
row = $("<div class='row row" + y + "'/>"); row = $('<div class="row row' + y + '"/>');
kb.append(row); kb.append(row);
for (x = 0; x < keys[0][y].length; x++) { for (x = 0; x < keys[0][y].length; x++) {
key1 = keys[0][y][x]; key1 = keys[0][y][x];
key2 = keys[1][y][x]; key2 = keys[1][y][x];
label = $("<div />"); label = $('<div />');
label1 = buildLabel(key1); label1 = buildLabel(key1);
label2 = buildLabel(key2); label2 = buildLabel(key2);
key = $("<div class='key'>"); key = $('<div class="key">');
key.addClass("key-" + key1.replace(/[&;]/g,"")); key.addClass('key-' + key1.replace(/[&;]/g,''));
if (key1.length > 1) if (key1.length > 1)
key.addClass("vcenter"); key.addClass('vcenter');
if (key1 != key2) { if (key1 != key2) {
key.addClass("key-" + key2.replace(/[&;]/g,"")); key.addClass('key-' + key2.replace(/[&;]/g,''));
label.append(label2); label.append(label2);
label.append("<br/>"); label.append('<br/>');
} }
label.append(label1); label.append(label1);
key.append(label); key.append(label);
key.data({"key1": key1, "key2": key2}); key.data({'key1': key1, 'key2': key2});
if (window.ontouchstart === undefined) { if (window.ontouchstart === undefined) {
key.bind("mousedown", _mousedown); key.bind('mousedown', _mousedown);
key.bind("mouseup mouseout", _mouseup); key.bind('mouseup mouseout', _mouseup);
} else { } else {
key.bind("touchstart", _mousedown); key.bind('touchstart', _mousedown);
key.bind("touchend touchleave", _mouseup); key.bind('touchend touchleave', _mouseup);
} }
row.append(key); row.append(key);
} }
@ -294,4 +292,3 @@ function KeyBoard(io) {
} }
}; };
} }

View File

@ -1,5 +1,5 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com> /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -18,46 +18,46 @@ function KeyBoard(io) {
// keycode: [plain, cntl, shift] // keycode: [plain, cntl, shift]
var keymap = { var keymap = {
// Most of these won't happen // Most of these won't happen
0x00: [0x00, 0x00, 0x00], // 0x00: [0x00, 0x00, 0x00], //
0x01: [0x01, 0x01, 0x01], // 0x01: [0x01, 0x01, 0x01], //
0x02: [0x02, 0x02, 0x02], // 0x02: [0x02, 0x02, 0x02], //
0x03: [0x03, 0x03, 0x03], // 0x03: [0x03, 0x03, 0x03], //
0x04: [0x04, 0x04, 0x04], // 0x04: [0x04, 0x04, 0x04], //
0x05: [0x05, 0x05, 0x05], // 0x05: [0x05, 0x05, 0x05], //
0x06: [0x06, 0x06, 0x06], // 0x06: [0x06, 0x06, 0x06], //
0x07: [0x07, 0x07, 0x07], // 0x07: [0x07, 0x07, 0x07], //
0x08: [0x7F, 0x7F, 0x7F], // BS/DELETE 0x08: [0x7F, 0x7F, 0x7F], // BS/DELETE
0x09: [0x09, 0x09, 0x09], // TAB 0x09: [0x09, 0x09, 0x09], // TAB
0x0A: [0x0A, 0x0A, 0x0A], // 0x0A: [0x0A, 0x0A, 0x0A], //
0x0B: [0x0B, 0x0B, 0x0B], // 0x0B: [0x0B, 0x0B, 0x0B], //
0x0C: [0x0C, 0x0C, 0x0C], // 0x0C: [0x0C, 0x0C, 0x0C], //
0x0D: [0x0D, 0x0D, 0x0D], // CR 0x0D: [0x0D, 0x0D, 0x0D], // CR
0x0E: [0x0E, 0x0E, 0x0E], // 0x0E: [0x0E, 0x0E, 0x0E], //
0x0F: [0x0F, 0x0F, 0x0F], // 0x0F: [0x0F, 0x0F, 0x0F], //
0x10: [0xff, 0xff, 0xff], // SHIFT 0x10: [0xff, 0xff, 0xff], // SHIFT
0x11: [0xff, 0xff, 0xff], // CTRL 0x11: [0xff, 0xff, 0xff], // CTRL
0x12: [0xff, 0xff, 0xff], // ALT/OPTION 0x12: [0xff, 0xff, 0xff], // ALT/OPTION
0x13: [0x13, 0x13, 0x13], // 0x13: [0x13, 0x13, 0x13], //
0x14: [0x14, 0x14, 0x14], // 0x14: [0x14, 0x14, 0x14], //
0x15: [0x15, 0x15, 0x15], // 0x15: [0x15, 0x15, 0x15], //
0x16: [0x16, 0x16, 0x16], // 0x16: [0x16, 0x16, 0x16], //
0x17: [0x17, 0x17, 0x18], // 0x17: [0x17, 0x17, 0x18], //
0x18: [0x18, 0x18, 0x18], // 0x18: [0x18, 0x18, 0x18], //
0x19: [0x19, 0x19, 0x19], // 0x19: [0x19, 0x19, 0x19], //
0x1A: [0x1A, 0x1A, 0x1A], // 0x1A: [0x1A, 0x1A, 0x1A], //
0x1B: [0x1B, 0x1B, 0x1B], // ESC 0x1B: [0x1B, 0x1B, 0x1B], // ESC
0x1C: [0x1C, 0x1C, 0x1C], // 0x1C: [0x1C, 0x1C, 0x1C], //
0x1D: [0x1D, 0x1D, 0x1D], // 0x1D: [0x1D, 0x1D, 0x1D], //
0x1E: [0x1E, 0x1E, 0x1E], // 0x1E: [0x1E, 0x1E, 0x1E], //
0x1F: [0x1F, 0x1F, 0x1F], // 0x1F: [0x1F, 0x1F, 0x1F], //
// Most of these besides space won't happen // Most of these besides space won't happen
0x20: [0x20, 0x20, 0x20], // 0x20: [0x20, 0x20, 0x20], //
0x21: [0x21, 0x21, 0x21], // 0x21: [0x21, 0x21, 0x21], //
0x22: [0x22, 0x22, 0x22], // 0x22: [0x22, 0x22, 0x22], //
0x23: [0x23, 0x23, 0x23], // 0x23: [0x23, 0x23, 0x23], //
0x24: [0x24, 0x24, 0x24], // 0x24: [0x24, 0x24, 0x24], //
0x25: [0x08, 0x08, 0x08], // <- left 0x25: [0x08, 0x08, 0x08], // <- left
0x26: [0x0B, 0x0B, 0x0B], // ^ up 0x26: [0x0B, 0x0B, 0x0B], // ^ up
0x27: [0x15, 0x15, 0x15], // -> right 0x27: [0x15, 0x15, 0x15], // -> right
@ -69,7 +69,7 @@ function KeyBoard(io) {
0x2D: [0x2D, 0x2D, 0x5F], // - - _ 0x2D: [0x2D, 0x2D, 0x5F], // - - _
0x2E: [0x2E, 0x2E, 0x3E], // . - > 0x2E: [0x2E, 0x2E, 0x3E], // . - >
0x2F: [0x2F, 0x2F, 0x3F], // / - ? 0x2F: [0x2F, 0x2F, 0x3F], // / - ?
0x30: [0x30, 0x30, 0x29], // 0 - ) 0x30: [0x30, 0x30, 0x29], // 0 - )
0x31: [0x31, 0x31, 0x21], // 1 - ! 0x31: [0x31, 0x31, 0x21], // 1 - !
0x32: [0x32, 0x00, 0x40], // 2 - @ 0x32: [0x32, 0x00, 0x40], // 2 - @
@ -86,7 +86,7 @@ function KeyBoard(io) {
0x3D: [0x3D, 0x3D, 0x2B], // = - + 0x3D: [0x3D, 0x3D, 0x2B], // = - +
0x3E: [0x3E, 0x3E, 0x3E], // > 0x3E: [0x3E, 0x3E, 0x3E], // >
0x3F: [0x3F, 0x3F, 0x3F], // ? 0x3F: [0x3F, 0x3F, 0x3F], // ?
// Alpha and control // Alpha and control
0x40: [0x40, 0x00, 0x40], // @ 0x40: [0x40, 0x00, 0x40], // @
0x41: [0x61, 0x01, 0x41], // A 0x41: [0x61, 0x01, 0x41], // A
@ -99,12 +99,12 @@ function KeyBoard(io) {
0x48: [0x68, 0x08, 0x48], // H 0x48: [0x68, 0x08, 0x48], // H
0x49: [0x69, 0x09, 0x49], // I - TAB 0x49: [0x69, 0x09, 0x49], // I - TAB
0x4A: [0x6A, 0x0A, 0x4A], // J - NL 0x4A: [0x6A, 0x0A, 0x4A], // J - NL
0x4B: [0x6B, 0x0B, 0x4B], // K - VT 0x4B: [0x6B, 0x0B, 0x4B], // K - VT
0x4C: [0x6C, 0x0C, 0x4C], // L 0x4C: [0x6C, 0x0C, 0x4C], // L
0x4D: [0x6D, 0x0D, 0x4D], // M - CR 0x4D: [0x6D, 0x0D, 0x4D], // M - CR
0x4E: [0x6E, 0x0E, 0x4E], // N 0x4E: [0x6E, 0x0E, 0x4E], // N
0x4F: [0x6F, 0x0F, 0x4F], // O 0x4F: [0x6F, 0x0F, 0x4F], // O
0x50: [0x70, 0x10, 0x50], // P 0x50: [0x70, 0x10, 0x50], // P
0x51: [0x71, 0x11, 0x51], // Q 0x51: [0x71, 0x11, 0x51], // Q
0x52: [0x72, 0x12, 0x52], // R 0x52: [0x72, 0x12, 0x52], // R
@ -119,7 +119,7 @@ function KeyBoard(io) {
0x5B: [0xFF, 0xFF, 0xFF], // Left window 0x5B: [0xFF, 0xFF, 0xFF], // Left window
0x5C: [0xFF, 0xFF, 0xFF], // Right window 0x5C: [0xFF, 0xFF, 0xFF], // Right window
0x5D: [0xFF, 0xFF, 0xFF], // Select 0x5D: [0xFF, 0xFF, 0xFF], // Select
0x5E: [0x5E, 0x1E, 0x5E], // 0x5E: [0x5E, 0x1E, 0x5E], //
0x5F: [0x5F, 0x1F, 0x5F], // _ 0x5F: [0x5F, 0x1F, 0x5F], // _
// Numeric pad // Numeric pad
@ -139,7 +139,7 @@ function KeyBoard(io) {
0x6D: [0x2D, 0x2D, 0x2D], // - 0x6D: [0x2D, 0x2D, 0x2D], // -
0x6E: [0x2E, 0x2E, 0x2E], // . 0x6E: [0x2E, 0x2E, 0x2E], // .
0x6F: [0x2F, 0x2F, 0x39], // / 0x6F: [0x2F, 0x2F, 0x39], // /
// Stray keys // Stray keys
0xBA: [0x3B, 0x3B, 0x3A], // ; - : 0xBA: [0x3B, 0x3B, 0x3A], // ; - :
0xBB: [0x3D, 0x3D, 0x2B], // = - + 0xBB: [0x3D, 0x3D, 0x2B], // = - +
@ -151,23 +151,23 @@ function KeyBoard(io) {
0xDB: [0x5B, 0x5B, 0x7B], // [ 0xDB: [0x5B, 0x5B, 0x7B], // [
0xDC: [0x5C, 0x5C, 0x7C], // \ 0xDC: [0x5C, 0x5C, 0x7C], // \
0xDD: [0x5D, 0x5D, 0x7D], // ] 0xDD: [0x5D, 0x5D, 0x7D], // ]
0xDE: [0x27, 0x22, 0x22], // ' - " 0xDE: [0x27, 0x22, 0x22], // ' - '
0xFF: [0xFF, 0xFF, 0xFF] // No comma line 0xFF: [0xFF, 0xFF, 0xFF] // No comma line
}; };
var keys = var keys =
[[['ESC','1','2','3','4','5','6','7','8','9','0','-','=','DELETE'], [[['ESC','1','2','3','4','5','6','7','8','9','0','-','=','DELETE'],
['TAB','Q','W','E','R','T','Y','U','I','O','P','[',']','\\'], ['TAB','Q','W','E','R','T','Y','U','I','O','P','[',']','\\'],
['CTRL','A','S','D','F','G','H','J','K','L',';','\'','RETURN'], ['CTRL','A','S','D','F','G','H','J','K','L',';','"','RETURN'],
['SHIFT','Z','X','C','V','B','N','M',',','.','/','SHIFT'], ['SHIFT','Z','X','C','V','B','N','M',',','.','/','SHIFT'],
['LOCK','`','POW','OPEN_APPLE','&nbsp;','CLOSED_APPLE','&larr;','&rarr;','&darr;','&uarr;']], ['LOCK','`','POW','OPEN_APPLE','&nbsp;','CLOSED_APPLE','&larr;','&rarr;','&darr;','&uarr;']],
[['ESC','!','@','#','$','%','^','&',"*",'(',')','_','+','DELETE'], [['ESC','!','@','#','$','%','^','&','*','(',')','_','+','DELETE'],
['TAB','Q','W','E','R','T','Y','U','I','O','P','{','}','|'], ['TAB','Q','W','E','R','T','Y','U','I','O','P','{','}','|'],
['CTRL','A','S','D','F','G','H','J','K','L',':','"','RETURN'], ['CTRL','A','S','D','F','G','H','J','K','L',':','\'','RETURN'],
['SHIFT','Z','X','C','V','B','N','M','<','>','?','SHIFT'], ['SHIFT','Z','X','C','V','B','N','M','<','>','?','SHIFT'],
['CAPS','~','POW','OPEN_APPLE','&nbsp;','CLOSED_APPLE','&larr;','&rarr;','&darr;','&uarr;']]]; ['CAPS','~','POW','OPEN_APPLE','&nbsp;','CLOSED_APPLE','&larr;','&rarr;','&darr;','&uarr;']]];
var shifted = false; var shifted = false;
var controlled = false; var controlled = false;
var capslocked = true; var capslocked = true;
@ -177,15 +177,15 @@ function KeyBoard(io) {
return { return {
mapKeyEvent: function keyboard_mapKeyEvent(evt) { mapKeyEvent: function keyboard_mapKeyEvent(evt) {
var code = evt.keyCode, key = 0xff; var code = evt.keyCode, key = 0xff;
if (code in keymap) { if (code in keymap) {
key = keymap[code][evt.shiftKey ? 2 : (evt.ctrlKey ? 1 : 0)]; key = keymap[code][evt.shiftKey ? 2 : (evt.ctrlKey ? 1 : 0)];
if (capslocked && key >= 0x61 && key <= 0x7A) if (capslocked && key >= 0x61 && key <= 0x7A)
key -= 0x20; key -= 0x20;
} else { } else {
debug("Unhandled key = " + toHex(code)); debug('Unhandled key = ' + toHex(code));
} }
return key; return key;
}, },
@ -193,19 +193,19 @@ function KeyBoard(io) {
shifted = down; shifted = down;
if (down) { if (down) {
io.buttonDown(2); io.buttonDown(2);
$("#keyboard .key-SHIFT").addClass("active"); $('#keyboard .key-SHIFT').addClass('active');
} else { } else {
io.buttonUp(2); io.buttonUp(2);
$("#keyboard .key-SHIFT").removeClass("active"); $('#keyboard .key-SHIFT').removeClass('active');
} }
}, },
controlKey: function keyboard_controlKey(down) { controlKey: function keyboard_controlKey(down) {
controlled = down; controlled = down;
if (down) { if (down) {
$("#keyboard .key-CTRL").addClass("active"); $('#keyboard .key-CTRL').addClass('active');
} else { } else {
$("#keyboard .key-CTRL").removeClass("active"); $('#keyboard .key-CTRL').removeClass('active');
} }
}, },
@ -213,10 +213,10 @@ function KeyBoard(io) {
commanded = down; commanded = down;
if (down) { if (down) {
io.buttonDown(0); io.buttonDown(0);
$("#keyboard .key-OPEN_APPLE").addClass("active"); $('#keyboard .key-OPEN_APPLE').addClass('active');
} else { } else {
io.buttonUp(0); io.buttonUp(0);
$("#keyboard .key-OPEN_APPLE").removeClass("active"); $('#keyboard .key-OPEN_APPLE').removeClass('active');
} }
}, },
@ -224,106 +224,106 @@ function KeyBoard(io) {
optioned = down; optioned = down;
if (down) { if (down) {
io.buttonDown(1); io.buttonDown(1);
$("#keyboard .key-CLOSED_APPLE").addClass("active"); $('#keyboard .key-CLOSED_APPLE').addClass('active');
} else { } else {
io.buttonUp(1); io.buttonUp(1);
$("#keyboard .key-CLOSED_APPLE").removeClass("active"); $('#keyboard .key-CLOSED_APPLE').removeClass('active');
} }
}, },
capslockKey: function keyboard_caplockKey(down) { capslockKey: function keyboard_caplockKey(down) {
capslocked = down; capslocked = down;
if (down) { if (down) {
$("#keyboard .key-LOCK").addClass("active"); $('#keyboard .key-LOCK').addClass('active');
} else { } else {
$("#keyboard .key-LOCK").removeClass("active"); $('#keyboard .key-LOCK').removeClass('active');
} }
}, },
create: function keyboard_create(kb) { create: function keyboard_create(kb) {
var x, y, row, key, key1, key2, label, label1, label2, self = this; var x, y, row, key, key1, key2, label, label1, label2, self = this;
kb.disableSelection(); kb.disableSelection();
function buildLabel(k) { function buildLabel(k) {
var span = $("<span>" + k + "</span>"); var span = $('<span>' + k + '</span>');
if (k.length > 1 && k.substr(0,1) != '&') if (k.length > 1 && k.substr(0,1) != '&')
span.addClass("small"); span.addClass('small');
return span; return span;
} }
function _mouseup(ev) { function _mouseup(ev) {
$(ev.currentTarget).removeClass("pressed"); $(ev.currentTarget).removeClass('pressed');
} }
function _mousedown(ev) { function _mousedown(ev) {
$(this).addClass("pressed"); $(this).addClass('pressed');
var key = $(ev.currentTarget).data(shifted ? "key2" : "key1"); var key = $(ev.currentTarget).data(shifted ? 'key2' : 'key1');
switch (key) { switch (key) {
case "BELL": case 'BELL':
key = "G"; key = 'G';
break; break;
case "RETURN": case 'RETURN':
key = "\r"; key = '\r';
break; break;
case "TAB": case 'TAB':
key = "\t"; key = '\t';
break; break;
case "DELETE": case 'DELETE':
key = "\0177"; key = '\0177';
break; break;
case "&larr;": case '&larr;':
key = "\010"; key = '\010';
break; break;
case "&rarr;": case '&rarr;':
key = "\025"; key = '\025';
break; break;
case "&darr;": case '&darr;':
key = "\012"; key = '\012';
break; break;
case "&uarr;": case '&uarr;':
key = "\013"; key = '\013';
break; break;
case "&nbsp;": case '&nbsp;':
key = " "; key = ' ';
break; break;
case "ESC": case 'ESC':
key = "\033"; key = '\033';
break; break;
default: default:
break; break;
} }
if (key.length > 1) { if (key.length > 1) {
switch (key) { switch (key) {
case "SHIFT": case 'SHIFT':
self.shiftKey(!shifted); self.shiftKey(!shifted);
break; break;
case "CTRL": case 'CTRL':
self.controlKey(!controlled); self.controlKey(!controlled);
break; break;
case "CAPS": case 'CAPS':
case "LOCK": case 'LOCK':
self.capslockKey(!capslocked); self.capslockKey(!capslocked);
break; break;
case "POW": case 'POW':
if (window.confirm("Power Cycle?")) if (window.confirm('Power Cycle?'))
window.location.reload(); window.location.reload();
break; break;
case "OPEN_APPLE": case 'OPEN_APPLE':
self.commandKey(!commanded); self.commandKey(!commanded);
break; break;
case "CLOSED_APPLE": case 'CLOSED_APPLE':
self.optionKey(!optioned); self.optionKey(!optioned);
break; break;
default: default:
break; break;
} }
} else { } else {
if (controlled && key >= "@" && key <= "_") { if (controlled && key >= '@' && key <= '_') {
io.keyDown(key.charCodeAt(0) - 0x40); io.keyDown(key.charCodeAt(0) - 0x40);
} else if (!shifted && !capslocked && } else if (!shifted && !capslocked &&
key >= 'A' && key <= 'Z') { key >= 'A' && key <= 'Z') {
io.keyDown(key.charCodeAt(0) + 0x20); io.keyDown(key.charCodeAt(0) + 0x20);
} else { } else {
@ -333,43 +333,43 @@ function KeyBoard(io) {
} }
for (y = 0; y < 5; y++) { for (y = 0; y < 5; y++) {
row = $("<div class='row row" + y + "e'/>"); row = $('<div class="row row' + y + 'e"/>');
kb.append(row); kb.append(row);
for (x = 0; x < keys[0][y].length; x++) { for (x = 0; x < keys[0][y].length; x++) {
key1 = keys[0][y][x]; key1 = keys[0][y][x];
key2 = keys[1][y][x]; key2 = keys[1][y][x];
label = $("<div />"); label = $('<div />');
label1 = buildLabel(key1); label1 = buildLabel(key1);
label2 = buildLabel(key2); label2 = buildLabel(key2);
key = $("<div class='key'>"); key = $('<div class="key">');
key.addClass("key-" + key1.replace(/[&#;]/g,"")); key.addClass('key-' + key1.replace(/[&#;]/g,''));
if (key1.length > 1) { if (key1.length > 1) {
if (key1 == "LOCK") if (key1 == 'LOCK')
key.addClass("vcenter2"); key.addClass('vcenter2');
else else
key.addClass("vcenter"); key.addClass('vcenter');
} }
if (key1 != key2) { if (key1 != key2) {
key.addClass("key-" + key2.replace(/[&;]/g,"")); key.addClass('key-' + key2.replace(/[&;]/g,''));
label.append(label2); label.append(label2);
label.append("<br/>"); label.append('<br/>');
} }
if (key1 == "LOCK") if (key1 == 'LOCK')
key.addClass("active"); key.addClass('active');
label.append(label1); label.append(label1);
key.append(label); key.append(label);
key.data({"key1": key1, "key2": key2}); key.data({'key1': key1, 'key2': key2});
if (window.ontouchstart === undefined) { if (window.ontouchstart === undefined) {
key.bind("mousedown", _mousedown); key.bind('mousedown', _mousedown);
key.bind("mouseup mouseout", _mouseup); key.bind('mouseup mouseout', _mouseup);
} else { } else {
key.bind("touchstart", _mousedown); key.bind('touchstart', _mousedown);
key.bind("touchend touchleave", _mouseup); key.bind('touchend touchleave', _mouseup);
} }
row.append(key); row.append(key);
@ -380,4 +380,3 @@ function KeyBoard(io) {
} }
}; };
} }

View File

@ -1,4 +1,3 @@
/*jshint browser:true */
/*exported Printer */ /*exported Printer */
function Printer() { function Printer() {
@ -6,21 +5,20 @@ function Printer() {
return { return {
putChar: function(val) { putChar: function(val) {
if (!_printer || _printer.closed) { if (!_printer || _printer.closed) {
_printer = window.open("", "_blank","toolbar=0,location=0"); _printer = window.open('', '_blank','toolbar=0,location=0');
_printer.document.title = "Printer"; _printer.document.title = 'Printer';
_printer.document.write("<div style='font: 12px courier'>"); _printer.document.write('<div style="font: 12px courier">');
_printer.document.write("<span>"); _printer.document.write('<span>');
window.focus(); window.focus();
} }
var c = String.fromCharCode(val & 0x7f); var c = String.fromCharCode(val & 0x7f);
if (c == '\r') { if (c == '\r') {
_printer.document.write("<br /></span>"); _printer.document.write('<br /></span>');
} else if (c == ' ') { } else if (c == ' ') {
_printer.document.write("&nbsp;"); _printer.document.write('&nbsp;');
} else { } else {
_printer.document.write(c); _printer.document.write(c);
} }
} }
}; };
} }

View File

@ -1,5 +1,4 @@
/* -*- mode: JavaScript; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
/* Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com>
* *
* Permission to use, copy, modify, distribute, and sell this software and its * Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that * documentation for any purpose is hereby granted without fee, provided that
@ -10,8 +9,10 @@
* implied warranty. * implied warranty.
*/ */
/*jshint rhino:true, browser: true, devel: true */ /*eslint no-console: 0*/
/*exported allocMem, allocMemPages, bytify, debug, toHex, toBinary, extend, gup, hup, each */ /*exported allocMemPages, bytify, debug, each extend, gup, hup, toBinary, toHex
*/
/*global Uint8Array: false */
if (!Date.now) { if (!Date.now) {
Date.now = function now() { Date.now = function now() {
@ -19,8 +20,8 @@ if (!Date.now) {
}; };
} }
var hex_digits = "0123456789ABCDEF"; var hex_digits = '0123456789ABCDEF';
var bin_digits = "01"; var bin_digits = '01';
function allocMem(size) { function allocMem(size) {
var result; var result;
@ -46,16 +47,14 @@ function bytify(ary) {
function extend(ary1, ary2) { function extend(ary1, ary2) {
ary2.forEach(function(val) { ary2.forEach(function(val) {
ary1.push(val); ary1.push(val);
}); });
return ary1; return ary1;
} }
function debug(msg) { function debug() {
if (typeof(console) != 'undefined' && 'log' in console) { if (typeof console != 'undefined' && 'log' in console) {
console.log(msg); console.log.apply(console, arguments);
} else if (typeof(environment) == 'object') { // rhino shell
print(msg);
} }
} }
@ -63,7 +62,7 @@ function toHex(v, n) {
if (!n) { if (!n) {
n = v < 256 ? 2 : 4; n = v < 256 ? 2 : 4;
} }
var result = ""; var result = '';
for (var idx = 0; idx < n; idx++) { for (var idx = 0; idx < n; idx++) {
result = hex_digits[v & 0x0f] + result; result = hex_digits[v & 0x0f] + result;
v >>= 4; v >>= 4;
@ -72,7 +71,7 @@ function toHex(v, n) {
} }
function toBinary(v) { function toBinary(v) {
var result = ""; var result = '';
for (var idx = 0; idx < 8; idx++) { for (var idx = 0; idx < 8; idx++) {
result = bin_digits[v & 0x01] + result; result = bin_digits[v & 0x01] + result;
v >>= 1; v >>= 1;
@ -83,25 +82,25 @@ function toBinary(v) {
// From http://www.netlobo.com/url_query_string_javascript.html // From http://www.netlobo.com/url_query_string_javascript.html
function gup( name ) function gup( name )
{ {
name = name.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]"); name = name.replace(/[\[]/,'\\[').replace(/[\]]/,'\\]');
var regexS = "[\\?&]"+name+"=([^&#]*)"; var regexS = '[\\?&]'+name+'=([^&#]*)';
var regex = new RegExp( regexS ); var regex = new RegExp( regexS );
var results = regex.exec( window.location.href ); var results = regex.exec( window.location.href );
if( !results ) if( !results )
return ""; return '';
else
return results[1];
}
function hup() {
var regex = new RegExp("#(.*)");
var results = regex.exec(window.location.hash);
if ( !results )
return "";
else else
return results[1]; return results[1];
} }
function hup() {
var regex = new RegExp('#(.*)');
var results = regex.exec(window.location.hash);
if ( !results )
return '';
else
return results[1];
}
function keys(obj) { function keys(obj) {
var result = []; var result = [];
for (var key in obj) { for (var key in obj) {

View File

@ -1,5 +1,5 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
# Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com> # Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
# #
# Permission to use, copy, modify, distribute, and sell this software and its # Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that # documentation for any purpose is hereby granted without fee, provided that

View File

@ -1,5 +1,5 @@
#!/usr/bin/env perl -w #!/usr/bin/env perl -w
# Copyright 2010-2013 Will Scullin <scullin@scullinsteel.com> # Copyright 2010-2016 Will Scullin <scullin@scullinsteel.com>
# #
# Permission to use, copy, modify, distribute, and sell this software and its # Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that # documentation for any purpose is hereby granted without fee, provided that