vcs: scanline view, fixed analysis with jsr

This commit is contained in:
Steven Hugg 2021-04-05 12:11:38 -05:00
parent c5ccd4ff48
commit 8afad5571b
8 changed files with 98 additions and 20 deletions

View File

@ -198,6 +198,7 @@ TODO:
- show current tool for file
- download non-text incbin source file
- show hidden header files that only exist in Emscripten FS
can't modify/delete an include file if project doesn't compile
Probing
- probe log doesn't start @ reset

View File

@ -143,6 +143,8 @@ abstract class CodeAnalyzer6502 implements CodeAnalyzer {
break;
case 0x20: // JSR
// TODO: handle bare RTS case
minclocks += meta.minCycles;
maxclocks += meta.maxCycles;
this.traceInstructions(addr, minclocks, maxclocks, addr, constraints);
var result = this.jsrresult[addr];
if (result) {
@ -150,7 +152,8 @@ abstract class CodeAnalyzer6502 implements CodeAnalyzer {
maxclocks = result.maxclocks;
} else {
console.log("No JSR result!", hex(pc), hex(addr));
return;
minclocks = maxclocks;
//return;
}
break;
case 0x4c: // JMP
@ -160,7 +163,7 @@ abstract class CodeAnalyzer6502 implements CodeAnalyzer {
abort = true;
break;
case 0x60: // RTS
if (subaddr) { // TODO: 0 doesn't work
if (subaddr) { // TODO: 0 doesn't work
// TODO: combine with previous result
var result = this.jsrresult[subaddr];
if (!result) {

View File

@ -347,13 +347,15 @@ export class CodeProject {
}
// returns first listing in format [prefix].lst (TODO: could be better)
getListingForFile(path) : CodeListing {
getListingForFile(path: string) : CodeListing {
// ignore include files (TODO)
if (path.toLowerCase().endsWith('.h') || path.toLowerCase().endsWith('.inc'))
return;
var fnprefix = getFilenamePrefix(this.stripLocalPath(path));
var listings = this.getListings();
var onlyfile = null;
for (var lstfn in listings) {
onlyfile = lstfn;
if (getFilenamePrefix(lstfn) == fnprefix) {
return listings[lstfn];
}

View File

@ -303,6 +303,9 @@ function refreshWindowList() {
addWindowItem("#probelog", "Probe Log", () => {
return new Views.ProbeLogView();
});
addWindowItem("#scanlineio", "Scanline I/O", () => {
return new Views.ScanlineIOView();
});
addWindowItem("#symbolprobe", "Symbol Profiler", () => {
return new Views.ProbeSymbolView();
});

View File

@ -1128,6 +1128,8 @@ abstract class ProbeViewBase extends ProbeViewBaseBase {
}
}
// TODO: remove all 160/262 constants (in case of PAL)
abstract class ProbeBitmapViewBase extends ProbeViewBase {
imageData : ImageData;
@ -1314,6 +1316,70 @@ export class ProbeLogView extends ProbeViewBaseBase {
}
}
export class ScanlineIOView extends ProbeViewBaseBase {
vlist : VirtualTextScroller;
maindiv : HTMLElement;
recreateOnResize = true;
dumplines;
createDiv(parent : HTMLElement) {
this.vlist = new VirtualTextScroller(parent);
this.vlist.create(parent, 262, this.getMemoryLineAt.bind(this));
return this.vlist.maindiv;
}
getMemoryLineAt(row : number) : VirtualTextLine {
var s = lpad(row+"",3) + ' ';
var c = 'seg_code';
var line = (this.dumplines && this.dumplines[row]) || [];
for (var i=0; i<76; i++) {
var opaddr = line[i];
if (opaddr !== undefined) {
var addr = opaddr & 0xffff;
var op = op & 0xff000000;
if (op == ProbeFlags.EXECUTE) {
s += ',';
} else {
var v = hex(addr);
s += v;
i += v.length - 1;
}
} else {
s += (i==23) ? '|' : '.';
}
}
if (line[-1]) s += ' ' + line[-1]; // executing symbol
return {text:s, clas:c};
}
refresh() {
this.tick();
}
tick() {
const isz80 = platform instanceof BaseZ80MachinePlatform || platform instanceof BaseZ80Platform; // TODO?
// cache each line in frame
this.dumplines = {};
this.redraw((op,addr,col,row,clk,value) => {
var line = this.dumplines[row];
if (line == null) {
this.dumplines[row] = line = [];
}
switch (op) {
case ProbeFlags.EXECUTE:
var sym = platform.debugSymbols.addr2symbol[addr];
if (sym) line[-1] = sym;
break;
case ProbeFlags.MEM_WRITE:
case ProbeFlags.IO_READ:
case ProbeFlags.IO_WRITE:
case ProbeFlags.VRAM_READ:
case ProbeFlags.VRAM_WRITE:
line[col] = op | addr;
break;
}
});
this.vlist.refresh();
}
}
///
export class ProbeSymbolView extends ProbeViewBaseBase {

View File

@ -126,13 +126,13 @@ class VCSPlatform extends BasePlatform {
return Javatari.getOpcodeMetadata(opcode, offset);
}
getRasterPosition() : {x:number,y:number} {
getRasterPosition() : {x:number,y:number,clk:number} {
var clkfs = Javatari.room.console.getClocksFromFrameStart() - 1;
var row = Math.floor(clkfs/76);
var col = clkfs - row*76;
var xpos = col*3-68;
var ypos = row-39;
return {x:xpos, y:ypos};
return {x:xpos, y:ypos, clk:clkfs%76};
}
getRasterScanline() : number {
return this.getRasterPosition().y;
@ -292,7 +292,7 @@ class VCSPlatform extends BasePlatform {
tiaStateToLongString(t) {
var pos = this.getRasterPosition();
var s = '';
s += "H" + lpad(pos.x.toString(),5) + " V" + lpad(pos.y.toString(),5) + " ";
s += "H" + lpad(pos.x.toString(),5) + " (clk " + lpad(pos.clk.toString(),3) + ") V" + lpad(pos.y.toString(),5) + " ";
s += (t.vs?"VSYNC ":"- ") + (t.vb?"VBLANK ":"- ") + "\n";
s += "\n";
s += "Playfield " + t.f + "\n";

View File

@ -10,7 +10,7 @@ MEMORY {
SEGMENTS {
RODATA: load=ROM, type=ro, align=$100;
CODE: load=ROM, type=ro, align=$100, define=yes;
CODE: load=ROM, type=ro, define=yes;
DATA: load=ROM, run=RAM, type=rw, define=yes;
BSS: load=RAM, type=bss, define=yes;
VECTORS: load=ROM, type=ro, start=$FFFA;

View File

@ -721,7 +721,6 @@ function parseDASMListing(code:string, listings:CodeListingMap, errors:WorkerErr
var lineMatch = /\s*(\d+)\s+(\S+)\s+([0-9a-f]+)\s+([?0-9a-f][?0-9a-f ]+)?\s+(.+)?/i;
var equMatch = /\bequ\b/i;
var macroMatch = /\bMAC\s+(.+)?/i;
var macrolines = [];
var lastline = 0;
var macros = {};
for (var line of code.split(re_crlf)) {
@ -752,23 +751,28 @@ function parseDASMListing(code:string, listings:CodeListingMap, errors:WorkerErr
}
lastline = linenum;
} else {
// inside of macro or include file
if (insns && linem[3] && lastline>0) {
lines.push({
line:lastline+1,
offset:offset,
insns:null
});
}
// inside of macro?
var mac = macros[filename.toLowerCase()];
if (insns && mac) {
macrolines.push({
filename:mac.file,
/*
lines.push({
path:mac.file,
line:mac.line+linenum,
offset:offset,
insns:insns
insns:insns,
iscode:true
});
*/
// TODO: a listing file can't include other files
} else {
// inside of macro or include file
if (insns && linem[3] && lastline>0) {
lines.push({
line:lastline+1,
offset:offset,
insns:null
});
}
}
}
// TODO: better symbol test (word boundaries)
@ -800,7 +804,6 @@ function parseDASMListing(code:string, listings:CodeListingMap, errors:WorkerErr
})
}
}
// TODO: use macrolines
}
function assembleDASM(step:BuildStep) {