mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2026-10-24 08:02:27 +00:00
ui: cmd+shift+g go-to-offset in disassembler and memory views
This commit is contained in:
1 parent
b4ea378903
commit
7c026da92a
4 files changed
+121
-3
No files matched your search
@@ -537,6 +537,11 @@ div.markdown th {
|
||||
.seg_io { color: #ffcccc; }
|
||||
.seg_stack { color: #ffff66; }
|
||||
.seg_unknown { color: #cccccc; }
|
||||
.goto_line {
|
||||
background-color: #1155cc;
|
||||
color: #ffffff;
|
||||
width: 100%;
|
||||
}
|
||||
.segment.segment-ram {
|
||||
background-color:#aaeeaa;
|
||||
}
|
||||
|
||||
+59
-1
@@ -1095,6 +1095,55 @@ function jumpToError(err: WorkerError) {
|
||||
}
|
||||
}
|
||||
|
||||
// go-to-address (mod+shift+g): works while the Disassembly, Memory Browser,
|
||||
// or VRAM Browser is the active view; accepts a hex address ("$1234", "0x1234",
|
||||
// "1234") or a symbol name ("main")
|
||||
|
||||
function getGoToAddressView(): DisassemblerView | MemoryView | null {
|
||||
var wnd = projectWindows.getActive();
|
||||
if (wnd instanceof DisassemblerView || wnd instanceof MemoryView) return wnd;
|
||||
return null;
|
||||
}
|
||||
|
||||
function parseGoToTarget(s: string): number {
|
||||
s = s.trim();
|
||||
if (!s) return -1;
|
||||
// symbol name first (so symbols like "add" aren't parsed as hex)
|
||||
var symmap = platform.debugSymbols && platform.debugSymbols.symbolmap;
|
||||
if (symmap && s in symmap) return symmap[s];
|
||||
var ls = s.toLowerCase();
|
||||
if (symmap) {
|
||||
for (var sym in symmap) {
|
||||
if (sym.toLowerCase() === ls) return symmap[sym];
|
||||
}
|
||||
}
|
||||
// hex address (bare digits are parsed as hex, like the listings)
|
||||
if (/^(0x|\$)[0-9a-f]+$/i.test(s)) return parseInt(s.replace(/^(0x|\$)/i, ''), 16);
|
||||
if (/^[0-9a-f]+$/i.test(s)) return parseInt(s, 16);
|
||||
return -1;
|
||||
}
|
||||
|
||||
function promptGoToAddress(): boolean {
|
||||
var wnd = getGoToAddressView();
|
||||
if (!wnd) return false;
|
||||
var cur = (wnd as any).getCursorPC ? (wnd as any).getCursorPC() : -1;
|
||||
(bootbox as any).prompt({
|
||||
title: "Go to Address",
|
||||
placeholder: "address in hex",
|
||||
value: cur >= 0 ? hex(cur, 4) : "",
|
||||
callback: (result: string) => {
|
||||
if (!result) return; // canceled or empty
|
||||
var addr = parseGoToTarget(result);
|
||||
if (isNaN(addr) || addr < 0) {
|
||||
alertError("Can't find address or symbol: " + DOMPurify.sanitize(result));
|
||||
return;
|
||||
}
|
||||
wnd.goToAddress(addr);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function getGlobalShortcuts(): Shortcut[] {
|
||||
var shortcuts: Shortcut[] = [];
|
||||
if (platform && isPlatformReady()) {
|
||||
@@ -1108,9 +1157,13 @@ function getGlobalShortcuts(): Shortcut[] {
|
||||
if (platform.isRunning && platform.isRunning()) {
|
||||
// in a debug session but emulator running: just Pause
|
||||
shortcuts.push({ key: 'mod+shift+h', label: 'Pause', fn: pause });
|
||||
} else if (platform.isRunning && !platform.isRunning()) {
|
||||
} else if (platform.isRunning && !platform.isRunning() && !getGoToAddressView()) {
|
||||
// mod+shift+g becomes "Go To Address" while a debug tool view is active
|
||||
shortcuts.push({ key: 'mod+shift+g', label: 'Resume', fn: resume });
|
||||
}
|
||||
if (getGoToAddressView()) {
|
||||
shortcuts.push({ key: 'mod+shift+g', label: 'Go To Address', fn: promptGoToAddress });
|
||||
}
|
||||
}
|
||||
return shortcuts;
|
||||
}
|
||||
@@ -1642,6 +1695,11 @@ function setupDebugControls() {
|
||||
uitoolbar.grp.prop('id', 'run_bar');
|
||||
uitoolbar.add('mod+shift+r', 'Reset', 'glyphicon-refresh', resetAndRun).prop('id', 'dbg_reset');
|
||||
uitoolbar.add('mod+shift+h', 'Pause', 'glyphicon-pause', pause).prop('id', 'dbg_pause');
|
||||
// bound before Resume so it takes priority in the debug tool views;
|
||||
// falls through to Resume everywhere else
|
||||
uitoolbar.add('mod+shift+g', 'Go To Address', '', (e) => {
|
||||
if (!promptGoToAddress()) resume();
|
||||
});
|
||||
uitoolbar.add('mod+shift+g', 'Resume', 'glyphicon-play', resume).prop('id', 'dbg_go');
|
||||
if (platform.restartAtPC) {
|
||||
uitoolbar.add('mod+shift+a', 'Restart at Cursor', 'glyphicon-play-circle', restartAtCursor).prop('id', 'dbg_restartatline');
|
||||
|
||||
@@ -37,6 +37,8 @@ export class MemoryView implements ProjectView {
|
||||
return this.maindiv = div;
|
||||
}
|
||||
|
||||
gotoRow = -1; // row highlighted by the Go To Address prompt
|
||||
|
||||
showMemoryWindow(workspace: HTMLElement, parent: HTMLElement) {
|
||||
this.memorylist = new VirtualList({
|
||||
w: $(workspace).width(),
|
||||
@@ -50,6 +52,7 @@ export class MemoryView implements ProjectView {
|
||||
var dlr = this.dumplines[row];
|
||||
if (dlr) linediv.classList.add('seg_' + this.getMemorySegment(this.dumplines[row].a | this.hibits));
|
||||
}
|
||||
if (row == this.gotoRow) linediv.classList.add('goto_line');
|
||||
linediv.appendChild(document.createTextNode(s));
|
||||
return linediv;
|
||||
}
|
||||
@@ -68,6 +71,28 @@ export class MemoryView implements ProjectView {
|
||||
}
|
||||
}
|
||||
|
||||
// jump to an address (or symbol), via the Go To Address prompt;
|
||||
// centers the target row in the viewport and highlights it
|
||||
goToAddress(addr: number) {
|
||||
this.hibits = addr & 0xffff0000;
|
||||
var dump = this.getDumpLines();
|
||||
var row;
|
||||
if (dump && dump.length) {
|
||||
row = this.findMemoryWindowLine(addr & 0xffff);
|
||||
} else {
|
||||
// no symbol map (e.g. VRAM): rows are raw 16-byte chunks
|
||||
row = (addr & 0xffff) >> 4;
|
||||
}
|
||||
if (row === undefined) return;
|
||||
this.gotoRow = row;
|
||||
if (this.memorylist) {
|
||||
var c = this.memorylist.container;
|
||||
var y = row * this.memorylist.itemHeight - (c.clientHeight - this.memorylist.itemHeight) / 2;
|
||||
c.scrollTop = Math.max(0, y);
|
||||
}
|
||||
this.tick();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.dumplines = null;
|
||||
this.tick();
|
||||
@@ -82,6 +107,7 @@ export class MemoryView implements ProjectView {
|
||||
var newtext = this.getMemoryLineAt(row);
|
||||
if (oldtext != newtext)
|
||||
div.text(newtext);
|
||||
div.toggleClass('goto_line', row == this.gotoRow);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -793,9 +793,9 @@ export class DisassemblerView implements ProjectView {
|
||||
}
|
||||
|
||||
// TODO: too many globals
|
||||
refresh(moveCursor: boolean) {
|
||||
refresh(moveCursor: boolean, centerAddr?: number) {
|
||||
let state = lastDebugState || platform.saveState(); // TODO?
|
||||
let pc = state.c ? state.c.PC : 0;
|
||||
let pc = centerAddr !== undefined ? centerAddr : (state.c ? state.c.PC : 0);
|
||||
let curline = 0;
|
||||
let selline = 0;
|
||||
let addr2symbol = (platform.debugSymbols && platform.debugSymbols.addr2symbol) || {};
|
||||
@@ -862,6 +862,35 @@ export class DisassemblerView implements ProjectView {
|
||||
}
|
||||
}
|
||||
|
||||
// jump to an address (or symbol), via the Go To Address prompt
|
||||
goToAddress(addr: number) {
|
||||
addr |= 0;
|
||||
if (!this.findAndSelectAddress(addr)) {
|
||||
// re-center the disassembly window on this address
|
||||
this.refresh(false, addr);
|
||||
this.findAndSelectAddress(addr);
|
||||
}
|
||||
this.disasmview.focus();
|
||||
}
|
||||
|
||||
private findAndSelectAddress(addr: number): boolean {
|
||||
const h = hex(addr, 4); // every line starts with the address + tab
|
||||
const doc = this.disasmview.state.doc;
|
||||
for (let i = 1; i <= doc.lines; i++) {
|
||||
const line = doc.line(i);
|
||||
if (line.text.startsWith(h + "\t")) {
|
||||
// select the address so the line stays highlighted; scrollIntoView
|
||||
// centers it in the viewport
|
||||
this.disasmview.dispatch({
|
||||
selection: { anchor: line.from, head: line.from + h.length },
|
||||
effects: EditorView.scrollIntoView(line.from, { y: "center" }),
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
getCursorPC(): number {
|
||||
const pos = this.disasmview.state.selection.main.head;
|
||||
const lineNum = this.disasmview.state.doc.lineAt(pos).number;
|
||||
|
||||
Reference in new issue
Block a user