mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-12-21 21:29:17 +00:00
moved ProbeRecorder to own module
This commit is contained in:
parent
8338c3a3d7
commit
02cb20ec87
@ -10,7 +10,7 @@ import { Z80 } from "./cpu/ZilogZ80";
|
||||
import { Bus, Resettable, FrameBased, VideoSource, SampledAudioSource, AcceptsROM, AcceptsBIOS, AcceptsKeyInput, SavesState, SavesInputState, HasCPU, HasSerialIO, SerialIOInterface, AcceptsJoyInput } from "./devices";
|
||||
import { Probeable, RasterFrameBased, AcceptsPaddleInput } from "./devices";
|
||||
import { SampledAudio } from "./audio";
|
||||
import { ProbeRecorder } from "./recorder";
|
||||
import { ProbeRecorder } from "./probe";
|
||||
import { BaseWASMMachine } from "./wasmplatform";
|
||||
import { CPU6809 } from "./cpu/6809";
|
||||
import { _MOS6502 } from "./cpu/MOS6502";
|
||||
|
160
src/common/probe.ts
Normal file
160
src/common/probe.ts
Normal file
@ -0,0 +1,160 @@
|
||||
|
||||
import { Probeable, ProbeAll } from "./devices";
|
||||
|
||||
export enum ProbeFlags {
|
||||
CLOCKS = 0x00000000,
|
||||
EXECUTE = 0x01000000,
|
||||
HAS_VALUE = 0x10000000,
|
||||
MEM_READ = 0x12000000,
|
||||
MEM_WRITE = 0x13000000,
|
||||
IO_READ = 0x14000000,
|
||||
IO_WRITE = 0x15000000,
|
||||
VRAM_READ = 0x16000000,
|
||||
VRAM_WRITE= 0x17000000,
|
||||
INTERRUPT = 0x08000000,
|
||||
ILLEGAL = 0x09000000,
|
||||
SP_PUSH = 0x0a000000,
|
||||
SP_POP = 0x0b000000,
|
||||
SCANLINE = 0x7e000000,
|
||||
FRAME = 0x7f000000,
|
||||
}
|
||||
|
||||
class ProbeFrame {
|
||||
data : Uint32Array;
|
||||
len : number;
|
||||
}
|
||||
|
||||
export class ProbeRecorder implements ProbeAll {
|
||||
|
||||
m : Probeable; // machine to probe
|
||||
buf : Uint32Array; // buffer
|
||||
idx : number = 0; // index into buffer
|
||||
sl : number = 0; // scanline
|
||||
cur_sp = -1; // last stack pointer
|
||||
singleFrame : boolean = true; // clear between frames
|
||||
|
||||
constructor(m:Probeable, buflen?:number) {
|
||||
this.m = m;
|
||||
this.reset(buflen || 0x100000);
|
||||
}
|
||||
start() {
|
||||
this.m.connectProbe(this);
|
||||
}
|
||||
stop() {
|
||||
this.m.connectProbe(null);
|
||||
}
|
||||
reset(newbuflen? : number) {
|
||||
if (newbuflen) this.buf = new Uint32Array(newbuflen);
|
||||
this.sl = 0;
|
||||
this.cur_sp = -1;
|
||||
this.clear();
|
||||
}
|
||||
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;
|
||||
this.buf[this.idx++] = a;
|
||||
}
|
||||
relog(a:number) {
|
||||
this.buf[this.idx-1] = a;
|
||||
}
|
||||
lastOp() {
|
||||
if (this.idx > 0)
|
||||
return this.buf[this.idx-1] & 0xff000000;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
lastAddr() {
|
||||
if (this.idx > 0)
|
||||
return this.buf[this.idx-1] & 0xffffff;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
addLogBuffer(src: Uint32Array) {
|
||||
if (this.idx + src.length > this.buf.length) {
|
||||
src = src.slice(0, this.buf.length - this.idx);
|
||||
}
|
||||
this.buf.set(src, this.idx);
|
||||
this.idx += src.length;
|
||||
}
|
||||
logClocks(clocks:number) {
|
||||
clocks |= 0;
|
||||
if (clocks > 0) {
|
||||
if (this.lastOp() == ProbeFlags.CLOCKS)
|
||||
this.relog((this.lastAddr() + clocks) | ProbeFlags.CLOCKS); // coalesce clocks
|
||||
else
|
||||
this.log(clocks | ProbeFlags.CLOCKS);
|
||||
}
|
||||
}
|
||||
logNewScanline() {
|
||||
this.log(ProbeFlags.SCANLINE);
|
||||
this.sl++;
|
||||
}
|
||||
logNewFrame() {
|
||||
this.log(ProbeFlags.FRAME);
|
||||
this.sl = 0;
|
||||
if (this.singleFrame) this.clear();
|
||||
}
|
||||
logExecute(address:number, SP:number) {
|
||||
// record stack pushes/pops (from last instruction)
|
||||
if (this.cur_sp !== SP) {
|
||||
if (SP < this.cur_sp) {
|
||||
this.log(ProbeFlags.SP_PUSH | SP);
|
||||
}
|
||||
if (SP > this.cur_sp) {
|
||||
this.log(ProbeFlags.SP_POP | SP);
|
||||
}
|
||||
this.cur_sp = SP;
|
||||
}
|
||||
this.log(address | ProbeFlags.EXECUTE);
|
||||
}
|
||||
logInterrupt(type:number) {
|
||||
this.log(type | ProbeFlags.INTERRUPT);
|
||||
}
|
||||
logValue(address:number, value:number, op:number) {
|
||||
this.log((address & 0xffff) | ((value & 0xff)<<16) | op);
|
||||
}
|
||||
logRead(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.MEM_READ);
|
||||
}
|
||||
logWrite(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.MEM_WRITE);
|
||||
}
|
||||
logIORead(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.IO_READ);
|
||||
}
|
||||
logIOWrite(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.IO_WRITE);
|
||||
}
|
||||
logVRAMRead(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.VRAM_READ);
|
||||
}
|
||||
logVRAMWrite(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.VRAM_WRITE);
|
||||
}
|
||||
logIllegal(address:number) {
|
||||
this.log(address | ProbeFlags.ILLEGAL);
|
||||
}
|
||||
countEvents(op : number) : number {
|
||||
var count = 0;
|
||||
for (var i=0; i<this.idx; i++) {
|
||||
if ((this.buf[i] & 0xff000000) == op)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
countClocks() : number {
|
||||
var count = 0;
|
||||
for (var i=0; i<this.idx; i++) {
|
||||
if ((this.buf[i] & 0xff000000) == ProbeFlags.CLOCKS)
|
||||
count += this.buf[i] & 0xffff;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
@ -146,164 +146,3 @@ export class StateRecorderImpl implements EmuRecorder {
|
||||
}
|
||||
}
|
||||
|
||||
/////
|
||||
|
||||
import { Probeable, ProbeAll } from "./devices";
|
||||
|
||||
export enum ProbeFlags {
|
||||
CLOCKS = 0x00000000,
|
||||
EXECUTE = 0x01000000,
|
||||
HAS_VALUE = 0x10000000,
|
||||
MEM_READ = 0x12000000,
|
||||
MEM_WRITE = 0x13000000,
|
||||
IO_READ = 0x14000000,
|
||||
IO_WRITE = 0x15000000,
|
||||
VRAM_READ = 0x16000000,
|
||||
VRAM_WRITE= 0x17000000,
|
||||
INTERRUPT = 0x08000000,
|
||||
ILLEGAL = 0x09000000,
|
||||
SP_PUSH = 0x0a000000,
|
||||
SP_POP = 0x0b000000,
|
||||
SCANLINE = 0x7e000000,
|
||||
FRAME = 0x7f000000,
|
||||
}
|
||||
|
||||
class ProbeFrame {
|
||||
data : Uint32Array;
|
||||
len : number;
|
||||
}
|
||||
|
||||
export class ProbeRecorder implements ProbeAll {
|
||||
|
||||
m : Probeable; // machine to probe
|
||||
buf : Uint32Array; // buffer
|
||||
idx : number = 0; // index into buffer
|
||||
sl : number = 0; // scanline
|
||||
cur_sp = -1; // last stack pointer
|
||||
singleFrame : boolean = true; // clear between frames
|
||||
|
||||
constructor(m:Probeable, buflen?:number) {
|
||||
this.m = m;
|
||||
this.reset(buflen || 0x100000);
|
||||
}
|
||||
start() {
|
||||
this.m.connectProbe(this);
|
||||
}
|
||||
stop() {
|
||||
this.m.connectProbe(null);
|
||||
}
|
||||
reset(newbuflen? : number) {
|
||||
if (newbuflen) this.buf = new Uint32Array(newbuflen);
|
||||
this.sl = 0;
|
||||
this.cur_sp = -1;
|
||||
this.clear();
|
||||
}
|
||||
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;
|
||||
this.buf[this.idx++] = a;
|
||||
}
|
||||
relog(a:number) {
|
||||
this.buf[this.idx-1] = a;
|
||||
}
|
||||
lastOp() {
|
||||
if (this.idx > 0)
|
||||
return this.buf[this.idx-1] & 0xff000000;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
lastAddr() {
|
||||
if (this.idx > 0)
|
||||
return this.buf[this.idx-1] & 0xffffff;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
addLogBuffer(src: Uint32Array) {
|
||||
if (this.idx + src.length > this.buf.length) {
|
||||
src = src.slice(0, this.buf.length - this.idx);
|
||||
}
|
||||
this.buf.set(src, this.idx);
|
||||
this.idx += src.length;
|
||||
}
|
||||
logClocks(clocks:number) {
|
||||
clocks |= 0;
|
||||
if (clocks > 0) {
|
||||
if (this.lastOp() == ProbeFlags.CLOCKS)
|
||||
this.relog((this.lastAddr() + clocks) | ProbeFlags.CLOCKS); // coalesce clocks
|
||||
else
|
||||
this.log(clocks | ProbeFlags.CLOCKS);
|
||||
}
|
||||
}
|
||||
logNewScanline() {
|
||||
this.log(ProbeFlags.SCANLINE);
|
||||
this.sl++;
|
||||
}
|
||||
logNewFrame() {
|
||||
this.log(ProbeFlags.FRAME);
|
||||
this.sl = 0;
|
||||
if (this.singleFrame) this.clear();
|
||||
}
|
||||
logExecute(address:number, SP:number) {
|
||||
// record stack pushes/pops (from last instruction)
|
||||
if (this.cur_sp !== SP) {
|
||||
if (SP < this.cur_sp) {
|
||||
this.log(ProbeFlags.SP_PUSH | SP);
|
||||
}
|
||||
if (SP > this.cur_sp) {
|
||||
this.log(ProbeFlags.SP_POP | SP);
|
||||
}
|
||||
this.cur_sp = SP;
|
||||
}
|
||||
this.log(address | ProbeFlags.EXECUTE);
|
||||
}
|
||||
logInterrupt(type:number) {
|
||||
this.log(type | ProbeFlags.INTERRUPT);
|
||||
}
|
||||
logValue(address:number, value:number, op:number) {
|
||||
this.log((address & 0xffff) | ((value & 0xff)<<16) | op);
|
||||
}
|
||||
logRead(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.MEM_READ);
|
||||
}
|
||||
logWrite(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.MEM_WRITE);
|
||||
}
|
||||
logIORead(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.IO_READ);
|
||||
}
|
||||
logIOWrite(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.IO_WRITE);
|
||||
}
|
||||
logVRAMRead(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.VRAM_READ);
|
||||
}
|
||||
logVRAMWrite(address:number, value:number) {
|
||||
this.logValue(address, value, ProbeFlags.VRAM_WRITE);
|
||||
}
|
||||
logIllegal(address:number) {
|
||||
this.log(address | ProbeFlags.ILLEGAL);
|
||||
}
|
||||
countEvents(op : number) : number {
|
||||
var count = 0;
|
||||
for (var i=0; i<this.idx; i++) {
|
||||
if ((this.buf[i] & 0xff000000) == op)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
countClocks() : number {
|
||||
var count = 0;
|
||||
for (var i=0; i<this.idx; i++) {
|
||||
if ((this.buf[i] & 0xff000000) == ProbeFlags.CLOCKS)
|
||||
count += this.buf[i] & 0xffff;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { platform, compparams, current_project, projectWindows } from "../ui";
|
||||
import { hex, lpad, rpad } from "../../common/util";
|
||||
import { VirtualList } from "../../common/vlist";
|
||||
import { getMousePos, getVisibleEditorLineHeight, VirtualTextLine, VirtualTextScroller } from "../../common/emu";
|
||||
import { ProbeFlags, ProbeRecorder } from "../../common/recorder";
|
||||
import { ProbeFlags, ProbeRecorder } from "../../common/probe";
|
||||
import { BaseZ80MachinePlatform, BaseZ80Platform } from "../../common/baseplatform";
|
||||
|
||||
///
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { dumpRAM } from "../../common/emu";
|
||||
import { ProbeFlags } from "../../common/recorder";
|
||||
import { ProbeFlags } from "../../common/probe";
|
||||
import { hex } from "../../common/util";
|
||||
import { platform } from "../ui";
|
||||
import { ProjectView } from "./baseviews";
|
||||
|
@ -4,7 +4,7 @@ import { PLATFORMS, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeK
|
||||
import { hex, byteArrayToString } from "../common/util";
|
||||
import { CodeAnalyzer_nes } from "../common/analysis";
|
||||
import { SampleAudio } from "../common/audio";
|
||||
import { ProbeRecorder } from "../common/recorder";
|
||||
import { ProbeRecorder } from "../common/probe";
|
||||
import { NullProbe, Probeable, ProbeAll } from "../common/devices";
|
||||
import Mousetrap = require('mousetrap');
|
||||
import jsnes = require('../../jsnes');
|
||||
|
@ -4,7 +4,7 @@ import { PLATFORMS, dumpRAM, EmuHalt, RasterVideo, __createCanvas } from "../com
|
||||
import { hex, loadScript, lpad, tobin } from "../common/util";
|
||||
import { CodeAnalyzer_vcs } from "../common/analysis";
|
||||
import { disassemble6502 } from "../common/cpu/disasm6502";
|
||||
import { ProbeRecorder } from "../common/recorder";
|
||||
import { ProbeRecorder } from "../common/probe";
|
||||
import { NullProbe, ProbeAll } from "../common/devices";
|
||||
import { BaseMAME6502Platform } from "../common/mameplatform";
|
||||
|
||||
|
@ -3,7 +3,7 @@ import { Platform, BaseZ80Platform, Base6502Platform, Base6809Platform } from ".
|
||||
import { PLATFORMS, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, VectorVideo, Keys, makeKeycodeMap } from "../common/emu";
|
||||
import { hex, lzgmini, stringToByteArray, safe_extend } from "../common/util";
|
||||
import { MasterAudio, AY38910_Audio } from "../common/audio";
|
||||
import { ProbeRecorder } from "../common/recorder";
|
||||
import { ProbeRecorder } from "../common/probe";
|
||||
import { NullProbe, Probeable, ProbeAll } from "../common/devices";
|
||||
|
||||
// emulator from https://github.com/raz0red/jsvecx
|
||||
|
Loading…
Reference in New Issue
Block a user