8bitworkshop/src/platform/apple2.ts

1064 lines
41 KiB
TypeScript

"use strict";
import { Platform, Base6502Platform, BaseMAMEPlatform, getOpcodeMetadata_6502 } from "../baseplatform";
import { PLATFORMS, RAM, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap, dumpRAM } from "../emu";
import { hex, lzgmini } from "../util";
import { SampleAudio } from "../audio";
declare var jt; // 6502
const APPLE2_PRESETS = [
{id:'sieve.c', name:'Sieve'},
{id:'keyboardtest.c', name:'Keyboard Test'},
{id:'mandel.c', name:'Mandelbrot'},
{id:'tgidemo.c', name:'TGI Graphics Demo'},
{id:'siegegame.c', name:'Siege Game'},
{id:'cosmic.c', name:'Cosmic Impalas'},
{id:'hgrtest.a', name:"HGR Test"},
{id:'conway.a', name:"Conway's Game of Life"},
{id:'lz4fh.a', name:"LZ4FH Graphics Compression"},
// {id:'tb_6502.s', name:'Tom Bombem (assembler game)'},
];
const GR_TXMODE = 1;
const GR_MIXMODE = 2;
const GR_PAGE1 = 4;
const GR_HIRES = 8;
type AppleGRParams = {dirty:boolean[], grswitch:number, mem:number[]};
const _Apple2Platform = function(mainElement) {
const cpuFrequency = 1023000;
const cpuCyclesPerLine = 65;
const VM_BASE = 0x803; // where to JMP after pr#6
const LOAD_BASE = VM_BASE; //0x7c9; // where to load ROM
const PGM_BASE = VM_BASE; //0x800; // where to load ROM
const HDR_SIZE = PGM_BASE - LOAD_BASE;
var cpu, ram, bus;
var video, ap2disp, audio, timer;
var grdirty = new Array(0xc000 >> 7);
var grswitch = GR_TXMODE;
var kbdlatch = 0;
var soundstate = 0;
var pgmbin;
// language card switches
var auxRAMselected = false;
var auxRAMbank = 1;
var writeinhibit = true;
// value to add when reading & writing each of these banks
// bank 1 is E000-FFFF, bank 2 is D000-DFFF
var bank2rdoffset=0, bank2wroffset=0;
var grparams : AppleGRParams;
class Apple2Platform extends Base6502Platform {
getPresets() {
return APPLE2_PRESETS;
}
start() {
cpu = new jt.M6502();
ram = new RAM(0x13000); // 64K + 16K LC RAM - 4K hardware
// ROM
var rom = new lzgmini().decode(APPLEIIGO_LZG);
ram.mem.set(rom, 0xd000);
ram.mem[0xbf00] = 0x4c; // fake DOS detect for C
ram.mem[0xbf6f] = 0x01; // fake DOS detect for C
// bus
bus = {
read: function(address) {
address &= 0xffff;
if (address < 0xc000) {
return ram.mem[address];
} else if (address >= 0xd000) {
//return rom[address - 0xd000] & 0xff;
//console.log(hex(address), rom[address-0xd000], ram.mem[address]);
if (!auxRAMselected)
return rom[address - 0xd000];
else if (address >= 0xe000)
return ram.mem[address];
else
return ram.mem[address + bank2rdoffset];
} 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 0; // TODO doLanguageCardIO(address, value);
case 9: case 10: case 11: case 12: case 13: case 14: case 15:
return noise(); // return slots[slot-8].doIO(address, value);
}
} else {
switch (address) {
// JMP VM_BASE
case 0xc600: {
// load program into RAM
if (pgmbin)
ram.mem.set(pgmbin.slice(HDR_SIZE), PGM_BASE);
return 0x4c;
}
case 0xc601: return VM_BASE&0xff;
case 0xc602: return (VM_BASE>>8)&0xff;
default: return noise();
}
}
return noise();
},
write: function(address, val) {
address &= 0xffff;
val &= 0xff;
if (address < 0xc000) {
ram.mem[address] = val;
grdirty[address>>7] = 1;
} else if (address < 0xc100) {
this.read(address); // strobe address, discard result
} else if (address >= 0xd000 && !writeinhibit) {
if (address >= 0xe000)
ram.mem[address] = val;
else
ram.mem[address + bank2wroffset] = val;
}
}
};
cpu.connectBus(bus);
// create video/audio
video = new RasterVideo(mainElement,280,192);
audio = new SampleAudio(cpuFrequency);
video.create();
video.setKeyboardEvents((key,code,flags) => {
if (flags & 1) {
if (code) {
// convert to uppercase for Apple ][
if (code >= 0x61 && code <= 0x7a)
code -= 0x20;
kbdlatch = (code | 0x80) & 0xff;
} else if (key) {
switch (key) {
case 16: return; // shift
case 17: return; // ctrl
case 18: return; // alt
case 37: key=8; break; // left
case 39: key=21; break; // right
case 38: key=11; break; // up
case 40: key=10; break; // down
}
if (key >= 65 && key < 65+26) {
if (flags & 5) key -= 64; // ctrl
}
kbdlatch = (key | 0x80) & 0xff;
}
}
});
var idata = video.getFrameData();
grparams = {dirty:grdirty, grswitch:grswitch, mem:ram.mem};
ap2disp = new Apple2Display(idata, grparams);
timer = new AnimationTimer(60, this.nextFrame.bind(this));
}
advance(novideo : boolean) {
// 262.5 scanlines per frame
var clock = 0;
var debugCond = this.getDebugCallback();
var rendered = false;
for (var sl=0; sl<262; sl++) {
for (var i=0; i<cpuCyclesPerLine; i++) {
if (debugCond && debugCond()) {
grparams.dirty = grdirty;
grparams.grswitch = grswitch;
ap2disp.updateScreen();
debugCond = null;
rendered = true;
}
clock++;
cpu.clockPulse();
audio.feedSample(soundstate, 1);
}
}
if (!novideo) {
if (!rendered) {
grparams.dirty = grdirty;
grparams.grswitch = grswitch;
ap2disp.updateScreen();
}
video.updateFrame();
}
}
loadROM(title, data) {
pgmbin = data;
this.reset();
}
isRunning() {
return timer.isRunning();
}
pause() {
timer.stop();
audio.stop();
}
resume() {
timer.start();
audio.start();
}
reset() {
cpu.reset();
// execute until $c600 boot
for (var i=0; i<2000000; i++) {
cpu.clockPulse();
if (this.getCPUState().PC == 0xc602) {
cpu.clockPulse();
cpu.clockPulse();
break;
}
}
}
readAddress(addr : number) {
return ((addr & 0xf000) != 0xc000) ? bus.read(addr) : null; // ignore I/O space
}
loadState(state) {
cpu.loadState(state.c);
ram.mem.set(state.b);
kbdlatch = state.kbd;
grswitch = state.gr;
auxRAMselected = state.lc.s;
auxRAMbank = state.lc.b;
writeinhibit = state.lc.w;
setupLanguageCardConstants();
ap2disp.invalidate(); // repaint entire screen
}
saveState() {
return {
c:cpu.saveState(),
b:ram.mem.slice(0),
kbd:kbdlatch,
gr:grswitch,
lc:{s:auxRAMselected,b:auxRAMbank,w:writeinhibit},
};
}
loadControlsState(state) {
kbdlatch = state.kbd;
}
saveControlsState() {
return {
kbd:kbdlatch
};
}
getCPUState() {
return cpu.saveState();
}
}
function doLanguageCardIO(address, value)
{
switch (address & 0x0f) {
// Select aux RAM bank 2, write protected.
case 0x0:
case 0x4:
auxRAMselected = true;
auxRAMbank = 2;
writeinhibit = true;
break;
// Select ROM, write enable aux RAM bank 2.
case 0x1:
case 0x5:
auxRAMselected = false;
auxRAMbank = 2;
writeinhibit = false;
break;
// Select ROM, write protect aux RAM (either bank).
case 0x2:
case 0x6:
case 0xA:
case 0xE:
auxRAMselected = false;
writeinhibit = true;
break;
// Select aux RAM bank 2, write enabled.
case 0x3:
case 0x7:
auxRAMselected = true;
auxRAMbank = 2;
writeinhibit = false;
break;
// Select aux RAM bank 1, write protected.
case 0x8:
case 0xC:
auxRAMselected = true;
auxRAMbank = 1;
writeinhibit = true;
break;
// Select ROM, write enable aux RAM bank 1.
case 0x9:
case 0xD:
auxRAMselected = false;
auxRAMbank = 1;
writeinhibit = false;
break;
// Select aux RAM bank 1, write enabled.
case 0xB:
case 0xF:
auxRAMselected = true;
auxRAMbank = 1;
writeinhibit = false;
break;
}
setupLanguageCardConstants();
return noise();
}
function setupLanguageCardConstants() {
// reset language card constants
if (auxRAMbank == 2)
bank2rdoffset = -0x1000; // map 0xd000-0xdfff -> 0xc000-0xcfff
else
bank2rdoffset = 0x3000; // map 0xd000-0xdfff -> 0x10000-0x10fff
if (auxRAMbank == 2)
bank2wroffset = -0x1000; // map 0xd000-0xdfff -> 0xc000-0xcfff
else
bank2wroffset = 0x3000; // map 0xd000-0xdfff -> 0x10000-0x10fff
}
return new Apple2Platform(); // return inner class from constructor
};
var Apple2Display = function(pixels : number[], apple : AppleGRParams) {
var XSIZE = 280;
var YSIZE = 192;
var PIXELON = 0xffffffff;
var PIXELOFF = 0xff000000;
var oldgrmode = -1;
var textbuf = new Array(40*24);
const flashInterval = 500;
const loresColor = [
(0xff000000), (0xffff00ff), (0xff00007f), (0xff7f007f),
(0xff007f00), (0xff7f7f7f), (0xff0000bf), (0xff0000ff),
(0xffbf7f00), (0xffffbf00), (0xffbfbfbf), (0xffff7f7f),
(0xff00ff00), (0xffffff00), (0xff00bf7f), (0xffffffff),
];
const 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
];
const 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 Array(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[d2*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<apple.dirty.length; 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<apple.dirty.length; i++)
apple.dirty[i] = false;
}
this.invalidate = function() {
oldgrmode = -1;
}
}
/*exported apple2_charset */
const 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
const APPLEIIGO_LZG = [
76,90,71,0,0,48,0,0,0,10,174,5,108,198,141,1,25,52,55,59,65,80,80,76,69,73,73,71,79,32,82,79,
77,49,46,49,255,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,3,133,109,132,110,56,165,150,229,155,133,94,
168,165,151,229,156,170,232,152,240,35,165,150,56,229,94,133,150,176,3,198,151,56,165,148,55,3,148,176,8,198,149,144,
4,177,150,145,148,136,208,249,59,194,198,151,198,149,202,208,242,96,52,30,128,59,27,255,255,32,0,224,52,30,67,59,
30,59,28,52,31,174,59,31,59,30,59,28,59,4,52,63,105,59,31,59,30,59,28,59,2,52,63,103,59,15,52,31,
137,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,26,160,32,59,28,32,
32,160,0,59,5,52,6,40,1,16,16,12,5,19,15,6,20,32,14,15,20,32,1,22,1,9,12,1,2,12,5,52,
16,40,198,207,210,160,205,207,210,197,160,201,206,55,3,205,193,212,201,207,206,160,208,204,197,193,211,197,160,195,204,201,
195,203,160,55,8,160,52,8,40,212,200,197,160,193,208,55,25,201,201,199,207,160,204,207,59,129,194,197,204,207,215,55,
28,59,10,52,6,40,59,29,59,14,76,3,224,32,88,252,162,39,189,0,223,157,128,4,202,16,247,55,3,48,223,157,
0,5,55,195,55,78,52,5,3,96,55,3,6,55,195,144,55,25,7,55,3,76,64,224,59,65,0,32,190,224,76,74,
224,104,24,105,1,133,244,104,105,0,133,245,165,226,72,165,225,72,165,227,133,225,165,228,133,226,160,0,169,225,133,250,
76,243,0,104,133,230,104,133,231,160,2,177,230,133,245,136,59,129,244,136,52,12,33,52,28,31,55,159,226,133,250,120,
141,3,192,55,35,160,16,185,127,225,153,238,0,136,208,247,132,227,132,225,169,191,133,55,24,162,16,96,234,59,28,59,
4,115,228,128,226,145,226,182,226,90,227,100,227,118,227,127,227,74,227,138,227,153,227,169,227,185,227,201,227,235,227,162,
226,24,228,63,228,41,228,142,228,102,229,125,59,161,164,228,239,0,83,228,95,228,105,228,96,232,109,232,66,232,81,232,
151,231,173,231,211,231,243,231,195,231,227,231,23,232,3,232,30,232,122,232,139,232,235,232,60,233,110,233,133,233,240,0,
248,228,15,229,124,229,148,229,234,229,12,230,228,230,247,230,132,230,155,230,183,230,203,230,15,231,47,231,84,231,115,231,
232,200,240,8,185,255,255,133,249,108,0,225,230,245,208,244,52,28,171,59,30,59,3,52,28,248,52,9,248,193,52,28,
248,122,232,183,232,14,233,60,233,106,233,129,233,240,0,41,229,70,229,173,229,203,229,49,230,89,52,19,248,181,192,24,
117,193,149,193,181,208,117,209,149,209,232,76,240,0,181,193,56,245,192,55,9,209,245,208,52,5,9,192,10,54,208,52,
13,29,132,229,160,16,181,193,73,255,133,230,181,209,59,161,231,169,0,149,193,70,231,102,230,176,12,149,209,181,192,52,
6,36,22,192,54,208,136,208,231,55,43,164,229,55,45,169,0,52,2,82,192,169,0,245,208,149,208,96,55,59,17,169,
0,133,230,133,231,181,208,41,128,133,224,16,5,32,235,226,230,224,181,209,16,9,232,55,2,202,230,224,208,4,21,193,
240,37,22,193,54,209,136,144,249,38,230,38,231,165,230,213,192,165,231,245,208,144,9,133,55,4,245,192,133,230,56,54,
55,86,208,226,232,164,229,96,52,11,87,76,240,0,32,249,226,70,224,176,233,55,194,165,230,149,55,51,149,208,165,224,
48,215,55,10,246,192,208,2,246,55,93,181,55,1,214,208,214,192,55,3,169,255,85,55,119,255,85,55,247,181,193,53,
52,3,255,53,52,6,255,193,21,55,136,21,52,7,8,55,39,55,8,55,39,52,37,11,181,192,201,8,144,10,180,193,
148,209,160,0,148,193,233,8,168,240,7,52,3,181,208,249,52,4,248,52,5,26,16,180,209,148,193,192,128,160,0,144,
1,136,148,209,56,55,96,12,181,209,201,128,106,118,193,136,208,248,52,38,37,181,192,21,208,240,2,169,255,73,255,149,
192,52,5,136,21,209,55,33,52,5,15,149,193,52,38,149,21,208,21,55,82,6,52,8,12,202,181,193,149,192,181,209,
55,238,192,72,181,208,72,55,142,104,149,208,104,149,52,2,225,202,169,0,52,5,76,202,200,208,2,230,245,177,244,52,
34,46,52,13,9,52,6,1,52,8,14,152,24,101,244,133,55,163,168,101,245,133,245,149,208,177,244,168,52,13,21,52,
5,19,55,17,73,255,24,101,227,133,227,55,38,255,101,228,133,228,55,101,145,227,136,192,255,208,247,200,55,239,181,192,
133,230,181,208,133,231,132,229,160,0,177,230,149,192,148,208,52,5,239,52,12,15,200,59,129,52,14,18,141,2,192,52,
8,44,52,130,128,52,19,21,52,5,50,55,216,52,5,198,202,24,101,225,52,2,185,101,226,52,3,208,52,5,14,132,
229,168,202,177,55,144,52,5,99,52,13,16,200,59,129,52,15,17,141,2,192,52,6,44,141,3,192,52,21,22,55,178,
52,13,23,133,230,52,6,1,52,5,221,202,52,7,245,52,25,26,52,40,0,52,18,29,52,5,237,52,3,66,52,26,
103,52,8,32,52,3,72,52,6,35,181,193,52,98,192,133,231,181,192,52,2,104,145,230,232,52,69,123,52,5,15,55,
77,181,192,145,230,200,181,208,52,7,20,52,8,228,55,18,225,52,18,12,55,102,52,19,17,52,22,36,52,21,174,52,
7,141,52,57,27,52,8,150,52,27,29,145,230,52,28,60,55,220,181,192,213,193,208,28,181,208,213,209,208,22,169,255,
232,52,102,124,55,78,240,55,142,234,169,0,52,7,14,193,213,192,52,162,39,80,2,73,128,16,210,48,230,55,94,181,
208,245,209,55,72,48,194,16,214,52,10,8,16,178,48,198,52,10,40,48,162,16,182,232,181,207,21,191,208,20,52,3,
134,59,131,76,240,0,55,204,236,165,245,133,231,165,244,55,141,24,113,244,133,230,165,231,55,132,55,3,245,165,52,226,
145,136,55,163,191,213,192,208,193,181,207,213,208,240,207,208,185,55,199,198,55,135,172,208,190,55,135,181,207,245,208,48,
179,16,157,232,181,192,213,191,181,208,245,207,48,166,16,144,165,244,24,117,192,133,244,165,245,117,208,133,245,52,130,26,
52,48,16,165,245,72,165,244,72,152,72,32,57,233,104,168,104,133,244,104,133,245,25,3,0,28,52,26,36,141,2,192,
88,55,40,120,141,3,192,52,7,44,226,55,172,52,102,157,232,52,24,79,52,15,27,52,24,70,108,230,0,200,177,244,
72,73,255,56,52,130,97,133,225,52,132,97,133,226,55,13,10,168,240,13,181,208,136,145,225,181,192,232,59,161,208,243,
160,2,55,41,52,2,67,104,24,101,225,133,227,52,98,249,133,228,104,133,225,104,133,226,96,55,79,165,55,13,165,52,
8,11,25,30,1,212,59,31,59,31,59,31,59,30,0,201,206,176,238,201,201,144,234,201,204,240,230,208,232,25,12,1,
185,72,74,41,3,9,4,133,41,104,41,24,144,2,105,127,133,40,10,10,5,40,133,40,52,94,61,0,0,165,37,32,
193,251,101,32,52,29,75,59,21,165,34,72,32,36,252,165,40,133,42,165,41,133,43,164,33,136,104,105,1,197,35,176,
13,55,78,177,40,145,42,136,16,249,48,225,160,0,32,158,252,176,134,164,36,169,160,145,40,200,196,33,144,249,52,30,
199,59,27,164,36,177,40,72,41,63,9,64,145,40,104,108,56,52,19,27,32,12,253,32,165,251,59,161,201,155,240,243,
52,28,141,59,6,32,142,253,165,51,32,237,253,162,1,138,240,243,202,32,53,253,201,149,208,2,177,40,201,224,144,2,
41,223,157,0,2,201,141,208,178,32,156,252,169,141,208,91,164,61,166,60,55,39,32,64,249,160,0,169,173,76,237,253,
52,28,87,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,31,59,28,59,7,169,
0,133,28,165,230,133,27,160,0,132,26,165,28,145,26,32,126,244,200,208,246,230,27,165,27,41,31,208,238,96,133,226,
134,224,132,225,72,41,192,133,38,74,74,5,38,133,38,104,133,39,10,10,10,38,39,59,66,102,38,165,39,41,31,5,
230,133,39,138,192,0,240,5,160,35,105,4,200,233,7,176,251,132,229,170,189,185,244,133,48,152,74,165,228,133,28,176,
25,28,0,35,59,4,10,201,192,16,6,165,28,73,127,133,28,52,254,218,59,31,59,31,59,31,59,31,59,31,59,31,
59,28,59,10,74,8,32,71,248,40,169,15,144,2,105,224,133,46,177,38,69,48,37,46,81,38,145,38,96,32,0,248,
196,44,176,17,200,32,14,248,144,246,105,1,72,55,8,104,197,45,144,245,96,160,47,208,2,160,39,132,45,160,39,169,
0,133,48,32,40,248,136,16,246,96,25,5,4,126,39,25,6,4,126,38,10,10,52,130,52,96,165,48,24,105,3,41,
15,133,48,10,59,1,5,48,133,48,52,103,223,144,4,74,59,1,41,15,52,107,240,168,74,144,9,106,176,16,201,162,
240,12,41,135,74,170,189,98,249,32,121,248,208,4,160,128,169,0,170,189,166,249,133,46,41,3,133,47,152,41,143,170,
152,160,3,224,138,240,11,74,144,8,74,74,9,32,136,208,250,200,136,208,242,52,159,59,59,31,59,31,59,20,216,32,
132,254,32,47,251,32,147,254,32,137,254,173,88,192,173,90,192,173,93,192,173,95,192,173,255,207,44,16,192,216,32,58,
255,32,96,251,169,0,133,0,169,198,133,1,108,52,30,111,59,29,25,3,19,108,221,219,199,207,52,10,13,173,112,192,
160,0,234,234,189,100,192,16,4,200,208,248,136,96,169,0,133,72,173,86,192,173,84,192,173,81,192,169,0,240,11,173,
80,192,173,83,192,32,54,248,169,20,133,34,55,22,32,169,40,133,33,169,24,133,35,169,23,133,37,76,34,252,32,88,
252,160,9,185,8,251,153,14,4,136,208,247,96,173,243,3,73,165,141,244,3,96,201,141,208,24,172,0,192,16,19,192,
147,208,15,44,16,192,55,68,251,192,131,240,3,55,4,76,253,251,52,12,148,25,29,7,248,40,133,40,96,201,135,208,
18,169,64,32,168,252,160,192,169,12,59,193,173,48,192,136,208,245,96,164,36,145,40,230,36,165,36,197,33,176,102,96,
201,160,176,239,168,16,236,201,141,240,90,201,138,59,97,136,208,201,198,36,16,232,165,33,133,36,198,36,165,34,197,37,
176,11,198,37,25,28,7,248,0,72,32,36,252,32,158,252,160,0,104,105,0,197,35,144,240,176,202,165,34,133,37,160,
0,132,36,240,228,169,0,133,36,230,55,62,55,16,182,198,37,25,29,7,248,25,6,7,248,56,72,233,1,208,252,104,
59,129,246,96,230,66,208,2,230,67,165,60,197,62,165,61,229,63,230,60,55,6,61,52,125,244,59,18,25,13,7,248,
230,78,208,2,230,79,44,0,192,16,245,145,40,173,0,192,44,16,192,96,25,10,7,248,254,96,165,50,72,169,255,133,
50,189,0,2,32,237,253,104,55,129,201,136,240,29,201,152,240,10,224,248,144,3,32,58,255,232,208,19,169,220,55,21,
25,10,7,248,254,25,30,7,248,59,27,0,72,52,162,88,32,229,253,104,41,15,9,176,201,186,144,2,105,6,108,54,
0,201,160,144,2,37,50,132,53,72,32,120,251,104,164,53,52,49,47,64,52,10,5,52,11,24,177,60,145,66,32,180,
252,144,247,52,190,97,59,1,160,63,208,2,160,255,132,50,52,98,82,62,162,56,160,27,208,8,55,130,54,160,240,165,
62,41,15,240,6,9,192,160,0,240,2,169,253,148,0,149,1,96,234,234,76,0,224,52,30,115,59,29,59,13,169,135,
76,237,253,165,72,72,165,69,166,70,164,71,52,110,22,52,62,27,59,30,59,14,245,3,251,3,98,250,98,250
];
/// MAME support
class Apple2MAMEPlatform extends BaseMAMEPlatform {
start () {
this.startModule(this.mainElement, {
jsfile:'mameapple2e.js',
biosfile:['apple2e.zip'],
//cfgfile:'nes.cfg',
driver:'apple2e',
width:280*2,
height:192*2,
//romfn:'/emulator/cart.nes',
//romsize:romSize,
//romdata:new lzgmini().decode(lzgRom).slice(0, romSize),
preInit:function(_self) {
},
});
}
getOpcodeMetadata = getOpcodeMetadata_6502;
getDefaultExtension () { return ".c"; };
getPresets () { return APPLE2_PRESETS; }
loadROM (title, data) {
this.loadROMFile(data);
// TODO
}
}
PLATFORMS['apple2'] = _Apple2Platform;
PLATFORMS['apple2-e'] = Apple2MAMEPlatform;