export interface SavesState { saveState() : S; loadState(state:S) : void; } export interface Bus { read(a:number) : number; write(a:number, v:number) : void; readConst?(a:number) : number; } export interface ClockBased { advanceClock() : void; } export interface InstructionBased { advanceInsn() : number; } export type TrapCondition = () => boolean; export interface FrameBased { advanceFrame(maxClocks:number, trap:TrapCondition) : number; } export interface VideoSource { getVideoParams() : VideoParams; connectVideo(pixels:Uint32Array) : void; } export interface RasterFrameBased extends FrameBased, VideoSource { getRasterY() : number; getRasterX() : number; } export interface VideoParams { width : number; height : number; overscan? : boolean; rotate? : number; } // TODO: frame buffer optimization (apple2, etc) export interface SampledAudioParams { sampleRate : number; stereo : boolean; } export interface SampledAudioSink { feedSample(value:number, count:number) : void; //sendAudioFrame(samples:Uint16Array) : void; } export interface SampledAudioSource { getAudioParams() : SampledAudioParams; connectAudio(audio : SampledAudioSink) : void; } export interface AcceptsROM { loadROM(data:Uint8Array, title?:string) : void; } export interface Resettable { reset() : void; } export interface MemoryBusConnected { connectMemoryBus(bus:Bus) : void; } export interface IOBusConnected { connectIOBus(bus:Bus) : void; } export interface CPU extends MemoryBusConnected, Resettable, SavesState { getPC() : number; getSP() : number; isStable() : boolean; } export interface HasCPU extends Resettable { cpu : CPU; } export interface Interruptable { interrupt(type:IT) : void; } export interface SavesInputState { loadControlsState(cs:CS) : void; saveControlsState() : CS; } // TODO export interface AcceptsKeyInput { setKeyInput(key:number, code:number, flags:number) : void; } // TODO? export function noise(x : number) : number { x ^= x << 13; x ^= x >> 17; x ^= x << 5; return x; } /// HOOKS export interface Hook { //target : T; unhook(); } export class BusHook implements Hook { //target : Bus; constructor(bus : Bus, profiler : LogBus) { //this.target = bus; var oldread = bus.read.bind(bus); var oldwrite = bus.write.bind(bus); bus.read = (a:number):number => { profiler.logRead(a); var val = oldread(a); return val; } bus.write = (a:number,v:number) => { profiler.logWrite(a); oldwrite(a,v); } this.unhook = () => { bus.read = oldread; bus.write = oldwrite; } } unhook : () => void; } export class CPUClockHook implements Hook { //target : CPU&ClockBased; constructor(cpu : CPU&ClockBased, profiler : LogCPU) { //this.target = cpu; var oldclock = cpu.advanceClock.bind(cpu); cpu.advanceClock = () => { profiler.logExecute(cpu.getPC()); return oldclock(); } this.unhook = () => { cpu.advanceClock = oldclock; } } unhook : () => void; } export class CPUInsnHook implements Hook { //target : CPU&InstructionBased; constructor(cpu : CPU&InstructionBased, profiler : LogCPU) { //this.target = cpu; var oldinsn = cpu.advanceInsn.bind(cpu); cpu.advanceInsn = () => { profiler.logExecute(cpu.getPC()); return oldinsn(); } this.unhook = () => { cpu.advanceInsn = oldinsn; } } unhook : () => void; } /// PROFILER export interface LogCPU { logExecute(address:number); logInterrupt(type:number); } export interface LogBus { logRead(address:number); logWrite(address:number); } export interface LogIO { logIORead(address:number); logIOWrite(address:number); } export interface LogAll extends LogCPU, LogBus, LogIO { } /// DEBUGGING class EmuBreakpoint extends Error { }