This commit is contained in:
Will Scullin 2020-11-24 08:53:43 -08:00
parent b80436d99c
commit 1e58e2c1b8
No known key found for this signature in database
GPG Key ID: 9092A5C0A673416B
28 changed files with 775 additions and 773 deletions

View File

@ -52,7 +52,7 @@ export class Apple2 implements Restorable<State> {
};
constructor(options: Options) {
this.cpu = new CPU6502({ '65C02': options.enhanced })
this.cpu = new CPU6502({ '65C02': options.enhanced });
this.gr = new LoresPage(1, options.characterRom, options.e, options.screen[0]);
this.gr2 = new LoresPage(2, options.characterRom, options.e, options.screen[1]);
this.hgr = new HiresPage(1, options.screen[2]);
@ -68,9 +68,9 @@ export class Apple2 implements Restorable<State> {
this.mmu = new MMU(this.cpu, this.vm, this.gr, this.gr2, this.hgr, this.hgr2, this.io, options.rom);
this.cpu.addPageHandler(this.mmu);
} else {
let ram1 = new RAM(0x00, 0x03);
let ram2 = new RAM(0x0C, 0x1F);
let ram3 = new RAM(0x60, 0xBF);
const ram1 = new RAM(0x00, 0x03);
const ram2 = new RAM(0x0C, 0x1F);
const ram3 = new RAM(0x60, 0xBF);
this.cpu.addPageHandler(ram1);
this.cpu.addPageHandler(this.gr);
@ -94,14 +94,15 @@ export class Apple2 implements Restorable<State> {
return; // already running
}
let interval = 30;
const interval = 30;
let now, last = Date.now();
let runFn = () => {
let kHz = this.io.getKHz();
const runFn = () => {
const kHz = this.io.getKHz();
now = Date.now();
let step = (now - last) * kHz, stepMax = kHz * interval;
const stepMax = kHz * interval;
let step = (now - last) * kHz;
last = now;
if (step > stepMax) {
step = stepMax;
@ -109,7 +110,7 @@ export class Apple2 implements Restorable<State> {
if (this.DEBUG) {
this.cpu.stepCyclesDebug(this.TRACE ? 1 : step, () => {
let line = this.cpu.dumpRegisters() + ' ' +
const line = this.cpu.dumpRegisters() + ' ' +
this.cpu.dumpPC(undefined, SYMBOLS);
if (this.TRACE) {
debug(line);
@ -165,7 +166,7 @@ export class Apple2 implements Restorable<State> {
}
getState(): State {
let state: State = {
const state: State = {
cpu: this.cpu.getState(),
};

View File

@ -112,8 +112,8 @@ export default class Apple2IO implements PageHandler {
}
_tick() {
let now = this.cpu.getCycles();
let phase = this._didAudio ? (this._phase > 0 ? this._high : this._low) : 0.0;
const now = this.cpu.getCycles();
const phase = this._didAudio ? (this._phase > 0 ? this._high : this._low) : 0.0;
for (; this._sampleTime < now; this._sampleTime += this._cycles_per_sample) {
this._sample[this._sampleIdx++] = phase;
if (this._sampleIdx === this._sample_size) {
@ -138,151 +138,151 @@ export default class Apple2IO implements PageHandler {
_access(off: byte, val?: byte): byte | undefined {
let result: number | undefined = 0;
let now = this.cpu.getCycles();
let delta = now - this._trigger;
const now = this.cpu.getCycles();
const delta = now - this._trigger;
switch (off) {
case LOC.CLRTEXT:
this._debug('Graphics Mode');
this.vm.text(false);
break;
case LOC.SETTEXT:
this._debug('Text Mode');
this.vm.text(true);
break;
case LOC.CLRMIXED:
this._debug('Mixed Mode off');
this.vm.mixed(false);
break;
case LOC.SETMIXED:
this._debug('Mixed Mode on');
this.vm.mixed(true);
break;
case LOC.CLRHIRES:
this._debug('LoRes Mode');
this.vm.hires(false);
break;
case LOC.SETHIRES:
this._debug('HiRes Mode');
this.vm.hires(true);
break;
case LOC.PAGE1:
this.vm.page(1);
break;
case LOC.PAGE2:
this.vm.page(2);
break;
case LOC.SETAN0:
this._debug('Annunciator 0 on');
this._annunciators[0] = true;
break;
case LOC.SETAN1:
this._debug('Annunciator 1 on');
this._annunciators[1] = true;
break;
case LOC.SETAN2:
this._debug('Annunciator 2 on');
this._annunciators[2] = true;
break;
case LOC.SETAN3:
this._debug('Annunciator 3 on');
this._annunciators[3] = true;
break;
case LOC.CLRAN0:
this._debug('Annunciator 0 off');
this._annunciators[0] = false;
break;
case LOC.CLRAN1:
this._debug('Annunciator 1 off');
this._annunciators[1] = false;
break;
case LOC.CLRAN2:
this._debug('Annunciator 2 off');
this._annunciators[2] = false;
break;
case LOC.CLRAN3:
this._debug('Annunciator 3 off');
this._annunciators[3] = false;
break;
case LOC.PB0:
result = this._button[0] ? 0x80 : 0;
break;
case LOC.PB1:
result = this._button[1] ? 0x80 : 0;
break;
case LOC.PB2:
result = this._button[2] ? 0x80 : 0;
break;
case LOC.PADDLE0:
result = (delta < (this._paddle[0] * 2756) ? 0x80 : 0x00);
break;
case LOC.PADDLE1:
result = (delta < (this._paddle[1] * 2756) ? 0x80 : 0x00);
break;
case LOC.PADDLE2:
result = (delta < (this._paddle[2] * 2756) ? 0x80 : 0x00);
break;
case LOC.PADDLE3:
result = (delta < (this._paddle[3] * 2756) ? 0x80 : 0x00);
break;
case LOC.ACCEL:
if (val !== undefined) {
this._updateKHz(val & 0x01 ? 1023 : 4096);
}
break;
case LOC.TAPEIN:
if (this._tapeOffset == -1) {
this._tapeOffset = 0;
this._tapeNext = now;
}
case LOC.CLRTEXT:
this._debug('Graphics Mode');
this.vm.text(false);
break;
case LOC.SETTEXT:
this._debug('Text Mode');
this.vm.text(true);
break;
case LOC.CLRMIXED:
this._debug('Mixed Mode off');
this.vm.mixed(false);
break;
case LOC.SETMIXED:
this._debug('Mixed Mode on');
this.vm.mixed(true);
break;
case LOC.CLRHIRES:
this._debug('LoRes Mode');
this.vm.hires(false);
break;
case LOC.SETHIRES:
this._debug('HiRes Mode');
this.vm.hires(true);
break;
case LOC.PAGE1:
this.vm.page(1);
break;
case LOC.PAGE2:
this.vm.page(2);
break;
case LOC.SETAN0:
this._debug('Annunciator 0 on');
this._annunciators[0] = true;
break;
case LOC.SETAN1:
this._debug('Annunciator 1 on');
this._annunciators[1] = true;
break;
case LOC.SETAN2:
this._debug('Annunciator 2 on');
this._annunciators[2] = true;
break;
case LOC.SETAN3:
this._debug('Annunciator 3 on');
this._annunciators[3] = true;
break;
case LOC.CLRAN0:
this._debug('Annunciator 0 off');
this._annunciators[0] = false;
break;
case LOC.CLRAN1:
this._debug('Annunciator 1 off');
this._annunciators[1] = false;
break;
case LOC.CLRAN2:
this._debug('Annunciator 2 off');
this._annunciators[2] = false;
break;
case LOC.CLRAN3:
this._debug('Annunciator 3 off');
this._annunciators[3] = false;
break;
case LOC.PB0:
result = this._button[0] ? 0x80 : 0;
break;
case LOC.PB1:
result = this._button[1] ? 0x80 : 0;
break;
case LOC.PB2:
result = this._button[2] ? 0x80 : 0;
break;
case LOC.PADDLE0:
result = (delta < (this._paddle[0] * 2756) ? 0x80 : 0x00);
break;
case LOC.PADDLE1:
result = (delta < (this._paddle[1] * 2756) ? 0x80 : 0x00);
break;
case LOC.PADDLE2:
result = (delta < (this._paddle[2] * 2756) ? 0x80 : 0x00);
break;
case LOC.PADDLE3:
result = (delta < (this._paddle[3] * 2756) ? 0x80 : 0x00);
break;
case LOC.ACCEL:
if (val !== undefined) {
this._updateKHz(val & 0x01 ? 1023 : 4096);
}
break;
case LOC.TAPEIN:
if (this._tapeOffset == -1) {
this._tapeOffset = 0;
this._tapeNext = now;
}
if (this._tapeOffset < this._tape.length) {
this._tapeCurrent = this._tape[this._tapeOffset][1];
while (now >= this._tapeNext) {
if ((this._tapeOffset % 1000) === 0) {
debug('Read ' + (this._tapeOffset / 1000));
}
this._tapeCurrent = this._tape[this._tapeOffset][1];
this._tapeNext += this._tape[this._tapeOffset++][0];
if (this._tapeOffset < this._tape.length) {
this._tapeCurrent = this._tape[this._tapeOffset][1];
while (now >= this._tapeNext) {
if ((this._tapeOffset % 1000) === 0) {
debug('Read ' + (this._tapeOffset / 1000));
}
this._tapeCurrent = this._tape[this._tapeOffset][1];
this._tapeNext += this._tape[this._tapeOffset++][0];
}
result = this._tapeCurrent ? 0x80 : 0x00;
}
result = this._tapeCurrent ? 0x80 : 0x00;
break;
default:
switch (off & 0xf0) {
case LOC.KEYBOARD: // C00x
result = this._key;
break;
default:
switch (off & 0xf0) {
case LOC.KEYBOARD: // C00x
result = this._key;
break;
case LOC.STROBE: // C01x
this._key &= 0x7f;
if (this._buffer.length > 0) {
let val = this._buffer.shift() as string;
if (val == '\n') {
val = '\r';
}
this._key = val.charCodeAt(0) | 0x80;
}
result = (this._keyDown ? 0x80 : 0x00) | this._key;
break;
case LOC.TAPEOUT: // C02x
this._phase = -this._phase;
this._didAudio = true;
this._tick();
break;
case LOC.SPEAKER: // C03x
this._phase = -this._phase;
this._didAudio = true;
this._tick();
break;
case LOC.C040STB: // C04x
// I/O Strobe
break;
case LOC.PDLTRIG: // C07x
this._trigger = this.cpu.getCycles();
break;
case LOC.STROBE: // C01x
this._key &= 0x7f;
if (this._buffer.length > 0) {
let val = this._buffer.shift() as string;
if (val == '\n') {
val = '\r';
}
this._key = val.charCodeAt(0) | 0x80;
}
result = (this._keyDown ? 0x80 : 0x00) | this._key;
break;
case LOC.TAPEOUT: // C02x
this._phase = -this._phase;
this._didAudio = true;
this._tick();
break;
case LOC.SPEAKER: // C03x
this._phase = -this._phase;
this._didAudio = true;
this._tick();
break;
case LOC.C040STB: // C04x
// I/O Strobe
break;
case LOC.PDLTRIG: // C07x
this._trigger = this.cpu.getCycles();
break;
}
}
if (val !== undefined) {
@ -305,8 +305,8 @@ export default class Apple2IO implements PageHandler {
if (off < 0x80) {
result = this._access(off, val);
} else {
let slot = (off & 0x70) >> 4;
let card = this._slot[slot];
const slot = (off & 0x70) >> 4;
const card = this._slot[slot];
if (card && card.ioSwitch) {
result = card.ioSwitch(off, val);
}
@ -317,7 +317,7 @@ export default class Apple2IO implements PageHandler {
reset() {
for (let slot = 0; slot < 8; slot++) {
let card = this._slot[slot];
const card = this._slot[slot];
if (card && card.reset) {
card.reset();
}
@ -326,7 +326,7 @@ export default class Apple2IO implements PageHandler {
}
blit() {
let card = this._slot[3];
const card = this._slot[3];
if (card && card.blit) {
return card.blit();
}
@ -334,36 +334,36 @@ export default class Apple2IO implements PageHandler {
}
read(page: byte, off: byte) {
var result = 0;
var slot;
var card;
let result = 0;
let slot;
let card;
switch (page) {
case 0xc0:
result = this.ioSwitch(off, undefined);
break;
case 0xc1:
case 0xc2:
case 0xc3:
case 0xc4:
case 0xc5:
case 0xc6:
case 0xc7:
slot = page & 0x0f;
card = this._slot[slot];
if (this._auxRom != card) {
// _debug('Setting auxRom to slot', slot);
this._auxRom = card;
}
if (card) {
result = card.read(page, off);
}
break;
default:
if (this._auxRom) {
result = this._auxRom.read(page, off);
}
break;
case 0xc0:
result = this.ioSwitch(off, undefined);
break;
case 0xc1:
case 0xc2:
case 0xc3:
case 0xc4:
case 0xc5:
case 0xc6:
case 0xc7:
slot = page & 0x0f;
card = this._slot[slot];
if (this._auxRom != card) {
// _debug('Setting auxRom to slot', slot);
this._auxRom = card;
}
if (card) {
result = card.read(page, off);
}
break;
default:
if (this._auxRom) {
result = this._auxRom.read(page, off);
}
break;
}
return result;
}
@ -373,31 +373,31 @@ export default class Apple2IO implements PageHandler {
let card;
switch (page) {
case 0xc0:
this.ioSwitch(off, val);
break;
case 0xc1:
case 0xc2:
case 0xc3:
case 0xc4:
case 0xc5:
case 0xc6:
case 0xc7:
slot = page & 0x0f;
card = this._slot[slot];
if (this._auxRom != card) {
// _debug('Setting auxRom to slot', slot);
this._auxRom = card;
}
if (card) {
card.write(page, off, val);
}
break;
default:
if (this._auxRom) {
this._auxRom.write(page, off, val);
}
break;
case 0xc0:
this.ioSwitch(off, val);
break;
case 0xc1:
case 0xc2:
case 0xc3:
case 0xc4:
case 0xc5:
case 0xc6:
case 0xc7:
slot = page & 0x0f;
card = this._slot[slot];
if (this._auxRom != card) {
// _debug('Setting auxRom to slot', slot);
this._auxRom = card;
}
if (card) {
card.write(page, off, val);
}
break;
default:
if (this._auxRom) {
this._auxRom.write(page, off, val);
}
break;
}
}
@ -448,7 +448,7 @@ export default class Apple2IO implements PageHandler {
this._buffer = buffer.split(''); // split to charaters
if (this._buffer.length > 0) {
this._keyDown = true;
let key = this._buffer.shift() as string; // never undefined
const key = this._buffer.shift() as string; // never undefined
this._key = key.charCodeAt(0) | 0x80;
}
}
@ -469,7 +469,7 @@ export default class Apple2IO implements PageHandler {
tick() {
this._tick();
for (var idx = 0; idx < 8; idx++) {
for (let idx = 0; idx < 8; idx++) {
if (this._slot[idx] && this._slot[idx].tick) {
this._slot[idx].tick();
}

View File

@ -24,7 +24,7 @@ let altCharMode = false;
let an3 = false;
let doubleHiresMode = false;
let monoDHRMode = false;
let colorDHRMode = false;
const colorDHRMode = false;
let mixedDHRMode = false;
let highColorHGRMode = false;
let highColorTextMode = false;
@ -74,9 +74,9 @@ function dim(c: Color): Color {
}
function rowToBase(row: number) {
let ab = (row >> 3) & 3;
let cd = (row >> 1) & 0x3;
let e = row & 1;
const ab = (row >> 3) & 3;
const cd = (row >> 1) & 0x3;
const e = row & 1;
return (cd << 8) | (e << 7) | (ab << 5) | (ab << 3);
}
@ -192,22 +192,22 @@ export class LoresPage implements Memory, Restorable<GraphicsState> {
}
_drawPixel(data: number[], off: number, color: Color) {
let c0 = color[0], c1 = color[1], c2 = color[2];
const c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = data[off + 4] = c0;
data[off + 1] = data[off + 5] = c1;
data[off + 2] = data[off + 6] = c2;
let nextOff = off + 560 * 4;
const nextOff = off + 560 * 4;
data[nextOff] = data[nextOff + 4] = c0;
data[nextOff + 1] = data[nextOff + 5] = c1;
data[nextOff + 2] = data[nextOff + 6] = c2;
}
_drawHalfPixel(data: number[], off: number, color: Color) {
let c0 = color[0], c1 = color[1], c2 = color[2];
const c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = c0;
data[off + 1] = c1;
data[off + 2] = c2;
let nextOff = off + 560 * 4;
const nextOff = off + 560 * 4;
data[nextOff] = c0;
data[nextOff + 1] = c1;
data[nextOff + 2] = c2;
@ -240,13 +240,13 @@ export class LoresPage implements Memory, Restorable<GraphicsState> {
_end() { return (0x04 * this.page) + 0x03; }
_read(page: byte, off: byte, bank: bank) {
var addr = (page << 8) | off, base = addr & 0x3FF;
const addr = (page << 8) | off, base = addr & 0x3FF;
return this._buffer[bank][base];
}
_write(page: byte, off: byte, val: byte, bank: bank) {
let addr = (page << 8) | off;
let base = addr & 0x3FF;
const addr = (page << 8) | off;
const base = addr & 0x3FF;
let fore, back;
if (this._buffer[bank][base] == val && !this._refreshing) {
@ -254,16 +254,16 @@ export class LoresPage implements Memory, Restorable<GraphicsState> {
}
this._buffer[bank][base] = val;
let col = (base % 0x80) % 0x28;
let adj = off - col;
const col = (base % 0x80) % 0x28;
const adj = off - col;
// 000001cd eabab000 -> 000abcde
let ab = (adj & 0x18);
let cd = (page & 0x03) << 1;
let ee = adj >> 7;
let row = ab | cd | ee;
const ab = (adj & 0x18);
const cd = (page & 0x03) << 1;
const ee = adj >> 7;
const row = ab | cd | ee;
let data = this._imageData.data;
const data = this._imageData.data;
if ((row < 24) && (col < 40)) {
let y = row << 4;
if (y < this._dirty.top) { this._dirty.top = y; }
@ -335,7 +335,7 @@ export class LoresPage implements Memory, Restorable<GraphicsState> {
off += 546 * 4 + 560 * 4;
}
} else {
var colorMode = mixedMode && !textMode && !this._monoMode;
const colorMode = mixedMode && !textMode && !this._monoMode;
// var val0 = col > 0 ? _buffer[0][base - 1] : 0;
// var val2 = col < 39 ? _buffer[0][base + 1] : 0;
@ -461,7 +461,7 @@ export class LoresPage implements Memory, Restorable<GraphicsState> {
this._refreshing = true;
this._blink = !this._blink;
for (let idx = 0; idx < 0x400; idx++, addr++) {
let b = this._buffer[0][idx];
const b = this._buffer[0][idx];
if ((b & 0xC0) == 0x40) {
this._write(addr >> 8, addr & 0xff, this._buffer[0][idx], 0);
}
@ -477,9 +477,9 @@ export class LoresPage implements Memory, Restorable<GraphicsState> {
blit(mixed: boolean = false): boolean {
if (this._dirty.top === 385) { return false; }
let top = this._dirty.top;
let bottom = this._dirty.bottom;
let left = this._dirty.left;
let right = this._dirty.right;
const bottom = this._dirty.bottom;
const left = this._dirty.left;
const right = this._dirty.right;
if (mixed) {
if (bottom < 320) { return false; }
@ -545,8 +545,8 @@ export class LoresPage implements Memory, Restorable<GraphicsState> {
}
getText() {
var buffer = '', line, charCode;
var row, col, base;
let buffer = '', line, charCode;
let row, col, base;
for (row = 0; row < 24; row++) {
base = rowToBase(row);
line = '';
@ -604,23 +604,23 @@ export class HiresPage implements Memory, Restorable<GraphicsState> {
}
_drawPixel(data: number[], off: number, color: Color) {
var c0 = color[0], c1 = color[1], c2 = color[2];
const c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = data[off + 4] = c0;
data[off + 1] = data[off + 5] = c1;
data[off + 2] = data[off + 6] = c2;
var nextOff = off + 560 * 4;
const nextOff = off + 560 * 4;
data[nextOff] = data[nextOff + 4] = c0;
data[nextOff + 1] = data[nextOff + 5] = c1;
data[nextOff + 2] = data[nextOff + 6] = c2;
}
_drawHalfPixel(data: number[], off: number, color: Color) {
var c0 = color[0], c1 = color[1], c2 = color[2];
const c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = c0;
data[off + 1] = c1;
data[off + 2] = c2;
var nextOff = off + 560 * 4;
const nextOff = off + 560 * 4;
data[nextOff] = c0;
data[nextOff + 1] = c1;
data[nextOff + 2] = c2;
@ -631,24 +631,24 @@ export class HiresPage implements Memory, Restorable<GraphicsState> {
//
_draw3Pixel(data: number[], off: number, color: Color) {
var c0 = color[0], c1 = color[1], c2 = color[2];
const c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = data[off + 4] = data[off + 8] = c0;
data[off + 1] = data[off + 5] = data[off + 9] = c1;
data[off + 2] = data[off + 6] = data[off + 10] = c2;
var nextOff = off + 560 * 4;
const nextOff = off + 560 * 4;
data[nextOff] = data[nextOff + 4] = data[nextOff + 8] = c0;
data[nextOff + 1] = data[nextOff + 5] = data[nextOff + 9] = c1;
data[nextOff + 2] = data[nextOff + 6] = data[nextOff + 10] = c2;
}
_draw4Pixel(data: number[], off: number, color: Color) {
var c0 = color[0], c1 = color[1], c2 = color[2];
const c0 = color[0], c1 = color[1], c2 = color[2];
data[off + 0] = data[off + 4] = data[off + 8] = data[off + 12] = c0;
data[off + 1] = data[off + 5] = data[off + 9] = data[off + 13] = c1;
data[off + 2] = data[off + 6] = data[off + 10] = data[off + 14] = c2;
var nextOff = off + 560 * 4;
const nextOff = off + 560 * 4;
data[nextOff] = data[nextOff + 4] = data[nextOff + 8] = data[nextOff + 12] = c0;
data[nextOff + 1] = data[nextOff + 5] = data[nextOff + 9] = data[nextOff + 13] = c1;
data[nextOff + 2] = data[nextOff + 6] = data[nextOff + 10] = data[nextOff + 14] = c2;
@ -677,13 +677,13 @@ export class HiresPage implements Memory, Restorable<GraphicsState> {
_end() { return (0x020 * this.page) + 0x1f; }
_read(page: byte, off: byte, bank: bank) {
let addr = (page << 8) | off, base = addr & 0x1FFF;
const addr = (page << 8) | off, base = addr & 0x1FFF;
return this._buffer[bank][base];
}
_write(page: byte, off: byte, val: byte, bank: bank) {
let addr = (page << 8) | off;
let base = addr & 0x1FFF;
const addr = (page << 8) | off;
const base = addr & 0x1FFF;
if (this._buffer[bank][base] == val && !this._refreshing) {
return;
@ -692,18 +692,19 @@ export class HiresPage implements Memory, Restorable<GraphicsState> {
let hbs = val & 0x80;
let col = (base % 0x80) % 0x28;
let adj = off - col;
const col = (base % 0x80) % 0x28;
const adj = off - col;
// 000001cd eabab000 -> 000abcde
let ab = (adj & 0x18);
let cd = (page & 0x03) << 1;
let e = adj >> 7;
const ab = (adj & 0x18);
const cd = (page & 0x03) << 1;
const e = adj >> 7;
let rowa = ab | cd | e,
const rowa = ab | cd | e,
rowb = base >> 10;
let dx, dy, data = this._imageData.data;
const data = this._imageData.data;
let dx, dy;
if ((rowa < 24) && (col < 40)) {
if (!multiScreen && !hiresMode) {
return;
@ -722,8 +723,8 @@ export class HiresPage implements Memory, Restorable<GraphicsState> {
let bz, b0, b1, b2, b3, b4, c, hb;
if (oneSixtyMode && !this._monoMode) {
// 1 byte = two pixels, but 3:4 ratio
let c3 = val & 0xf;
let c4 = val >> 4;
const c3 = val & 0xf;
const c4 = val >> 4;
dx = col * 2 + (bank ^ 1);
off = dx * 28 + dy * 280 * 4 * 2;
@ -741,7 +742,7 @@ export class HiresPage implements Memory, Restorable<GraphicsState> {
// 76543210 76543210 76543210 76543210
// 1111222 2333344 4455556 6667777
let mod = col % 2, mcol = col - mod, baseOff = base - mod;
const mod = col % 2, mcol = col - mod, baseOff = base - mod;
bz = this._buffer[0][baseOff - 1];
b0 = this._buffer[1][baseOff];
b1 = this._buffer[0][baseOff];
@ -759,17 +760,17 @@ export class HiresPage implements Memory, Restorable<GraphicsState> {
((b3 & 0x78) >> 3), // 6
0
], // 7
hb = [
0,
b0 & 0x80, // 0
b0 & 0x80, // 1
b1 & 0x80, // 2
b2 & 0x80, // 3
b2 & 0x80, // 4
b3 & 0x80, // 5
b3 & 0x80, // 6
0
]; // 7
hb = [
0,
b0 & 0x80, // 0
b0 & 0x80, // 1
b1 & 0x80, // 2
b2 & 0x80, // 3
b2 & 0x80, // 4
b3 & 0x80, // 5
b3 & 0x80, // 6
0
]; // 7
if (col > 0) {
c[0] = (bz & 0x78) >> 3;
hb[0] = bz & 0x80;
@ -788,7 +789,7 @@ export class HiresPage implements Memory, Restorable<GraphicsState> {
for (let idx = 1; idx < 8; idx++) {
hbs = hb[idx];
let dcolor = dcolors[r4[c[idx]]];
const dcolor = dcolors[r4[c[idx]]];
let bits = c[idx - 1] | (c[idx] << 4) | (c[idx + 1] << 8);
for (let jdx = 0; jdx < 4; jdx++, off += 4) {
if (monoColor) {
@ -833,9 +834,9 @@ export class HiresPage implements Memory, Restorable<GraphicsState> {
if (!this._refreshing) {
this._refreshing = true;
let bb: bank = bank ? 0 : 1;
const bb: bank = bank ? 0 : 1;
for (let rr = addr - 1; rr <= addr + 1; rr++) {
let vv = this._buffer[bb][rr - 0x2000 * this.page];
const vv = this._buffer[bb][rr - 0x2000 * this.page];
this._write(rr >> 8, rr & 0xff, vv, bb);
}
this._refreshing = false;
@ -848,11 +849,11 @@ export class HiresPage implements Memory, Restorable<GraphicsState> {
b0 = col > 0 ? this._buffer[0][base - 1] : 0;
b2 = col < 39 ? this._buffer[0][base + 1] : 0;
val |= (b2 & 0x3) << 7;
var v0 = b0 & 0x20, v1 = b0 & 0x40, v2 = val & 0x1,
let v0 = b0 & 0x20, v1 = b0 & 0x40, v2 = val & 0x1,
odd = !(col & 0x1),
color,
oddCol = (hbs ? orangeCol : greenCol),
evenCol = (hbs ? blueCol : violetCol);
color;
const oddCol = (hbs ? orangeCol : greenCol);
const evenCol = (hbs ? blueCol : violetCol);
off = dx * 4 + dy * 280 * 4 * 2;
@ -1027,7 +1028,7 @@ export class VideoModes implements Restorable<VideoModesState> {
}
text(on: boolean) {
var old = textMode;
const old = textMode;
textMode = on;
if (old != on) {
@ -1038,7 +1039,7 @@ export class VideoModes implements Restorable<VideoModesState> {
_80col(on: boolean) {
if (!this.e) { return; }
var old = _80colMode;
const old = _80colMode;
_80colMode = on;
if (old != on) {
@ -1049,7 +1050,7 @@ export class VideoModes implements Restorable<VideoModesState> {
altchar(on: boolean) {
if (!this.e) { return; }
var old = altCharMode;
const old = altCharMode;
altCharMode = on;
if (old != on) {
this._refresh();
@ -1057,7 +1058,7 @@ export class VideoModes implements Restorable<VideoModesState> {
}
hires(on: boolean) {
var old = hiresMode;
const old = hiresMode;
hiresMode = on;
if (!on) {
this._flag = 0;
@ -1071,7 +1072,7 @@ export class VideoModes implements Restorable<VideoModesState> {
an3(on: boolean) {
if (!this.e) { return; }
var old = an3;
const old = an3;
an3 = on;
if (on) {
@ -1088,7 +1089,7 @@ export class VideoModes implements Restorable<VideoModesState> {
}
mixed(on: boolean) {
var old = mixedMode;
const old = mixedMode;
mixedMode = on;
if (old != on) {
this._refresh();
@ -1096,7 +1097,7 @@ export class VideoModes implements Restorable<VideoModesState> {
}
page(pageNo: pageNo) {
var old = pageMode;
const old = pageMode;
pageMode = pageNo;
if (old != pageNo) {
this._refresh();
@ -1140,7 +1141,7 @@ export class VideoModes implements Restorable<VideoModesState> {
}
blit() {
var blitted = false;
let blitted = false;
if (multiScreen) {
blitted = this._grs[0].blit() || blitted;
blitted = this._grs[1].blit() || blitted;

View File

@ -1008,68 +1008,68 @@ export default class CPU6502 {
let off, val;
let result = '';
switch (m) {
case 'implied':
break;
case 'immediate':
result = '#' + toHexOrSymbol(this.readByteDebug(addr));
break;
case 'absolute':
result = '' + toHexOrSymbol(this.readWordDebug(addr), 4);
break;
case 'zeroPage':
result = '' + toHexOrSymbol(this.readByteDebug(addr));
break;
case 'relative':
{
let off = this.readByteDebug(addr);
if (off > 127) {
off -= 256;
}
addr += off + 1;
result = '' + toHexOrSymbol(addr, 4) + ' (' + off + ')';
}
break;
case 'absoluteX':
result = '' + toHexOrSymbol(this.readWordDebug(addr), 4) + ',X';
break;
case 'absoluteY':
result = '' + toHexOrSymbol(this.readWordDebug(addr), 4) + ',Y';
break;
case 'zeroPageX':
result = '' + toHexOrSymbol(this.readByteDebug(addr)) + ',X';
break;
case 'zeroPageY':
result = '' + toHexOrSymbol(this.readByteDebug(addr)) + ',Y';
break;
case 'absoluteIndirect':
result = '(' + toHexOrSymbol(this.readWordDebug(addr), 4) + ')';
break;
case 'zeroPageXIndirect':
result = '(' + toHexOrSymbol(this.readByteDebug(addr)) + ',X)';
break;
case 'zeroPageIndirectY':
result = '(' + toHexOrSymbol(this.readByteDebug(addr)) + '),Y';
break;
case 'accumulator':
result = 'A';
break;
case 'zeroPageIndirect':
result = '(' + toHexOrSymbol(this.readByteDebug(addr)) + ')';
break;
case 'absoluteXIndirect':
result = '(' + toHexOrSymbol(this.readWordDebug(addr), 4) + ',X)';
break;
case 'zeroPage_relative':
val = this.readByteDebug(addr);
off = this.readByteDebug(addr + 1);
case 'implied':
break;
case 'immediate':
result = '#' + toHexOrSymbol(this.readByteDebug(addr));
break;
case 'absolute':
result = '' + toHexOrSymbol(this.readWordDebug(addr), 4);
break;
case 'zeroPage':
result = '' + toHexOrSymbol(this.readByteDebug(addr));
break;
case 'relative':
{
let off = this.readByteDebug(addr);
if (off > 127) {
off -= 256;
}
addr += off + 2;
result = '' + toHexOrSymbol(val) + ',' + toHexOrSymbol(addr, 4) + ' (' + off + ')';
break;
default:
break;
addr += off + 1;
result = '' + toHexOrSymbol(addr, 4) + ' (' + off + ')';
}
break;
case 'absoluteX':
result = '' + toHexOrSymbol(this.readWordDebug(addr), 4) + ',X';
break;
case 'absoluteY':
result = '' + toHexOrSymbol(this.readWordDebug(addr), 4) + ',Y';
break;
case 'zeroPageX':
result = '' + toHexOrSymbol(this.readByteDebug(addr)) + ',X';
break;
case 'zeroPageY':
result = '' + toHexOrSymbol(this.readByteDebug(addr)) + ',Y';
break;
case 'absoluteIndirect':
result = '(' + toHexOrSymbol(this.readWordDebug(addr), 4) + ')';
break;
case 'zeroPageXIndirect':
result = '(' + toHexOrSymbol(this.readByteDebug(addr)) + ',X)';
break;
case 'zeroPageIndirectY':
result = '(' + toHexOrSymbol(this.readByteDebug(addr)) + '),Y';
break;
case 'accumulator':
result = 'A';
break;
case 'zeroPageIndirect':
result = '(' + toHexOrSymbol(this.readByteDebug(addr)) + ')';
break;
case 'absoluteXIndirect':
result = '(' + toHexOrSymbol(this.readWordDebug(addr), 4) + ',X)';
break;
case 'zeroPage_relative':
val = this.readByteDebug(addr);
off = this.readByteDebug(addr + 1);
if (off > 127) {
off -= 256;
}
addr += off + 2;
result = '' + toHexOrSymbol(val) + ',' + toHexOrSymbol(addr, 4) + ' (' + off + ')';
break;
default:
break;
}
return result;
}

View File

@ -92,8 +92,8 @@ export const detrans62 = [
* From Beneath Apple DOS
*/
export function fourXfour(val: byte): [xx: byte, yy: byte] {
var xx = val & 0xaa;
var yy = val & 0x55;
let xx = val & 0xaa;
let yy = val & 0x55;
xx >>= 1;
xx |= 0xaa;
@ -128,7 +128,7 @@ export function explodeSector16(volume: byte, track: byte, sector: byte, data: m
* Address Field
*/
let checksum = volume ^ track ^ sector;
const checksum = volume ^ track ^ sector;
buf = buf.concat([0xd5, 0xaa, 0x96]); // Address Prolog D5 AA 96
buf = buf.concat(fourXfour(volume));
buf = buf.concat(fourXfour(track));
@ -150,7 +150,7 @@ export function explodeSector16(volume: byte, track: byte, sector: byte, data: m
buf = buf.concat([0xd5, 0xaa, 0xad]); // Data Prolog D5 AA AD
let nibbles: byte[] = [];
const nibbles: byte[] = [];
const ptr2 = 0;
const ptr6 = 0x56;
@ -216,7 +216,7 @@ export function explodeSector13(volume: byte, track: byte, sector: byte, data: b
* Address Field
*/
let checksum = volume ^ track ^ sector;
const checksum = volume ^ track ^ sector;
buf = buf.concat([0xd5, 0xaa, 0xb5]); // Address Prolog D5 AA B5
buf = buf.concat(fourXfour(volume));
buf = buf.concat(fourXfour(track));
@ -238,24 +238,24 @@ export function explodeSector13(volume: byte, track: byte, sector: byte, data: b
buf = buf.concat([0xd5, 0xaa, 0xad]); // Data Prolog D5 AA AD
let nibbles = [];
const nibbles = [];
let jdx = 0;
for (let idx = 0x32; idx >= 0; idx--) {
var a5 = data[jdx] >> 3;
var a3 = data[jdx] & 0x07;
const a5 = data[jdx] >> 3;
const a3 = data[jdx] & 0x07;
jdx++;
var b5 = data[jdx] >> 3;
var b3 = data[jdx] & 0x07;
const b5 = data[jdx] >> 3;
const b3 = data[jdx] & 0x07;
jdx++;
var c5 = data[jdx] >> 3;
var c3 = data[jdx] & 0x07;
const c5 = data[jdx] >> 3;
const c3 = data[jdx] & 0x07;
jdx++;
var d5 = data[jdx] >> 3;
var d3 = data[jdx] & 0x07;
const d5 = data[jdx] >> 3;
const d3 = data[jdx] & 0x07;
jdx++;
var e5 = data[jdx] >> 3;
var e3 = data[jdx] & 0x07;
const e5 = data[jdx] >> 3;
const e3 = data[jdx] & 0x07;
jdx++;
nibbles[idx + 0x00] = a5;
nibbles[idx + 0x33] = b5;
@ -294,14 +294,14 @@ export function explodeSector13(volume: byte, track: byte, sector: byte, data: b
}
export function readSector(drive: Drive, track: byte, sector: byte) {
let _sector = drive.format == 'po' ? _PO[sector] : _DO[sector];
const _sector = drive.format == 'po' ? _PO[sector] : _DO[sector];
let val, state = 0;
let idx = 0;
let retry = 0;
let cur = drive.tracks[track];
const cur = drive.tracks[track];
function _readNext() {
var result = cur[idx++];
const result = cur[idx++];
if (idx >= cur.length) {
idx = 0;
retry++;
@ -316,73 +316,73 @@ export function readSector(drive: Drive, track: byte, sector: byte) {
}
}
let t = 0, s = 0, v = 0, checkSum;
let data = [];
const data = [];
while (retry < 4) {
switch (state) {
case 0:
val = _readNext();
state = (val === 0xd5) ? 1 : 0;
break;
case 1:
val = _readNext();
state = (val === 0xaa) ? 2 : 0;
break;
case 2:
val = _readNext();
state = (val === 0x96) ? 3 : (val === 0xad ? 4 : 0);
break;
case 3: // Address
v = defourXfour(_readNext(), _readNext()); // Volume
t = defourXfour(_readNext(), _readNext());
s = defourXfour(_readNext(), _readNext());
checkSum = defourXfour(_readNext(), _readNext());
if (checkSum != (v ^ t ^ s)) {
debug('Invalid header checksum:', toHex(v), toHex(t), toHex(s), toHex(checkSum));
case 0:
val = _readNext();
state = (val === 0xd5) ? 1 : 0;
break;
case 1:
val = _readNext();
state = (val === 0xaa) ? 2 : 0;
break;
case 2:
val = _readNext();
state = (val === 0x96) ? 3 : (val === 0xad ? 4 : 0);
break;
case 3: // Address
v = defourXfour(_readNext(), _readNext()); // Volume
t = defourXfour(_readNext(), _readNext());
s = defourXfour(_readNext(), _readNext());
checkSum = defourXfour(_readNext(), _readNext());
if (checkSum != (v ^ t ^ s)) {
debug('Invalid header checksum:', toHex(v), toHex(t), toHex(s), toHex(checkSum));
}
_skipBytes(3); // Skip footer
state = 0;
break;
case 4: // Data
if (s === _sector && t === track) {
const data2 = [];
let last = 0;
for (let jdx = 0x55; jdx >= 0; jdx--) {
val = detrans62[_readNext() - 0x80] ^ last;
data2[jdx] = val;
last = val;
}
_skipBytes(3); // Skip footer
state = 0;
break;
case 4: // Data
if (s === _sector && t === track) {
var data2 = [];
var last = 0;
for (let jdx = 0x55; jdx >= 0; jdx--) {
val = detrans62[_readNext() - 0x80] ^ last;
data2[jdx] = val;
last = val;
}
for (let jdx = 0; jdx < 0x100; jdx++) {
val = detrans62[_readNext() - 0x80] ^ last;
data[jdx] = val;
last = val;
}
checkSum = detrans62[_readNext() - 0x80] ^ last;
if (checkSum) {
debug('Invalid data checksum:', toHex(v), toHex(t), toHex(s), toHex(checkSum));
}
for (let kdx = 0, jdx = 0x55; kdx < 0x100; kdx++) {
data[kdx] <<= 1;
if ((data2[jdx] & 0x01) !== 0) {
data[kdx] |= 0x01;
}
data2[jdx] >>= 1;
data[kdx] <<= 1;
if ((data2[jdx] & 0x01) !== 0) {
data[kdx] |= 0x01;
}
data2[jdx] >>= 1;
if (--jdx < 0) jdx = 0x55;
}
return data;
for (let jdx = 0; jdx < 0x100; jdx++) {
val = detrans62[_readNext() - 0x80] ^ last;
data[jdx] = val;
last = val;
}
else
_skipBytes(0x159); // Skip data, checksum and footer
state = 0;
break;
default:
break;
checkSum = detrans62[_readNext() - 0x80] ^ last;
if (checkSum) {
debug('Invalid data checksum:', toHex(v), toHex(t), toHex(s), toHex(checkSum));
}
for (let kdx = 0, jdx = 0x55; kdx < 0x100; kdx++) {
data[kdx] <<= 1;
if ((data2[jdx] & 0x01) !== 0) {
data[kdx] |= 0x01;
}
data2[jdx] >>= 1;
data[kdx] <<= 1;
if ((data2[jdx] & 0x01) !== 0) {
data[kdx] |= 0x01;
}
data2[jdx] >>= 1;
if (--jdx < 0) jdx = 0x55;
}
return data;
}
else
_skipBytes(0x159); // Skip data, checksum and footer
state = 0;
break;
default:
break;
}
}
return [];
@ -391,7 +391,7 @@ export function readSector(drive: Drive, track: byte, sector: byte) {
export function jsonEncode(cur: Drive, pretty: boolean) {
// For 'nib', tracks are encoded as strings. For all other formats,
// tracks are arrays of sectors which are encoded as strings.
let data: string[] | string[][] = [];
const data: string[] | string[][] = [];
let format = 'dsk';
for (let t = 0; t < cur.tracks.length; t++) {
data[t] = [];
@ -399,7 +399,7 @@ export function jsonEncode(cur: Drive, pretty: boolean) {
format = 'nib';
data[t] = base64_encode(cur.tracks[t]);
} else {
for (var s = 0; s < 0x10; s++) {
for (let s = 0; s < 0x10; s++) {
(data[t] as string[])[s] = base64_encode(readSector(cur, t, s));
}
}
@ -414,21 +414,21 @@ export function jsonEncode(cur: Drive, pretty: boolean) {
}
export function jsonDecode(data: string) {
let tracks: memory[] = [];
let json = JSON.parse(data);
let v = json.volume;
let readOnly = json.readOnly;
const tracks: memory[] = [];
const json = JSON.parse(data);
const v = json.volume;
const readOnly = json.readOnly;
for (let t = 0; t < json.data.length; t++) {
let track: byte[] = [];
for (let s = 0; s < json.data[t].length; s++) {
let _s = 15 - s;
let sector: string = json.data[t][_s];
const _s = 15 - s;
const sector: string = json.data[t][_s];
const d = base64_decode(sector);
track = track.concat(explodeSector16(v, t, s, d));
}
tracks[t] = bytify(track);
}
let cur: Drive = {
const cur: Drive = {
volume: v,
format: json.type,
tracks,

572
js/mmu.ts
View File

@ -106,7 +106,7 @@ class Switches implements Memory {
constructor(private readonly mmu: MMU, private readonly io: any) {
Object.keys(LOC).forEach((loc: keyof typeof LOC) => {
let v = LOC[loc];
const v = LOC[loc];
this.locs[v] = loc;
});
}
@ -120,7 +120,7 @@ class Switches implements Memory {
}
read(_page: byte, off: byte) {
var result;
let result;
if (off in this.locs) {
result = this.mmu._access(off);
} else {
@ -306,7 +306,7 @@ export default class MMU implements Memory {
}
// I/O Switches
{
let idx = 0xc0;
const idx = 0xc0;
this._pages[idx] = this.memC0_C0;
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
@ -329,7 +329,7 @@ export default class MMU implements Memory {
this._readPages[idx] = this._pages[idx][0];
this._writePages[idx] = this._pages[idx][0];
}
};
}
_initSwitches() {
this._bank1 = true;
@ -482,306 +482,306 @@ export default class MMU implements Memory {
_access(off: byte, val?: byte) {
let result;
let readMode = val === undefined;
let writeMode = val !== undefined;
const readMode = val === undefined;
const writeMode = val !== undefined;
switch (off) {
// Apple //e memory management
// Apple //e memory management
case LOC._80STOREOFF:
if (writeMode) {
this._80store = false;
this._debug('80 Store Off');
this.vm.page(this._page2 ? 2 : 1);
} else {
// Chain to io for keyboard
result = this.io.ioSwitch(off, val);
}
break;
case LOC._80STOREON:
if (writeMode) {
this._80store = true;
this._debug('80 Store On');
} else
result = 0;
break;
case LOC.RAMRDOFF:
if (writeMode) {
this._auxRamRead = false;
this._debug('Aux RAM Read Off');
} else
result = 0;
break;
case LOC.RAMRDON:
if (writeMode) {
this._auxRamRead = true;
this._debug('Aux RAM Read On');
} else
result = 0;
break;
case LOC.RAMWROFF:
if (writeMode) {
this._auxRamWrite = false;
this._debug('Aux RAM Write Off');
} else
result = 0;
break;
case LOC.RAMWRON:
if (writeMode) {
this._auxRamWrite = true;
this._debug('Aux RAM Write On');
} else
result = 0;
break;
case LOC._80STOREOFF:
if (writeMode) {
this._80store = false;
this._debug('80 Store Off');
this.vm.page(this._page2 ? 2 : 1);
} else {
// Chain to io for keyboard
result = this.io.ioSwitch(off, val);
}
break;
case LOC._80STOREON:
if (writeMode) {
this._80store = true;
this._debug('80 Store On');
} else
result = 0;
break;
case LOC.RAMRDOFF:
if (writeMode) {
this._auxRamRead = false;
this._debug('Aux RAM Read Off');
} else
result = 0;
break;
case LOC.RAMRDON:
if (writeMode) {
this._auxRamRead = true;
this._debug('Aux RAM Read On');
} else
result = 0;
break;
case LOC.RAMWROFF:
if (writeMode) {
this._auxRamWrite = false;
this._debug('Aux RAM Write Off');
} else
result = 0;
break;
case LOC.RAMWRON:
if (writeMode) {
this._auxRamWrite = true;
this._debug('Aux RAM Write On');
} else
result = 0;
break;
case LOC.INTCXROMOFF:
if (writeMode) {
this._intcxrom = false;
this._intc8rom = false;
this._debug('Int CX ROM Off');
}
break;
case LOC.INTCXROMON:
if (writeMode) {
this._intcxrom = true;
this._debug('Int CX ROM On');
}
break;
case LOC.ALTZPOFF: // 0x08
if (writeMode) {
this._altzp = false;
this._debug('Alt ZP Off');
}
break;
case LOC.ALTZPON: // 0x09
if (writeMode) {
this._altzp = true;
this._debug('Alt ZP On');
}
break;
case LOC.SLOTC3ROMOFF: // 0x0A
if (writeMode) {
this._slot3rom = false;
this._debug('Slot 3 ROM Off');
}
break;
case LOC.SLOTC3ROMON: // 0x0B
if (writeMode) {
this._slot3rom = true;
this._debug('Slot 3 ROM On');
}
break;
case LOC.INTCXROMOFF:
if (writeMode) {
this._intcxrom = false;
this._intc8rom = false;
this._debug('Int CX ROM Off');
}
break;
case LOC.INTCXROMON:
if (writeMode) {
this._intcxrom = true;
this._debug('Int CX ROM On');
}
break;
case LOC.ALTZPOFF: // 0x08
if (writeMode) {
this._altzp = false;
this._debug('Alt ZP Off');
}
break;
case LOC.ALTZPON: // 0x09
if (writeMode) {
this._altzp = true;
this._debug('Alt ZP On');
}
break;
case LOC.SLOTC3ROMOFF: // 0x0A
if (writeMode) {
this._slot3rom = false;
this._debug('Slot 3 ROM Off');
}
break;
case LOC.SLOTC3ROMON: // 0x0B
if (writeMode) {
this._slot3rom = true;
this._debug('Slot 3 ROM On');
}
break;
// Graphics Switches
case LOC.CLR80VID:
if (writeMode) {
this._debug('80 Column Mode off');
this.vm._80col(false);
}
break;
case LOC.SET80VID:
if (writeMode) {
this._debug('80 Column Mode on');
this.vm._80col(true);
}
break;
case LOC.CLRALTCH:
if (writeMode) {
this._debug('Alt Char off');
this.vm.altchar(false);
}
break;
case LOC.SETALTCH:
if (writeMode) {
this._debug('Alt Char on');
this.vm.altchar(true);
}
break;
case LOC.PAGE1:
this._page2 = false;
if (!this._80store) {
result = this.io.ioSwitch(off, val);
}
this._debug('Page 2 off');
break;
case LOC.PAGE2:
this._page2 = true;
if (!this._80store) {
result = this.io.ioSwitch(off, val);
}
this._debug('Page 2 on');
break;
case LOC.RESET_HIRES:
this._hires = false;
case LOC.CLR80VID:
if (writeMode) {
this._debug('80 Column Mode off');
this.vm._80col(false);
}
break;
case LOC.SET80VID:
if (writeMode) {
this._debug('80 Column Mode on');
this.vm._80col(true);
}
break;
case LOC.CLRALTCH:
if (writeMode) {
this._debug('Alt Char off');
this.vm.altchar(false);
}
break;
case LOC.SETALTCH:
if (writeMode) {
this._debug('Alt Char on');
this.vm.altchar(true);
}
break;
case LOC.PAGE1:
this._page2 = false;
if (!this._80store) {
result = this.io.ioSwitch(off, val);
this._debug('Hires off');
break;
case LOC.DHIRESON:
if (this._iouDisable) {
this.vm.doubleHires(true);
} else {
result = this.io.ioSwitch(off, val); // an3
}
break;
case LOC.DHIRESOFF:
if (this._iouDisable) {
this.vm.doubleHires(false);
} else {
result = this.io.ioSwitch(off, val); // an3
}
break;
case LOC.SET_HIRES:
this._hires = true;
}
this._debug('Page 2 off');
break;
case LOC.PAGE2:
this._page2 = true;
if (!this._80store) {
result = this.io.ioSwitch(off, val);
this._debug('Hires on');
break;
}
this._debug('Page 2 on');
break;
case LOC.IOUDISON:
if (writeMode) {
this._iouDisable = true;
}
result = this._iouDisable ? 0x00 : 0x80;
break;
case LOC.RESET_HIRES:
this._hires = false;
result = this.io.ioSwitch(off, val);
this._debug('Hires off');
break;
case LOC.IOUDISOFF:
if (writeMode) {
this._iouDisable = false;
}
result = this.vm.isDoubleHires() ? 0x80 : 0x00;
break;
case LOC.DHIRESON:
if (this._iouDisable) {
this.vm.doubleHires(true);
} else {
result = this.io.ioSwitch(off, val); // an3
}
break;
case LOC.DHIRESOFF:
if (this._iouDisable) {
this.vm.doubleHires(false);
} else {
result = this.io.ioSwitch(off, val); // an3
}
break;
case LOC.SET_HIRES:
this._hires = true;
result = this.io.ioSwitch(off, val);
this._debug('Hires on');
break;
case LOC.IOUDISON:
if (writeMode) {
this._iouDisable = true;
}
result = this._iouDisable ? 0x00 : 0x80;
break;
case LOC.IOUDISOFF:
if (writeMode) {
this._iouDisable = false;
}
result = this.vm.isDoubleHires() ? 0x80 : 0x00;
break;
// Language Card Switches
case LOC.READBSR2: // 0xC080
case LOC._READBSR2: // 0xC084
this._bank1 = false;
this._readbsr = true;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 2 Read');
break;
case LOC.WRITEBSR2: // 0xC081
case LOC._WRITEBSR2: // 0xC085
this._bank1 = false;
this._readbsr = false;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
// _debug('Bank 2 Write');
break;
case LOC.OFFBSR2: // 0xC082
case LOC._OFFBSR2: // 0xC086
this._bank1 = false;
this._readbsr = false;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 2 Off');
break;
case LOC.READWRBSR2: // 0xC083
case LOC._READWRBSR2: // 0xC087
this._bank1 = false;
this._readbsr = true;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
// _debug('Bank 2 Read/Write');
break;
case LOC.READBSR1: // 0xC088
case LOC._READBSR1: // 0xC08c
this._bank1 = true;
this._readbsr = true;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 1 Read');
break;
case LOC.WRITEBSR1: // 0xC089
case LOC._WRITEBSR1: // 0xC08D
this._bank1 = true;
this._readbsr = false;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
// _debug('Bank 1 Write');
break;
case LOC.OFFBSR1: // 0xC08A
case LOC._OFFBSR1: // 0xC08E
this._bank1 = true;
this._readbsr = false;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 1 Off');
break;
case LOC.READWRBSR1: // 0xC08B
case LOC._READWRBSR1: // 0xC08F
this._bank1 = true;
this._readbsr = true;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
//_debug('Bank 1 Read/Write');
break;
case LOC.READBSR2: // 0xC080
case LOC._READBSR2: // 0xC084
this._bank1 = false;
this._readbsr = true;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 2 Read');
break;
case LOC.WRITEBSR2: // 0xC081
case LOC._WRITEBSR2: // 0xC085
this._bank1 = false;
this._readbsr = false;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
// _debug('Bank 2 Write');
break;
case LOC.OFFBSR2: // 0xC082
case LOC._OFFBSR2: // 0xC086
this._bank1 = false;
this._readbsr = false;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 2 Off');
break;
case LOC.READWRBSR2: // 0xC083
case LOC._READWRBSR2: // 0xC087
this._bank1 = false;
this._readbsr = true;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
// _debug('Bank 2 Read/Write');
break;
case LOC.READBSR1: // 0xC088
case LOC._READBSR1: // 0xC08c
this._bank1 = true;
this._readbsr = true;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 1 Read');
break;
case LOC.WRITEBSR1: // 0xC089
case LOC._WRITEBSR1: // 0xC08D
this._bank1 = true;
this._readbsr = false;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
// _debug('Bank 1 Write');
break;
case LOC.OFFBSR1: // 0xC08A
case LOC._OFFBSR1: // 0xC08E
this._bank1 = true;
this._readbsr = false;
this._writebsr = false;
this._prewrite = false;
// _debug('Bank 1 Off');
break;
case LOC.READWRBSR1: // 0xC08B
case LOC._READWRBSR1: // 0xC08F
this._bank1 = true;
this._readbsr = true;
if (readMode) { this._writebsr = this._prewrite; }
this._prewrite = readMode;
//_debug('Bank 1 Read/Write');
break;
// Status registers
case LOC.BSRBANK2:
this._debug('Bank 2 Read ' + !this._bank1);
result = !this._bank1 ? 0x80 : 0x00;
break;
case LOC.BSRREADRAM:
this._debug('Bank SW RAM Read ' + this._readbsr);
result = this._readbsr ? 0x80 : 0x00;
break;
case LOC.RAMRD: // 0xC013
this._debug('Aux RAM Read ' + this._auxRamRead);
result = this._auxRamRead ? 0x80 : 0x0;
break;
case LOC.RAMWRT: // 0xC014
this._debug('Aux RAM Write ' + this._auxRamWrite);
result = this._auxRamWrite ? 0x80 : 0x0;
break;
case LOC.INTCXROM: // 0xC015
// _debug('Int CX ROM ' + _intcxrom);
result = this._intcxrom ? 0x80 : 0x00;
break;
case LOC.ALTZP: // 0xC016
this._debug('Alt ZP ' + this._altzp);
result = this._altzp ? 0x80 : 0x0;
break;
case LOC.SLOTC3ROM: // 0xC017
this._debug('Slot C3 ROM ' + this._slot3rom);
result = this._slot3rom ? 0x80 : 0x00;
break;
case LOC._80STORE: // 0xC018
this._debug('80 Store ' + this._80store);
result = this._80store ? 0x80 : 0x00;
break;
case LOC.VERTBLANK: // 0xC019
// result = cpu.getCycles() % 20 < 5 ? 0x80 : 0x00;
result = (this.cpu.getCycles() < this._vbEnd) ? 0x80 : 0x00;
break;
case LOC.RDTEXT:
result = this.vm.isText() ? 0x80 : 0x0;
break;
case LOC.RDMIXED:
result = this.vm.isMixed() ? 0x80 : 0x0;
break;
case LOC.RDPAGE2:
result = this.vm.isPage2() ? 0x80 : 0x0;
break;
case LOC.RDHIRES:
result = this.vm.isHires() ? 0x80 : 0x0;
break;
case LOC.RD80VID:
result = this.vm.is80Col() ? 0x80 : 0x0;
break;
case LOC.RDALTCH:
result = this.vm.isAltChar() ? 0x80 : 0x0;
break;
case LOC.BSRBANK2:
this._debug('Bank 2 Read ' + !this._bank1);
result = !this._bank1 ? 0x80 : 0x00;
break;
case LOC.BSRREADRAM:
this._debug('Bank SW RAM Read ' + this._readbsr);
result = this._readbsr ? 0x80 : 0x00;
break;
case LOC.RAMRD: // 0xC013
this._debug('Aux RAM Read ' + this._auxRamRead);
result = this._auxRamRead ? 0x80 : 0x0;
break;
case LOC.RAMWRT: // 0xC014
this._debug('Aux RAM Write ' + this._auxRamWrite);
result = this._auxRamWrite ? 0x80 : 0x0;
break;
case LOC.INTCXROM: // 0xC015
// _debug('Int CX ROM ' + _intcxrom);
result = this._intcxrom ? 0x80 : 0x00;
break;
case LOC.ALTZP: // 0xC016
this._debug('Alt ZP ' + this._altzp);
result = this._altzp ? 0x80 : 0x0;
break;
case LOC.SLOTC3ROM: // 0xC017
this._debug('Slot C3 ROM ' + this._slot3rom);
result = this._slot3rom ? 0x80 : 0x00;
break;
case LOC._80STORE: // 0xC018
this._debug('80 Store ' + this._80store);
result = this._80store ? 0x80 : 0x00;
break;
case LOC.VERTBLANK: // 0xC019
// result = cpu.getCycles() % 20 < 5 ? 0x80 : 0x00;
result = (this.cpu.getCycles() < this._vbEnd) ? 0x80 : 0x00;
break;
case LOC.RDTEXT:
result = this.vm.isText() ? 0x80 : 0x0;
break;
case LOC.RDMIXED:
result = this.vm.isMixed() ? 0x80 : 0x0;
break;
case LOC.RDPAGE2:
result = this.vm.isPage2() ? 0x80 : 0x0;
break;
case LOC.RDHIRES:
result = this.vm.isHires() ? 0x80 : 0x0;
break;
case LOC.RD80VID:
result = this.vm.is80Col() ? 0x80 : 0x0;
break;
case LOC.RDALTCH:
result = this.vm.isAltChar() ? 0x80 : 0x0;
break;
default:
debug('MMU missing register ' + toHex(off));
break;
default:
debug('MMU missing register ' + toHex(off));
break;
}
if (result !== undefined)

View File

@ -1,4 +1,4 @@
import { bytify } from "../util";
import { bytify } from '../util';
const apple2_charset = bytify([
0x00,0x1c,0x22,0x2a,0x2e,0x2c,0x20,0x1e,

View File

@ -1,5 +1,5 @@
import { bytify } from "../util";
import ROM from "./rom";
import { bytify } from '../util';
import ROM from './rom';
const rom = bytify([
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

View File

@ -1,4 +1,4 @@
import { bytify } from "../util";
import { bytify } from '../util';
/* exported apple2e_charset */

View File

@ -1,5 +1,5 @@
import { bytify } from "../util";
import ROM from "./rom";
import { bytify } from '../util';
import ROM from './rom';
const rom = bytify([
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View File

@ -1,4 +1,4 @@
import { bytify } from "../util";
import { bytify } from '../util';
const apple2enh_charset = bytify([
0x1c,0x22,0x2a,0x3a,0x1a,0x02,0x3c,0x00,

View File

@ -1,5 +1,5 @@
import { bytify } from "../util";
import ROM from "./rom";
import { bytify } from '../util';
import ROM from './rom';
const rom = bytify([
0x6f,0xd8,0x65,0xd7,0xf8,0xdc,0x94,0xd9,

View File

@ -1,4 +1,4 @@
import { bytify } from "../util";
import { bytify } from '../util';
const apple2j_charset = bytify([
0xff,0xef,0xe1,0xed,0xd5,0xfb,0xf7,0xef,

View File

@ -1,4 +1,4 @@
import { bytify } from "../util";
import { bytify } from '../util';
const apple2lc_charset = bytify([
0x1c,0x22,0x2a,0x2a,0x2c,0x20,0x1e,0x00,

View File

@ -1,4 +1,4 @@
import { bytify } from "../../util";
import { bytify } from '../../util';
/*
* http://dreher.net/?s=projects/CFforAppleII&c=projects/CFforAppleII/downloads1.php

View File

@ -1,4 +1,4 @@
import { bytify } from "../../util";
import { bytify } from '../../util';
export const P5_16 = bytify([
0xa2,0x20,0xa0,0x00,0xa2,0x03,0x86,0x3c,

View File

@ -1,4 +1,4 @@
import { bytify } from "../../util";
import { bytify } from '../../util';
export const rom = bytify([
0x18,0xb0,0x38,0x48,0x8a,0x48,0x98,0x48,

View File

@ -1,4 +1,4 @@
import { bytify } from "../../util";
import { bytify } from '../../util';
export const rom = bytify([
0x43,0x4f,0x50,0x59,0x52,0x49,0x47,0x48,

View File

@ -1,4 +1,4 @@
import { bytify } from "../../util";
import { bytify } from '../../util';
/*
$Cn01=$20

View File

@ -1,4 +1,4 @@
import { bytify } from "../../util";
import { bytify } from '../../util';
export const rom = bytify([
0x08,0x78,0x28,0x2c,0x58,0xff,0x70,0x05, // 00

View File

@ -1,6 +1,6 @@
import { bytify } from "../../util";
import { bytify } from '../../util';
export var ROM = bytify([
export const ROM = bytify([
0xad,0x7b,0x07,0x29,0xf8,0xc9,0x30,0xf0,
0x21,0xa9,0x30,0x8d,0x7b,0x07,0x8d,0xfb,
0x07,0xa9,0x00,0x8d,0xfb,0x06,0x20,0x61,

View File

@ -1,5 +1,5 @@
import { bytify } from "../util";
import ROM from "./rom";
import { bytify } from '../util';
import ROM from './rom';
const rom = bytify([
0x6f, 0xd8, 0x65, 0xd7, 0xf8, 0xdc, 0x94, 0xd9,

View File

@ -1,5 +1,5 @@
import { bytify } from "../util";
import ROM from "./rom";
import { bytify } from '../util';
import ROM from './rom';
const rom = bytify([
0xa9, 0x20, 0x8d, 0x26, 0x03, 0xad, 0x57, 0xc0,

View File

@ -1,5 +1,5 @@
import { bytify } from "../util";
import ROM from "./rom";
import { bytify } from '../util';
import ROM from './rom';
const rom = bytify([
0xa9, 0x20, 0x8d, 0x26, 0x03, 0xad, 0x57, 0xc0,

View File

@ -1,4 +1,4 @@
import { bytify } from "../util";
import { bytify } from '../util';
const pigfont_charset = bytify([
0x00,0x1c,0x22,0x2a,0x2e,0x20,0x1e,0x00,

View File

@ -1,4 +1,4 @@
import { bytify } from "../util";
import { bytify } from '../util';
const rmfont_charset = bytify([
0x3c,0x42,0x59,0x55,0x55,0x39,0x02,0x3c,

View File

@ -1,27 +1,27 @@
import { PageHandler } from "../cpu6502";
import { byte, memory } from "../types";
import { PageHandler } from '../cpu6502';
import { byte, memory } from '../types';
export default class ROM implements PageHandler {
constructor(
constructor(
private readonly startPage: byte,
private readonly endPage: byte,
private readonly rom: memory) {
const expectedLength = (endPage-startPage+1) * 256;
if (rom.length != expectedLength) {
throw Error(`rom does not have the correct length: expected ${expectedLength} was ${rom.length}`);
}
const expectedLength = (endPage-startPage+1) * 256;
if (rom.length != expectedLength) {
throw Error(`rom does not have the correct length: expected ${expectedLength} was ${rom.length}`);
}
}
start() {
return this.startPage;
}
end() {
return this.endPage;
}
read(page: byte, off: byte) {
return this.rom[(page - this.startPage) << 8 | off];
}
write() {
}
start() {
return this.startPage;
}
end() {
return this.endPage;
}
read(page: byte, off: byte) {
return this.rom[(page - this.startPage) << 8 | off];
}
write() {
}
}

View File

@ -7,18 +7,18 @@ import Apple2enhROM from '../../js/roms/apple2enh';
import Apple2jROM from '../../js/roms/apple2j';
const roms: { [name: string]: { new(): ROM } } = {
'original': OriginalROM,
'integer': IntegerROM,
'fpbasic': FPBasicROM,
'apple2e': Apple2eROM,
'apple2enh': Apple2enhROM,
'apple2j': Apple2jROM,
'original': OriginalROM,
'integer': IntegerROM,
'fpbasic': FPBasicROM,
'apple2e': Apple2eROM,
'apple2enh': Apple2enhROM,
'apple2j': Apple2jROM,
};
for (let rom of Object.keys(roms)) {
describe(`${rom}`, () => {
it('is constructable', () => {
new roms[rom]();
for (const rom of Object.keys(roms)) {
describe(`${rom}`, () => {
it('is constructable', () => {
new roms[rom]();
});
});
});
}