mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2026-10-25 00:02:16 +00:00
c64, zx: added probe buffer support, need to log scanlines
This commit is contained in:
1 parent
95e1ef8a0d
commit
93aff314c8
8 files changed
+48
-573
No files matched your search
Binary file not shown.
BIN
Binary file not shown.
@@ -965,7 +965,7 @@ export function lookupSymbol(platform:Platform, addr:number, extra:boolean) {
|
||||
/// new Machine platform adapters
|
||||
|
||||
import { Bus, Resettable, FrameBased, VideoSource, SampledAudioSource, AcceptsROM, AcceptsKeyInput, SavesState, SavesInputState, HasCPU, TrapCondition, CPU } from "./devices";
|
||||
import { Probeable, RasterFrameBased, AcceptsPaddleInput, SampledAudioSink } from "./devices";
|
||||
import { Probeable, RasterFrameBased, AcceptsPaddleInput, SampledAudioSink, ProbeAll, NullProbe } from "./devices";
|
||||
import { SampledAudio } from "./audio";
|
||||
import { ProbeRecorder } from "./recorder";
|
||||
|
||||
@@ -1205,6 +1205,7 @@ export abstract class BaseWASMMachine {
|
||||
romarr : Uint8Array;
|
||||
audio : SampledAudioSink;
|
||||
audioarr : Float32Array;
|
||||
probe : ProbeAll;
|
||||
|
||||
abstract getCPUState() : CpuState;
|
||||
|
||||
@@ -1235,7 +1236,7 @@ export abstract class BaseWASMMachine {
|
||||
var wasmResult = await WebAssembly.instantiate(wasmCompiled);
|
||||
this.instance = wasmResult;
|
||||
this.exports = wasmResult.exports;
|
||||
this.exports.memory.grow(32);
|
||||
this.exports.memory.grow(64); // TODO: need more when probing?
|
||||
// fetch BIOS
|
||||
var biosResponse = await fetch('res/'+this.prefix+'.bios');
|
||||
var biosBinary = await biosResponse.arrayBuffer();
|
||||
@@ -1347,5 +1348,19 @@ export abstract class BaseWASMMachine {
|
||||
this.syncAudio();
|
||||
return i;
|
||||
}
|
||||
copyProbeData() {
|
||||
if (this.probe && !(this.probe instanceof NullProbe)) {
|
||||
var datalen = this.exports.machine_get_probe_buffer_size();
|
||||
var dataaddr = this.exports.machine_get_probe_buffer_address();
|
||||
// TODO: more efficient way to put into probe
|
||||
var databuf = new Uint32Array(this.exports.memory.buffer, dataaddr, datalen);
|
||||
this.probe.logNewFrame(); // TODO: machine should do this
|
||||
for (var i=0; i<datalen; i++)
|
||||
this.probe.logData(databuf[i]);
|
||||
}
|
||||
}
|
||||
connectProbe(probe: ProbeAll): void {
|
||||
this.probe = probe;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +144,7 @@ export interface ProbeVRAM {
|
||||
}
|
||||
|
||||
export interface ProbeAll extends ProbeTime, ProbeCPU, ProbeBus, ProbeIO, ProbeVRAM {
|
||||
logData(data:number); // entire 32 bits
|
||||
}
|
||||
|
||||
export class NullProbe implements ProbeAll {
|
||||
@@ -159,6 +160,7 @@ export class NullProbe implements ProbeAll {
|
||||
logVRAMRead() {}
|
||||
logVRAMWrite() {}
|
||||
logIllegal() {}
|
||||
logData() {}
|
||||
}
|
||||
|
||||
/// CONVENIENCE
|
||||
|
||||
@@ -203,6 +203,9 @@ export class ProbeRecorder implements ProbeAll {
|
||||
clear() {
|
||||
this.idx = 0;
|
||||
}
|
||||
logData(a:number) {
|
||||
this.log(a);
|
||||
}
|
||||
log(a:number) {
|
||||
// TODO: coalesce READ and EXECUTE and PUSH/POP
|
||||
if (this.idx >= this.buf.length) return;
|
||||
|
||||
+16
-557
@@ -1,6 +1,6 @@
|
||||
|
||||
import { MOS6502, MOS6502State } from "../common/cpu/MOS6502";
|
||||
import { BasicMachine, RasterFrameBased, Bus, ProbeAll } from "../common/devices";
|
||||
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";
|
||||
|
||||
@@ -10,566 +10,15 @@ import { lzgmini, stringToByteArray, hex, rgb2bgr } from "../common/util";
|
||||
// http://sta.c64.org/cbm64mem.html
|
||||
// http://hitmen.c02.at/temp/palstuff/
|
||||
|
||||
// native JS emulator (NOT USED)
|
||||
|
||||
const KEYBOARD_ROW_0 = 0;
|
||||
const SWCHA = 8;
|
||||
const SWCHB = 9;
|
||||
const INPT0 = 10;
|
||||
|
||||
const C64_KEYCODE_MAP = makeKeycodeMap([
|
||||
[Keys.A, INPT0+0, 0x80],
|
||||
[Keys.B, INPT0+1, 0x80],
|
||||
[Keys.SELECT, SWCHB, -0x02],
|
||||
[Keys.START, SWCHB, -0x01],
|
||||
[Keys.UP, SWCHA, -0x10],
|
||||
[Keys.DOWN, SWCHA, -0x20],
|
||||
[Keys.LEFT, SWCHA, -0x40],
|
||||
[Keys.RIGHT, SWCHA, -0x80],
|
||||
|
||||
[Keys.P2_A, INPT0+2, 0x80],
|
||||
[Keys.P2_B, INPT0+3, 0x80],
|
||||
//[Keys.P2_SELECT, 1, 2],
|
||||
//[Keys.P2_START, 1, 3],
|
||||
[Keys.P2_UP, SWCHA, -0x01],
|
||||
[Keys.P2_DOWN, SWCHA, -0x02],
|
||||
[Keys.P2_LEFT, SWCHA, -0x04],
|
||||
[Keys.P2_RIGHT, SWCHA, -0x08],
|
||||
]);
|
||||
|
||||
const C64_KEYMATRIX_NOSHIFT = [
|
||||
Keys.VK_DELETE, Keys.VK_ENTER, Keys.VK_RIGHT, Keys.VK_F10, Keys.VK_F2, Keys.VK_F4, Keys.VK_F8, Keys.VK_DOWN,
|
||||
Keys.VK_3, Keys.VK_W, Keys.VK_A, Keys.VK_4, Keys.VK_Z, Keys.VK_S, Keys.VK_E, Keys.VK_SHIFT,
|
||||
Keys.VK_5, Keys.VK_R, Keys.VK_D, Keys.VK_6, Keys.VK_C, Keys.VK_F, Keys.VK_T, Keys.VK_X,
|
||||
Keys.VK_7, Keys.VK_Y, Keys.VK_G, Keys.VK_8, Keys.VK_B, Keys.VK_H, Keys.VK_U, Keys.VK_V,
|
||||
Keys.VK_9, Keys.VK_I, Keys.VK_J, Keys.VK_0, Keys.VK_M, Keys.VK_K, Keys.VK_O, Keys.VK_N,
|
||||
null/*Keys.VK_PLUS*/, Keys.VK_P, Keys.VK_L, Keys.VK_MINUS, Keys.VK_PERIOD, null/*Keys.VK_COLON*/, null/*Keys.VK_AT*/, Keys.VK_COMMA,
|
||||
null/*Keys.VK_POUND*/, null/*TIMES*/, Keys.VK_SEMICOLON, Keys.VK_HOME, Keys.VK_SHIFT/*right*/, Keys.VK_EQUALS, Keys.VK_TILDE, Keys.VK_SLASH,
|
||||
Keys.VK_1, Keys.VK_LEFT, Keys.VK_CONTROL, Keys.VK_2, Keys.VK_SPACE, Keys.VK_ALT, Keys.VK_Q, null/*STOP*/,
|
||||
];
|
||||
|
||||
// CIA
|
||||
// TODO: https://www.c64-wiki.com/wiki/CIA
|
||||
|
||||
class CIA {
|
||||
regs = new Uint8Array(0x10);
|
||||
|
||||
reset() {
|
||||
this.regs.fill(0);
|
||||
}
|
||||
read(a : number) : number {
|
||||
return this.regs[a] | 0;
|
||||
}
|
||||
write(a : number, v : number) {
|
||||
this.regs[a] = v;
|
||||
}
|
||||
}
|
||||
|
||||
// VIC-II chip
|
||||
|
||||
class VIC_II {
|
||||
platform : C64;
|
||||
scanline : number = 0;
|
||||
regs = new Uint8Array(0x40); // 64 bytes
|
||||
cram = new Uint8Array(0x400); // color RAM
|
||||
pixels = new Uint8Array(numVisiblePixels); // output pixel buffer
|
||||
cycle : number = 0;
|
||||
vc : number = 0;
|
||||
vcbase : number = 0;
|
||||
rc : number = 0;
|
||||
vmli : number = 0; // TODO: we don't use
|
||||
|
||||
constructor(platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
reset() {
|
||||
this.regs.fill(0);
|
||||
this.cram.fill(0);
|
||||
this.vc = 0;
|
||||
this.vcbase = 0;
|
||||
this.rc = 0;
|
||||
this.vmli = 0;
|
||||
}
|
||||
read(a : number) : number {
|
||||
switch (a) {
|
||||
case 0x12: return this.scanline;
|
||||
}
|
||||
return this.regs[a] | 0;
|
||||
}
|
||||
write(a : number, v : number) {
|
||||
this.regs[a] = v;
|
||||
}
|
||||
setScanline(sl : number) {
|
||||
this.scanline = sl;
|
||||
// interrupt?
|
||||
if (sl == (this.regs[0x12] | ((this.regs[0x11]&0x80)<<1))) {
|
||||
this.regs[0x19] |= 0x81;
|
||||
}
|
||||
// reset pixel clock
|
||||
this.cycle = 0;
|
||||
// reset VCBASE
|
||||
if (sl < firstScanline) this.vcbase = 0;
|
||||
// clear pixel buffer w/ background
|
||||
this.pixels.fill(this.regs[0x21]);
|
||||
}
|
||||
saveState() {
|
||||
return {
|
||||
regs: this.regs.slice(0),
|
||||
cram: this.cram.slice(0)
|
||||
};
|
||||
}
|
||||
loadState(s) {
|
||||
for (let i=0; i<32; i++)
|
||||
this.write(i, s.regs[i]);
|
||||
this.cram.set(s.cram);
|
||||
}
|
||||
c_access() : number {
|
||||
let vm = this.regs[0x18];
|
||||
let vadr = (this.vc & 0x3ff) | ((vm & 0xf0) << 6);
|
||||
//this.platform.profiler && this.platform.profiler.logRead(vadr);
|
||||
return this.platform.readVRAMAddress(vadr) | (this.cram[vadr & 0x3ff] << 8);
|
||||
}
|
||||
g_access(data : number) : number {
|
||||
let cb = this.regs[0x18];
|
||||
let vadr = (this.rc & 7) | ((data & 0xff) << 3) | ((cb & 0xe) << 10);
|
||||
this.vc = (this.vc + 1) & 0x3ff;
|
||||
//this.vcbase = (this.vcbase + 1) & 0x3ff;
|
||||
//this.platform.profiler && this.platform.profiler.logRead(vadr);
|
||||
return this.platform.readVRAMAddress(vadr);
|
||||
}
|
||||
getx() : number {
|
||||
// TODO: left border 0x1f, 0x18
|
||||
return (this.cycle - 16)*8 + numBorderPixels;
|
||||
}
|
||||
clockPulse() {
|
||||
switch (this.cycle) {
|
||||
case 14:
|
||||
this.vc = this.vcbase;
|
||||
//console.log("VC ->",hex(this.vc));
|
||||
this.vmli = 0;
|
||||
break;
|
||||
case 58:
|
||||
if (this.rc == 7) {
|
||||
this.vcbase = this.vc;
|
||||
//console.log("VCBASE",hex(this.vc));
|
||||
// TODO
|
||||
}
|
||||
this.rc = (this.rc + 1) & 7;
|
||||
break;
|
||||
}
|
||||
let x = this.getx();
|
||||
if (this.cycle >= 16 && this.cycle < 56) {
|
||||
var cdata = this.c_access();
|
||||
let gdata = this.g_access(cdata);
|
||||
let fgcol = cdata >> 8;
|
||||
let bgcol = this.regs[0x21];
|
||||
for (let i=0; i<8; i++) {
|
||||
this.pixels[x+i] = (gdata & 0x80) ? fgcol : bgcol;
|
||||
gdata <<= 1;
|
||||
}
|
||||
}
|
||||
this.cycle++;
|
||||
}
|
||||
doDMA() {
|
||||
// TODO
|
||||
//let bus = this.platform.bus;
|
||||
//let profiler = this.platform.profiler;
|
||||
if (true) { //this.isDMAEnabled()) {
|
||||
}
|
||||
return 0; //TODO
|
||||
}
|
||||
doInterrupt() : boolean {
|
||||
return false; // TODO
|
||||
}
|
||||
static stateToLongString(state) : string {
|
||||
let s = "";
|
||||
s += dumpRAM(state.regs, 0, 64);
|
||||
//s += "\nScanline: " + state.scanline;
|
||||
//s += "\n DLL: $" + hex((state.regs[0x0c] << 8) + state.regs[0x10],4) + " @ $" + hex(state.dll,4);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
const cpuFrequency = 10227273; // NTSC
|
||||
const linesPerFrame = 263; // (6567R8)
|
||||
const firstScanline = 0x30;
|
||||
const lastScanline = 0xf7;
|
||||
const numVisibleLines = 235; // (6567R8)
|
||||
const numScreenPixels = 320;
|
||||
const numBorderPixels = 16;
|
||||
const numVisiblePixels = numScreenPixels+numBorderPixels*2; // (6567R8)
|
||||
const cpuClocksPerLine = 65; // 65*8 (6567R8)
|
||||
const cpuClocksPreDMA = 7; // TODO
|
||||
const audioOversample = 4;
|
||||
const audioSampleRate = linesPerFrame*60*audioOversample;
|
||||
|
||||
export class C64 extends BasicMachine implements RasterFrameBased {
|
||||
|
||||
cpuFrequency = cpuFrequency;
|
||||
canvasWidth = numVisiblePixels;
|
||||
overscan = true;
|
||||
numTotalScanlines = linesPerFrame;
|
||||
numVisibleScanlines = numVisibleLines;
|
||||
defaultROMSize = 0x6000;
|
||||
cpuCyclesPerLine = 65; // 65*8 (6567R8)
|
||||
cpuCyclesPreDMA = 7; // TODO
|
||||
sampleRate = audioSampleRate;
|
||||
|
||||
cpu : MOS6502;
|
||||
ram : Uint8Array;
|
||||
rom : Uint8Array; // cartridge ROM
|
||||
bios : Uint8Array;
|
||||
vic : VIC_II = new VIC_II(this);
|
||||
cia1 : CIA = new CIA();
|
||||
cia2 : CIA = new CIA();
|
||||
probeDMABus;
|
||||
lastFrameCycles : number = 0;
|
||||
|
||||
enableKERNAL : boolean = true;
|
||||
enableIO : boolean = true;
|
||||
enableBASIC : boolean = true;
|
||||
enableCART : boolean = true;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.cpu = new MOS6502();
|
||||
this.ram = new Uint8Array(0x10000); // 64 KB, of course
|
||||
this.bios = new lzgmini().decode(stringToByteArray(atob(C64_BIOS_LZG))); // BASIC-CHAR-KERNAL ROMs
|
||||
this.connectCPUMemoryBus(this);
|
||||
this.probeDMABus = this.probeIOBus(this);
|
||||
this.handler = newKeyboardHandler(this.inputs, C64_KEYCODE_MAP, this.getKeyboardFunction(), true);
|
||||
}
|
||||
|
||||
read = newAddressDecoder([
|
||||
[0x8000, 0x9fff, 0x1fff, (a) => { return this.enableCART ? (this.rom&&this.rom[a]) : this.ram[a|0x8000]; }], // CART ROM
|
||||
[0xa000, 0xbfff, 0x1fff, (a) => { return this.enableBASIC ? this.bios[a] : this.ram[a|0xa000]; }], // BASIC ROM
|
||||
[0xd000, 0xdfff, 0xfff, (a) => { return !this.enableIO ? this.bios[a + 0x2000] : this.readIO(a) }], // CHAR ROM
|
||||
[0xe000, 0xffff, 0x1fff, (a) => { return this.enableKERNAL ? this.bios[a + 0x3000] : this.ram[a|0xe000]; }], // KERNAL ROM
|
||||
[0x0000, 0xffff, 0xffff, (a) => { return this.ram[a]; }],
|
||||
]);
|
||||
|
||||
write = newAddressDecoder([
|
||||
[0x0000, 0x0001, 0xffff, (a,v) => { this.write6510(a,v); }],
|
||||
[0xd000, 0xdfff, 0xfff, (a,v) => { this.writeIO(a,v); }],
|
||||
[0x0000, 0xffff, 0xffff, (a,v) => { this.ram[a] = v; }],
|
||||
]);
|
||||
|
||||
getKeyboardMap() { return null; /* TODO: C64_KEYCODE_MAP;*/ }
|
||||
|
||||
// http://map.grauw.nl/articles/keymatrix.php
|
||||
// https://codebase64.org/doku.php?id=base:reading_the_keyboard
|
||||
// http://www.c64os.com/post?p=45
|
||||
// https://www.c64-wiki.com/wiki/Keyboard
|
||||
|
||||
getKeyboardFunction() {
|
||||
return (o,key,code,flags) => {
|
||||
//console.log(o,key,code,flags);
|
||||
var keymap = C64_KEYMATRIX_NOSHIFT;
|
||||
for (var i=0; i<keymap.length; i++) {
|
||||
if (keymap[i] && keymap[i].c == key) {
|
||||
let row = i >> 3;
|
||||
let col = i & 7;
|
||||
// is column selected?
|
||||
if (flags & KeyFlags.KeyDown) {
|
||||
this.inputs[KEYBOARD_ROW_0 + row] |= (1<<col);
|
||||
} else if (flags & KeyFlags.KeyUp) {
|
||||
this.inputs[KEYBOARD_ROW_0 + row] &= ~(1<<col);
|
||||
}
|
||||
//console.log(key, row, col, hex(this.inputs[KEYBOARD_ROW_0 + row]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: https://www.c64-wiki.com/wiki/Zeropage
|
||||
write6510(a:number, v:number) {
|
||||
this.ram[a] = v;
|
||||
switch (a) {
|
||||
case 0:
|
||||
this.enableBASIC = (v & 0x1) != 0; // LORAM
|
||||
this.enableKERNAL = (v & 0x2) != 0; // HIRAM
|
||||
this.enableIO = (v & 0x4) != 0; // CHAREN
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
writeIO(a:number, v:number) {
|
||||
//this.profiler && this.profiler.logWrite(a+0xd000);
|
||||
var page = (a>>8);
|
||||
switch (page) {
|
||||
case 0x0: case 0x1: case 0x2: case 0x3:
|
||||
this.vic.write(a & 0x3f, v);
|
||||
break;
|
||||
case 0x8: case 0x9: case 0xa: case 0xb:
|
||||
this.vic.cram[a & 0x3ff] = v;
|
||||
break;
|
||||
case 0xc:
|
||||
this.cia1.write(a & 0xf, v);
|
||||
break;
|
||||
case 0xd:
|
||||
this.cia2.write(a & 0xf, v);
|
||||
break;
|
||||
default:
|
||||
return; //TODO
|
||||
}
|
||||
}
|
||||
|
||||
readIO(a:number) : number {
|
||||
//this.profiler && this.profiler.logRead(a+0xd000);
|
||||
var page = (a>>8);
|
||||
switch (page) {
|
||||
case 0x0: case 0x1: case 0x2: case 0x3: // VIC-II
|
||||
return this.vic.read(a & 0x3f);
|
||||
case 0x8: case 0x9: case 0xa: case 0xb:
|
||||
return this.vic.cram[a & 0x3ff];
|
||||
case 0xc:
|
||||
switch (a & 0xf) {
|
||||
// scan keyboard matrix for CIA 1
|
||||
// CIA 1 regs: [00, 00, ff, 00] or [ff, 00, ff, 00]
|
||||
// http://www.c64os.com/post?p=45
|
||||
case 0x1:
|
||||
let cols = 0;
|
||||
for (let i=0; i<8; i++)
|
||||
if ((this.cia1.regs[0] & (1<<i)) == 0)
|
||||
cols |= this.inputs[KEYBOARD_ROW_0 + i];
|
||||
//if (cols) console.log(this.cia1.regs[0], cols);
|
||||
return cols ^ 0xff;
|
||||
}
|
||||
return this.cia1.read(a & 0xf);
|
||||
case 0xd:
|
||||
return this.cia2.read(a & 0xf);
|
||||
default:
|
||||
return 0; //TODO
|
||||
}
|
||||
}
|
||||
|
||||
readVRAMAddress(a:number) {
|
||||
let bank = ~this.cia2.regs[0] & 3; // CIA 2 port A
|
||||
a &= 0x3fff; // VIC II sees 14 bits
|
||||
if ((a >= 0x1000 && a < 0x2000) && (bank == 0 || bank == 2)) return this.bios[0x1000 + a]; // CHAR ROM
|
||||
else return this.ram[a];
|
||||
}
|
||||
|
||||
advanceFrame(trap) : number {
|
||||
var idata = this.pixels;
|
||||
var iofs = 0;
|
||||
var vicClocks = cpuClocksPreDMA;
|
||||
var fc = 0;
|
||||
this.probe.logNewFrame();
|
||||
// visible lines
|
||||
for (var sl=0; sl<linesPerFrame; sl++) {
|
||||
this.vic.setScanline(sl);
|
||||
// interrupt?
|
||||
// TODO: https://www.c64-wiki.com/wiki/Raster_interrupt
|
||||
if (this.vic.regs[0x19] & 0x1) {
|
||||
this.vic.regs[0x19] &= 0x7e;
|
||||
//TODO: this.cpu.IRQ();
|
||||
//this.profiler && this.profiler.logInterrupt(0x1);
|
||||
}
|
||||
// is this scanline visible?
|
||||
let visible = sl >= firstScanline && sl <= lastScanline;
|
||||
// iterate CPU with free clocks
|
||||
while (vicClocks > 0) {
|
||||
// next CPU clock
|
||||
vicClocks--;
|
||||
if (trap && trap()) {
|
||||
trap = null;
|
||||
sl = 999;
|
||||
break;
|
||||
}
|
||||
if (visible) this.vic.clockPulse(); // VIC first
|
||||
this.advanceCPU();
|
||||
fc++;
|
||||
}
|
||||
vicClocks += cpuClocksPerLine;
|
||||
if (visible) {
|
||||
// do DMA for scanline?
|
||||
vicClocks -= this.vic.doDMA();
|
||||
}
|
||||
// copy line to frame buffer
|
||||
if (idata && sl > firstScanline-24 && iofs < idata.length) {
|
||||
for (var i=0; i<numVisiblePixels; i++) {
|
||||
idata[iofs++] = COLORS_RGBA[this.vic.pixels[i]];
|
||||
}
|
||||
}
|
||||
this.probe.logNewScanline();
|
||||
}
|
||||
return this.lastFrameCycles = fc;
|
||||
}
|
||||
|
||||
getRasterX() { return this.lastFrameCycles % this.cpuCyclesPerLine; }
|
||||
getRasterY() { return Math.floor(this.lastFrameCycles / this.cpuCyclesPerLine); }
|
||||
|
||||
loadROM(data) {
|
||||
// BASIC stub?
|
||||
if (data[0] == 0x01 && data[1] == 0x08) {
|
||||
this.ram.set(data.slice(2), 0x801);
|
||||
this.enableCART = false;
|
||||
// hack BASIC interpreter loop (TODO?)
|
||||
var prgstart = 0x80a; //TODO (this.debugSymbols && this.debugSymbols.symbolmap['__MAIN_START__']) || 0x80a;
|
||||
this.bios[0x3f9b] = 0x4c;
|
||||
this.bios[0x3f9c] = prgstart & 0xff;
|
||||
this.bios[0x3f9d] = prgstart >> 8;
|
||||
} else {
|
||||
// assume cartridge ROM
|
||||
this.rom = padBytes(data, this.defaultROMSize);
|
||||
}
|
||||
this.reset();
|
||||
}
|
||||
|
||||
// BASIC (0x2000 bytes)
|
||||
// CHAR (0x1000 bytes)
|
||||
// KERNAL (0x2000 bytes)
|
||||
loadBIOS(data) {
|
||||
this.bios = padBytes(data, 0x5000);
|
||||
this.reset();
|
||||
}
|
||||
|
||||
reset() {
|
||||
super.reset();
|
||||
this.vic.reset();
|
||||
this.cia1.reset();
|
||||
this.cia2.reset();
|
||||
this.write6510(0, 0xff);
|
||||
this.inputs.fill(0x0);
|
||||
}
|
||||
|
||||
// TODO: don't log if profiler active
|
||||
readConst(addr : number) {
|
||||
return this.read(addr) | 0;
|
||||
}
|
||||
|
||||
loadState(state) {
|
||||
this.cpu.loadState(state.c);
|
||||
this.ram.set(state.ram);
|
||||
this.vic.loadState(state.vic);
|
||||
this.loadControlsState(state);
|
||||
}
|
||||
saveState() {
|
||||
return {
|
||||
c:this.getCPUState(),
|
||||
ram:this.ram.slice(0),
|
||||
vic:this.vic.saveState(),
|
||||
inputs:this.inputs.slice(0)
|
||||
};
|
||||
}
|
||||
|
||||
loadControlsState(state) {
|
||||
this.inputs.set(state.inputs);
|
||||
}
|
||||
|
||||
saveControlsState() {
|
||||
return {
|
||||
inputs:this.inputs.slice(0)
|
||||
};
|
||||
}
|
||||
|
||||
getCPUState() {
|
||||
return this.cpu.saveState();
|
||||
}
|
||||
|
||||
getRasterScanline() {
|
||||
return this.vic.scanline;
|
||||
}
|
||||
|
||||
getDebugCategories() {
|
||||
return ['CPU','Stack','VIC-II'];
|
||||
}
|
||||
getDebugInfo(category, state) {
|
||||
switch (category) {
|
||||
case 'VIC-II': return VIC_II.stateToLongString(state.vic);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const VIC_NTSC_RGB = [
|
||||
0x000000,
|
||||
0xFFFFFF,
|
||||
0x880000,
|
||||
0xAAFFEE,
|
||||
0xCC44CC,
|
||||
0x00CC55,
|
||||
0x00CC55,
|
||||
0xEEEE77,
|
||||
0xDD8855,
|
||||
0x664400,
|
||||
0xFF7777,
|
||||
0x333333,
|
||||
0x777777,
|
||||
0xAAFF66,
|
||||
0x0088FF,
|
||||
0xBBBBBB,
|
||||
];
|
||||
|
||||
var COLORS_RGBA = new Uint32Array(256);
|
||||
var COLORS_WEB = [];
|
||||
for (var i=0; i<256; i++) {
|
||||
COLORS_RGBA[i] = rgb2bgr(VIC_NTSC_RGB[i & 15]) | 0xff000000;
|
||||
COLORS_WEB[i] = "#"+hex(VIC_NTSC_RGB[i & 15],6);
|
||||
}
|
||||
|
||||
// bank-switching table
|
||||
// TODO: https://www.c64-wiki.com/wiki/Bank_Switching
|
||||
|
||||
enum BankSwitchFlags {
|
||||
LORAM=1, HIRAM=2, CHAREN=4, _GAME=8, _EXROM=16
|
||||
};
|
||||
|
||||
enum Bank {
|
||||
NONE, RAM, IO, CART_ROM_LO, CART_ROM_HI, CHAR_ROM, KERN_ROM, BASIC_ROM
|
||||
};
|
||||
|
||||
function getBankMapping(flags:number, region:number) : Bank {
|
||||
return BANK_TABLE[flags & 0x1f][region];
|
||||
};
|
||||
|
||||
const BANK_TABLE : Bank[][] = [
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.CART_ROM_HI, Bank.RAM, Bank.CHAR_ROM, Bank.KERN_ROM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.CART_ROM_LO, Bank.CART_ROM_HI, Bank.RAM, Bank.CHAR_ROM, Bank.KERN_ROM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.IO, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.CART_ROM_HI, Bank.RAM, Bank.IO, Bank.KERN_ROM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.CART_ROM_LO, Bank.CART_ROM_HI, Bank.RAM, Bank.IO, Bank.KERN_ROM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.CHAR_ROM, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.CHAR_ROM, Bank.KERN_ROM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.CART_ROM_LO, Bank.BASIC_ROM, Bank.RAM, Bank.CHAR_ROM, Bank.KERN_ROM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.IO, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.IO, Bank.KERN_ROM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.CART_ROM_LO, Bank.BASIC_ROM, Bank.RAM, Bank.IO, Bank.KERN_ROM ],
|
||||
[ Bank.RAM, Bank.NONE, Bank.CART_ROM_LO, Bank.NONE, Bank.NONE, Bank.IO, Bank.CART_ROM_HI ],
|
||||
[ Bank.RAM, Bank.NONE, Bank.CART_ROM_LO, Bank.NONE, Bank.NONE, Bank.IO, Bank.CART_ROM_HI ],
|
||||
[ Bank.RAM, Bank.NONE, Bank.CART_ROM_LO, Bank.NONE, Bank.NONE, Bank.IO, Bank.CART_ROM_HI ],
|
||||
[ Bank.RAM, Bank.NONE, Bank.CART_ROM_LO, Bank.NONE, Bank.NONE, Bank.IO, Bank.CART_ROM_HI ],
|
||||
[ Bank.RAM, Bank.NONE, Bank.CART_ROM_LO, Bank.NONE, Bank.NONE, Bank.IO, Bank.CART_ROM_HI ],
|
||||
[ Bank.RAM, Bank.NONE, Bank.CART_ROM_LO, Bank.NONE, Bank.NONE, Bank.IO, Bank.CART_ROM_HI ],
|
||||
[ Bank.RAM, Bank.NONE, Bank.CART_ROM_LO, Bank.NONE, Bank.NONE, Bank.IO, Bank.CART_ROM_HI ],
|
||||
[ Bank.RAM, Bank.NONE, Bank.CART_ROM_LO, Bank.NONE, Bank.NONE, Bank.IO, Bank.CART_ROM_HI ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.CHAR_ROM, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.CHAR_ROM, Bank.KERN_ROM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.BASIC_ROM, Bank.RAM, Bank.CHAR_ROM, Bank.KERN_ROM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.IO, Bank.RAM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.RAM, Bank.IO, Bank.KERN_ROM ],
|
||||
[ Bank.RAM, Bank.RAM, Bank.RAM, Bank.BASIC_ROM, Bank.RAM, Bank.IO, Bank.KERN_ROM ],
|
||||
];
|
||||
|
||||
// https://github.com/MEGA65/open-roms
|
||||
var C64_BIOS_LZG = `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
Line truncated
|
||||
|
||||
//// WASM Machine
|
||||
|
||||
import { Machine, BaseWASMMachine } from "../common/baseplatform";
|
||||
import { TrapCondition } from "../common/devices";
|
||||
|
||||
export class C64_WASMMachine extends BaseWASMMachine implements Machine {
|
||||
export class C64_WASMMachine extends BaseWASMMachine implements Machine, Probeable {
|
||||
|
||||
numTotalScanlines = 312;
|
||||
cpuCyclesPerLine = 63;
|
||||
|
||||
prgstart : number;
|
||||
joymask0 = 0;
|
||||
@@ -616,9 +65,18 @@ export class C64_WASMMachine extends BaseWASMMachine implements Machine {
|
||||
this.exports.machine_tick(this.sys);
|
||||
}
|
||||
}
|
||||
// TODO: shouldn't we return here @ start of frame?
|
||||
// and stop probing
|
||||
}
|
||||
advanceFrame(trap: TrapCondition) : number {
|
||||
return super.advanceFrameClock(trap, 19656+295); // TODO: can we sync with VSYNC?
|
||||
// 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);
|
||||
@@ -691,4 +149,5 @@ export class C64_WASMMachine extends BaseWASMMachine implements Machine {
|
||||
}
|
||||
this.exports.c64_joystick(this.sys, this.joymask0, this.joymask1);
|
||||
}
|
||||
|
||||
}
|
||||
+9
-1
@@ -11,6 +11,9 @@ import { TrapCondition } from "../common/devices";
|
||||
|
||||
export class ZX_WASMMachine extends BaseWASMMachine implements Machine {
|
||||
|
||||
numTotalScanlines = 312;
|
||||
cpuCyclesPerLine = 224;
|
||||
|
||||
joymask0 = 0;
|
||||
|
||||
reset() {
|
||||
@@ -34,7 +37,12 @@ export class ZX_WASMMachine extends BaseWASMMachine implements Machine {
|
||||
}
|
||||
}
|
||||
advanceFrame(trap: TrapCondition) : number {
|
||||
return super.advanceFrameClock(trap, Math.floor(1000000 / 50)); // TODO: use ticks, not msec
|
||||
//var scanline = this.exports.machine_get_raster_line(this.sys);
|
||||
var probing = this.probe != null;
|
||||
if (probing) this.exports.machine_reset_probe_buffer();
|
||||
var clocks = super.advanceFrameClock(trap, Math.floor(1000000 / 50)); // TODO: use ticks, not msec
|
||||
if (probing) this.copyProbeData();
|
||||
return clocks;
|
||||
}
|
||||
/*
|
||||
z80_tick_t tick_cb; // 0
|
||||
|
||||
+1
-13
@@ -1,5 +1,5 @@
|
||||
|
||||
import { C64, C64_WASMMachine } from "../machine/c64";
|
||||
import { C64_WASMMachine } from "../machine/c64";
|
||||
import { Platform, Base6502MachinePlatform, getToolForFilename_6502, getOpcodeMetadata_6502 } from "../common/baseplatform";
|
||||
import { PLATFORMS } from "../common/emu";
|
||||
|
||||
@@ -37,17 +37,6 @@ const C64_MEMORY_MAP = { main:[
|
||||
{name:'KERNAL ROM', start:0xe000,size:0x2000,type:'rom'},
|
||||
] }
|
||||
|
||||
// native C64 platform (NOT USED)
|
||||
class C64Platform extends Base6502MachinePlatform<C64> implements Platform {
|
||||
|
||||
newMachine() { return new C64(); }
|
||||
getPresets() { return C64_PRESETS; }
|
||||
getDefaultExtension() { return ".c"; };
|
||||
readAddress(a) { return this.machine.readConst(a); }
|
||||
loadBIOS(bios) { this.machine.loadBIOS(bios); }
|
||||
getMemoryMap() { return C64_MEMORY_MAP; }
|
||||
}
|
||||
|
||||
// WASM C64 platform
|
||||
class C64WASMPlatform extends Base6502MachinePlatform<C64_WASMMachine> implements Platform {
|
||||
|
||||
@@ -76,4 +65,3 @@ class C64WASMPlatform extends Base6502MachinePlatform<C64_WASMMachine> implement
|
||||
|
||||
PLATFORMS['c64'] = C64WASMPlatform;
|
||||
PLATFORMS['c64.wasm'] = C64WASMPlatform;
|
||||
PLATFORMS['c64.js'] = C64Platform;
|
||||
Reference in new issue
Block a user