added apple II display, sound; more tools; acme, plasm (PLASMA); platform switch

This commit is contained in:
Steven Hugg 2017-01-04 16:07:59 -05:00
parent 9391cafac6
commit 346bab90fd
7 changed files with 51051 additions and 92 deletions

View File

@ -100,6 +100,7 @@ div.booklink {
right: 0;
padding: 6px;
background-color: #ffffff;
display:none;
}
div.twitbtn {
position: fixed;
@ -115,6 +116,48 @@ a.dropdown-toggle {
color:#66ee66;
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>
</head>
<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_share_file">Share File...</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>
</span>
<select id="preset_select" name="">
@ -155,7 +206,7 @@ a.dropdown-toggle {
<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>
</div>
<div class="booklink">
<div class="booklink" id="booklink_vcs">
<!--
<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&region=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>
<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>
<link rel="stylesheet" href="bootstrap/css/bootstrap-tour.min.css">
<script src="bootstrap/js/bootstrap-tour.min.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="src/emu.js"></script>
<script src="src/util.js"></script>
<script src="src/platform/vcs.js"></script>
<script src="src/platform/apple2.js"></script>
<script src="src/platform/atarivec.js"></script>
@ -202,6 +254,5 @@ a.dropdown-toggle {
ga('create', 'UA-54497476-9', 'auto');
ga('send', 'pageview');
</script>
</html>

28715
js/acme.js Normal file

File diff suppressed because one or more lines are too long

21378
js/plasm.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -2,28 +2,33 @@
// 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 self = this;
var canvas, ctx;
var imageData, buf8, datau32;
this.start = function() {
// TODO
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);
canvas = __createCanvas(mainElement, width, height);
ctx = canvas.getContext('2d');
imageData = ctx.createImageData(width, height);
var buf = new ArrayBuffer(imageData.data.length);
@ -93,23 +98,7 @@ var VectorVideo = function(mainElement, width, height) {
var jitter = 1.0;
this.start = function() {
// TODO
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);
canvas = __createCanvas(mainElement, width, height);
ctx = canvas.getContext('2d');
}
@ -152,10 +141,6 @@ var VectorVideo = function(mainElement, width, height) {
}
}
var SampleAudio = function(clockfreq) {
}
var RAM = function(size) {
var memArray = new ArrayBuffer(size);
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;
}
}
}
}
}

View File

@ -3,33 +3,106 @@
var APPLE2_PRESETS = [
];
var GR_TXMODE = 1;
var GR_MIXMODE = 2;
var GR_PAGE1 = 4;
var GR_HIRES = 8;
var Apple2Platform = function(mainElement) {
var self = this;
var cpuFrequency = 1.023;
var cpuFrequency = 1023000;
var cpuCyclesPerLine = 65;
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() {
return APPLE2_PRESETS;
}
function noise() {
return (Math.random() * 256) & 0xff;
}
this.start = function() {
cpu = new jt.M6502();
ram = new RAM(0xc000);
//rom = new lzgmini().decode(APPLEIIGO_LZG).slice(0,12288);
rom = new lzgmini().decode(APPLEIIGO_LZG).slice(0,12288);
// bus
bus = {
read: function(address) {
address &= 0xffff;
if (address >= 0xd000 && address <= 0xffff) {
return rom[address - 0xd000];
} else if (address < 0xc000) {
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) {
address &= 0xffff;
if (address < 0xc000) {
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);
audio = new SampleAudio(cpuFrequency);
video.start();
audio.start();
var idata = video.getFrameData();
var grparams = {dirty:grdirty, grswitch:grswitch, mem:ram.mem};
ap2disp = new Apple2Display(idata, grparams);
var colors = [0xffff0000, 0xff00ff00];
timer = new AnimationTimer(60, function() {
// 262.5 scanlines per frame
var iaddr = 0x2000;
var iofs = 0;
breakClock = -1;
clock = 0;
var clock = 0;
for (var sl=0; sl<262; sl++) {
for (var i=0; i<cpuCyclesPerLine; i++) {
if (debugCondition && breakClock < 0 && debugCondition()) { breakClock = clock; }
clock++;
cpu.clockPulse();
// TODO: audio
}
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];
}
audio.feedSample(soundstate, 1);
}
}
grparams.dirty = grdirty;
grparams.grswitch = grswitch;
ap2disp.updateScreen();
video.updateFrame();
});
}
@ -75,15 +142,20 @@ var Apple2Platform = function(mainElement) {
}
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) {
throw "ROM length must be == 0x3000";
}
rom = data;
this.reset();
*/
}
this.getRasterPosition = function() {
return {x:xpos, y:ypos};
return {x:0, y:0};
}
this.isRunning = function() {
@ -188,8 +260,587 @@ var Apple2Platform = function(mainElement) {
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 = [
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,

View File

@ -1,5 +1,34 @@
"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
var worker = new Worker("./src/worker/workermain.js");
@ -9,6 +38,7 @@ var current_preset_id = null;
var offset2line = null;
var line2offset = null;
var trace_pending_at_pc;
var store;
var PRESETS, platform, platform_id;
@ -40,7 +70,7 @@ function setLastPreset(id) {
function updatePreset(current_preset_id, text) {
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) {
current_preset_id = fileid;
current_preset_index = index;
var text = localStorage.getItem(fileid) || localStorage.getItem(fileid.replace(platform_id+"/","")) || "";
var text = store.loadFile(fileid)|| "";
if (text) {
loadCode(text);
setLastPreset(fileid);
@ -107,6 +137,7 @@ function gotoPresetNamed(id) {
updateSelector();
}
} else {
qs['platform'] = platform_id;
qs['file'] = id;
window.location = "?" + $.param(qs);
}
@ -118,7 +149,7 @@ function _createNewFile(e) {
if (filename.indexOf(".") < 0) {
filename += ".a";
}
qs['file'] = "local/" + platform_id + "/" + filename;
qs['file'] = "local/" + filename;
window.location = "?" + $.param(qs);
}
return true;
@ -172,23 +203,21 @@ function populateExamples(sel) {
function populateLocalFiles(sel) {
sel.append($("<option />").text("------- Local Files -------"));
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
if (key.startsWith("local/")) {
var name = key.substring(6);
sel.append($("<option />").val("local/"+name).text(name).attr('selected',key==current_preset_id));
}
var filenames = store.getFiles("local/");
for (var i = 0; i < filenames.length; i++) {
var name = filenames[i];
var key = "local/" + name;
sel.append($("<option />").val(key).text(name).attr('selected',key==current_preset_id));
}
}
function populateSharedFiles(sel) {
sel.append($("<option />").text("--------- Shared ---------"));
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
if (key.startsWith("shared/")) {
var name = key.substring(6);
sel.append($("<option />").val("shared/"+name).text(name).attr('selected',key==current_preset_id));
}
var filenames = store.getFiles("shared/");
for (var i = 0; i < filenames.length; i++) {
var name = filenames[i];
var key = "shared/" + name;
sel.append($("<option />").val(key).text(name).attr('selected',key==current_preset_id));
}
}
@ -210,7 +239,10 @@ function updateSelector() {
}
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) {
@ -738,6 +770,7 @@ try {
// load and start platform object
if (platform_id == 'vcs') {
platform = new VCSPlatform();
$("#booklink_vcs").show();
} else if (platform_id == 'apple2') {
platform = new Apple2Platform($("#emulator")[0]);
} else if (platform_id == 'atarivec') {
@ -745,12 +778,12 @@ try {
} else {
alert("Platform " + platform_id + " not recognized");
}
store = new FileStore(localStorage, platform_id + '/');
PRESETS = platform.getPresets();
platform.start();
// reset file?
if (qs['file'] && qs['reset']) {
localStorage.removeItem(qs['file']);
localStorage.removeItem('local/' + qs['file']);
store.deleteFile(qs['file']);
qs['reset'] = '';
window.location = "?" + $.param(qs);
} else if (qs['file']) {

View File

@ -2,6 +2,8 @@
// set up require.js for worker
importScripts("../../js/dasm.js");
importScripts("../../js/acme.js");
importScripts("../../js/plasm.js");
// shim out window and document objects
// https://github.com/mbostock/d3/issues/1053
@ -19,11 +21,11 @@ var document = noop();
document.documentElement = noop();
document.documentElement.style = noop();
var MAIN_FILENAME = "main.a";
var PREAMBLE = "\tprocessor 6502\n";
var PREAMBLE_LINES = 1;
var DASM_MAIN_FILENAME = "main.a";
var DASM_PREAMBLE = "\tprocessor 6502\n";
var DASM_PREAMBLE_LINES = 1;
function parseListing(code, unresolved) {
function parseDASMListing(code, unresolved) {
var errorMatch = /main.a [(](\d+)[)]: error: (.+)/;
// 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+(.+)/;
@ -34,13 +36,13 @@ function parseListing(code, unresolved) {
for (var line of code.split(/\r?\n/)) {
var linem = lineMatch.exec(line);
if (linem && linem[1]) {
var linenum = parseInt(linem[1]) - PREAMBLE_LINES;
var linenum = parseInt(linem[1]) - DASM_PREAMBLE_LINES;
var filename = linem[2];
var offset = parseInt(linem[3], 16);
var insns = linem[4];
var restline = linem[5];
// inside of main file?
if (filename == MAIN_FILENAME) {
if (filename == DASM_MAIN_FILENAME) {
if (insns && !restline.match(equMatch)) {
lines.push({
line:linenum,
@ -52,7 +54,7 @@ function parseListing(code, unresolved) {
lastline = linenum;
} else {
// inside of macro or include file
if (linenum == -PREAMBLE_LINES) { // start of macro?
if (linenum == -DASM_PREAMBLE_LINES) { // start of macro?
lines.push({
line:lastline+1,
offset:offset,
@ -83,7 +85,7 @@ function parseListing(code, unresolved) {
return {lines:lines, errors:errors};
}
function assemble(code) {
function assembleDASM(code) {
var re_usl = /(\w+)\s+0000\s+[?][?][?][?]/;
var unresolved = {};
function print_fn(s) {
@ -97,23 +99,73 @@ function assemble(code) {
print:print_fn
});
var FS = Module['FS'];
FS.writeFile(MAIN_FILENAME, PREAMBLE + code);
Module.callMain([MAIN_FILENAME, "-v3", "-la.lst"]);
FS.writeFile(DASM_MAIN_FILENAME, DASM_PREAMBLE + code);
Module.callMain([DASM_MAIN_FILENAME, "-v3", "-la.lst"]);
var aout = FS.readFile("a.out");
//console.log(aout);
var alst = FS.readFile("a.lst", {'encoding':'utf8'});
//console.log(alst);
var listing = parseListing(alst, unresolved);
var listing = parseDASMListing(alst, unresolved);
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) {
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);
postMessage(result);
}