mirror of
https://github.com/whscullin/apple2js.git
synced 2024-01-12 14:14:38 +00:00
Convert more cards to typescript (#63)
Convert more cards to typescript
This commit is contained in:
parent
027b113cd4
commit
ab3e97e8d1
@ -148,6 +148,7 @@ export class Apple2 implements Restorable<State>, DebuggerContainer {
|
||||
const imageData = this.io.blit();
|
||||
if (imageData) {
|
||||
this.vm.blit(imageData);
|
||||
this.stats.renderedFrames++;
|
||||
}
|
||||
} else {
|
||||
if (this.vm.blit()) {
|
||||
|
@ -9,10 +9,9 @@
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
import { byte, memory, MemoryPages, rom } from './types';
|
||||
import { byte, Color, memory, MemoryPages, rom } from './types';
|
||||
import { allocMemPages } from './util';
|
||||
import {
|
||||
Color,
|
||||
GraphicsState,
|
||||
HiresPage,
|
||||
LoresPage,
|
||||
|
@ -10,39 +10,49 @@
|
||||
*/
|
||||
|
||||
import { debug } from '../util';
|
||||
import { Card, Restorable, byte } from '../types';
|
||||
import { rom } from '../roms/cards/parallel';
|
||||
|
||||
export default function Parallel(io, cbs) {
|
||||
const LOC = {
|
||||
IOREG: 0x80
|
||||
} as const;
|
||||
|
||||
debug('Parallel card');
|
||||
export interface ParallelState {}
|
||||
export interface ParallelOptions {
|
||||
putChar: (val: byte) => void;
|
||||
}
|
||||
|
||||
var LOC = {
|
||||
IOREG: 0x80
|
||||
};
|
||||
export default class Parallel implements Card, Restorable<ParallelState> {
|
||||
constructor(private cbs: ParallelOptions) {
|
||||
debug('Parallel card');
|
||||
}
|
||||
|
||||
function _access(off, val) {
|
||||
private access(off: byte, val?: byte) {
|
||||
switch (off & 0x8f) {
|
||||
case LOC.IOREG:
|
||||
if (cbs.putChar && val) {
|
||||
cbs.putChar(val);
|
||||
if (this.cbs.putChar && val) {
|
||||
this.cbs.putChar(val);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
debug('Parallel card unknown softswitch', off);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return {
|
||||
ioSwitch: function (off, val) {
|
||||
return _access(off, val);
|
||||
},
|
||||
read: function(page, off) {
|
||||
return rom[off];
|
||||
},
|
||||
write: function() {},
|
||||
getState() {
|
||||
return {};
|
||||
},
|
||||
setState(_) {}
|
||||
};
|
||||
ioSwitch(off: byte, val?: byte) {
|
||||
return this.access(off, val);
|
||||
}
|
||||
|
||||
read(_page: byte, off: byte) {
|
||||
return rom[off];
|
||||
}
|
||||
|
||||
write() {}
|
||||
|
||||
getState() {
|
||||
return {};
|
||||
}
|
||||
|
||||
setState(_state: ParallelState) {}
|
||||
}
|
@ -1,156 +0,0 @@
|
||||
/* Copyright 2010-2019 Will Scullin <scullin@scullinsteel.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation. No representations are made about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express or
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
import { allocMem, debug } from '../util';
|
||||
import { rom } from '../roms/cards/ramfactor';
|
||||
|
||||
export default function RAMFactor(io, size) {
|
||||
var mem = [];
|
||||
|
||||
var _firmware = 0;
|
||||
var _ramlo = 0;
|
||||
var _rammid = 0;
|
||||
var _ramhi = 0;
|
||||
|
||||
var _loc = 0;
|
||||
|
||||
var LOC = {
|
||||
// Disk II Stuff
|
||||
RAMLO: 0x80,
|
||||
RAMMID: 0x81,
|
||||
RAMHI: 0x82,
|
||||
RAMDATA: 0x83,
|
||||
_RAMLO: 0x84,
|
||||
_RAMMID: 0x85,
|
||||
_RAMHI: 0x86,
|
||||
_RAMDATA: 0x87,
|
||||
BANK: 0x8F
|
||||
};
|
||||
|
||||
function _init() {
|
||||
debug('RAMFactor card');
|
||||
|
||||
mem = allocMem(size);
|
||||
for (var off = 0; off < size; off++) {
|
||||
mem[off] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function _sethi(val) {
|
||||
_ramhi = (val & 0xff);
|
||||
}
|
||||
|
||||
function _setmid(val) {
|
||||
if (((_rammid & 0x80) !== 0) && ((val & 0x80) === 0)) {
|
||||
_sethi(_ramhi + 1);
|
||||
}
|
||||
_rammid = (val & 0xff);
|
||||
}
|
||||
|
||||
function _setlo(val) {
|
||||
if (((_ramlo & 0x80) !== 0) && ((val & 0x80) === 0)) {
|
||||
_setmid(_rammid + 1);
|
||||
}
|
||||
_ramlo = (val & 0xff);
|
||||
}
|
||||
|
||||
function _access(off, val) {
|
||||
var result = 0;
|
||||
switch (off & 0x8f) {
|
||||
case LOC.RAMLO:
|
||||
case LOC._RAMLO:
|
||||
if (val !== undefined) {
|
||||
_setlo(val);
|
||||
} else {
|
||||
result = _ramlo;
|
||||
}
|
||||
break;
|
||||
case LOC.RAMMID:
|
||||
case LOC._RAMMID:
|
||||
if (val !== undefined) {
|
||||
_setmid(val);
|
||||
} else {
|
||||
result = _rammid;
|
||||
}
|
||||
break;
|
||||
case LOC.RAMHI:
|
||||
case LOC._RAMHI:
|
||||
if (val !== undefined) {
|
||||
_sethi(val);
|
||||
} else {
|
||||
result = _ramhi;
|
||||
result |= 0xf0;
|
||||
}
|
||||
break;
|
||||
case LOC.RAMDATA:
|
||||
case LOC._RAMDATA:
|
||||
if (val !== undefined) {
|
||||
mem[_loc % mem.length] = val;
|
||||
} else {
|
||||
result = mem[_loc % mem.length];
|
||||
}
|
||||
_setlo(_ramlo + 1);
|
||||
break;
|
||||
case LOC.BANK:
|
||||
if (val !== undefined) {
|
||||
_firmware = val & 0x01;
|
||||
} else {
|
||||
result = _firmware;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_loc = (_ramhi << 16) | (_rammid << 8) | (_ramlo);
|
||||
|
||||
/*
|
||||
if (val === undefined) {
|
||||
debug("Read: " + toHex(result) + " from " + toHex(off) + " (loc = " + _loc + ")");
|
||||
} else {
|
||||
debug("Wrote: " + toHex(val) + " to " + toHex(off) + " (loc = " + _loc + ")");
|
||||
}
|
||||
*/
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
_init();
|
||||
|
||||
return {
|
||||
ioSwitch: function (off, val) {
|
||||
return _access(off, val);
|
||||
},
|
||||
read: function ramfactor_read(page, off) {
|
||||
return rom[_firmware << 12 | (page - 0xC0) << 8 | off];
|
||||
},
|
||||
write: function ramfactor_write() {},
|
||||
reset: function ramfactor_reset() {
|
||||
_firmware = 0;
|
||||
},
|
||||
getState: function() {
|
||||
return {
|
||||
loc: _loc,
|
||||
firmware: _firmware,
|
||||
mem: new Uint8Array(mem)
|
||||
};
|
||||
},
|
||||
|
||||
setState: function(state) {
|
||||
_loc = state.loc;
|
||||
_firmware = state.firmware;
|
||||
mem = new Uint8Array(state.mem);
|
||||
|
||||
_ramhi = (_loc >> 16) & 0xff;
|
||||
_rammid = (_loc >> 8) & 0xff;
|
||||
_ramlo = (_loc) & 0xff;
|
||||
}
|
||||
};
|
||||
}
|
163
js/cards/ramfactor.ts
Normal file
163
js/cards/ramfactor.ts
Normal file
@ -0,0 +1,163 @@
|
||||
/* Copyright 2010-2019 Will Scullin <scullin@scullinsteel.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation. No representations are made about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express or
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
import { allocMem, debug } from '../util';
|
||||
import { Card, Restorable, byte, memory } from '../types';
|
||||
import { rom } from '../roms/cards/ramfactor';
|
||||
|
||||
const LOC = {
|
||||
// Disk II Stuff
|
||||
RAMLO: 0x80,
|
||||
RAMMID: 0x81,
|
||||
RAMHI: 0x82,
|
||||
RAMDATA: 0x83,
|
||||
_RAMLO: 0x84,
|
||||
_RAMMID: 0x85,
|
||||
_RAMHI: 0x86,
|
||||
_RAMDATA: 0x87,
|
||||
BANK: 0x8F
|
||||
} as const;
|
||||
|
||||
export class RAMFactorState {
|
||||
loc: number
|
||||
firmware: byte
|
||||
mem: memory
|
||||
}
|
||||
|
||||
export default class RAMFactor implements Card, Restorable<RAMFactorState> {
|
||||
private mem: memory;
|
||||
|
||||
private firmware = 0;
|
||||
private ramlo = 0;
|
||||
private rammid = 0;
|
||||
private ramhi = 0;
|
||||
|
||||
private loc = 0;
|
||||
|
||||
constructor(size: number) {
|
||||
debug('RAMFactor card');
|
||||
|
||||
this.mem = allocMem(size);
|
||||
for (let off = 0; off < size; off++) {
|
||||
this.mem[off] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private sethi(val: byte) {
|
||||
this.ramhi = (val & 0xff);
|
||||
}
|
||||
|
||||
private setmid(val: byte) {
|
||||
if (((this.rammid & 0x80) !== 0) && ((val & 0x80) === 0)) {
|
||||
this.sethi(this.ramhi + 1);
|
||||
}
|
||||
this.rammid = (val & 0xff);
|
||||
}
|
||||
|
||||
private setlo(val: byte) {
|
||||
if (((this.ramlo & 0x80) !== 0) && ((val & 0x80) === 0)) {
|
||||
this.setmid(this.rammid + 1);
|
||||
}
|
||||
this.ramlo = (val & 0xff);
|
||||
}
|
||||
|
||||
private access(off: byte, val: byte) {
|
||||
let result = 0;
|
||||
switch (off & 0x8f) {
|
||||
case LOC.RAMLO:
|
||||
case LOC._RAMLO:
|
||||
if (val !== undefined) {
|
||||
this.setlo(val);
|
||||
} else {
|
||||
result = this.ramlo;
|
||||
}
|
||||
break;
|
||||
case LOC.RAMMID:
|
||||
case LOC._RAMMID:
|
||||
if (val !== undefined) {
|
||||
this.setmid(val);
|
||||
} else {
|
||||
result = this.rammid;
|
||||
}
|
||||
break;
|
||||
case LOC.RAMHI:
|
||||
case LOC._RAMHI:
|
||||
if (val !== undefined) {
|
||||
this.sethi(val);
|
||||
} else {
|
||||
result = this.ramhi;
|
||||
result |= 0xf0;
|
||||
}
|
||||
break;
|
||||
case LOC.RAMDATA:
|
||||
case LOC._RAMDATA:
|
||||
if (val !== undefined) {
|
||||
this.mem[this.loc % this.mem.length] = val;
|
||||
} else {
|
||||
result = this.mem[this.loc % this.mem.length];
|
||||
}
|
||||
this.setlo(this.ramlo + 1);
|
||||
break;
|
||||
case LOC.BANK:
|
||||
if (val !== undefined) {
|
||||
this.firmware = val & 0x01;
|
||||
} else {
|
||||
result = this.firmware;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this.loc = (this.ramhi << 16) | (this.rammid << 8) | (this.ramlo);
|
||||
|
||||
/*
|
||||
if (val === undefined) {
|
||||
debug("Read: " + toHex(result) + " from " + toHex(off) + " (loc = " + _loc + ")");
|
||||
} else {
|
||||
debug("Wrote: " + toHex(val) + " to " + toHex(off) + " (loc = " + _loc + ")");
|
||||
}
|
||||
*/
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ioSwitch(off: byte, val: byte) {
|
||||
return this.access(off, val);
|
||||
}
|
||||
|
||||
read(page: byte, off: byte) {
|
||||
return rom[this.firmware << 12 | (page - 0xC0) << 8 | off];
|
||||
}
|
||||
|
||||
write() {}
|
||||
|
||||
reset() {
|
||||
this.firmware = 0;
|
||||
}
|
||||
|
||||
getState() {
|
||||
return {
|
||||
loc: this.loc,
|
||||
firmware: this.firmware,
|
||||
mem: new Uint8Array(this.mem)
|
||||
};
|
||||
}
|
||||
|
||||
setState(state: RAMFactorState) {
|
||||
this.loc = state.loc;
|
||||
this.firmware = state.firmware;
|
||||
this.mem = new Uint8Array(state.mem);
|
||||
|
||||
this.ramhi = (this.loc >> 16) & 0xff;
|
||||
this.rammid = (this.loc >> 8) & 0xff;
|
||||
this.ramlo = (this.loc) & 0xff;
|
||||
}
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
/* Copyright 2010-2019 Will Scullin <scullin@scullinsteel.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation. No representations are made about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express or
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
import { debug, toHex } from '../util';
|
||||
import { rom } from '../roms/cards/thunderclock';
|
||||
|
||||
export default function Thunderclock()
|
||||
{
|
||||
var LOC = {
|
||||
CONTROL: 0x80,
|
||||
AUX: 0x88
|
||||
};
|
||||
|
||||
var COMMANDS = {
|
||||
MASK: 0x18,
|
||||
REGHOLD: 0x00,
|
||||
REGSHIFT: 0x08,
|
||||
TIMED: 0x18
|
||||
};
|
||||
|
||||
var FLAGS = {
|
||||
DATA: 0x01,
|
||||
CLOCK: 0x02,
|
||||
STROBE: 0x04
|
||||
};
|
||||
|
||||
function _init() {
|
||||
debug('Thunderclock');
|
||||
}
|
||||
|
||||
var _clock = false;
|
||||
var _strobe = false;
|
||||
var _shiftMode = false;
|
||||
var _register = 0;
|
||||
var _bits = [];
|
||||
var _command = COMMANDS.HOLD;
|
||||
|
||||
function _debug() {
|
||||
// debug.apply(this, arguments);
|
||||
}
|
||||
|
||||
function _calcBits() {
|
||||
function shift(val) {
|
||||
for (var idx = 0; idx < 4; idx++) {
|
||||
_bits.push((val & 0x08) !== 0);
|
||||
val <<= 1;
|
||||
}
|
||||
}
|
||||
function shiftBCD(val) {
|
||||
shift(parseInt(val / 10, 10));
|
||||
shift(parseInt(val % 10, 10));
|
||||
}
|
||||
|
||||
var now = new Date();
|
||||
var day = now.getDate();
|
||||
var weekday = now.getDay();
|
||||
var month = now.getMonth() + 1;
|
||||
var hour = now.getHours();
|
||||
var minutes = now.getMinutes();
|
||||
var seconds = now.getSeconds();
|
||||
|
||||
_bits = [];
|
||||
shift(month);
|
||||
shift(weekday);
|
||||
shiftBCD(day);
|
||||
shiftBCD(hour);
|
||||
shiftBCD(minutes);
|
||||
shiftBCD(seconds);
|
||||
}
|
||||
|
||||
function _shift() {
|
||||
if (_shiftMode) {
|
||||
if (_bits.pop()) {
|
||||
_debug('shifting 1');
|
||||
_register |= 0x80;
|
||||
} else {
|
||||
_debug('shifting 0');
|
||||
_register &= 0x7f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _access(off, val) {
|
||||
switch (off & 0x8F) {
|
||||
case LOC.CONTROL:
|
||||
if (val !== undefined) {
|
||||
var strobe = val & FLAGS.STROBE ? true : false;
|
||||
if (strobe !== _strobe) {
|
||||
_debug('strobe', _strobe ? 'high' : 'low');
|
||||
if (strobe) {
|
||||
_command = val & COMMANDS.MASK;
|
||||
switch (_command) {
|
||||
case COMMANDS.TIMED:
|
||||
_debug('TIMED');
|
||||
_calcBits();
|
||||
break;
|
||||
case COMMANDS.REGSHIFT:
|
||||
_debug('REGSHIFT');
|
||||
_shiftMode = true;
|
||||
_shift();
|
||||
break;
|
||||
case COMMANDS.REGHOLD:
|
||||
_debug('REGHOLD');
|
||||
_shiftMode = false;
|
||||
break;
|
||||
default:
|
||||
_debug('Unknown command', toHex(_command));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var clock = val & FLAGS.CLOCK ? true : false;
|
||||
|
||||
if (clock !== _clock) {
|
||||
_clock = clock;
|
||||
_debug('clock', _clock ? 'high' : 'low');
|
||||
if (clock) {
|
||||
_shift();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LOC.AUX:
|
||||
break;
|
||||
}
|
||||
return _register;
|
||||
}
|
||||
|
||||
_init();
|
||||
|
||||
return {
|
||||
read: function thunderclock_read(page, off) {
|
||||
var result;
|
||||
if (page < 0xc8) {
|
||||
result = rom[off];
|
||||
} else {
|
||||
result = rom[(page - 0xc8) << 8 | off];
|
||||
}
|
||||
return result;
|
||||
},
|
||||
write: function thunderclock_write() {
|
||||
},
|
||||
ioSwitch: function thunderclock_ioSwitch(off, val) {
|
||||
return _access(off, val);
|
||||
},
|
||||
getState() {
|
||||
return {};
|
||||
},
|
||||
setState(_) {}
|
||||
};
|
||||
}
|
163
js/cards/thunderclock.ts
Normal file
163
js/cards/thunderclock.ts
Normal file
@ -0,0 +1,163 @@
|
||||
/* Copyright 2010-2019 Will Scullin <scullin@scullinsteel.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation. No representations are made about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express or
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
import { debug, toHex } from '../util';
|
||||
import { Card, Restorable, byte } from '../types';
|
||||
import { rom } from '../roms/cards/thunderclock';
|
||||
|
||||
const LOC = {
|
||||
CONTROL: 0x80,
|
||||
AUX: 0x88
|
||||
} as const;
|
||||
|
||||
const COMMANDS = {
|
||||
MASK: 0x18,
|
||||
REGHOLD: 0x00,
|
||||
REGSHIFT: 0x08,
|
||||
TIMED: 0x18
|
||||
} as const;
|
||||
|
||||
const FLAGS = {
|
||||
DATA: 0x01,
|
||||
CLOCK: 0x02,
|
||||
STROBE: 0x04
|
||||
} as const;
|
||||
|
||||
export interface ThunderclockState {}
|
||||
|
||||
export default class Thunderclock implements Card, Restorable<ThunderclockState>
|
||||
{
|
||||
constructor() {
|
||||
debug('Thunderclock');
|
||||
}
|
||||
|
||||
private clock = false;
|
||||
private strobe = false;
|
||||
private shiftMode = false;
|
||||
private register = 0;
|
||||
private bits: boolean[] = [];
|
||||
private command: byte = COMMANDS.REGHOLD;
|
||||
|
||||
private debug(..._args: any[]) {
|
||||
// debug.apply(this, arguments);
|
||||
}
|
||||
|
||||
private calcBits() {
|
||||
const shift = (val: byte) => {
|
||||
for (let idx = 0; idx < 4; idx++) {
|
||||
this.bits.push((val & 0x08) !== 0);
|
||||
val <<= 1;
|
||||
}
|
||||
};
|
||||
|
||||
const shiftBCD = (val: byte) => {
|
||||
shift(Math.floor(val / 10));
|
||||
shift(val % 10);
|
||||
};
|
||||
|
||||
const now = new Date();
|
||||
const day = now.getDate();
|
||||
const weekday = now.getDay();
|
||||
const month = now.getMonth() + 1;
|
||||
const hour = now.getHours();
|
||||
const minutes = now.getMinutes();
|
||||
const seconds = now.getSeconds();
|
||||
|
||||
this.bits = [];
|
||||
shift(month);
|
||||
shift(weekday);
|
||||
shiftBCD(day);
|
||||
shiftBCD(hour);
|
||||
shiftBCD(minutes);
|
||||
shiftBCD(seconds);
|
||||
}
|
||||
|
||||
private shift() {
|
||||
if (this.shiftMode) {
|
||||
if (this.bits.pop()) {
|
||||
this.debug('shifting 1');
|
||||
this.register |= 0x80;
|
||||
} else {
|
||||
this.debug('shifting 0');
|
||||
this.register &= 0x7f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private access(off: byte, val?: byte) {
|
||||
switch (off & 0x8F) {
|
||||
case LOC.CONTROL:
|
||||
if (val !== undefined) {
|
||||
const strobe = val & FLAGS.STROBE ? true : false;
|
||||
if (strobe !== this.strobe) {
|
||||
this.debug('strobe', this.strobe ? 'high' : 'low');
|
||||
if (strobe) {
|
||||
this.command = val & COMMANDS.MASK;
|
||||
switch (this.command) {
|
||||
case COMMANDS.TIMED:
|
||||
this.debug('TIMED');
|
||||
this.calcBits();
|
||||
break;
|
||||
case COMMANDS.REGSHIFT:
|
||||
this.debug('REGSHIFT');
|
||||
this.shiftMode = true;
|
||||
this.shift();
|
||||
break;
|
||||
case COMMANDS.REGHOLD:
|
||||
this.debug('REGHOLD');
|
||||
this.shiftMode = false;
|
||||
break;
|
||||
default:
|
||||
this.debug('Unknown command', toHex(this.command));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const clock = val & FLAGS.CLOCK ? true : false;
|
||||
|
||||
if (clock !== this.clock) {
|
||||
this.clock = clock;
|
||||
this.debug('clock', this.clock ? 'high' : 'low');
|
||||
if (clock) {
|
||||
this.shift();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LOC.AUX:
|
||||
break;
|
||||
}
|
||||
return this.register;
|
||||
}
|
||||
|
||||
read(page: byte, off: byte) {
|
||||
let result;
|
||||
if (page < 0xc8) {
|
||||
result = rom[off];
|
||||
} else {
|
||||
result = rom[(page - 0xc8) << 8 | off];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
write() {
|
||||
}
|
||||
|
||||
ioSwitch(off: byte, val?: byte) {
|
||||
return this.access(off, val);
|
||||
}
|
||||
|
||||
getState() {
|
||||
return {};
|
||||
}
|
||||
|
||||
setState() {}
|
||||
}
|
@ -1,284 +0,0 @@
|
||||
/* Copyright 2017 Will Scullin <scullin@scullinsteel.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation. No representations are made about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express or
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
import { allocMemPages, debug } from '../util';
|
||||
import { ROM, VIDEO_ROM } from '../roms/cards/videoterm';
|
||||
|
||||
export default function Videoterm(_io) {
|
||||
debug('Videx Videoterm');
|
||||
|
||||
var LOC = {
|
||||
IOREG: 0x80,
|
||||
IOVAL: 0x81
|
||||
};
|
||||
|
||||
|
||||
var REGS = {
|
||||
CURSOR_UPPER: 0x0A,
|
||||
CURSOR_LOWER: 0x0B,
|
||||
STARTPOS_HI: 0x0C,
|
||||
STARTPOS_LO: 0x0D,
|
||||
CURSOR_HI: 0x0E,
|
||||
CURSOR_LO: 0x0F,
|
||||
LIGHTPEN_HI: 0x10,
|
||||
LIGHTPEN_LO: 0x11
|
||||
};
|
||||
|
||||
var CURSOR_MODES = {
|
||||
SOLID: 0x00,
|
||||
HIDDEN: 0x01,
|
||||
BLINK: 0x10,
|
||||
FAST_BLINK: 0x11
|
||||
};
|
||||
|
||||
var _regs = [
|
||||
0x7b, // 00 - Horiz. total
|
||||
0x50, // 01 - Horiz. displayed
|
||||
0x62, // 02 - Horiz. sync pos
|
||||
0x29, // 03 - Horiz. sync width
|
||||
0x1b, // 04 - Vert. total
|
||||
0x08, // 05 - Vert. adjust
|
||||
0x18, // 06 - Vert. displayed
|
||||
0x19, // 07 - Vert. sync pos
|
||||
0x00, // 08 - Interlaced
|
||||
0x08, // 09 - Max. scan line
|
||||
0xc0, // 0A - Cursor upper
|
||||
0x08, // 0B - Cursor lower
|
||||
0x00, // 0C - Startpos Hi
|
||||
0x00, // 0D - Startpos Lo
|
||||
0x00, // 0E - Cursor Hi
|
||||
0x00, // 0F - Cursor Lo
|
||||
0x00, // 10 - Lightpen Hi
|
||||
0x00 // 11 - Lightpen Lo
|
||||
];
|
||||
|
||||
var _blink = false;
|
||||
var _curReg = 0;
|
||||
var _startPos;
|
||||
var _cursorPos;
|
||||
var _shouldRefresh;
|
||||
|
||||
// var _cursor = 0;
|
||||
var _bank = 0;
|
||||
var _buffer = allocMemPages(8);
|
||||
var _imageData;
|
||||
var _dirty = false;
|
||||
|
||||
var _black = [0x00, 0x00, 0x00];
|
||||
var _white = [0xff, 0xff, 0xff];
|
||||
|
||||
function _init() {
|
||||
var idx;
|
||||
|
||||
_imageData = new ImageData(560, 384);
|
||||
for (idx = 0; idx < 560 * 384 * 4; idx++) {
|
||||
_imageData.data[idx] = 0xff;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < 0x800; idx++) {
|
||||
_buffer[idx] = idx & 0xff;
|
||||
}
|
||||
|
||||
_refresh();
|
||||
|
||||
setInterval(function() {
|
||||
_blink = !_blink;
|
||||
_refreshCursor();
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function _updateBuffer(addr, val) {
|
||||
_buffer[addr] = val;
|
||||
val &= 0x7f; // XXX temp
|
||||
var saddr = (0x800 + addr - _startPos) & 0x7ff;
|
||||
var data = _imageData.data;
|
||||
var row = (saddr / 80) & 0xff;
|
||||
var col = saddr % 80;
|
||||
var x = col * 7;
|
||||
var y = row << 4;
|
||||
var c = val << 4;
|
||||
var color;
|
||||
|
||||
if (row < 25) {
|
||||
_dirty = true;
|
||||
for (var idx = 0; idx < 8; idx++) {
|
||||
var cdata = VIDEO_ROM[c + idx];
|
||||
for (var jdx = 0; jdx < 7; jdx++) {
|
||||
if (cdata & 0x80) {
|
||||
color = _white;
|
||||
} else {
|
||||
color = _black;
|
||||
}
|
||||
data[(y + idx * 2) * 560 * 4 + (x + jdx) * 4] = color[0];
|
||||
data[(y + idx * 2) * 560 * 4 + (x + jdx) * 4 + 1] = color[1];
|
||||
data[(y + idx * 2) * 560 * 4 + (x + jdx) * 4 + 2] = color[2];
|
||||
data[(y + idx * 2 + 1) * 560 * 4 + (x + jdx) * 4] = color[0];
|
||||
data[(y + idx * 2 + 1) * 560 * 4 + (x + jdx) * 4 + 1] = color[1];
|
||||
data[(y + idx * 2 + 1) * 560 * 4 + (x + jdx) * 4 + 2] = color[2];
|
||||
cdata <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _refreshCursor(fromRegs) {
|
||||
var addr = _regs[REGS.CURSOR_HI] << 8 | _regs[REGS.CURSOR_LO];
|
||||
var saddr = (0x800 + addr - _startPos) & 0x7ff;
|
||||
var data = _imageData.data;
|
||||
var row = (saddr / 80) & 0xff;
|
||||
var col = saddr % 80;
|
||||
var x = col * 7;
|
||||
var y = row * 16;
|
||||
var blinkmode = (_regs[REGS.CURSOR_UPPER] & 0x60) >> 5;
|
||||
|
||||
if (fromRegs) {
|
||||
if (addr !== _cursorPos) {
|
||||
var caddr = (0x800 + _cursorPos - _startPos) & 0x7ff;
|
||||
_updateBuffer(caddr, _buffer[caddr]);
|
||||
_cursorPos = addr;
|
||||
}
|
||||
}
|
||||
|
||||
_updateBuffer(addr, _buffer[addr]);
|
||||
if (blinkmode === CURSOR_MODES.HIDDEN) {
|
||||
return;
|
||||
}
|
||||
if (_blink || (blinkmode === CURSOR_MODES.SOLID)) {
|
||||
_dirty = true;
|
||||
for (var idx = 0; idx < 8; idx++) {
|
||||
var color = _white;
|
||||
if (idx >= (_regs[REGS.CURSOR_UPPER] & 0x1f) &&
|
||||
idx <= (_regs[REGS.CURSOR_LOWER] & 0x1f)) {
|
||||
for (var jdx = 0; jdx < 7; jdx++) {
|
||||
data[(y + idx * 2) * 560 * 4 + (x + jdx) * 4] = color[0];
|
||||
data[(y + idx * 2) * 560 * 4 + (x + jdx) * 4 + 1] = color[1];
|
||||
data[(y + idx * 2) * 560 * 4 + (x + jdx) * 4 + 2] = color[2];
|
||||
data[(y + idx * 2 + 1) * 560 * 4 + (x + jdx) * 4] = color[0];
|
||||
data[(y + idx * 2 + 1) * 560 * 4 + (x + jdx) * 4 + 1] = color[1];
|
||||
data[(y + idx * 2 + 1) * 560 * 4 + (x + jdx) * 4 + 2] = color[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _updateStartPos() {
|
||||
var startPos =
|
||||
_regs[REGS.STARTPOS_HI] << 8 |
|
||||
_regs[REGS.STARTPOS_LO];
|
||||
if (_startPos != startPos) {
|
||||
_startPos = startPos;
|
||||
_shouldRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
function _refresh() {
|
||||
for (var idx = 0; idx < 0x800; idx++) {
|
||||
_updateBuffer(idx, _buffer[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
function _access(off, val) {
|
||||
var writeMode = val !== undefined;
|
||||
var result = undefined;
|
||||
switch (off & 0x81) {
|
||||
case LOC.IOREG:
|
||||
if (writeMode) {
|
||||
_curReg = val;
|
||||
} else {
|
||||
result = _curReg;
|
||||
}
|
||||
break;
|
||||
case LOC.IOVAL:
|
||||
if (writeMode) {
|
||||
_regs[_curReg] = val;
|
||||
switch (_curReg) {
|
||||
case REGS.CURSOR_UPPER:
|
||||
case REGS.CURSOR_LOWER:
|
||||
_refreshCursor(true);
|
||||
break;
|
||||
case REGS.CURSOR_HI:
|
||||
case REGS.CURSOR_LO:
|
||||
_refreshCursor(true);
|
||||
break;
|
||||
case REGS.STARTPOS_HI:
|
||||
case REGS.STARTPOS_LO:
|
||||
_updateStartPos();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
result = _regs[_curReg];
|
||||
}
|
||||
break;
|
||||
}
|
||||
_bank = (off & 0x0C) >> 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
_init();
|
||||
|
||||
return {
|
||||
ioSwitch: function (off, val) {
|
||||
return _access(off, val);
|
||||
},
|
||||
|
||||
read: function(page, off) {
|
||||
if (page < 0xcc) {
|
||||
return ROM[(page & 0x03) << 8 | off];
|
||||
} else if (page < 0xce){
|
||||
var addr = ((page & 0x01) + (_bank << 1)) << 8 | off;
|
||||
return _buffer[addr];
|
||||
}
|
||||
},
|
||||
|
||||
write: function(page, off, val) {
|
||||
if (page > 0xcb && page < 0xce) {
|
||||
var addr = ((page & 0x01) + (_bank << 1)) << 8 | off;
|
||||
_updateBuffer(addr, val);
|
||||
}
|
||||
},
|
||||
|
||||
blit: function() {
|
||||
if (_shouldRefresh) {
|
||||
_refresh();
|
||||
_shouldRefresh = false;
|
||||
}
|
||||
if (_dirty) {
|
||||
_dirty = false;
|
||||
return _imageData;
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
getState() {
|
||||
return {
|
||||
curReg: _curReg,
|
||||
startPos: _startPos,
|
||||
cursorPos: _cursorPos,
|
||||
bank: _bank,
|
||||
buffer: new Uint8Array(_buffer),
|
||||
regs: [..._regs],
|
||||
};
|
||||
},
|
||||
|
||||
setState(state) {
|
||||
_curReg = state.curReg;
|
||||
_startPos = state.startPos;
|
||||
_cursorPos = state.cursorPos;
|
||||
_bank = state.bank;
|
||||
_buffer = new Uint8Array(_buffer);
|
||||
_regs = [...state.regs];
|
||||
|
||||
_shouldRefresh = true;
|
||||
_dirty = true;
|
||||
}
|
||||
};
|
||||
}
|
281
js/cards/videoterm.ts
Normal file
281
js/cards/videoterm.ts
Normal file
@ -0,0 +1,281 @@
|
||||
/* Copyright 2017 Will Scullin <scullin@scullinsteel.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation. No representations are made about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express or
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
import { allocMemPages, debug } from '../util';
|
||||
import { Card, Restorable, byte, Color, memory, word } from '../types';
|
||||
import { ROM, VIDEO_ROM } from '../roms/cards/videoterm';
|
||||
|
||||
interface VideotermState {
|
||||
curReg: byte,
|
||||
startPos: word,
|
||||
cursorPos: word,
|
||||
bank: byte,
|
||||
buffer: memory,
|
||||
regs: byte[],
|
||||
}
|
||||
|
||||
const LOC = {
|
||||
IOREG: 0x80,
|
||||
IOVAL: 0x81
|
||||
} as const;
|
||||
|
||||
const REGS = {
|
||||
CURSOR_UPPER: 0x0A,
|
||||
CURSOR_LOWER: 0x0B,
|
||||
STARTPOS_HI: 0x0C,
|
||||
STARTPOS_LO: 0x0D,
|
||||
CURSOR_HI: 0x0E,
|
||||
CURSOR_LO: 0x0F,
|
||||
LIGHTPEN_HI: 0x10,
|
||||
LIGHTPEN_LO: 0x11
|
||||
} as const;
|
||||
|
||||
const CURSOR_MODES = {
|
||||
SOLID: 0x00,
|
||||
HIDDEN: 0x01,
|
||||
BLINK: 0x10,
|
||||
FAST_BLINK: 0x11
|
||||
} as const;
|
||||
|
||||
const BLACK: Color = [0x00, 0x00, 0x00];
|
||||
const WHITE: Color = [0xff, 0xff, 0xff];
|
||||
|
||||
export default class Videoterm implements Card, Restorable<VideotermState> {
|
||||
private regs = [
|
||||
0x7b, // 00 - Horiz. total
|
||||
0x50, // 01 - Horiz. displayed
|
||||
0x62, // 02 - Horiz. sync pos
|
||||
0x29, // 03 - Horiz. sync width
|
||||
0x1b, // 04 - Vert. total
|
||||
0x08, // 05 - Vert. adjust
|
||||
0x18, // 06 - Vert. displayed
|
||||
0x19, // 07 - Vert. sync pos
|
||||
0x00, // 08 - Interlaced
|
||||
0x08, // 09 - Max. scan line
|
||||
0xc0, // 0A - Cursor upper
|
||||
0x08, // 0B - Cursor lower
|
||||
0x00, // 0C - Startpos Hi
|
||||
0x00, // 0D - Startpos Lo
|
||||
0x00, // 0E - Cursor Hi
|
||||
0x00, // 0F - Cursor Lo
|
||||
0x00, // 10 - Lightpen Hi
|
||||
0x00 // 11 - Lightpen Lo
|
||||
];
|
||||
|
||||
private blink = false;
|
||||
private curReg = 0;
|
||||
private startPos: word;
|
||||
private cursorPos: word;
|
||||
private shouldRefresh: boolean;
|
||||
|
||||
// private cursor = 0;
|
||||
private bank = 0;
|
||||
private buffer = allocMemPages(8);
|
||||
private imageData;
|
||||
private dirty = false;
|
||||
|
||||
constructor() {
|
||||
debug('Videx Videoterm');
|
||||
|
||||
this.imageData = new ImageData(560, 192);
|
||||
for (let idx = 0; idx < 560 * 192 * 4; idx++) {
|
||||
this.imageData.data[idx] = 0xff;
|
||||
}
|
||||
|
||||
for (let idx = 0; idx < 0x800; idx++) {
|
||||
this.buffer[idx] = idx & 0xff;
|
||||
}
|
||||
|
||||
this.refresh();
|
||||
|
||||
setInterval(() => {
|
||||
this.blink = !this.blink;
|
||||
this.refreshCursor(false);
|
||||
}, 300);
|
||||
}
|
||||
|
||||
private updateBuffer(addr: word, val: byte) {
|
||||
this.buffer[addr] = val;
|
||||
val &= 0x7f; // XXX temp
|
||||
const saddr = (0x800 + addr - this.startPos) & 0x7ff;
|
||||
const data = this.imageData.data;
|
||||
const row = (saddr / 80) & 0xff;
|
||||
const col = saddr % 80;
|
||||
const x = col * 7;
|
||||
const y = row << 3;
|
||||
const c = val << 4;
|
||||
let color;
|
||||
|
||||
if (row < 25) {
|
||||
this.dirty = true;
|
||||
for (let idx = 0; idx < 8; idx++) {
|
||||
let cdata = VIDEO_ROM[c + idx];
|
||||
for (let jdx = 0; jdx < 7; jdx++) {
|
||||
if (cdata & 0x80) {
|
||||
color = WHITE;
|
||||
} else {
|
||||
color = BLACK;
|
||||
}
|
||||
data[(y + idx) * 560 * 4 + (x + jdx) * 4] = color[0];
|
||||
data[(y + idx) * 560 * 4 + (x + jdx) * 4 + 1] = color[1];
|
||||
data[(y + idx) * 560 * 4 + (x + jdx) * 4 + 2] = color[2];
|
||||
cdata <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private refreshCursor(fromRegs: boolean) {
|
||||
const addr = this.regs[REGS.CURSOR_HI] << 8 | this.regs[REGS.CURSOR_LO];
|
||||
const saddr = (0x800 + addr - this.startPos) & 0x7ff;
|
||||
const data = this.imageData.data;
|
||||
const row = (saddr / 80) & 0xff;
|
||||
const col = saddr % 80;
|
||||
const x = col * 7;
|
||||
const y = row << 3;
|
||||
const blinkmode = (this.regs[REGS.CURSOR_UPPER] & 0x60) >> 5;
|
||||
|
||||
if (fromRegs) {
|
||||
if (addr !== this.cursorPos) {
|
||||
const caddr = (0x800 + this.cursorPos - this.startPos) & 0x7ff;
|
||||
this.updateBuffer(caddr, this.buffer[caddr]);
|
||||
this.cursorPos = addr;
|
||||
}
|
||||
}
|
||||
|
||||
this.updateBuffer(addr, this.buffer[addr]);
|
||||
if (blinkmode === CURSOR_MODES.HIDDEN) {
|
||||
return;
|
||||
}
|
||||
if (this.blink || (blinkmode === CURSOR_MODES.SOLID)) {
|
||||
this.dirty = true;
|
||||
for (let idx = 0; idx < 8; idx++) {
|
||||
const color = WHITE;
|
||||
if (idx >= (this.regs[REGS.CURSOR_UPPER] & 0x1f) &&
|
||||
idx <= (this.regs[REGS.CURSOR_LOWER] & 0x1f)) {
|
||||
for (let jdx = 0; jdx < 7; jdx++) {
|
||||
data[(y + idx) * 560 * 4 + (x + jdx) * 4] = color[0];
|
||||
data[(y + idx) * 560 * 4 + (x + jdx) * 4 + 1] = color[1];
|
||||
data[(y + idx) * 560 * 4 + (x + jdx) * 4 + 2] = color[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private updateStartPos() {
|
||||
const startPos =
|
||||
this.regs[REGS.STARTPOS_HI] << 8 |
|
||||
this.regs[REGS.STARTPOS_LO];
|
||||
if (this.startPos != startPos) {
|
||||
this.startPos = startPos;
|
||||
this.shouldRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
private refresh() {
|
||||
for (let idx = 0; idx < 0x800; idx++) {
|
||||
this.updateBuffer(idx, this.buffer[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
private access(off: byte, val?: byte) {
|
||||
let result = undefined;
|
||||
switch (off & 0x81) {
|
||||
case LOC.IOREG:
|
||||
if (val !== undefined) {
|
||||
this.curReg = val;
|
||||
} else {
|
||||
result = this.curReg;
|
||||
}
|
||||
break;
|
||||
case LOC.IOVAL:
|
||||
if (val !== undefined) {
|
||||
this.regs[this.curReg] = val;
|
||||
switch (this.curReg) {
|
||||
case REGS.CURSOR_UPPER:
|
||||
case REGS.CURSOR_LOWER:
|
||||
this.refreshCursor(true);
|
||||
break;
|
||||
case REGS.CURSOR_HI:
|
||||
case REGS.CURSOR_LO:
|
||||
this.refreshCursor(true);
|
||||
break;
|
||||
case REGS.STARTPOS_HI:
|
||||
case REGS.STARTPOS_LO:
|
||||
this.updateStartPos();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
result = this.regs[this.curReg];
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.bank = (off & 0x0C) >> 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
ioSwitch(off: byte, val?: byte) {
|
||||
return this.access(off, val);
|
||||
}
|
||||
|
||||
read(page: byte, off: byte) {
|
||||
if (page < 0xcc) {
|
||||
return ROM[(page & 0x03) << 8 | off];
|
||||
} else if (page < 0xce){
|
||||
const addr = ((page & 0x01) + (this.bank << 1)) << 8 | off;
|
||||
return this.buffer[addr];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
write(page: byte, off: byte, val: byte) {
|
||||
if (page > 0xcb && page < 0xce) {
|
||||
const addr = ((page & 0x01) + (this.bank << 1)) << 8 | off;
|
||||
this.updateBuffer(addr, val);
|
||||
}
|
||||
}
|
||||
|
||||
blit() {
|
||||
if (this.shouldRefresh) {
|
||||
this.refresh();
|
||||
this.shouldRefresh = false;
|
||||
}
|
||||
if (this.dirty) {
|
||||
this.dirty = false;
|
||||
return this.imageData;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
getState() {
|
||||
return {
|
||||
curReg: this.curReg,
|
||||
startPos: this.startPos,
|
||||
cursorPos: this.cursorPos,
|
||||
bank: this.bank,
|
||||
buffer: new Uint8Array(this.buffer),
|
||||
regs: [...this.regs],
|
||||
};
|
||||
}
|
||||
|
||||
setState(state: VideotermState) {
|
||||
this.curReg = state.curReg;
|
||||
this.startPos = state.startPos;
|
||||
this.cursorPos = state.cursorPos;
|
||||
this.bank = state.bank;
|
||||
this.buffer = new Uint8Array(this.buffer);
|
||||
this.regs = [...state.regs];
|
||||
|
||||
this.shouldRefresh = true;
|
||||
this.dirty = true;
|
||||
}
|
||||
}
|
3
js/gl.ts
3
js/gl.ts
@ -9,12 +9,11 @@
|
||||
* implied warranty.
|
||||
*/
|
||||
|
||||
import { byte, memory, MemoryPages, rom } from './types';
|
||||
import { byte, Color, memory, MemoryPages, rom } from './types';
|
||||
import { allocMemPages } from './util';
|
||||
|
||||
import { screenEmu } from 'apple2shader';
|
||||
import {
|
||||
Color,
|
||||
GraphicsState,
|
||||
HiresPage,
|
||||
LoresPage,
|
||||
|
@ -77,11 +77,11 @@ var io = apple2.getIO();
|
||||
var printer = new Printer('#printer-modal .paper');
|
||||
|
||||
var lc = new LanguageCard(rom);
|
||||
var parallel = new Parallel(io, printer);
|
||||
var videoTerm = new VideoTerm(io);
|
||||
var slinky = new RAMFactor(io, 1024 * 1024);
|
||||
var parallel = new Parallel(printer);
|
||||
var videoTerm = new VideoTerm();
|
||||
var slinky = new RAMFactor(1024 * 1024);
|
||||
var disk2 = new DiskII(io, driveLights, sectors);
|
||||
var clock = new Thunderclock(io);
|
||||
var clock = new Thunderclock();
|
||||
var smartport = new SmartPort(cpu, { block: true });
|
||||
|
||||
initUI(apple2, disk2, smartport, printer, false);
|
||||
|
@ -58,10 +58,10 @@ var cpu = apple2.getCPU();
|
||||
|
||||
var printer = new Printer('#printer-modal .paper');
|
||||
|
||||
var parallel = new Parallel(io, printer);
|
||||
var slinky = new RAMFactor(io, 1024 * 1024);
|
||||
var parallel = new Parallel(printer);
|
||||
var slinky = new RAMFactor(1024 * 1024);
|
||||
var disk2 = new DiskII(io, driveLights);
|
||||
var clock = new Thunderclock(io);
|
||||
var clock = new Thunderclock();
|
||||
var smartport = new SmartPort(cpu, { block: !enhanced });
|
||||
|
||||
initUI(apple2, disk2, smartport, printer, options.e);
|
||||
|
@ -50,7 +50,7 @@ export interface Card extends Memory, Restorable {
|
||||
reset?(): void;
|
||||
|
||||
/* Draw card to canvas */
|
||||
blit?(): ImageData;
|
||||
blit?(): ImageData | undefined;
|
||||
|
||||
/* Process period events */
|
||||
tick?(): void;
|
||||
@ -100,3 +100,6 @@ export type TypedArrayMutableProperties = 'copyWithin' | 'fill' | 'reverse' | 's
|
||||
export interface ReadonlyUint8Array extends Omit<Uint8Array, TypedArrayMutableProperties> {
|
||||
readonly [n: number]: number
|
||||
}
|
||||
|
||||
// Readonly RGB color value
|
||||
export type Color = readonly [r: byte, g: byte, b: byte];
|
||||
|
@ -3,12 +3,6 @@ import { MemoryPages, Restorable, byte, memory } from './types';
|
||||
export type bank = 0 | 1;
|
||||
export type pageNo = 1 | 2;
|
||||
|
||||
export interface Color {
|
||||
0: byte, // red
|
||||
1: byte, // green
|
||||
2: byte, // blue
|
||||
}
|
||||
|
||||
export interface Region {
|
||||
top: number,
|
||||
bottom: number,
|
||||
|
Loading…
Reference in New Issue
Block a user