160 lines
4.9 KiB
TypeScript
160 lines
4.9 KiB
TypeScript
import CPU6502 from '../cpu6502';
|
|
import { debug } from '../util';
|
|
import { byte } from '../types';
|
|
|
|
const rom = [
|
|
0xa9, 0xaa, 0x20, 0xef, 0xff, 0xa9, 0x8d, 0x20, 0xef, 0xff, 0xa0, 0xff, 0xc8,
|
|
0xad, 0x11, 0xd0, 0x10, 0xfb, 0xad, 0x10, 0xd0, 0x99, 0x00, 0x02, 0x20, 0xef,
|
|
0xff, 0xc9, 0x9b, 0xf0, 0xe1, 0xc9, 0x8d, 0xd0, 0xe9, 0xa2, 0xff, 0xa9, 0x00,
|
|
0x85, 0x24, 0x85, 0x25, 0x85, 0x26, 0x85, 0x27, 0xe8, 0xbd, 0x00, 0x02, 0xc9,
|
|
0xd2, 0xf0, 0x56, 0xc9, 0xd7, 0xf0, 0x35, 0xc9, 0xae, 0xf0, 0x27, 0xc9, 0x8d,
|
|
0xf0, 0x20, 0xc9, 0xa0, 0xf0, 0xe8, 0x49, 0xb0, 0xc9, 0x0a, 0x90, 0x06, 0x69,
|
|
0x88, 0xc9, 0xfa, 0x90, 0xad, 0x0a, 0x0a, 0x0a, 0x0a, 0xa0, 0x04, 0x0a, 0x26,
|
|
0x24, 0x26, 0x25, 0x88, 0xd0, 0xf8, 0xf0, 0xcc, 0x4c, 0x1a, 0xff, 0xa5, 0x24,
|
|
0x85, 0x26, 0xa5, 0x25, 0x85, 0x27, 0xb0, 0xbf, 0xa9, 0x40, 0x20, 0xcc, 0xc1,
|
|
0x88, 0xa2, 0x00, 0xa1, 0x26, 0xa2, 0x10, 0x0a, 0x20, 0xdb, 0xc1, 0xd0, 0xfa,
|
|
0x20, 0xf1, 0xc1, 0xa0, 0x1e, 0x90, 0xec, 0xa6, 0x28, 0xb0, 0x98, 0x20, 0xbc,
|
|
0xc1, 0xa9, 0x16, 0x20, 0xcc, 0xc1, 0x20, 0xbc, 0xc1, 0xa0, 0x1f, 0x20, 0xbf,
|
|
0xc1, 0xb0, 0xf9, 0x20, 0xbf, 0xc1, 0xa0, 0x3a, 0xa2, 0x08, 0x48, 0x20, 0xbc,
|
|
0xc1, 0x68, 0x2a, 0xa0, 0x39, 0xca, 0xd0, 0xf5, 0x81, 0x26, 0x20, 0xf1, 0xc1,
|
|
0xa0, 0x35, 0x90, 0xea, 0xb0, 0xcd, 0x20, 0xbf, 0xc1, 0x88, 0xad, 0x81, 0xc0,
|
|
0xc5, 0x29, 0xf0, 0xf8, 0x85, 0x29, 0xc0, 0x80, 0x60, 0x86, 0x28, 0xa0, 0x42,
|
|
0x20, 0xe0, 0xc1, 0xd0, 0xf9, 0x69, 0xfe, 0xb0, 0xf5, 0xa0, 0x1e, 0x20, 0xe0,
|
|
0xc1, 0xa0, 0x2c, 0x88, 0xd0, 0xfd, 0x90, 0x05, 0xa0, 0x2f, 0x88, 0xd0, 0xfd,
|
|
0xbc, 0x00, 0xc0, 0xa0, 0x29, 0xca, 0x60, 0xa5, 0x26, 0xc5, 0x24, 0xa5, 0x27,
|
|
0xe5, 0x25, 0xe6, 0x26, 0xd0, 0x02, 0xe6, 0x27, 0x60,
|
|
] as const;
|
|
|
|
export interface ACICallback {
|
|
progress: (value: number) => void;
|
|
}
|
|
|
|
export default class ACI {
|
|
_last: number;
|
|
_next: number;
|
|
_recording = false;
|
|
_readOffset = 0;
|
|
_flip = false;
|
|
_beKind = false;
|
|
_progress = 0;
|
|
|
|
constructor(private cpu: CPU6502, private cb: ACICallback) {
|
|
this._last = cpu.getCycles();
|
|
this._next = this._last;
|
|
}
|
|
|
|
start() {
|
|
return 0xc0;
|
|
}
|
|
end() {
|
|
return 0xc1;
|
|
}
|
|
read(page: byte, off: byte) {
|
|
const now = this.cpu.getCycles();
|
|
let result = rom[off];
|
|
if (page === 0xc0) {
|
|
if (this._recording) {
|
|
const delta = now - this._last;
|
|
this.buffer.push(delta);
|
|
this._last = now;
|
|
} else {
|
|
if (this._readOffset < this.buffer.length) {
|
|
if (now > this._next) {
|
|
if (this._readOffset % 1000 === 0) {
|
|
debug('Read ' + this._readOffset / 1000);
|
|
}
|
|
this._flip = !this._flip;
|
|
this._next = now + this.buffer[this._readOffset++];
|
|
}
|
|
}
|
|
result = this._flip ? rom[off | 0x01] : rom[off & 0xfe];
|
|
|
|
const progress =
|
|
Math.round((this._readOffset / this.buffer.length) * 100) / 100;
|
|
if (this._progress !== progress) {
|
|
this._progress = progress;
|
|
this.cb.progress(this._progress);
|
|
}
|
|
}
|
|
} else {
|
|
if (this.cpu.getSync()) {
|
|
switch (off) {
|
|
case 0x00:
|
|
this._recording = false;
|
|
this._beKind = true;
|
|
debug('Entering ACI CLI');
|
|
break;
|
|
case 0x63:
|
|
if (this._recording) {
|
|
this.buffer.push(5000000);
|
|
this._recording = false;
|
|
}
|
|
debug('Exiting ACI CLI');
|
|
break;
|
|
case 0x70: // WRITE
|
|
this._recording = true;
|
|
if (this._beKind) {
|
|
this._beKind = false;
|
|
this.buffer = [];
|
|
}
|
|
debug('Start write');
|
|
this._last = now;
|
|
break;
|
|
//case 0x7c: // WBITLOOP:
|
|
// _debug = true;
|
|
// debug("Write bit loop");
|
|
// break;
|
|
case 0x8d: // READ
|
|
this._recording = false;
|
|
debug('Start read');
|
|
if (this._beKind) {
|
|
this._readOffset = 0;
|
|
this._next = now + 5000000;
|
|
this._beKind = false;
|
|
|
|
this.cb.progress(0);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
write() {}
|
|
|
|
getState() {
|
|
return {};
|
|
}
|
|
setState() {}
|
|
|
|
setData(data: number[][]) {
|
|
let seg, idx, jdx, d, b;
|
|
this.buffer = [];
|
|
for (seg = 0; seg < data.length; seg++) {
|
|
for (idx = 0; idx < 16384; idx++) {
|
|
this.buffer.push(592);
|
|
}
|
|
this.buffer.push(180);
|
|
this.buffer.push(238);
|
|
d = data[seg];
|
|
for (idx = 0; idx < d.length; idx++) {
|
|
b = d[idx];
|
|
for (jdx = 0; jdx < 8; jdx++) {
|
|
if (b & 0x80) {
|
|
this.buffer.push(473);
|
|
this.buffer.push(473);
|
|
} else {
|
|
this.buffer.push(238);
|
|
this.buffer.push(238);
|
|
}
|
|
b <<= 1;
|
|
}
|
|
}
|
|
this.buffer.push(5000000);
|
|
}
|
|
}
|
|
buffer: byte[] = [];
|
|
}
|