From 50cac5afd41f1365324f7c6e17048705e74cf6d5 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Tue, 9 Aug 2022 13:29:06 -0500 Subject: [PATCH] debugger: made debug views "sticky" but not listings or certain debug commands --- src/common/workertypes.ts | 2 +- src/ide/ui.ts | 66 +++++++++++++++++++++++++-------------- src/ide/views/editors.ts | 7 +++-- 3 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/common/workertypes.ts b/src/common/workertypes.ts index 198a2292..6d768485 100644 --- a/src/common/workertypes.ts +++ b/src/common/workertypes.ts @@ -52,7 +52,7 @@ export class SourceFile { } } // TODO: smarter about looking for source lines between two addresses - findLineForOffset(PC:number, lookbehind:number) { + findLineForOffset(PC:number, lookbehind:number) : SourceLine { if (this.offset2loc) { for (var i=0; i<=lookbehind; i++) { var loc = this.offset2loc[PC]; diff --git a/src/ide/ui.ts b/src/ide/ui.ts index e4b9f4ab..2362e991 100644 --- a/src/ide/ui.ts +++ b/src/ide/ui.ts @@ -14,7 +14,7 @@ import { StateRecorderImpl } from "../common/recorder"; import { GHSession, GithubService, getRepos, parseGithubURL } from "./services"; import Split = require('split.js'); import { importPlatform } from "../platform/_index"; -import { DisassemblerView, ListingView, SourceEditor } from "./views/editors"; +import { DisassemblerView, ListingView, PC_LINE_LOOKAHEAD, SourceEditor } from "./views/editors"; import { AddressHeatMapView, BinaryFileView, MemoryMapView, MemoryView, ProbeLogView, ProbeSymbolView, RasterPCHeatMapView, ScanlineIOView, VRAMMemoryView } from "./views/debugviews"; import { AssetEditorView } from "./views/asseteditor"; import { isMobileDevice } from "./views/baseviews"; @@ -80,11 +80,16 @@ var store : LocalForage; // persistent store export var compparams; // received build params from worker export var lastDebugState : EmuState; // last debug state (object) +type DebugCommandType = null + | 'toline' | 'step' | 'stepout' | 'stepover' + | 'tovsync' | 'stepback' | 'restart'; + var lastDebugInfo; // last debug info (CPU text) var debugCategory; // current debug category var debugTickPaused = false; var recorderActive = false; -var lastViewClicked = null; +var lastViewClicked : string = null; +var lastDebugCommand : DebugCommandType = null; var errorWasRuntime = false; var lastBreakExpr = "c.PC == 0x6000"; @@ -1425,30 +1430,40 @@ function checkRunReady() { } function openRelevantListing(state: EmuState) { - // if we clicked on another window, retain it - if (lastViewClicked != null) return; + // if we clicked on a specific tool, don't switch windows + if (lastViewClicked && lastViewClicked.startsWith('#')) return; + // don't switch windows for specific debug commands + if (['toline','restart','tovsync','stepover'].includes(lastDebugCommand)) return; // has to support disassembly, at least if (!platform.disassemble) return; // search through listings - var listings = current_project.getListings(); - var bestid = "#disasm"; - var bestscore = 32; + let listings = current_project.getListings(); + let bestid = "#disasm"; + let bestscore = 256; if (listings) { - var pc = state.c ? (state.c.EPC || state.c.PC) : 0; - for (var lstfn in listings) { - var lst = listings[lstfn]; - var file = lst.assemblyfile || lst.sourcefile; + let pc = state.c ? (state.c.EPC || state.c.PC) : 0; + for (let lstfn in listings) { + let lst = listings[lstfn]; + let file = lst.assemblyfile || lst.sourcefile; // pick either listing or source file - var wndid = current_project.filename2path[lstfn] || lstfn; + let wndid = current_project.filename2path[lstfn] || lstfn; if (file == lst.sourcefile) wndid = projectWindows.findWindowWithFilePrefix(lstfn); // does this window exist? if (projectWindows.isWindow(wndid)) { - var res = file && file.findLineForOffset(pc, 32); // TODO: const - if (res && pc-res.offset < bestscore) { - bestid = wndid; - bestscore = pc-res.offset; + // find the source line at the PC or closely before it + let srcline1 = file && file.findLineForOffset(pc, PC_LINE_LOOKAHEAD); + if (srcline1) { + // try to find the next line and bound the PC + let srcline2 = file.lines[srcline1.line+1]; + if (!srcline2 || pc < srcline2.offset) { + let score = pc - srcline1.offset; + if (score < bestscore) { + bestid = wndid; + bestscore = score; + } + } + //console.log(hex(pc,4), srcline1, srcline2, wndid, lstfn, bestid, bestscore); } - //console.log(hex(pc,4), wndid, lstfn, bestid, bestscore); } } } @@ -1464,15 +1479,18 @@ function uiDebugCallback(state: EmuState) { debugTickPaused = true; } -function setupDebugCallback(btnid? : string) { - if (platform.setupDebug) platform.setupDebug((state:EmuState, msg:string) => { - uiDebugCallback(state); - setDebugButtonState(btnid||"pause", "stopped"); - msg && showErrorAlert([{msg:"STOPPED: " + msg, line:0}], true); - }); +function setupDebugCallback(btnid? : DebugCommandType) { + if (platform.setupDebug) { + platform.setupDebug((state:EmuState, msg:string) => { + uiDebugCallback(state); + setDebugButtonState(btnid||"pause", "stopped"); + msg && showErrorAlert([{msg:"STOPPED: " + msg, line:0}], true); + }); + lastDebugCommand = btnid; + } } -function setupBreakpoint(btnid? : string) { +function setupBreakpoint(btnid? : DebugCommandType) { if (!checkRunReady()) return; _disableRecording(); setupDebugCallback(btnid); diff --git a/src/ide/views/editors.ts b/src/ide/views/editors.ts index eff2e84f..8cbcf401 100644 --- a/src/ide/views/editors.ts +++ b/src/ide/views/editors.ts @@ -23,6 +23,9 @@ function createTextSpan(text:string, className:string) : HTMLElement { ///// +// look ahead this many bytes when finding source lines for a PC +export const PC_LINE_LOOKAHEAD = 64; + const MAX_ERRORS = 200; const MODEDEFS = { @@ -384,7 +387,7 @@ export class SourceEditor implements ProjectView { cpustate = platform.getCPUState(); if (cpustate) { var EPC = (cpustate && (cpustate.EPC || cpustate.PC)); - var res = this.sourcefile.findLineForOffset(EPC, 15); + var res = this.sourcefile.findLineForOffset(EPC, PC_LINE_LOOKAHEAD); return res; } } @@ -598,7 +601,7 @@ export class ListingView extends DisassemblerView implements ProjectView { var state = lastDebugState || platform.saveState(); var pc = state.c ? (state.c.EPC || state.c.PC) : 0; if (pc >= 0 && this.assemblyfile) { - var res = this.assemblyfile.findLineForOffset(pc, 15); + var res = this.assemblyfile.findLineForOffset(pc, PC_LINE_LOOKAHEAD); if (res) { // set cursor while debugging if (moveCursor) {