import { MOS6502, MOS6502State } from "../common/cpu/MOS6502"; import { BasicMachine, RasterFrameBased, Bus, ProbeAll, Probeable, NullProbe } from "../common/devices"; import { KeyFlags, newAddressDecoder, padBytes, Keys, makeKeycodeMap, newKeyboardHandler, EmuHalt, dumpRAM } from "../common/emu"; import { lzgmini, stringToByteArray, hex, rgb2bgr } from "../common/util"; // https://www.c64-wiki.com/wiki/C64 // http://www.zimmers.net/cbmpics/cbm/c64/vic-ii.txt // http://www.zimmers.net/cbmpics/cbm/c64/c64prg.txt // http://sta.c64.org/cbm64mem.html // http://hitmen.c02.at/temp/palstuff/ //// WASM Machine import { Machine, BaseWASMMachine } from "../common/baseplatform"; import { TrapCondition } from "../common/devices"; export class C64_WASMMachine extends BaseWASMMachine implements Machine, Probeable { numTotalScanlines = 312; cpuCyclesPerLine = 63; prgstart : number; joymask0 = 0; joymask1 = 0; reset() { super.reset(); // load rom if (this.romptr && this.romlen) { this.exports.machine_load_rom(this.sys, this.romptr, this.romlen); this.prgstart = this.romarr[0] + (this.romarr[1]<<8); // get load address // look for BASIC program start if (this.prgstart == 0x801) { this.prgstart = this.romarr[2] + (this.romarr[3]<<8) + 2; // point to after BASIC program console.log("prgstart", hex(this.prgstart)); } } // clear keyboard for (var ch=0; ch<128; ch++) { this.setKeyInput(ch, 0, KeyFlags.KeyUp); } // is program loaded into RAM? if (this.prgstart < 0x8000) { // advance BIOS a few frames this.exports.machine_exec(this.sys, 150000); // set IRQ routine @ 0x314 var old0x314 = this.read(0x314) + this.read(0x315) * 256; this.write(0x314, this.prgstart & 0xff); this.write(0x315, (this.prgstart >> 8) & 0xff); // wait until IRQ fires for (var i=0; i<50000 && this.getPC() != this.prgstart; i++) { this.exports.machine_tick(this.sys); } // reset 0x314 to old value this.write(0x314, old0x314 & 0xff); this.write(0x315, old0x314 >> 8); } else { // get out of reset this.exports.machine_exec(this.sys, 100); // wait until cartridge start // TODO: detect ROM cartridge var warmstart = this.romarr[0x4] + this.romarr[0x5]*256; for (var i=0; i<150000 && this.getPC() != warmstart; i++) { this.exports.machine_tick(this.sys); } } // TODO: shouldn't we return here @ start of frame? // and stop probing } advanceFrame(trap: TrapCondition) : number { // TODO: does this sync with VSYNC? var scanline = this.exports.machine_get_raster_line(this.sys); var clocks = Math.floor((this.numTotalScanlines - scanline) * (19656+295) / this.numTotalScanlines); var probing = this.probe != null; if (probing) this.exports.machine_reset_probe_buffer(); var clocks = super.advanceFrameClock(trap, clocks); if (probing) this.copyProbeData(); return clocks; } getCPUState() { this.exports.machine_save_cpu_state(this.sys, this.cpustateptr); var s = this.cpustatearr; var pc = s[2] + (s[3]<<8); return { PC:pc, SP:s[9], A:s[6], X:s[7], Y:s[8], C:s[10] & 1, Z:s[10] & 2, I:s[10] & 4, D:s[10] & 8, V:s[10] & 64, N:s[10] & 128, o:this.readConst(pc), } } saveState() { this.exports.machine_save_state(this.sys, this.stateptr); /* for (var i=0; i