8bitworkshop/src/platform/devel.ts

182 lines
4.6 KiB
TypeScript

import { Platform } from "../common/baseplatform";
import { EmuHalt, PLATFORMS } from "../common/emu";
import { Devel6502 } from "../machine/devel";
import { Base6502MachinePlatform } from "../common/baseplatform";
import { SerialIOInterface } from "../common/devices";
import { byteArrayToString, convertDataToUint8Array } from "../common/util";
import { TeleType } from "../common/teletype";
import { haltEmulation } from "../ide/ui";
var DEVEL_6502_PRESETS = [
{id:'hello.dasm', name:'Hello World (ASM)'},
];
class SerialInOutViewer {
div : HTMLElement;
tty : TeleType;
constructor(div: HTMLElement) {
div.style.overflowY = 'auto';
var gameport = $('<div id="gameport"/>').appendTo(div);
$('<p class="transcript-header">Serial Output</p>').appendTo(gameport);
var windowport = $('<div id="windowport" class="transcript"/>').appendTo(gameport);
this.div = windowport[0];
}
start() {
this.tty = new TeleType(this.div, false);
//this.tty.ncols = 40;
}
reset() {
this.tty.clear();
}
saveState() {
return this.tty.saveState();
}
loadState(state) {
this.tty.loadState(state);
}
}
function byteToASCII(b: number) : string {
if (b == 10) return '';
if (b < 32)
return String.fromCharCode(b + 0x2400);
else
return String.fromCharCode(b);
}
export class SerialTestHarness implements SerialIOInterface {
viewer : SerialInOutViewer;
bufferedRead : boolean = true;
cyclesPerByte = 1000000/(57600/8); // 138.88888 cycles
maxOutputBytes = 4096;
inputBytes : Uint8Array;
outputBytes : number[];
inputIndex : number;
clk : number;
bufin : string;
clearToSend(): boolean {
return this.outputBytes.length < this.maxOutputBytes;
}
sendByte(b: number) {
if (this.clearToSend()) {
this.outputBytes.push(b);
this.viewer.tty.addtext(byteToASCII(b), 2|32);
if (b == 10) this.viewer.tty.newline();
if (!this.clearToSend()) {
this.viewer.tty.newline();
this.viewer.tty.addtext("⚠️ OUTPUT BUFFER FULL ⚠️", 4);
}
}
}
byteAvailable(): boolean {
return this.readIndex() > this.inputIndex;
}
recvByte(): number {
var index = this.readIndex();
this.inputIndex = index;
var b = (this.inputBytes && this.inputBytes[index]) | 0;
//this.bufin += byteToASCII(b);
this.viewer.tty.addtext(byteToASCII(b), 2|16);
if (b == 10) this.viewer.tty.newline();
return b;
}
readIndex(): number {
return this.bufferedRead ? (this.inputIndex+1) : Math.floor(this.clk / this.cyclesPerByte);
}
reset() {
this.inputIndex = -1;
this.clk = 0;
this.outputBytes = [];
this.bufin = '';
}
advance(clocks: number) {
this.clk += clocks;
}
saveState() {
return {
clk: this.clk,
idx: this.inputIndex,
out: this.outputBytes.slice()
}
}
loadState(state) {
this.clk = state.clk;
this.inputIndex = state.idx;
this.outputBytes = state.out.slice();
}
}
class Devel6502Platform extends Base6502MachinePlatform<Devel6502> implements Platform {
serial : SerialTestHarness;
serview : SerialInOutViewer;
constructor(mainElement: HTMLElement) {
super(mainElement);
this.serview = new SerialInOutViewer(mainElement);
}
async start() {
super.start();
this.serial = new SerialTestHarness();
this.serial.viewer = this.serview;
this.serview.start();
this.machine.connectSerialIO(this.serial);
}
reset() {
this.serial.inputBytes = convertDataToUint8Array(this.internalFiles['serialin.dat']);
super.reset();
this.serview.reset();
}
isBlocked() {
return this.machine.isHalted();
}
advance(novideo: boolean) {
if (this.isBlocked()) {
this.internalFiles['serialout.dat'] = byteArrayToString(this.serial.outputBytes);
haltEmulation();
return 0;
}
return super.advance(novideo);
}
saveState() {
var state : any = super.saveState();
state.serial = this.serial.saveState();
state.serview = this.serview.saveState();
return state;
}
loadState(state) {
super.loadState(state);
this.serial.loadState(state.serial);
this.serview.loadState(state.serview);
// TODO: reload tty UI
}
newMachine() { return new Devel6502(); }
getPresets() { return DEVEL_6502_PRESETS; }
getDefaultExtension() { return ".dasm"; };
readAddress(a) { return this.machine.readConst(a); }
getMemoryMap = function() { return { main:[
{name:'RAM', start:0x0000,size:0x4000,type:'ram'},
{name:'ROM', start:0x8000,size:0x8000,type:'rom'},
] } };
}
///
PLATFORMS['devel-6502'] = Devel6502Platform;