mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-06-01 20:41:36 +00:00
added apple II display, sound; more tools; acme, plasm (PLASMA); platform switch
This commit is contained in:
parent
9391cafac6
commit
346bab90fd
57
index.html
57
index.html
|
@ -100,6 +100,7 @@ div.booklink {
|
||||||
right: 0;
|
right: 0;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
display:none;
|
||||||
}
|
}
|
||||||
div.twitbtn {
|
div.twitbtn {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -115,6 +116,48 @@ a.dropdown-toggle {
|
||||||
color:#66ee66;
|
color:#66ee66;
|
||||||
padding:3px;
|
padding:3px;
|
||||||
}
|
}
|
||||||
|
// http://stackoverflow.com/questions/18023493/bootstrap-3-dropdown-sub-menu-missing
|
||||||
|
.dropdown-submenu {
|
||||||
|
position:relative;
|
||||||
|
}
|
||||||
|
.dropdown-submenu>.dropdown-menu {
|
||||||
|
top:0;
|
||||||
|
left:100%;
|
||||||
|
margin-top:-6px;
|
||||||
|
margin-left:-1px;
|
||||||
|
-webkit-border-radius:0 6px 6px 6px;
|
||||||
|
-moz-border-radius:0 6px 6px 6px;
|
||||||
|
border-radius:0 6px 6px 6px;
|
||||||
|
}
|
||||||
|
.dropdown-submenu:hover>.dropdown-menu {
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
.dropdown-submenu>a:after {
|
||||||
|
display:block;
|
||||||
|
content:" ";
|
||||||
|
float:right;
|
||||||
|
width:0;
|
||||||
|
height:0;
|
||||||
|
border-color:transparent;
|
||||||
|
border-style:solid;
|
||||||
|
border-width:5px 0 5px 5px;
|
||||||
|
border-left-color:#cccccc;
|
||||||
|
margin-top:5px;
|
||||||
|
margin-right:-10px;
|
||||||
|
}
|
||||||
|
.dropdown-submenu:hover>a:after {
|
||||||
|
border-left-color:#ffffff;
|
||||||
|
}
|
||||||
|
.dropdown-submenu.pull-left {
|
||||||
|
float:none;
|
||||||
|
}
|
||||||
|
.dropdown-submenu.pull-left>.dropdown-menu {
|
||||||
|
left:-100%;
|
||||||
|
margin-left:10px;
|
||||||
|
-webkit-border-radius:6px 0 6px 6px;
|
||||||
|
-moz-border-radius:6px 0 6px 6px;
|
||||||
|
border-radius:6px 0 6px 6px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -130,6 +173,14 @@ a.dropdown-toggle {
|
||||||
<li><a class="dropdown-item" href="#" id="item_new_file">New File...</a></li>
|
<li><a class="dropdown-item" href="#" id="item_new_file">New File...</a></li>
|
||||||
<li><a class="dropdown-item" href="#" id="item_share_file">Share File...</a></li>
|
<li><a class="dropdown-item" href="#" id="item_share_file">Share File...</a></li>
|
||||||
<li><a class="dropdown-item" href="#" id="item_reset_file">Reset to Original...</a></li>
|
<li><a class="dropdown-item" href="#" id="item_reset_file">Reset to Original...</a></li>
|
||||||
|
<li class="dropdown dropdown-submenu">
|
||||||
|
<a tabindex="-1" href="#">Platform</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a class="dropdown-item" href="?platform=vcs" id="item_platform_vcs">Atari VCS</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=apple2" id="item_platform_apple2">Apple ][</a></li>
|
||||||
|
<li><a class="dropdown-item" href="?platform=atarivec" id="item_platform_atarivec">Asteroids</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
<select id="preset_select" name="">
|
<select id="preset_select" name="">
|
||||||
|
@ -155,7 +206,7 @@ a.dropdown-toggle {
|
||||||
<div class="twitbtn">
|
<div class="twitbtn">
|
||||||
<a href="https://twitter.com/8bitworkshop" class="twitter-follow-button" data-show-count="false">Follow @8bitworkshop</a><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
|
<a href="https://twitter.com/8bitworkshop" class="twitter-follow-button" data-show-count="false">Follow @8bitworkshop</a><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||||
</div>
|
</div>
|
||||||
<div class="booklink">
|
<div class="booklink" id="booklink_vcs">
|
||||||
<!--
|
<!--
|
||||||
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0"
|
<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0"
|
||||||
src="http://ws-na.amazon-adsystem.com/widgets/q?ServiceVersion=20070822&OneJS=1&Operation=GetAdHtml&MarketPlace=US&source=ac&ref=tf_til&ad_type=product_link&tracking_id=pzp-20&marketplace=amazon®ion=US&placement=B01N4DSRIZ&asins=B01N4DSRIZ&linkId=67b114b83ce0b13ceaf715ee86833626&show_border=true&link_opens_in_new_window=false&price_color=333333&title_color=0066c0&bg_color=7d6d6d">
|
src="http://ws-na.amazon-adsystem.com/widgets/q?ServiceVersion=20070822&OneJS=1&Operation=GetAdHtml&MarketPlace=US&source=ac&ref=tf_til&ad_type=product_link&tracking_id=pzp-20&marketplace=amazon®ion=US&placement=B01N4DSRIZ&asins=B01N4DSRIZ&linkId=67b114b83ce0b13ceaf715ee86833626&show_border=true&link_opens_in_new_window=false&price_color=333333&title_color=0066c0&bg_color=7d6d6d">
|
||||||
|
@ -172,8 +223,8 @@ a.dropdown-toggle {
|
||||||
<script src="jquery/jquery-2.2.3.min.js"></script>
|
<script src="jquery/jquery-2.2.3.min.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
|
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="bootstrap/css/bootstrap-tour.min.css">
|
|
||||||
<script src="bootstrap/js/bootstrap.min.js"></script>
|
<script src="bootstrap/js/bootstrap.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="bootstrap/css/bootstrap-tour.min.css">
|
||||||
<script src="bootstrap/js/bootstrap-tour.min.js"></script>
|
<script src="bootstrap/js/bootstrap-tour.min.js"></script>
|
||||||
|
|
||||||
<script src="codemirror/lib/codemirror.js"></script>
|
<script src="codemirror/lib/codemirror.js"></script>
|
||||||
|
@ -188,6 +239,7 @@ a.dropdown-toggle {
|
||||||
|
|
||||||
<script src="javatari.js/release/javatari/javatari.js"></script>
|
<script src="javatari.js/release/javatari/javatari.js"></script>
|
||||||
<script src="src/emu.js"></script>
|
<script src="src/emu.js"></script>
|
||||||
|
<script src="src/util.js"></script>
|
||||||
<script src="src/platform/vcs.js"></script>
|
<script src="src/platform/vcs.js"></script>
|
||||||
<script src="src/platform/apple2.js"></script>
|
<script src="src/platform/apple2.js"></script>
|
||||||
<script src="src/platform/atarivec.js"></script>
|
<script src="src/platform/atarivec.js"></script>
|
||||||
|
@ -202,6 +254,5 @@ a.dropdown-toggle {
|
||||||
|
|
||||||
ga('create', 'UA-54497476-9', 'auto');
|
ga('create', 'UA-54497476-9', 'auto');
|
||||||
ga('send', 'pageview');
|
ga('send', 'pageview');
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
|
28715
js/acme.js
Normal file
28715
js/acme.js
Normal file
File diff suppressed because one or more lines are too long
21378
js/plasm.js
Normal file
21378
js/plasm.js
Normal file
File diff suppressed because one or more lines are too long
153
src/emu.js
153
src/emu.js
|
@ -2,28 +2,33 @@
|
||||||
|
|
||||||
// Emulator classes
|
// Emulator classes
|
||||||
|
|
||||||
|
function __createCanvas(mainElement, width, height) {
|
||||||
|
// TODO
|
||||||
|
var fsElement = document.createElement('div');
|
||||||
|
fsElement.style.position = "relative";
|
||||||
|
fsElement.style.padding = "20px";
|
||||||
|
fsElement.style.overflow = "hidden";
|
||||||
|
fsElement.style.background = "black";
|
||||||
|
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
canvas.style.width = "100%";
|
||||||
|
canvas.style.height = "100%";
|
||||||
|
canvas.tabIndex = "-1"; // Make it focusable
|
||||||
|
|
||||||
|
fsElement.appendChild(canvas);
|
||||||
|
mainElement.appendChild(fsElement);
|
||||||
|
return canvas;
|
||||||
|
}
|
||||||
|
|
||||||
var RasterVideo = function(mainElement, width, height, options) {
|
var RasterVideo = function(mainElement, width, height, options) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var canvas, ctx;
|
var canvas, ctx;
|
||||||
var imageData, buf8, datau32;
|
var imageData, buf8, datau32;
|
||||||
|
|
||||||
this.start = function() {
|
this.start = function() {
|
||||||
// TODO
|
canvas = __createCanvas(mainElement, width, height);
|
||||||
fsElement = document.createElement('div');
|
|
||||||
fsElement.style.position = "relative";
|
|
||||||
fsElement.style.padding = "50px";
|
|
||||||
//fsElement.style.width = "100%";
|
|
||||||
//fsElement.style.height = "100%";
|
|
||||||
fsElement.style.overflow = "hidden";
|
|
||||||
fsElement.style.background = "black";
|
|
||||||
|
|
||||||
canvas = document.createElement('canvas');
|
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
|
|
||||||
fsElement.appendChild(canvas);
|
|
||||||
mainElement.appendChild(fsElement);
|
|
||||||
|
|
||||||
ctx = canvas.getContext('2d');
|
ctx = canvas.getContext('2d');
|
||||||
imageData = ctx.createImageData(width, height);
|
imageData = ctx.createImageData(width, height);
|
||||||
var buf = new ArrayBuffer(imageData.data.length);
|
var buf = new ArrayBuffer(imageData.data.length);
|
||||||
|
@ -93,23 +98,7 @@ var VectorVideo = function(mainElement, width, height) {
|
||||||
var jitter = 1.0;
|
var jitter = 1.0;
|
||||||
|
|
||||||
this.start = function() {
|
this.start = function() {
|
||||||
// TODO
|
canvas = __createCanvas(mainElement, width, height);
|
||||||
var fsElement = document.createElement('div');
|
|
||||||
fsElement.style.position = "relative";
|
|
||||||
fsElement.style.padding = "20px";
|
|
||||||
fsElement.style.overflow = "hidden";
|
|
||||||
fsElement.style.background = "black";
|
|
||||||
|
|
||||||
canvas = document.createElement('canvas');
|
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
canvas.style.width = "100%";
|
|
||||||
canvas.style.height = "100%";
|
|
||||||
canvas.tabIndex = "-1"; // Make it focusable
|
|
||||||
|
|
||||||
fsElement.appendChild(canvas);
|
|
||||||
mainElement.appendChild(fsElement);
|
|
||||||
|
|
||||||
ctx = canvas.getContext('2d');
|
ctx = canvas.getContext('2d');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,10 +141,6 @@ var VectorVideo = function(mainElement, width, height) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var SampleAudio = function(clockfreq) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var RAM = function(size) {
|
var RAM = function(size) {
|
||||||
var memArray = new ArrayBuffer(size);
|
var memArray = new ArrayBuffer(size);
|
||||||
this.mem = new Uint8Array(memArray);
|
this.mem = new Uint8Array(memArray);
|
||||||
|
@ -197,3 +182,97 @@ var AnimationTimer = function(frequencyHz, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
var SampleAudio = function(clockfreq) {
|
||||||
|
var self = this;
|
||||||
|
var sfrac, sinc, accum;
|
||||||
|
var buffer, bufpos, bufferlist;
|
||||||
|
|
||||||
|
function mix(ape) {
|
||||||
|
var buflen=ape.outputBuffer.length;
|
||||||
|
var lbuf = ape.outputBuffer.getChannelData(0);
|
||||||
|
//var rbuf = ape.outputBuffer.getChannelData(1);
|
||||||
|
var m = this.module;
|
||||||
|
if (!m) m = ape.srcElement.module;
|
||||||
|
if (!m) return;
|
||||||
|
|
||||||
|
var buf = bufferlist[1];
|
||||||
|
for (var i=0; i<lbuf.length; i++) {
|
||||||
|
lbuf[i] = buf[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createContext() {
|
||||||
|
if ( typeof AudioContext !== 'undefined') {
|
||||||
|
self.context = new AudioContext();
|
||||||
|
} else {
|
||||||
|
self.context = new webkitAudioContext();
|
||||||
|
}
|
||||||
|
self.sr=self.context.sampleRate;
|
||||||
|
self.bufferlen=(self.sr > 44100) ? 4096 : 2048;
|
||||||
|
|
||||||
|
// Amiga 500 fixed filter at 6kHz. WebAudio lowpass is 12dB/oct, whereas
|
||||||
|
// older Amigas had a 6dB/oct filter at 4900Hz.
|
||||||
|
self.filterNode=self.context.createBiquadFilter();
|
||||||
|
if (self.amiga500) {
|
||||||
|
self.filterNode.frequency.value=6000;
|
||||||
|
} else {
|
||||||
|
self.filterNode.frequency.value=28867;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "LED filter" at 3275kHz - off by default
|
||||||
|
self.lowpassNode=self.context.createBiquadFilter();
|
||||||
|
self.lowpassNode.frequency.value=28867;
|
||||||
|
self.filter=false;
|
||||||
|
|
||||||
|
// mixer
|
||||||
|
if ( typeof self.context.createScriptProcessor === 'function') {
|
||||||
|
self.mixerNode=self.context.createScriptProcessor(self.bufferlen, 1, 1);
|
||||||
|
} else {
|
||||||
|
self.mixerNode=self.context.createJavaScriptNode(self.bufferlen, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mixerNode.module=self;
|
||||||
|
self.mixerNode.onaudioprocess=mix;
|
||||||
|
|
||||||
|
// compressor for a bit of volume boost, helps with multich tunes
|
||||||
|
self.compressorNode=self.context.createDynamicsCompressor();
|
||||||
|
|
||||||
|
// patch up some cables :)
|
||||||
|
self.mixerNode.connect(self.filterNode);
|
||||||
|
self.filterNode.connect(self.lowpassNode);
|
||||||
|
self.lowpassNode.connect(self.compressorNode);
|
||||||
|
self.compressorNode.connect(self.context.destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.start = function() {
|
||||||
|
if (!this.context) createContext();
|
||||||
|
sinc = this.sr * 1.0 / clockfreq;
|
||||||
|
sfrac = 0;
|
||||||
|
accum = 0;
|
||||||
|
bufpos = 0;
|
||||||
|
bufferlist = [];
|
||||||
|
for (var i=0; i<2; i++) {
|
||||||
|
var arrbuf = new ArrayBuffer(self.bufferlen*4);
|
||||||
|
bufferlist[i] = new Float32Array(arrbuf);
|
||||||
|
}
|
||||||
|
buffer = bufferlist[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.feedSample = function(value, count) {
|
||||||
|
while (count-- > 0) {
|
||||||
|
accum += value;
|
||||||
|
sfrac += sinc;
|
||||||
|
if (sfrac >= 1) {
|
||||||
|
buffer[bufpos++] = accum / sfrac;
|
||||||
|
sfrac -= 1;
|
||||||
|
accum = 0;
|
||||||
|
if (bufpos >= buffer.length) {
|
||||||
|
bufpos = 0;
|
||||||
|
bufferlist[0] = bufferlist[1];
|
||||||
|
bufferlist[1] = buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,33 +3,106 @@
|
||||||
var APPLE2_PRESETS = [
|
var APPLE2_PRESETS = [
|
||||||
];
|
];
|
||||||
|
|
||||||
|
var GR_TXMODE = 1;
|
||||||
|
var GR_MIXMODE = 2;
|
||||||
|
var GR_PAGE1 = 4;
|
||||||
|
var GR_HIRES = 8;
|
||||||
|
|
||||||
var Apple2Platform = function(mainElement) {
|
var Apple2Platform = function(mainElement) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var cpuFrequency = 1.023;
|
var cpuFrequency = 1023000;
|
||||||
var cpuCyclesPerLine = 65;
|
var cpuCyclesPerLine = 65;
|
||||||
var cpu, ram, rom, bus;
|
var cpu, ram, rom, bus;
|
||||||
var video, audio, timer;
|
var video, ap2disp, audio, timer;
|
||||||
|
var grdirty = [];
|
||||||
|
var grswitch = GR_TXMODE;
|
||||||
|
var kbdlatch = 0;
|
||||||
|
var soundstate = 0;
|
||||||
|
var PGM_BASE = 0x6000;
|
||||||
|
|
||||||
this.getPresets = function() {
|
this.getPresets = function() {
|
||||||
return APPLE2_PRESETS;
|
return APPLE2_PRESETS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function noise() {
|
||||||
|
return (Math.random() * 256) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
this.start = function() {
|
this.start = function() {
|
||||||
cpu = new jt.M6502();
|
cpu = new jt.M6502();
|
||||||
ram = new RAM(0xc000);
|
ram = new RAM(0xc000);
|
||||||
//rom = new lzgmini().decode(APPLEIIGO_LZG).slice(0,12288);
|
rom = new lzgmini().decode(APPLEIIGO_LZG).slice(0,12288);
|
||||||
// bus
|
// bus
|
||||||
bus = {
|
bus = {
|
||||||
read: function(address) {
|
read: function(address) {
|
||||||
|
address &= 0xffff;
|
||||||
if (address >= 0xd000 && address <= 0xffff) {
|
if (address >= 0xd000 && address <= 0xffff) {
|
||||||
return rom[address - 0xd000];
|
return rom[address - 0xd000];
|
||||||
} else if (address < 0xc000) {
|
} else if (address < 0xc000) {
|
||||||
return ram.mem[address];
|
return ram.mem[address];
|
||||||
|
} else if (address < 0xc100) {
|
||||||
|
var slot = (address >> 4) & 0x0f;
|
||||||
|
switch (slot)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return kbdlatch;
|
||||||
|
case 1:
|
||||||
|
kbdlatch &= 0x7f;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
soundstate = soundstate ^ 1;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
if ((address & 0x0f) < 8) {
|
||||||
|
// graphics
|
||||||
|
if ((address & 1) != 0)
|
||||||
|
grswitch |= 1 << ((address >> 1) & 0x07);
|
||||||
|
else
|
||||||
|
grswitch &= ~(1 << ((address >> 1) & 0x07));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
// tapein, joystick, buttons
|
||||||
|
switch (address & 7) {
|
||||||
|
// buttons (off)
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
return noise() & 0x7f;
|
||||||
|
// joystick
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
return noise() | 0x80;
|
||||||
|
default:
|
||||||
|
return noise();
|
||||||
|
}
|
||||||
|
case 7:
|
||||||
|
// joy reset
|
||||||
|
if (address == 0xc070)
|
||||||
|
return noise() | 0x80;
|
||||||
|
case 8:
|
||||||
|
return doLanguageCardIO(address, value);
|
||||||
|
case 9: case 10: case 11: case 12: case 13: case 14: case 15:
|
||||||
|
return slots[slot-8].doIO(address, value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (address) {
|
||||||
|
// JMP $c600
|
||||||
|
case 0xc600: return 0x4c;
|
||||||
|
case 0xc601: return PGM_BASE&0xff;
|
||||||
|
case 0xc602: return (PGM_BASE>>8)&0xff;
|
||||||
|
default: return noise();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return noise();
|
||||||
},
|
},
|
||||||
write: function(address, val) {
|
write: function(address, val) {
|
||||||
|
address &= 0xffff;
|
||||||
if (address < 0xc000) {
|
if (address < 0xc000) {
|
||||||
ram.mem[address] = val;
|
ram.mem[address] = val;
|
||||||
|
grdirty[address>>7] = 1;
|
||||||
|
} else if (address < 0xc100) {
|
||||||
|
this.read(address); // strobe address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -38,34 +111,28 @@ var Apple2Platform = function(mainElement) {
|
||||||
video = new RasterVideo(mainElement,280,192);
|
video = new RasterVideo(mainElement,280,192);
|
||||||
audio = new SampleAudio(cpuFrequency);
|
audio = new SampleAudio(cpuFrequency);
|
||||||
video.start();
|
video.start();
|
||||||
|
audio.start();
|
||||||
var idata = video.getFrameData();
|
var idata = video.getFrameData();
|
||||||
|
var grparams = {dirty:grdirty, grswitch:grswitch, mem:ram.mem};
|
||||||
|
ap2disp = new Apple2Display(idata, grparams);
|
||||||
var colors = [0xffff0000, 0xff00ff00];
|
var colors = [0xffff0000, 0xff00ff00];
|
||||||
timer = new AnimationTimer(60, function() {
|
timer = new AnimationTimer(60, function() {
|
||||||
// 262.5 scanlines per frame
|
// 262.5 scanlines per frame
|
||||||
var iaddr = 0x2000;
|
var iaddr = 0x2000;
|
||||||
var iofs = 0;
|
var iofs = 0;
|
||||||
breakClock = -1;
|
breakClock = -1;
|
||||||
clock = 0;
|
var clock = 0;
|
||||||
for (var sl=0; sl<262; sl++) {
|
for (var sl=0; sl<262; sl++) {
|
||||||
for (var i=0; i<cpuCyclesPerLine; i++) {
|
for (var i=0; i<cpuCyclesPerLine; i++) {
|
||||||
if (debugCondition && breakClock < 0 && debugCondition()) { breakClock = clock; }
|
if (debugCondition && breakClock < 0 && debugCondition()) { breakClock = clock; }
|
||||||
clock++;
|
clock++;
|
||||||
cpu.clockPulse();
|
cpu.clockPulse();
|
||||||
// TODO: audio
|
audio.feedSample(soundstate, 1);
|
||||||
}
|
|
||||||
if (sl < 192) {
|
|
||||||
for (var xo=0; xo<35; xo++) {
|
|
||||||
var b = ram.mem[iaddr++];
|
|
||||||
idata[iofs++] = colors[(b>>0)&1];
|
|
||||||
idata[iofs++] = colors[(b>>1)&1];
|
|
||||||
idata[iofs++] = colors[(b>>2)&1];
|
|
||||||
idata[iofs++] = colors[(b>>3)&1];
|
|
||||||
idata[iofs++] = colors[(b>>4)&1];
|
|
||||||
idata[iofs++] = colors[(b>>5)&1];
|
|
||||||
idata[iofs++] = colors[(b>>6)&1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
grparams.dirty = grdirty;
|
||||||
|
grparams.grswitch = grswitch;
|
||||||
|
ap2disp.updateScreen();
|
||||||
video.updateFrame();
|
video.updateFrame();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -75,15 +142,20 @@ var Apple2Platform = function(mainElement) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadROM = function(title, data) {
|
this.loadROM = function(title, data) {
|
||||||
|
this.reset();
|
||||||
|
for (var i=0; i<data.length; i++) {
|
||||||
|
ram.mem[i+PGM_BASE] = data[i];
|
||||||
|
}
|
||||||
|
/*
|
||||||
if(data.length != 0x3000) {
|
if(data.length != 0x3000) {
|
||||||
throw "ROM length must be == 0x3000";
|
throw "ROM length must be == 0x3000";
|
||||||
}
|
}
|
||||||
rom = data;
|
rom = data;
|
||||||
this.reset();
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getRasterPosition = function() {
|
this.getRasterPosition = function() {
|
||||||
return {x:xpos, y:ypos};
|
return {x:0, y:0};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isRunning = function() {
|
this.isRunning = function() {
|
||||||
|
@ -188,8 +260,587 @@ var Apple2Platform = function(mainElement) {
|
||||||
b:ram.mem.slice(0),
|
b:ram.mem.slice(0),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
this.getRAMForState = function(state) {
|
||||||
|
return ram.mem;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var Apple2Display = function(pixels, apple) {
|
||||||
|
var XSIZE = 280;
|
||||||
|
var YSIZE = 192;
|
||||||
|
var PIXELON = 0xffffffff;
|
||||||
|
var PIXELOFF = 0xff000000;
|
||||||
|
|
||||||
|
var oldgrmode = -1;
|
||||||
|
var textbuf = [];
|
||||||
|
|
||||||
|
var flashInterval = 500;
|
||||||
|
|
||||||
|
var loresColor = [
|
||||||
|
(0xff000000), (0xffff00ff), (0xff00007f), (0xff7f007f),
|
||||||
|
(0xff007f00), (0xff7f7f7f), (0xff0000bf), (0xff0000ff),
|
||||||
|
(0xffbf7f00), (0xffffbf00), (0xffbfbfbf), (0xffff7f7f),
|
||||||
|
(0xff00ff00), (0xffffff00), (0xff00bf7f), (0xffffffff),
|
||||||
|
];
|
||||||
|
|
||||||
|
var text_lut = [
|
||||||
|
0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380,
|
||||||
|
0x028, 0x0a8, 0x128, 0x1a8, 0x228, 0x2a8, 0x328, 0x3a8,
|
||||||
|
0x050, 0x0d0, 0x150, 0x1d0, 0x250, 0x2d0, 0x350, 0x3d0
|
||||||
|
];
|
||||||
|
|
||||||
|
var hires_lut = [
|
||||||
|
0x0000, 0x0400, 0x0800, 0x0c00, 0x1000, 0x1400, 0x1800, 0x1c00,
|
||||||
|
0x0080, 0x0480, 0x0880, 0x0c80, 0x1080, 0x1480, 0x1880, 0x1c80,
|
||||||
|
0x0100, 0x0500, 0x0900, 0x0d00, 0x1100, 0x1500, 0x1900, 0x1d00,
|
||||||
|
0x0180, 0x0580, 0x0980, 0x0d80, 0x1180, 0x1580, 0x1980, 0x1d80,
|
||||||
|
0x0200, 0x0600, 0x0a00, 0x0e00, 0x1200, 0x1600, 0x1a00, 0x1e00,
|
||||||
|
0x0280, 0x0680, 0x0a80, 0x0e80, 0x1280, 0x1680, 0x1a80, 0x1e80,
|
||||||
|
0x0300, 0x0700, 0x0b00, 0x0f00, 0x1300, 0x1700, 0x1b00, 0x1f00,
|
||||||
|
0x0380, 0x0780, 0x0b80, 0x0f80, 0x1380, 0x1780, 0x1b80, 0x1f80,
|
||||||
|
0x0028, 0x0428, 0x0828, 0x0c28, 0x1028, 0x1428, 0x1828, 0x1c28,
|
||||||
|
0x00a8, 0x04a8, 0x08a8, 0x0ca8, 0x10a8, 0x14a8, 0x18a8, 0x1ca8,
|
||||||
|
0x0128, 0x0528, 0x0928, 0x0d28, 0x1128, 0x1528, 0x1928, 0x1d28,
|
||||||
|
0x01a8, 0x05a8, 0x09a8, 0x0da8, 0x11a8, 0x15a8, 0x19a8, 0x1da8,
|
||||||
|
0x0228, 0x0628, 0x0a28, 0x0e28, 0x1228, 0x1628, 0x1a28, 0x1e28,
|
||||||
|
0x02a8, 0x06a8, 0x0aa8, 0x0ea8, 0x12a8, 0x16a8, 0x1aa8, 0x1ea8,
|
||||||
|
0x0328, 0x0728, 0x0b28, 0x0f28, 0x1328, 0x1728, 0x1b28, 0x1f28,
|
||||||
|
0x03a8, 0x07a8, 0x0ba8, 0x0fa8, 0x13a8, 0x17a8, 0x1ba8, 0x1fa8,
|
||||||
|
0x0050, 0x0450, 0x0850, 0x0c50, 0x1050, 0x1450, 0x1850, 0x1c50,
|
||||||
|
0x00d0, 0x04d0, 0x08d0, 0x0cd0, 0x10d0, 0x14d0, 0x18d0, 0x1cd0,
|
||||||
|
0x0150, 0x0550, 0x0950, 0x0d50, 0x1150, 0x1550, 0x1950, 0x1d50,
|
||||||
|
0x01d0, 0x05d0, 0x09d0, 0x0dd0, 0x11d0, 0x15d0, 0x19d0, 0x1dd0,
|
||||||
|
0x0250, 0x0650, 0x0a50, 0x0e50, 0x1250, 0x1650, 0x1a50, 0x1e50,
|
||||||
|
0x02d0, 0x06d0, 0x0ad0, 0x0ed0, 0x12d0, 0x16d0, 0x1ad0, 0x1ed0,
|
||||||
|
0x0350, 0x0750, 0x0b50, 0x0f50, 0x1350, 0x1750, 0x1b50, 0x1f50,
|
||||||
|
0x03d0, 0x07d0, 0x0bd0, 0x0fd0, 0x13d0, 0x17d0, 0x1bd0, 0x1fd0
|
||||||
|
];
|
||||||
|
|
||||||
|
var colors_lut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function makes the color lookup table for hires mode.
|
||||||
|
* We make a table of 1024 * 2 * 7 entries.
|
||||||
|
* Why? Because we assume each color byte has 10 bits
|
||||||
|
* (8 real bits + 1 on each side) and we need different colors
|
||||||
|
* for odd and even addresses (2) and each byte displays 7 pixels.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
colors_lut = []; //new int[256*4*2*7];
|
||||||
|
var i,j;
|
||||||
|
var c1,c2,c3 = 15;
|
||||||
|
var base = 0;
|
||||||
|
|
||||||
|
// go thru odd and even
|
||||||
|
for (j=0; j<2; j++)
|
||||||
|
{
|
||||||
|
// go thru 1024 values
|
||||||
|
for (var b1=0; b1<1024; b1++)
|
||||||
|
{
|
||||||
|
// see if the hi bit is set
|
||||||
|
if ((b1 & 0x80) == 0)
|
||||||
|
{
|
||||||
|
c1 = 1; c2 = 12; // red & green
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
c1 = 7; c2 = 9; // blue & orange
|
||||||
|
}
|
||||||
|
// make a value consisting of:
|
||||||
|
// the 8th bit, then bits 0-7, then the 9th bit
|
||||||
|
var b = ((b1 & 0x100) >> 8) | ((b1 & 0x7f) << 1) |
|
||||||
|
((b1 & 0x200) >> 1);
|
||||||
|
// go through each pixel
|
||||||
|
for (i=0; i<7; i++)
|
||||||
|
{
|
||||||
|
var c;
|
||||||
|
// is this pixel lit?
|
||||||
|
if (((2<<i)&b) != 0)
|
||||||
|
{
|
||||||
|
// are there pixels lit on both sides of this one?
|
||||||
|
if (((7<<i)&b) == (7<<i))
|
||||||
|
// yes, make it white
|
||||||
|
c = 15;
|
||||||
|
else
|
||||||
|
// no, choose color based on odd/even byte
|
||||||
|
// and odd/even pixel column
|
||||||
|
c = ((((j ^ i) & 1) == 0) ? c1 : c2);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// are there pixels lit in the previous & next
|
||||||
|
// column but none in this?
|
||||||
|
if (((5<<i)&b) == (5<<i))
|
||||||
|
// color this pixel
|
||||||
|
c = ((((j ^ i) & 1) != 0) ? c1 : c2);
|
||||||
|
else
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
colors_lut[base] = loresColor[c];
|
||||||
|
base++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawLoresChar(x, y, b)
|
||||||
|
{
|
||||||
|
var i,base,adr,c;
|
||||||
|
base = (y<<3)*XSIZE + x*7; //(x<<2) + (x<<1) + x
|
||||||
|
c = loresColor[b & 0x0f];
|
||||||
|
for (i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
pixels[base] =
|
||||||
|
pixels[base+1] =
|
||||||
|
pixels[base+2] =
|
||||||
|
pixels[base+3] =
|
||||||
|
pixels[base+4] =
|
||||||
|
pixels[base+5] =
|
||||||
|
pixels[base+6] = c;
|
||||||
|
base += XSIZE;
|
||||||
|
}
|
||||||
|
c = loresColor[b >> 4];
|
||||||
|
for (i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
pixels[base] =
|
||||||
|
pixels[base+1] =
|
||||||
|
pixels[base+2] =
|
||||||
|
pixels[base+3] =
|
||||||
|
pixels[base+4] =
|
||||||
|
pixels[base+5] =
|
||||||
|
pixels[base+6] = c;
|
||||||
|
base += XSIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawTextChar(x, y, b, invert)
|
||||||
|
{
|
||||||
|
var base = (y<<3)*XSIZE + x*7; // (x<<2) + (x<<1) + x
|
||||||
|
var on,off;
|
||||||
|
if (invert)
|
||||||
|
{
|
||||||
|
on = PIXELOFF;
|
||||||
|
off = PIXELON;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
on = PIXELON;
|
||||||
|
off = PIXELOFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var yy=0; yy<8; yy++)
|
||||||
|
{
|
||||||
|
var chr = apple2_charset[(b<<3)+yy];
|
||||||
|
pixels[base] = ((chr & 64) > 0)?on:off;
|
||||||
|
pixels[base+1] = ((chr & 32) > 0)?on:off;
|
||||||
|
pixels[base+2] = ((chr & 16) > 0)?on:off;
|
||||||
|
pixels[base+3] = ((chr & 8) > 0)?on:off;
|
||||||
|
pixels[base+4] = ((chr & 4) > 0)?on:off;
|
||||||
|
pixels[base+5] = ((chr & 2) > 0)?on:off;
|
||||||
|
pixels[base+6] = ((chr & 1) > 0)?on:off;
|
||||||
|
base += XSIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawHiresLines(y, maxy)
|
||||||
|
{
|
||||||
|
var yb = y*XSIZE;
|
||||||
|
for (; y < maxy; y++)
|
||||||
|
{
|
||||||
|
var base = hires_lut[y] + (((apple.grswitch & GR_PAGE1) != 0) ? 0x4000 : 0x2000);
|
||||||
|
if (!apple.dirty[base >> 7])
|
||||||
|
{
|
||||||
|
yb += XSIZE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var c1, c2;
|
||||||
|
var b = 0;
|
||||||
|
var b1 = apple.mem[base] & 0xff;
|
||||||
|
for (var x1=0; x1<20; x1++)
|
||||||
|
{
|
||||||
|
var b2 = apple.mem[base+1] & 0xff;
|
||||||
|
var b3 = apple.mem[base+2] & 0xff;
|
||||||
|
var d1 = (((b&0x40)<<2) | b1 | b2<<9) & 0x3ff;
|
||||||
|
for (var i=0; i<7; i++)
|
||||||
|
pixels[yb+i] = colors_lut[d1*7+i];
|
||||||
|
var d2 = (((b1&0x40)<<2) | b2 | b3<<9) & 0x3ff;
|
||||||
|
for (var i=0; i<7; i++)
|
||||||
|
pixels[yb+7+i] = colors_lut[d1*7+7168+i];
|
||||||
|
yb += 14;
|
||||||
|
base += 2;
|
||||||
|
b = b2;
|
||||||
|
b1 = b3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawLoresLine(y)
|
||||||
|
{
|
||||||
|
// get the base address of this line
|
||||||
|
var base = text_lut[y] +
|
||||||
|
(((apple.grswitch & GR_PAGE1) != 0) ? 0x800 : 0x400);
|
||||||
|
// if (!dirty[base >> 7])
|
||||||
|
// return;
|
||||||
|
for (var x=0; x<40; x++)
|
||||||
|
{
|
||||||
|
var b = apple.mem[base+x] & 0xff;
|
||||||
|
// if the char. changed, draw it
|
||||||
|
if (b != textbuf[y*40+x])
|
||||||
|
{
|
||||||
|
drawLoresChar(x, y, b);
|
||||||
|
textbuf[y*40+x] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawTextLine(y, flash)
|
||||||
|
{
|
||||||
|
// get the base address of this line
|
||||||
|
var base = text_lut[y] +
|
||||||
|
(((apple.grswitch & GR_PAGE1) != 0) ? 0x800 : 0x400);
|
||||||
|
// if (!dirty[base >> 7])
|
||||||
|
// return;
|
||||||
|
for (var x=0; x<40; x++)
|
||||||
|
{
|
||||||
|
var b = apple.mem[base+x] & 0xff;
|
||||||
|
var invert;
|
||||||
|
// invert flash characters 1/2 of the time
|
||||||
|
if (b >= 0x80)
|
||||||
|
{
|
||||||
|
invert = false;
|
||||||
|
} else if (b >= 0x40)
|
||||||
|
{
|
||||||
|
invert = flash;
|
||||||
|
if (flash)
|
||||||
|
b -= 0x40;
|
||||||
|
else
|
||||||
|
b += 0x40;
|
||||||
|
} else
|
||||||
|
invert = true;
|
||||||
|
// if the char. changed, draw it
|
||||||
|
if (b != textbuf[y*40+x])
|
||||||
|
{
|
||||||
|
drawTextChar(x, y, b & 0x7f, invert);
|
||||||
|
textbuf[y*40+x] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateScreen = function(totalrepaint)
|
||||||
|
{
|
||||||
|
var y;
|
||||||
|
var flash = (new Date().getTime() % (flashInterval<<1)) > flashInterval;
|
||||||
|
|
||||||
|
// if graphics mode changed, repaint whole screen
|
||||||
|
if (apple.grswitch != oldgrmode)
|
||||||
|
{
|
||||||
|
oldgrmode = apple.grswitch;
|
||||||
|
totalrepaint = true;
|
||||||
|
}
|
||||||
|
if (totalrepaint)
|
||||||
|
{
|
||||||
|
// clear textbuf if in text mode
|
||||||
|
if ((apple.grswitch & GR_TXMODE) != 0 || (apple.grswitch & GR_MIXMODE) != 0)
|
||||||
|
{
|
||||||
|
for (y=0; y<24; y++)
|
||||||
|
for (var x=0; x<40; x++)
|
||||||
|
textbuf[y*40+x] = -1;
|
||||||
|
}
|
||||||
|
for (var i=0; i<384; i++)
|
||||||
|
apple.dirty[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// first, draw top part of window
|
||||||
|
if ((apple.grswitch & GR_TXMODE) != 0)
|
||||||
|
{
|
||||||
|
for (y=0; y<20; y++)
|
||||||
|
drawTextLine(y, flash);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if ((apple.grswitch & GR_HIRES) != 0)
|
||||||
|
drawHiresLines(0, 160);
|
||||||
|
else
|
||||||
|
for (y=0; y<20; y++)
|
||||||
|
drawLoresLine(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now do mixed part of window
|
||||||
|
if ((apple.grswitch & GR_TXMODE) != 0 || (apple.grswitch & GR_MIXMODE) != 0)
|
||||||
|
{
|
||||||
|
for (y=20; y<24; y++)
|
||||||
|
drawTextLine(y, flash);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if ((apple.grswitch & GR_HIRES) != 0)
|
||||||
|
drawHiresLines(160, 192);
|
||||||
|
else
|
||||||
|
for (y=20; y<24; y++)
|
||||||
|
drawLoresLine(y);
|
||||||
|
}
|
||||||
|
for (var i=0; i<384; i++)
|
||||||
|
apple.dirty[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*exported apple2_charset */
|
||||||
|
|
||||||
|
var apple2_charset = [
|
||||||
|
0x00,0x1c,0x22,0x2a,0x2e,0x2c,0x20,0x1e,
|
||||||
|
0x00,0x08,0x14,0x22,0x22,0x3e,0x22,0x22,
|
||||||
|
0x00,0x3c,0x22,0x22,0x3c,0x22,0x22,0x3c,
|
||||||
|
0x00,0x1c,0x22,0x20,0x20,0x20,0x22,0x1c,
|
||||||
|
0x00,0x3c,0x22,0x22,0x22,0x22,0x22,0x3c,
|
||||||
|
0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x3e,
|
||||||
|
0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x20,
|
||||||
|
0x00,0x1e,0x20,0x20,0x20,0x26,0x22,0x1e,
|
||||||
|
0x00,0x22,0x22,0x22,0x3e,0x22,0x22,0x22,
|
||||||
|
0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x1c,
|
||||||
|
0x00,0x02,0x02,0x02,0x02,0x02,0x22,0x1c,
|
||||||
|
0x00,0x22,0x24,0x28,0x30,0x28,0x24,0x22,
|
||||||
|
0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x3e,
|
||||||
|
0x00,0x22,0x36,0x2a,0x2a,0x22,0x22,0x22,
|
||||||
|
0x00,0x22,0x22,0x32,0x2a,0x26,0x22,0x22,
|
||||||
|
0x00,0x1c,0x22,0x22,0x22,0x22,0x22,0x1c,
|
||||||
|
0x00,0x3c,0x22,0x22,0x3c,0x20,0x20,0x20,
|
||||||
|
0x00,0x1c,0x22,0x22,0x22,0x2a,0x24,0x1a,
|
||||||
|
0x00,0x3c,0x22,0x22,0x3c,0x28,0x24,0x22,
|
||||||
|
0x00,0x1c,0x22,0x20,0x1c,0x02,0x22,0x1c,
|
||||||
|
0x00,0x3e,0x08,0x08,0x08,0x08,0x08,0x08,
|
||||||
|
0x00,0x22,0x22,0x22,0x22,0x22,0x22,0x1c,
|
||||||
|
0x00,0x22,0x22,0x22,0x22,0x22,0x14,0x08,
|
||||||
|
0x00,0x22,0x22,0x22,0x2a,0x2a,0x36,0x22,
|
||||||
|
0x00,0x22,0x22,0x14,0x08,0x14,0x22,0x22,
|
||||||
|
0x00,0x22,0x22,0x14,0x08,0x08,0x08,0x08,
|
||||||
|
0x00,0x3e,0x02,0x04,0x08,0x10,0x20,0x3e,
|
||||||
|
0x00,0x3e,0x30,0x30,0x30,0x30,0x30,0x3e,
|
||||||
|
0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x00,
|
||||||
|
0x00,0x3e,0x06,0x06,0x06,0x06,0x06,0x3e,
|
||||||
|
0x00,0x00,0x00,0x08,0x14,0x22,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x08,
|
||||||
|
0x00,0x14,0x14,0x14,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x14,0x14,0x3e,0x14,0x3e,0x14,0x14,
|
||||||
|
0x00,0x08,0x1e,0x28,0x1c,0x0a,0x3c,0x08,
|
||||||
|
0x00,0x30,0x32,0x04,0x08,0x10,0x26,0x06,
|
||||||
|
0x00,0x10,0x28,0x28,0x10,0x2a,0x24,0x1a,
|
||||||
|
0x00,0x08,0x08,0x08,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x08,0x10,0x20,0x20,0x20,0x10,0x08,
|
||||||
|
0x00,0x08,0x04,0x02,0x02,0x02,0x04,0x08,
|
||||||
|
0x00,0x08,0x2a,0x1c,0x08,0x1c,0x2a,0x08,
|
||||||
|
0x00,0x00,0x08,0x08,0x3e,0x08,0x08,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x10,
|
||||||
|
0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
|
||||||
|
0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x00,
|
||||||
|
0x00,0x1c,0x22,0x26,0x2a,0x32,0x22,0x1c,
|
||||||
|
0x00,0x08,0x18,0x08,0x08,0x08,0x08,0x1c,
|
||||||
|
0x00,0x1c,0x22,0x02,0x0c,0x10,0x20,0x3e,
|
||||||
|
0x00,0x3e,0x02,0x04,0x0c,0x02,0x22,0x1c,
|
||||||
|
0x00,0x04,0x0c,0x14,0x24,0x3e,0x04,0x04,
|
||||||
|
0x00,0x3e,0x20,0x3c,0x02,0x02,0x22,0x1c,
|
||||||
|
0x00,0x0e,0x10,0x20,0x3c,0x22,0x22,0x1c,
|
||||||
|
0x00,0x3e,0x02,0x04,0x08,0x10,0x10,0x10,
|
||||||
|
0x00,0x1c,0x22,0x22,0x1c,0x22,0x22,0x1c,
|
||||||
|
0x00,0x1c,0x22,0x22,0x1e,0x02,0x04,0x38,
|
||||||
|
0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x08,0x00,0x08,0x08,0x10,
|
||||||
|
0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04,
|
||||||
|
0x00,0x00,0x00,0x3e,0x00,0x3e,0x00,0x00,
|
||||||
|
0x00,0x10,0x08,0x04,0x02,0x04,0x08,0x10,
|
||||||
|
0x00,0x1c,0x22,0x04,0x08,0x08,0x00,0x08,
|
||||||
|
0x80,0x9c,0xa2,0xaa,0xae,0xac,0xa0,0x9e,
|
||||||
|
0x80,0x88,0x94,0xa2,0xa2,0xbe,0xa2,0xa2,
|
||||||
|
0x80,0xbc,0xa2,0xa2,0xbc,0xa2,0xa2,0xbc,
|
||||||
|
0x80,0x9c,0xa2,0xa0,0xa0,0xa0,0xa2,0x9c,
|
||||||
|
0x80,0xbc,0xa2,0xa2,0xa2,0xa2,0xa2,0xbc,
|
||||||
|
0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xbe,
|
||||||
|
0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xa0,
|
||||||
|
0x80,0x9e,0xa0,0xa0,0xa0,0xa6,0xa2,0x9e,
|
||||||
|
0x80,0xa2,0xa2,0xa2,0xbe,0xa2,0xa2,0xa2,
|
||||||
|
0x80,0x9c,0x88,0x88,0x88,0x88,0x88,0x9c,
|
||||||
|
0x80,0x82,0x82,0x82,0x82,0x82,0xa2,0x9c,
|
||||||
|
0x80,0xa2,0xa4,0xa8,0xb0,0xa8,0xa4,0xa2,
|
||||||
|
0x80,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xbe,
|
||||||
|
0x80,0xa2,0xb6,0xaa,0xaa,0xa2,0xa2,0xa2,
|
||||||
|
0x80,0xa2,0xa2,0xb2,0xaa,0xa6,0xa2,0xa2,
|
||||||
|
0x80,0x9c,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c,
|
||||||
|
0x80,0xbc,0xa2,0xa2,0xbc,0xa0,0xa0,0xa0,
|
||||||
|
0x80,0x9c,0xa2,0xa2,0xa2,0xaa,0xa4,0x9a,
|
||||||
|
0x80,0xbc,0xa2,0xa2,0xbc,0xa8,0xa4,0xa2,
|
||||||
|
0x80,0x9c,0xa2,0xa0,0x9c,0x82,0xa2,0x9c,
|
||||||
|
0x80,0xbe,0x88,0x88,0x88,0x88,0x88,0x88,
|
||||||
|
0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c,
|
||||||
|
0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0x94,0x88,
|
||||||
|
0x80,0xa2,0xa2,0xa2,0xaa,0xaa,0xb6,0xa2,
|
||||||
|
0x80,0xa2,0xa2,0x94,0x88,0x94,0xa2,0xa2,
|
||||||
|
0x80,0xa2,0xa2,0x94,0x88,0x88,0x88,0x88,
|
||||||
|
0x80,0xbe,0x82,0x84,0x88,0x90,0xa0,0xbe,
|
||||||
|
0x80,0xbe,0xb0,0xb0,0xb0,0xb0,0xb0,0xbe,
|
||||||
|
0x80,0x80,0xa0,0x90,0x88,0x84,0x82,0x80,
|
||||||
|
0x80,0xbe,0x86,0x86,0x86,0x86,0x86,0xbe,
|
||||||
|
0x80,0x80,0x80,0x88,0x94,0xa2,0x80,0x80,
|
||||||
|
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xbe,
|
||||||
|
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||||
|
0x80,0x88,0x88,0x88,0x88,0x88,0x80,0x88,
|
||||||
|
0x80,0x94,0x94,0x94,0x80,0x80,0x80,0x80,
|
||||||
|
0x80,0x94,0x94,0xbe,0x94,0xbe,0x94,0x94,
|
||||||
|
0x80,0x88,0x9e,0xa8,0x9c,0x8a,0xbc,0x88,
|
||||||
|
0x80,0xb0,0xb2,0x84,0x88,0x90,0xa6,0x86,
|
||||||
|
0x80,0x90,0xa8,0xa8,0x90,0xaa,0xa4,0x9a,
|
||||||
|
0x80,0x88,0x88,0x88,0x80,0x80,0x80,0x80,
|
||||||
|
0x80,0x88,0x90,0xa0,0xa0,0xa0,0x90,0x88,
|
||||||
|
0x80,0x88,0x84,0x82,0x82,0x82,0x84,0x88,
|
||||||
|
0x80,0x88,0xaa,0x9c,0x88,0x9c,0xaa,0x88,
|
||||||
|
0x80,0x80,0x88,0x88,0xbe,0x88,0x88,0x80,
|
||||||
|
0x80,0x80,0x80,0x80,0x80,0x88,0x88,0x90,
|
||||||
|
0x80,0x80,0x80,0x80,0xbe,0x80,0x80,0x80,
|
||||||
|
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x88,
|
||||||
|
0x80,0x80,0x82,0x84,0x88,0x90,0xa0,0x80,
|
||||||
|
0x80,0x9c,0xa2,0xa6,0xaa,0xb2,0xa2,0x9c,
|
||||||
|
0x80,0x88,0x98,0x88,0x88,0x88,0x88,0x9c,
|
||||||
|
0x80,0x9c,0xa2,0x82,0x8c,0x90,0xa0,0xbe,
|
||||||
|
0x80,0xbe,0x82,0x84,0x8c,0x82,0xa2,0x9c,
|
||||||
|
0x80,0x84,0x8c,0x94,0xa4,0xbe,0x84,0x84,
|
||||||
|
0x80,0xbe,0xa0,0xbc,0x82,0x82,0xa2,0x9c,
|
||||||
|
0x80,0x8e,0x90,0xa0,0xbc,0xa2,0xa2,0x9c,
|
||||||
|
0x80,0xbe,0x82,0x84,0x88,0x90,0x90,0x90,
|
||||||
|
0x80,0x9c,0xa2,0xa2,0x9c,0xa2,0xa2,0x9c,
|
||||||
|
0x80,0x9c,0xa2,0xa2,0x9e,0x82,0x84,0xb8,
|
||||||
|
0x80,0x80,0x80,0x88,0x80,0x88,0x80,0x80,
|
||||||
|
0x80,0x80,0x80,0x88,0x80,0x88,0x88,0x90,
|
||||||
|
0x80,0x84,0x88,0x90,0xa0,0x90,0x88,0x84,
|
||||||
|
0x80,0x80,0x80,0xbe,0x80,0xbe,0x80,0x80,
|
||||||
|
0x80,0x90,0x88,0x84,0x82,0x84,0x88,0x90,
|
||||||
|
0x80,0x9c,0xa2,0x84,0x88,0x88,0x80,0x88,
|
||||||
|
0x00,0x1c,0x22,0x2a,0x2e,0x2c,0x20,0x1e,
|
||||||
|
0x00,0x08,0x14,0x22,0x22,0x3e,0x22,0x22,
|
||||||
|
0x00,0x3c,0x22,0x22,0x3c,0x22,0x22,0x3c,
|
||||||
|
0x00,0x1c,0x22,0x20,0x20,0x20,0x22,0x1c,
|
||||||
|
0x00,0x3c,0x22,0x22,0x22,0x22,0x22,0x3c,
|
||||||
|
0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x3e,
|
||||||
|
0x00,0x3e,0x20,0x20,0x3c,0x20,0x20,0x20,
|
||||||
|
0x00,0x1e,0x20,0x20,0x20,0x26,0x22,0x1e,
|
||||||
|
0x00,0x22,0x22,0x22,0x3e,0x22,0x22,0x22,
|
||||||
|
0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x1c,
|
||||||
|
0x00,0x02,0x02,0x02,0x02,0x02,0x22,0x1c,
|
||||||
|
0x00,0x22,0x24,0x28,0x30,0x28,0x24,0x22,
|
||||||
|
0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x3e,
|
||||||
|
0x00,0x22,0x36,0x2a,0x2a,0x22,0x22,0x22,
|
||||||
|
0x00,0x22,0x22,0x32,0x2a,0x26,0x22,0x22,
|
||||||
|
0x00,0x1c,0x22,0x22,0x22,0x22,0x22,0x1c,
|
||||||
|
0x00,0x3c,0x22,0x22,0x3c,0x20,0x20,0x20,
|
||||||
|
0x00,0x1c,0x22,0x22,0x22,0x2a,0x24,0x1a,
|
||||||
|
0x00,0x3c,0x22,0x22,0x3c,0x28,0x24,0x22,
|
||||||
|
0x00,0x1c,0x22,0x20,0x1c,0x02,0x22,0x1c,
|
||||||
|
0x00,0x3e,0x08,0x08,0x08,0x08,0x08,0x08,
|
||||||
|
0x00,0x22,0x22,0x22,0x22,0x22,0x22,0x1c,
|
||||||
|
0x00,0x22,0x22,0x22,0x22,0x22,0x14,0x08,
|
||||||
|
0x00,0x22,0x22,0x22,0x2a,0x2a,0x36,0x22,
|
||||||
|
0x00,0x22,0x22,0x14,0x08,0x14,0x22,0x22,
|
||||||
|
0x00,0x22,0x22,0x14,0x08,0x08,0x08,0x08,
|
||||||
|
0x00,0x3e,0x02,0x04,0x08,0x10,0x20,0x3e,
|
||||||
|
0x00,0x3e,0x30,0x30,0x30,0x30,0x30,0x3e,
|
||||||
|
0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x00,
|
||||||
|
0x00,0x3e,0x06,0x06,0x06,0x06,0x06,0x3e,
|
||||||
|
0x00,0x00,0x00,0x08,0x14,0x22,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x08,
|
||||||
|
0x00,0x14,0x14,0x14,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x14,0x14,0x3e,0x14,0x3e,0x14,0x14,
|
||||||
|
0x00,0x08,0x1e,0x28,0x1c,0x0a,0x3c,0x08,
|
||||||
|
0x00,0x30,0x32,0x04,0x08,0x10,0x26,0x06,
|
||||||
|
0x00,0x10,0x28,0x28,0x10,0x2a,0x24,0x1a,
|
||||||
|
0x00,0x08,0x08,0x08,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x08,0x10,0x20,0x20,0x20,0x10,0x08,
|
||||||
|
0x00,0x08,0x04,0x02,0x02,0x02,0x04,0x08,
|
||||||
|
0x00,0x08,0x2a,0x1c,0x08,0x1c,0x2a,0x08,
|
||||||
|
0x00,0x00,0x08,0x08,0x3e,0x08,0x08,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x10,
|
||||||
|
0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
|
||||||
|
0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x00,
|
||||||
|
0x00,0x1c,0x22,0x26,0x2a,0x32,0x22,0x1c,
|
||||||
|
0x00,0x08,0x18,0x08,0x08,0x08,0x08,0x1c,
|
||||||
|
0x00,0x1c,0x22,0x02,0x0c,0x10,0x20,0x3e,
|
||||||
|
0x00,0x3e,0x02,0x04,0x0c,0x02,0x22,0x1c,
|
||||||
|
0x00,0x04,0x0c,0x14,0x24,0x3e,0x04,0x04,
|
||||||
|
0x00,0x3e,0x20,0x3c,0x02,0x02,0x22,0x1c,
|
||||||
|
0x00,0x0e,0x10,0x20,0x3c,0x22,0x22,0x1c,
|
||||||
|
0x00,0x3e,0x02,0x04,0x08,0x10,0x10,0x10,
|
||||||
|
0x00,0x1c,0x22,0x22,0x1c,0x22,0x22,0x1c,
|
||||||
|
0x00,0x1c,0x22,0x22,0x1e,0x02,0x04,0x38,
|
||||||
|
0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x08,0x00,0x08,0x08,0x10,
|
||||||
|
0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04,
|
||||||
|
0x00,0x00,0x00,0x3e,0x00,0x3e,0x00,0x00,
|
||||||
|
0x00,0x10,0x08,0x04,0x02,0x04,0x08,0x10,
|
||||||
|
0x00,0x1c,0x22,0x04,0x08,0x08,0x00,0x08,
|
||||||
|
0x80,0x9c,0xa2,0xaa,0xae,0xac,0xa0,0x9e,
|
||||||
|
0x80,0x88,0x94,0xa2,0xa2,0xbe,0xa2,0xa2,
|
||||||
|
0x80,0xbc,0xa2,0xa2,0xbc,0xa2,0xa2,0xbc,
|
||||||
|
0x80,0x9c,0xa2,0xa0,0xa0,0xa0,0xa2,0x9c,
|
||||||
|
0x80,0xbc,0xa2,0xa2,0xa2,0xa2,0xa2,0xbc,
|
||||||
|
0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xbe,
|
||||||
|
0x80,0xbe,0xa0,0xa0,0xbc,0xa0,0xa0,0xa0,
|
||||||
|
0x80,0x9e,0xa0,0xa0,0xa0,0xa6,0xa2,0x9e,
|
||||||
|
0x80,0xa2,0xa2,0xa2,0xbe,0xa2,0xa2,0xa2,
|
||||||
|
0x80,0x9c,0x88,0x88,0x88,0x88,0x88,0x9c,
|
||||||
|
0x80,0x82,0x82,0x82,0x82,0x82,0xa2,0x9c,
|
||||||
|
0x80,0xa2,0xa4,0xa8,0xb0,0xa8,0xa4,0xa2,
|
||||||
|
0x80,0xa0,0xa0,0xa0,0xa0,0xa0,0xa0,0xbe,
|
||||||
|
0x80,0xa2,0xb6,0xaa,0xaa,0xa2,0xa2,0xa2,
|
||||||
|
0x80,0xa2,0xa2,0xb2,0xaa,0xa6,0xa2,0xa2,
|
||||||
|
0x80,0x9c,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c,
|
||||||
|
0x80,0xbc,0xa2,0xa2,0xbc,0xa0,0xa0,0xa0,
|
||||||
|
0x80,0x9c,0xa2,0xa2,0xa2,0xaa,0xa4,0x9a,
|
||||||
|
0x80,0xbc,0xa2,0xa2,0xbc,0xa8,0xa4,0xa2,
|
||||||
|
0x80,0x9c,0xa2,0xa0,0x9c,0x82,0xa2,0x9c,
|
||||||
|
0x80,0xbe,0x88,0x88,0x88,0x88,0x88,0x88,
|
||||||
|
0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0xa2,0x9c,
|
||||||
|
0x80,0xa2,0xa2,0xa2,0xa2,0xa2,0x94,0x88,
|
||||||
|
0x80,0xa2,0xa2,0xa2,0xaa,0xaa,0xb6,0xa2,
|
||||||
|
0x80,0xa2,0xa2,0x94,0x88,0x94,0xa2,0xa2,
|
||||||
|
0x80,0xa2,0xa2,0x94,0x88,0x88,0x88,0x88,
|
||||||
|
0x80,0xbe,0x82,0x84,0x88,0x90,0xa0,0xbe,
|
||||||
|
0x80,0xbe,0xb0,0xb0,0xb0,0xb0,0xb0,0xbe,
|
||||||
|
0x80,0x80,0xa0,0x90,0x88,0x84,0x82,0x80,
|
||||||
|
0x80,0xbe,0x86,0x86,0x86,0x86,0x86,0xbe,
|
||||||
|
0x80,0x80,0x80,0x88,0x94,0xa2,0x80,0x80,
|
||||||
|
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xbe,
|
||||||
|
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||||
|
0x80,0x88,0x88,0x88,0x88,0x88,0x80,0x88,
|
||||||
|
0x80,0x94,0x94,0x94,0x80,0x80,0x80,0x80,
|
||||||
|
0x80,0x94,0x94,0xbe,0x94,0xbe,0x94,0x94,
|
||||||
|
0x80,0x88,0x9e,0xa8,0x9c,0x8a,0xbc,0x88,
|
||||||
|
0x80,0xb0,0xb2,0x84,0x88,0x90,0xa6,0x86,
|
||||||
|
0x80,0x90,0xa8,0xa8,0x90,0xaa,0xa4,0x9a,
|
||||||
|
0x80,0x88,0x88,0x88,0x80,0x80,0x80,0x80,
|
||||||
|
0x80,0x88,0x90,0xa0,0xa0,0xa0,0x90,0x88,
|
||||||
|
0x80,0x88,0x84,0x82,0x82,0x82,0x84,0x88,
|
||||||
|
0x80,0x88,0xaa,0x9c,0x88,0x9c,0xaa,0x88,
|
||||||
|
0x80,0x80,0x88,0x88,0xbe,0x88,0x88,0x80,
|
||||||
|
0x80,0x80,0x80,0x80,0x80,0x88,0x88,0x90,
|
||||||
|
0x80,0x80,0x80,0x80,0xbe,0x80,0x80,0x80,
|
||||||
|
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x88,
|
||||||
|
0x80,0x80,0x82,0x84,0x88,0x90,0xa0,0x80,
|
||||||
|
0x80,0x9c,0xa2,0xa6,0xaa,0xb2,0xa2,0x9c,
|
||||||
|
0x80,0x88,0x98,0x88,0x88,0x88,0x88,0x9c,
|
||||||
|
0x80,0x9c,0xa2,0x82,0x8c,0x90,0xa0,0xbe,
|
||||||
|
0x80,0xbe,0x82,0x84,0x8c,0x82,0xa2,0x9c,
|
||||||
|
0x80,0x84,0x8c,0x94,0xa4,0xbe,0x84,0x84,
|
||||||
|
0x80,0xbe,0xa0,0xbc,0x82,0x82,0xa2,0x9c,
|
||||||
|
0x80,0x8e,0x90,0xa0,0xbc,0xa2,0xa2,0x9c,
|
||||||
|
0x80,0xbe,0x82,0x84,0x88,0x90,0x90,0x90,
|
||||||
|
0x80,0x9c,0xa2,0xa2,0x9c,0xa2,0xa2,0x9c,
|
||||||
|
0x80,0x9c,0xa2,0xa2,0x9e,0x82,0x84,0xb8,
|
||||||
|
0x80,0x80,0x80,0x88,0x80,0x88,0x80,0x80,
|
||||||
|
0x80,0x80,0x80,0x88,0x80,0x88,0x88,0x90,
|
||||||
|
0x80,0x84,0x88,0x90,0xa0,0x90,0x88,0x84,
|
||||||
|
0x80,0x80,0x80,0xbe,0x80,0xbe,0x80,0x80,
|
||||||
|
0x80,0x90,0x88,0x84,0x82,0x84,0x88,0x90,
|
||||||
|
0x80,0x9c,0xa2,0x84,0x88,0x88,0x80,0x88
|
||||||
|
];
|
||||||
|
|
||||||
|
// public domain ROM
|
||||||
var APPLEIIGO_LZG = [
|
var APPLEIIGO_LZG = [
|
||||||
76,90,71,0,0,48,0,0,0,5,159,47,60,46,159,1,21,25,30,52,65,80,80,76,69,73,73,71,79,32,82,79,
|
76,90,71,0,0,48,0,0,0,5,159,47,60,46,159,1,21,25,30,52,65,80,80,76,69,73,73,71,79,32,82,79,
|
||||||
77,49,46,48,0,52,31,52,31,52,31,52,31,52,31,52,31,52,31,52,31,52,28,52,6,32,0,224,25,30,67,52,
|
77,49,46,48,0,52,31,52,31,52,31,52,31,52,31,52,31,52,31,52,31,52,28,52,6,32,0,224,25,30,67,52,
|
||||||
|
|
69
src/ui.js
69
src/ui.js
|
@ -1,5 +1,34 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var FileStore = function(storage, prefix) {
|
||||||
|
var self = this;
|
||||||
|
this.saveFile = function(name, text) {
|
||||||
|
storage.setItem(prefix + name, text);
|
||||||
|
}
|
||||||
|
this.loadFile = function(name) {
|
||||||
|
return storage.getItem(prefix + name) || storage.getItem(name);
|
||||||
|
}
|
||||||
|
this.getFiles = function(prefix2) {
|
||||||
|
var files = [];
|
||||||
|
for (var i = 0; i < storage.length; i++) {
|
||||||
|
var key = storage.key(i);
|
||||||
|
if (key.startsWith(prefix + prefix2)) {
|
||||||
|
var name = key.substring(prefix.length + prefix2.length);
|
||||||
|
files.push(name);
|
||||||
|
}
|
||||||
|
else if (key.startsWith(prefix2)) {
|
||||||
|
var name = key.substring(prefix2.length);
|
||||||
|
files.push(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
this.deleteFile = function(name) {
|
||||||
|
storage.removeItem(name);
|
||||||
|
storage.removeItem('local/' + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 8bitworkshop IDE user interface
|
// 8bitworkshop IDE user interface
|
||||||
|
|
||||||
var worker = new Worker("./src/worker/workermain.js");
|
var worker = new Worker("./src/worker/workermain.js");
|
||||||
|
@ -9,6 +38,7 @@ var current_preset_id = null;
|
||||||
var offset2line = null;
|
var offset2line = null;
|
||||||
var line2offset = null;
|
var line2offset = null;
|
||||||
var trace_pending_at_pc;
|
var trace_pending_at_pc;
|
||||||
|
var store;
|
||||||
|
|
||||||
var PRESETS, platform, platform_id;
|
var PRESETS, platform, platform_id;
|
||||||
|
|
||||||
|
@ -40,7 +70,7 @@ function setLastPreset(id) {
|
||||||
|
|
||||||
function updatePreset(current_preset_id, text) {
|
function updatePreset(current_preset_id, text) {
|
||||||
if (text.trim().length) {
|
if (text.trim().length) {
|
||||||
localStorage.setItem(current_preset_id, text);
|
store.saveFile(current_preset_id, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +83,7 @@ function loadCode(text) {
|
||||||
function loadFile(fileid, filename, index) {
|
function loadFile(fileid, filename, index) {
|
||||||
current_preset_id = fileid;
|
current_preset_id = fileid;
|
||||||
current_preset_index = index;
|
current_preset_index = index;
|
||||||
var text = localStorage.getItem(fileid) || localStorage.getItem(fileid.replace(platform_id+"/","")) || "";
|
var text = store.loadFile(fileid)|| "";
|
||||||
if (text) {
|
if (text) {
|
||||||
loadCode(text);
|
loadCode(text);
|
||||||
setLastPreset(fileid);
|
setLastPreset(fileid);
|
||||||
|
@ -107,6 +137,7 @@ function gotoPresetNamed(id) {
|
||||||
updateSelector();
|
updateSelector();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
qs['platform'] = platform_id;
|
||||||
qs['file'] = id;
|
qs['file'] = id;
|
||||||
window.location = "?" + $.param(qs);
|
window.location = "?" + $.param(qs);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +149,7 @@ function _createNewFile(e) {
|
||||||
if (filename.indexOf(".") < 0) {
|
if (filename.indexOf(".") < 0) {
|
||||||
filename += ".a";
|
filename += ".a";
|
||||||
}
|
}
|
||||||
qs['file'] = "local/" + platform_id + "/" + filename;
|
qs['file'] = "local/" + filename;
|
||||||
window.location = "?" + $.param(qs);
|
window.location = "?" + $.param(qs);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -172,23 +203,21 @@ function populateExamples(sel) {
|
||||||
|
|
||||||
function populateLocalFiles(sel) {
|
function populateLocalFiles(sel) {
|
||||||
sel.append($("<option />").text("------- Local Files -------"));
|
sel.append($("<option />").text("------- Local Files -------"));
|
||||||
for (var i = 0; i < localStorage.length; i++) {
|
var filenames = store.getFiles("local/");
|
||||||
var key = localStorage.key(i);
|
for (var i = 0; i < filenames.length; i++) {
|
||||||
if (key.startsWith("local/")) {
|
var name = filenames[i];
|
||||||
var name = key.substring(6);
|
var key = "local/" + name;
|
||||||
sel.append($("<option />").val("local/"+name).text(name).attr('selected',key==current_preset_id));
|
sel.append($("<option />").val(key).text(name).attr('selected',key==current_preset_id));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateSharedFiles(sel) {
|
function populateSharedFiles(sel) {
|
||||||
sel.append($("<option />").text("--------- Shared ---------"));
|
sel.append($("<option />").text("--------- Shared ---------"));
|
||||||
for (var i = 0; i < localStorage.length; i++) {
|
var filenames = store.getFiles("shared/");
|
||||||
var key = localStorage.key(i);
|
for (var i = 0; i < filenames.length; i++) {
|
||||||
if (key.startsWith("shared/")) {
|
var name = filenames[i];
|
||||||
var name = key.substring(6);
|
var key = "shared/" + name;
|
||||||
sel.append($("<option />").val("shared/"+name).text(name).attr('selected',key==current_preset_id));
|
sel.append($("<option />").val(key).text(name).attr('selected',key==current_preset_id));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +239,10 @@ function updateSelector() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCode(text) {
|
function setCode(text) {
|
||||||
worker.postMessage({code:text});
|
if (current_preset_id.endsWith(".pla"))
|
||||||
|
worker.postMessage({code:text, tool:'plasm'});
|
||||||
|
else
|
||||||
|
worker.postMessage({code:text, tool:'dasm'});
|
||||||
}
|
}
|
||||||
|
|
||||||
function arrayCompare(a,b) {
|
function arrayCompare(a,b) {
|
||||||
|
@ -738,6 +770,7 @@ try {
|
||||||
// load and start platform object
|
// load and start platform object
|
||||||
if (platform_id == 'vcs') {
|
if (platform_id == 'vcs') {
|
||||||
platform = new VCSPlatform();
|
platform = new VCSPlatform();
|
||||||
|
$("#booklink_vcs").show();
|
||||||
} else if (platform_id == 'apple2') {
|
} else if (platform_id == 'apple2') {
|
||||||
platform = new Apple2Platform($("#emulator")[0]);
|
platform = new Apple2Platform($("#emulator")[0]);
|
||||||
} else if (platform_id == 'atarivec') {
|
} else if (platform_id == 'atarivec') {
|
||||||
|
@ -745,12 +778,12 @@ try {
|
||||||
} else {
|
} else {
|
||||||
alert("Platform " + platform_id + " not recognized");
|
alert("Platform " + platform_id + " not recognized");
|
||||||
}
|
}
|
||||||
|
store = new FileStore(localStorage, platform_id + '/');
|
||||||
PRESETS = platform.getPresets();
|
PRESETS = platform.getPresets();
|
||||||
platform.start();
|
platform.start();
|
||||||
// reset file?
|
// reset file?
|
||||||
if (qs['file'] && qs['reset']) {
|
if (qs['file'] && qs['reset']) {
|
||||||
localStorage.removeItem(qs['file']);
|
store.deleteFile(qs['file']);
|
||||||
localStorage.removeItem('local/' + qs['file']);
|
|
||||||
qs['reset'] = '';
|
qs['reset'] = '';
|
||||||
window.location = "?" + $.param(qs);
|
window.location = "?" + $.param(qs);
|
||||||
} else if (qs['file']) {
|
} else if (qs['file']) {
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
// set up require.js for worker
|
// set up require.js for worker
|
||||||
importScripts("../../js/dasm.js");
|
importScripts("../../js/dasm.js");
|
||||||
|
importScripts("../../js/acme.js");
|
||||||
|
importScripts("../../js/plasm.js");
|
||||||
|
|
||||||
// shim out window and document objects
|
// shim out window and document objects
|
||||||
// https://github.com/mbostock/d3/issues/1053
|
// https://github.com/mbostock/d3/issues/1053
|
||||||
|
@ -19,11 +21,11 @@ var document = noop();
|
||||||
document.documentElement = noop();
|
document.documentElement = noop();
|
||||||
document.documentElement.style = noop();
|
document.documentElement.style = noop();
|
||||||
|
|
||||||
var MAIN_FILENAME = "main.a";
|
var DASM_MAIN_FILENAME = "main.a";
|
||||||
var PREAMBLE = "\tprocessor 6502\n";
|
var DASM_PREAMBLE = "\tprocessor 6502\n";
|
||||||
var PREAMBLE_LINES = 1;
|
var DASM_PREAMBLE_LINES = 1;
|
||||||
|
|
||||||
function parseListing(code, unresolved) {
|
function parseDASMListing(code, unresolved) {
|
||||||
var errorMatch = /main.a [(](\d+)[)]: error: (.+)/;
|
var errorMatch = /main.a [(](\d+)[)]: error: (.+)/;
|
||||||
// 4 08ee a9 00 start lda #01workermain.js:23:5
|
// 4 08ee a9 00 start lda #01workermain.js:23:5
|
||||||
var lineMatch = /\s*(\d+)\s+(\S+)\s+([0-9a-f]+)\s+([0-9a-f][0-9a-f ]+)\s+(.+)/;
|
var lineMatch = /\s*(\d+)\s+(\S+)\s+([0-9a-f]+)\s+([0-9a-f][0-9a-f ]+)\s+(.+)/;
|
||||||
|
@ -34,13 +36,13 @@ function parseListing(code, unresolved) {
|
||||||
for (var line of code.split(/\r?\n/)) {
|
for (var line of code.split(/\r?\n/)) {
|
||||||
var linem = lineMatch.exec(line);
|
var linem = lineMatch.exec(line);
|
||||||
if (linem && linem[1]) {
|
if (linem && linem[1]) {
|
||||||
var linenum = parseInt(linem[1]) - PREAMBLE_LINES;
|
var linenum = parseInt(linem[1]) - DASM_PREAMBLE_LINES;
|
||||||
var filename = linem[2];
|
var filename = linem[2];
|
||||||
var offset = parseInt(linem[3], 16);
|
var offset = parseInt(linem[3], 16);
|
||||||
var insns = linem[4];
|
var insns = linem[4];
|
||||||
var restline = linem[5];
|
var restline = linem[5];
|
||||||
// inside of main file?
|
// inside of main file?
|
||||||
if (filename == MAIN_FILENAME) {
|
if (filename == DASM_MAIN_FILENAME) {
|
||||||
if (insns && !restline.match(equMatch)) {
|
if (insns && !restline.match(equMatch)) {
|
||||||
lines.push({
|
lines.push({
|
||||||
line:linenum,
|
line:linenum,
|
||||||
|
@ -52,7 +54,7 @@ function parseListing(code, unresolved) {
|
||||||
lastline = linenum;
|
lastline = linenum;
|
||||||
} else {
|
} else {
|
||||||
// inside of macro or include file
|
// inside of macro or include file
|
||||||
if (linenum == -PREAMBLE_LINES) { // start of macro?
|
if (linenum == -DASM_PREAMBLE_LINES) { // start of macro?
|
||||||
lines.push({
|
lines.push({
|
||||||
line:lastline+1,
|
line:lastline+1,
|
||||||
offset:offset,
|
offset:offset,
|
||||||
|
@ -83,7 +85,7 @@ function parseListing(code, unresolved) {
|
||||||
return {lines:lines, errors:errors};
|
return {lines:lines, errors:errors};
|
||||||
}
|
}
|
||||||
|
|
||||||
function assemble(code) {
|
function assembleDASM(code) {
|
||||||
var re_usl = /(\w+)\s+0000\s+[?][?][?][?]/;
|
var re_usl = /(\w+)\s+0000\s+[?][?][?][?]/;
|
||||||
var unresolved = {};
|
var unresolved = {};
|
||||||
function print_fn(s) {
|
function print_fn(s) {
|
||||||
|
@ -97,23 +99,73 @@ function assemble(code) {
|
||||||
print:print_fn
|
print:print_fn
|
||||||
});
|
});
|
||||||
var FS = Module['FS'];
|
var FS = Module['FS'];
|
||||||
FS.writeFile(MAIN_FILENAME, PREAMBLE + code);
|
FS.writeFile(DASM_MAIN_FILENAME, DASM_PREAMBLE + code);
|
||||||
|
Module.callMain([DASM_MAIN_FILENAME, "-v3", "-la.lst"]);
|
||||||
Module.callMain([MAIN_FILENAME, "-v3", "-la.lst"]);
|
|
||||||
|
|
||||||
var aout = FS.readFile("a.out");
|
var aout = FS.readFile("a.out");
|
||||||
//console.log(aout);
|
//console.log(aout);
|
||||||
var alst = FS.readFile("a.lst", {'encoding':'utf8'});
|
var alst = FS.readFile("a.lst", {'encoding':'utf8'});
|
||||||
//console.log(alst);
|
//console.log(alst);
|
||||||
var listing = parseListing(alst, unresolved);
|
var listing = parseDASMListing(alst, unresolved);
|
||||||
return {exitstatus:Module.EXITSTATUS, output:aout, listing:listing};
|
return {exitstatus:Module.EXITSTATUS, output:aout, listing:listing};
|
||||||
}
|
}
|
||||||
|
|
||||||
//assemblepgm("\tprocessor 6502\n\torg $800\n\tlda #0");
|
function assembleACME(code) {
|
||||||
|
var re_usl = /(\w+)\s+0000\s+[?][?][?][?]/;
|
||||||
|
var unresolved = {};
|
||||||
|
function print_fn(s) {
|
||||||
|
var matches = re_usl.exec(s);
|
||||||
|
if (matches) {
|
||||||
|
unresolved[matches[1]] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var Module = ACME({
|
||||||
|
noInitialRun:true,
|
||||||
|
print:print_fn
|
||||||
|
});
|
||||||
|
var FS = Module['FS'];
|
||||||
|
FS.writeFile("main.a", code);
|
||||||
|
Module.callMain(["-o", "a.out", "-r", "a.rpt", "-l", "a.sym", "--setpc", "24576", "main.a"]);
|
||||||
|
var aout = FS.readFile("a.out");
|
||||||
|
var alst = FS.readFile("a.rpt", {'encoding':'utf8'});
|
||||||
|
var asym = FS.readFile("a.sym", {'encoding':'utf8'});
|
||||||
|
console.log("acme", code.length, "->", aout.length);
|
||||||
|
console.log(alst);
|
||||||
|
console.log(asym);
|
||||||
|
var listing = parseDASMListing(alst, unresolved);
|
||||||
|
return {exitstatus:Module.EXITSTATUS, output:aout, listing:listing};
|
||||||
|
}
|
||||||
|
|
||||||
|
function compilePLASMA(code) {
|
||||||
|
function print_fn(s) { console.log(s); }
|
||||||
|
var outstr = "";
|
||||||
|
function out_fn(s) { outstr += s; outstr += "\n"; }
|
||||||
|
var Module = PLASM({
|
||||||
|
noInitialRun:true,
|
||||||
|
noFSInit:true,
|
||||||
|
print:out_fn
|
||||||
|
});
|
||||||
|
var FS = Module['FS'];
|
||||||
|
var i = 0;
|
||||||
|
var output = [];
|
||||||
|
FS.init(
|
||||||
|
function() { return i<code.length ? code.charCodeAt(i++) : null; }
|
||||||
|
);
|
||||||
|
FS.writeFile("main.pla", code);
|
||||||
|
Module.callMain(["-A"]);
|
||||||
|
console.log("plasm", code.length, "->", outstr.length);
|
||||||
|
return assembleACME(outstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tools = {
|
||||||
|
'dasm': assembleDASM,
|
||||||
|
'plasm': compilePLASMA,
|
||||||
|
}
|
||||||
|
|
||||||
onmessage = function(e) {
|
onmessage = function(e) {
|
||||||
var code = e.data.code;
|
var code = e.data.code;
|
||||||
var result = assemble(code);
|
var toolfn = tools[e.data.tool];
|
||||||
|
if (!toolfn) throw "no tool named " + e.data.tool;
|
||||||
|
var result = toolfn(code);
|
||||||
//console.log("RESULT", result);
|
//console.log("RESULT", result);
|
||||||
postMessage(result);
|
postMessage(result);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user