diff --git a/doc/notes.txt b/doc/notes.txt index 89cc4869..375b3006 100644 --- a/doc/notes.txt +++ b/doc/notes.txt @@ -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 diff --git a/src/common/analysis.ts b/src/common/analysis.ts index 9c421784..fb454194 100644 --- a/src/common/analysis.ts +++ b/src/common/analysis.ts @@ -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) { diff --git a/src/ide/project.ts b/src/ide/project.ts index e24c54fd..fc442f4d 100644 --- a/src/ide/project.ts +++ b/src/ide/project.ts @@ -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]; } diff --git a/src/ide/ui.ts b/src/ide/ui.ts index ff163c05..1c8fd66f 100644 --- a/src/ide/ui.ts +++ b/src/ide/ui.ts @@ -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(); }); diff --git a/src/ide/views.ts b/src/ide/views.ts index 8a05fdb1..6504c320 100644 --- a/src/ide/views.ts +++ b/src/ide/views.ts @@ -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 { diff --git a/src/platform/vcs.ts b/src/platform/vcs.ts index 60273b72..109bea7f 100644 --- a/src/platform/vcs.ts +++ b/src/platform/vcs.ts @@ -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"; diff --git a/src/worker/lib/vcs/atari2600.cfg b/src/worker/lib/vcs/atari2600.cfg index 0615ba1e..3afbbd90 100644 --- a/src/worker/lib/vcs/atari2600.cfg +++ b/src/worker/lib/vcs/atari2600.cfg @@ -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; diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts index e78c21bb..81b2e628 100644 --- a/src/worker/workermain.ts +++ b/src/worker/workermain.ts @@ -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) {