mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-02-16 17:30:27 +00:00
vcs: scanline view, fixed analysis with jsr
This commit is contained in:
parent
c5ccd4ff48
commit
8afad5571b
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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 {
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user