1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-06-11 12:29:29 +00:00
8bitworkshop/src/machine/vdp_z80.ts
2019-08-25 12:15:22 -04:00

95 lines
2.2 KiB
TypeScript

import { Z80, Z80State } from "../cpu/ZilogZ80";
import { BasicScanlineMachine, Bus } from "../devices";
import { newAddressDecoder, newKeyboardHandler } from "../emu";
import { TssChannelAdapter } from "../audio";
import { TMS9918A } from "../video/tms9918a";
const audioOversample = 2;
export abstract class BaseZ80VDPBasedMachine extends BasicScanlineMachine {
cpuFrequency = 3579545; // MHz
canvasWidth = 304;
numTotalScanlines = 262;
numVisibleScanlines = 240;
cpuCyclesPerLine = this.cpuFrequency / (262*60);
sampleRate = 262*60*audioOversample;
overscan = true;
cpu: Z80 = new Z80();
vdp: TMS9918A;
psg;
handler;
audioadapter;
init(membus:Bus, iobus:Bus, keycodemap, psg) {
this.connectCPUMemoryBus(membus);
this.connectCPUIOBus(iobus);
this.handler = newKeyboardHandler(this.inputs, keycodemap);
this.psg = psg;
this.audioadapter = psg && new TssChannelAdapter(psg.psg, audioOversample, this.sampleRate);
}
setKeyInput(key:number, code:number, flags:number) : void {
this.handler(key,code,flags);
}
connectVideo(pixels) {
super.connectVideo(pixels);
this.vdp = this.newVDP(this.pixels);
}
newVDP(frameData) {
var cru = {
setVDPInterrupt: (b) => {
if (b) {
this.cpu.NMI();
} else {
// TODO: reset interrupt?
}
}
};
return new TMS9918A(frameData, cru, true);
}
startScanline() {
this.audio && this.audioadapter && this.audioadapter.generate(this.audio);
}
drawScanline() {
this.vdp.drawScanline(this.scanline);
}
loadState(state) {
super.loadState(state);
this.vdp.restoreState(state['vdp']);
}
saveState() {
var state = super.saveState();
state['vdp'] = this.vdp.getState();
return state;
}
reset() {
super.reset();
this.vdp.reset();
this.psg.reset();
}
getDebugCategories() {
return ['VDP'];
}
getDebugInfo(category, state) {
switch (category) {
case 'VDP': return this.vdpStateToLongString(state.vdp);
}
}
vdpStateToLongString(ppu) {
return this.vdp.getRegsString();
}
readVRAMAddress(a : number) : number {
return this.vdp.ram[a & 0x3fff];
}
}