mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
Merge pull request #1 from whscullin/whscullin/cleanup-refactor
Cleanup and refactoring.
This commit is contained in:
commit
9bd56466b4
14
.editorconfig
Normal file
14
.editorconfig
Normal 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
25
.eslintrc.json
Normal 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"
|
||||||
|
}
|
22
about.html
22
about.html
@ -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>
|
||||||
|
769
apple2js.html
769
apple2js.html
@ -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">
|
||||||
|
772
apple2jse.html
772
apple2jse.html
@ -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">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2010-2013 Will Scullin */
|
/* Copyright 2010-2016 Will Scullin */
|
||||||
|
|
||||||
.disklabel {
|
.disklabel {
|
||||||
color: #000;
|
color: #000;
|
||||||
|
523
js/apple2char.js
523
js/apple2char.js
@ -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);
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
1035
js/apple2echar.js
1035
js/apple2echar.js
File diff suppressed because it is too large
Load Diff
@ -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
173
js/applesoft/decompiler.js
Normal 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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
28
js/base64.js
28
js/base64.js
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
220
js/canvas2e.js
220
js/canvas2e.js
@ -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) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
581
js/cpu6502.js
581
js/cpu6502.js
File diff suppressed because it is too large
Load Diff
159
js/disk2.js
159
js/disk2.js
@ -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++) {
|
||||||
|
@ -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;
|
||||||
|
@ -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() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
876
js/main2.js
Normal 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
877
js/main2e.js
Normal 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');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
47
js/mmu.js
47
js/mmu.js
@ -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;
|
||||||
|
|
||||||
|
@ -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() {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
12
js/prefs.js
12
js/prefs.js
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
1474
js/symbols.js
1474
js/symbols.js
File diff suppressed because it is too large
Load Diff
@ -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)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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',';','←','→'],
|
['CTRL','A','S','D','F','G','H','J','K','L',';','←','→'],
|
||||||
['SHIFT','Z','X','C','V','B','N','M',',','.','/','SHIFT'],
|
['SHIFT','Z','X','C','V','B','N','M',',','.','/','SHIFT'],
|
||||||
['POWER', ' ']],
|
['POWER', ' ']],
|
||||||
[['!','"','#','$','%','&',"'",'(',')','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','+','←','→'],
|
['CTRL','A','S','D','F','BELL','H','J','K','L','+','←','→'],
|
||||||
['SHIFT','Z','X','C','V','B','^',']','<','>','?','SHIFT'],
|
['SHIFT','Z','X','C','V','B','^',']','<','>','?','SHIFT'],
|
||||||
['POWER', ' ']]];
|
['POWER', ' ']]];
|
||||||
|
|
||||||
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 "←":
|
case '←':
|
||||||
key = "\010";
|
key = '\010';
|
||||||
break;
|
break;
|
||||||
case "→":
|
case '→':
|
||||||
key = "\025";
|
key = '\025';
|
||||||
break;
|
break;
|
||||||
case " ":
|
case ' ':
|
||||||
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) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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',' ','CLOSED_APPLE','←','→','↓','↑']],
|
['LOCK','`','POW','OPEN_APPLE',' ','CLOSED_APPLE','←','→','↓','↑']],
|
||||||
[['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',' ','CLOSED_APPLE','←','→','↓','↑']]];
|
['CAPS','~','POW','OPEN_APPLE',' ','CLOSED_APPLE','←','→','↓','↑']]];
|
||||||
|
|
||||||
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 "←":
|
case '←':
|
||||||
key = "\010";
|
key = '\010';
|
||||||
break;
|
break;
|
||||||
case "→":
|
case '→':
|
||||||
key = "\025";
|
key = '\025';
|
||||||
break;
|
break;
|
||||||
case "↓":
|
case '↓':
|
||||||
key = "\012";
|
key = '\012';
|
||||||
break;
|
break;
|
||||||
case "↑":
|
case '↑':
|
||||||
key = "\013";
|
key = '\013';
|
||||||
break;
|
break;
|
||||||
case " ":
|
case ' ':
|
||||||
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) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(" ");
|
_printer.document.write(' ');
|
||||||
} else {
|
} else {
|
||||||
_printer.document.write(c);
|
_printer.document.write(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
59
js/util.js
59
js/util.js
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user