mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-01-02 23:30:21 +00:00
working on tree view for state, extra debuginfo
This commit is contained in:
parent
741df9f5b8
commit
71fa79cec5
56
css/ui.css
56
css/ui.css
@ -594,8 +594,8 @@ div.asset_toolbar {
|
||||
font-weight: bold;
|
||||
}
|
||||
.transcript-style-8 { /* input */
|
||||
font-weight: bold;
|
||||
font-variant: small-caps;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
color: #6666ff;
|
||||
background-color: #eeeeff;
|
||||
padding: 0.25em;
|
||||
@ -607,10 +607,54 @@ div.asset_toolbar {
|
||||
color: #ddd;
|
||||
}
|
||||
.transcript-input {
|
||||
margin:1%;
|
||||
font-weight: bold;
|
||||
font-variant: small-caps;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
color: #6666ff;
|
||||
background-color: #eeeeff;
|
||||
margin:1%;
|
||||
}
|
||||
|
||||
.tree-header {
|
||||
border: 2px solid #555;
|
||||
border-radius:8px;
|
||||
color: #fff;
|
||||
background-color:#666;
|
||||
padding-left:1em;
|
||||
font-family: "Andale Mono", "Menlo", "Lucida Console", monospace;
|
||||
}
|
||||
.tree-content {
|
||||
padding-left:0.75em;
|
||||
padding-right:0.75em;
|
||||
font-size: small;
|
||||
}
|
||||
.tree-value {
|
||||
float:right;
|
||||
font-weight:normal;
|
||||
padding-right:1em;
|
||||
}
|
||||
.tree-expanded::after {
|
||||
float: right;
|
||||
margin-right: 1em;
|
||||
content: '\25b2';
|
||||
}
|
||||
.tree-collapsed::after {
|
||||
float: right;
|
||||
margin-right: 1em;
|
||||
content: '\25bc';
|
||||
}
|
||||
.tree-collapsed:hover, .tree-expanded:hover {
|
||||
border-color: rgba(255,255,255,0.7);
|
||||
}
|
||||
.tree-header:hover {
|
||||
background-color: rgba(255,255,255,0.3);
|
||||
}
|
||||
.tree-level-0 { display:none;}
|
||||
.tree-level-1 { background-color: #638283;}
|
||||
.tree-level-2 { background-color: #636e83;}
|
||||
.tree-level-3 { background-color: #636483;}
|
||||
.tree-level-4 { background-color: #756383;}
|
||||
.tree-level-5 { background-color: #83637e;}
|
||||
.tree-level-6 { background-color: #83636e;}
|
||||
.tree-level-7 { background-color: #836363;}
|
||||
.tree-level-8 { background-color: #837163;}
|
||||
.tree-level-9 { background-color: #7b8363;}
|
||||
.tree-level-10 { background-color: #738363;}
|
||||
|
39
presets/zmachine/skeleton.inform6
Normal file
39
presets/zmachine/skeleton.inform6
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
Constant Story "My Story Name";
|
||||
|
||||
Constant Headline
|
||||
"^This is My Story^
|
||||
By New Writer (2020)^";
|
||||
|
||||
Constant MAX_SCORE 100;
|
||||
|
||||
Release 1;
|
||||
|
||||
Include "Parser";
|
||||
Include "VerbLib";
|
||||
|
||||
!-------------------------------------------------------------------------------
|
||||
! Initialise
|
||||
!-------------------------------------------------------------------------------
|
||||
|
||||
[ Initialise;
|
||||
|
||||
location = Main_Lobby;
|
||||
|
||||
];
|
||||
|
||||
! ----------------------------------------------------------------------------
|
||||
! Locations
|
||||
! ----------------------------------------------------------------------------
|
||||
|
||||
Object Main_Lobby "Main Lobby"
|
||||
with description
|
||||
"You are in the main lobby.",
|
||||
has light;
|
||||
|
||||
! ----------------------------------------------------------------------------
|
||||
! Grammar
|
||||
! ----------------------------------------------------------------------------
|
||||
|
||||
Include "Grammar";
|
||||
|
@ -45,9 +45,11 @@ export type AddrSymbolMap = {[address:number]:string};
|
||||
export class DebugSymbols {
|
||||
symbolmap : SymbolMap; // symbol -> address
|
||||
addr2symbol : AddrSymbolMap; // address -> symbol
|
||||
debuginfo : {}; // extra platform-specific debug info
|
||||
|
||||
constructor(symbolmap : SymbolMap) {
|
||||
constructor(symbolmap : SymbolMap, debuginfo : {}) {
|
||||
this.symbolmap = symbolmap;
|
||||
this.debuginfo = debuginfo;
|
||||
this.addr2symbol = invertMap(symbolmap);
|
||||
//// TODO: shouldn't be necc.
|
||||
if (!this.addr2symbol[0x0]) this.addr2symbol[0x0] = '$00'; // needed for ...
|
||||
@ -123,6 +125,7 @@ export interface Platform {
|
||||
getCPUState?() : CpuState;
|
||||
|
||||
debugSymbols? : DebugSymbols;
|
||||
getDebugTree?() : {};
|
||||
|
||||
startProbing?() : ProbeRecorder;
|
||||
stopProbing?() : void;
|
||||
@ -194,6 +197,9 @@ export abstract class BasePlatform {
|
||||
inspect(sym: string) : string {
|
||||
return inspectSymbol((this as any) as Platform, sym);
|
||||
}
|
||||
getDebugTree() {
|
||||
return this.saveState();
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class BaseDebugPlatform extends BasePlatform {
|
||||
|
@ -96,12 +96,13 @@ export type WorkerOutput = Uint8Array | VerilogOutput;
|
||||
export type Segment = {name:string, start:number, size:number, last?:number, type?:string};
|
||||
|
||||
export interface WorkerResult {
|
||||
output:WorkerOutput,
|
||||
errors:WorkerError[],
|
||||
listings:CodeListingMap,
|
||||
symbolmap:{[sym:string]:number},
|
||||
params:{},
|
||||
segments?:Segment[],
|
||||
unchanged?:boolean,
|
||||
output:WorkerOutput
|
||||
errors:WorkerError[]
|
||||
listings:CodeListingMap
|
||||
symbolmap:{[sym:string]:number}
|
||||
params:{}
|
||||
segments?:Segment[]
|
||||
unchanged?:boolean
|
||||
debuginfo?:{} // optional info
|
||||
}
|
||||
|
||||
|
@ -278,6 +278,11 @@ function refreshWindowList() {
|
||||
return new Views.VRAMMemoryView();
|
||||
});
|
||||
}
|
||||
if (platform.getDebugTree) {
|
||||
addWindowItem("#debugview", "Debug Browser", () => {
|
||||
return new Views.DebugBrowserView();
|
||||
});
|
||||
}
|
||||
if (platform.startProbing) {
|
||||
addWindowItem("#memheatmap", "Memory Probe", () => {
|
||||
return new Views.AddressHeatMapView();
|
||||
@ -1031,7 +1036,7 @@ function setCompileOutput(data: WorkerResult) {
|
||||
showErrorAlert(data.errors);
|
||||
} else {
|
||||
// process symbol map
|
||||
platform.debugSymbols = new DebugSymbols(data.symbolmap);
|
||||
platform.debugSymbols = new DebugSymbols(data.symbolmap, data.debuginfo);
|
||||
compparams = data.params;
|
||||
// load ROM
|
||||
var rom = data.output;
|
||||
|
244
src/ide/views.ts
244
src/ide/views.ts
@ -6,7 +6,7 @@ import { hex, lpad, rpad, safeident, rgb2bgr } from "../common/util";
|
||||
import { CodeAnalyzer } from "../common/analysis";
|
||||
import { platform, platform_id, compparams, current_project, lastDebugState, projectWindows, runToPC } from "./ui";
|
||||
import { ProbeRecorder, ProbeFlags } from "../common/recorder";
|
||||
import { getMousePos } from "../common/emu";
|
||||
import { getMousePos, dumpRAM } from "../common/emu";
|
||||
import * as pixed from "./pixeleditor";
|
||||
declare var Mousetrap;
|
||||
|
||||
@ -809,7 +809,7 @@ export class VRAMMemoryView extends MemoryView {
|
||||
///
|
||||
|
||||
export class BinaryFileView implements ProjectView {
|
||||
memorylist;
|
||||
vlist : VirtualTextScroller;
|
||||
maindiv : HTMLElement;
|
||||
path:string;
|
||||
data:Uint8Array;
|
||||
@ -821,30 +821,12 @@ export class BinaryFileView implements ProjectView {
|
||||
}
|
||||
|
||||
createDiv(parent : HTMLElement) {
|
||||
var div = document.createElement('div');
|
||||
div.setAttribute("class", "memdump");
|
||||
parent.appendChild(div);
|
||||
this.showMemoryWindow(parent, div);
|
||||
return this.maindiv = div;
|
||||
this.vlist = new VirtualTextScroller(parent);
|
||||
this.vlist.create(parent, ((this.data.length+15) >> 4), this.getMemoryLineAt.bind(this));
|
||||
return this.vlist.maindiv;
|
||||
}
|
||||
|
||||
showMemoryWindow(workspace:HTMLElement, parent:HTMLElement) {
|
||||
this.memorylist = new VirtualList({
|
||||
w: $(workspace).width(),
|
||||
h: $(workspace).height(),
|
||||
itemHeight: getVisibleEditorLineHeight(),
|
||||
totalRows: ((this.data.length+15) >> 4),
|
||||
generatorFn: (row : number) => {
|
||||
var s = this.getMemoryLineAt(row);
|
||||
var linediv = document.createElement("div");
|
||||
linediv.appendChild(document.createTextNode(s));
|
||||
return linediv;
|
||||
}
|
||||
});
|
||||
$(parent).append(this.memorylist.container);
|
||||
}
|
||||
|
||||
getMemoryLineAt(row : number) : string {
|
||||
getMemoryLineAt(row : number) : VirtualTextLine {
|
||||
var offset = row * 16;
|
||||
var n1 = 0;
|
||||
var n2 = 16;
|
||||
@ -856,10 +838,11 @@ export class BinaryFileView implements ProjectView {
|
||||
if (i==8) s += ' ';
|
||||
s += ' ' + (read>=0?hex(read,2):' ');
|
||||
}
|
||||
return s;
|
||||
return {text:s};
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.vlist.refresh();
|
||||
}
|
||||
|
||||
getPath() { return this.path; }
|
||||
@ -1216,41 +1199,26 @@ export class RasterStackMapView extends ProbeBitmapViewBase implements ProjectVi
|
||||
}
|
||||
|
||||
export class ProbeLogView extends ProbeViewBaseBase {
|
||||
memorylist;
|
||||
vlist : VirtualTextScroller;
|
||||
maindiv : HTMLElement;
|
||||
recreateOnResize = true;
|
||||
dumplines;
|
||||
|
||||
createDiv(parent : HTMLElement) {
|
||||
var div = document.createElement('div');
|
||||
div.setAttribute("class", "memdump");
|
||||
parent.appendChild(div);
|
||||
this.showMemoryWindow(parent, div);
|
||||
return this.maindiv = div;
|
||||
this.vlist = new VirtualTextScroller(parent);
|
||||
this.vlist.create(parent, 160*262, this.getMemoryLineAt.bind(this));
|
||||
return this.vlist.maindiv;
|
||||
}
|
||||
|
||||
showMemoryWindow(workspace:HTMLElement, parent:HTMLElement) {
|
||||
this.memorylist = new VirtualList({
|
||||
w: $(workspace).width(),
|
||||
h: $(workspace).height(),
|
||||
itemHeight: getVisibleEditorLineHeight(),
|
||||
totalRows: 160*262, // TODO?
|
||||
generatorFn: (row : number) => {
|
||||
var s = this.getMemoryLineAt(row);
|
||||
var linediv = document.createElement("div");
|
||||
linediv.appendChild(document.createTextNode(s));
|
||||
return linediv;
|
||||
}
|
||||
});
|
||||
$(parent).append(this.memorylist.container);
|
||||
}
|
||||
|
||||
getMemoryLineAt(row : number) : string {
|
||||
getMemoryLineAt(row : number) : VirtualTextLine {
|
||||
var s : string = "";
|
||||
var c : string = "seg_data";
|
||||
var line = this.dumplines && this.dumplines[row];
|
||||
if (line != null) {
|
||||
var xtra = line.info.join(", ");
|
||||
return "(" + lpad(line.row,3) + ", " + lpad(line.col,3) + ") " + rpad(line.asm||"",20) + xtra;
|
||||
} else return "";
|
||||
var xtra : string = line.info.join(", ");
|
||||
s = "(" + lpad(line.row,3) + ", " + lpad(line.col,3) + ") " + rpad(line.asm||"",20) + xtra;
|
||||
if (xtra.indexOf("Write ") >= 0) c = "seg_io";
|
||||
}
|
||||
return {text:s, clas:c};
|
||||
}
|
||||
refresh() {
|
||||
this.tick();
|
||||
@ -1279,17 +1247,7 @@ export class ProbeLogView extends ProbeViewBaseBase {
|
||||
break;
|
||||
}
|
||||
});
|
||||
// TODO: refactor with elsewhere
|
||||
if (this.memorylist) {
|
||||
$(this.maindiv).find('[data-index]').each( (i,e) => {
|
||||
var div = $(e);
|
||||
var row = parseInt(div.attr('data-index'));
|
||||
var oldtext = div.text();
|
||||
var newtext = this.getMemoryLineAt(row);
|
||||
if (oldtext != newtext)
|
||||
div.text(newtext);
|
||||
});
|
||||
}
|
||||
this.vlist.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1362,6 +1320,166 @@ export class ProbeSymbolView extends ProbeViewBaseBase {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
const MAX_CHILDREN = 200;
|
||||
const MAX_STRING_LEN = 100;
|
||||
const MAX_DUMP_BYTES = 256;
|
||||
|
||||
class TreeNode {
|
||||
parent : TreeNode;
|
||||
name : string;
|
||||
_div : HTMLElement;
|
||||
_header : HTMLElement;
|
||||
_inline : HTMLElement;
|
||||
_content : HTMLElement;
|
||||
children : Map<string,TreeNode>;
|
||||
expanded = false;
|
||||
level : number;
|
||||
view : TreeViewBase;
|
||||
|
||||
constructor(parent : TreeNode, name : string) {
|
||||
this.parent = parent;
|
||||
this.name = name;
|
||||
this.children = new Map();
|
||||
this.level = parent ? (parent.level+1) : -1;
|
||||
this.view = parent ? parent.view : null;
|
||||
}
|
||||
getDiv() {
|
||||
if (this._div == null) {
|
||||
this._div = document.createElement("div");
|
||||
this._div.classList.add("vertical-scroll");
|
||||
this._div.classList.add("tree-content");
|
||||
this._header = document.createElement("div");
|
||||
this._header.classList.add("tree-header");
|
||||
this._header.classList.add("tree-level-" + this.level);
|
||||
this._header.append(this.name);
|
||||
this._inline = document.createElement("span");
|
||||
this._inline.classList.add("tree-value");
|
||||
this._header.append(this._inline);
|
||||
this._div.append(this._header);
|
||||
this.parent._content.append(this._div);
|
||||
this._header.onclick = (e) => {
|
||||
this.toggleExpanded();
|
||||
};
|
||||
}
|
||||
if (this.expanded && this._content == null) {
|
||||
this._content = document.createElement("div");
|
||||
this._div.append(this._content);
|
||||
}
|
||||
else if (!this.expanded && this._content != null) {
|
||||
this._content.remove();
|
||||
this._content = null;
|
||||
this.children.clear();
|
||||
}
|
||||
return this._div;
|
||||
}
|
||||
toggleExpanded() {
|
||||
this.expanded = !this.expanded;
|
||||
this.view.tick();
|
||||
}
|
||||
remove() {
|
||||
this._div.remove();
|
||||
this._div = null;
|
||||
}
|
||||
update(obj : any) {
|
||||
this.getDiv();
|
||||
var text = "";
|
||||
// is it a function? call it first, if we are expanded
|
||||
if (typeof obj == 'function' && this._content != null) {
|
||||
obj = obj();
|
||||
}
|
||||
// check null first
|
||||
if (obj == null) {
|
||||
text = obj+"";
|
||||
// primitive types
|
||||
} else if (typeof obj == 'number') {
|
||||
text = obj.toString();
|
||||
} else if (typeof obj == 'boolean') {
|
||||
text = obj.toString();
|
||||
} else if (typeof obj == 'string') {
|
||||
if (obj.length < MAX_STRING_LEN)
|
||||
text = obj;
|
||||
else
|
||||
text = obj.substring(0, MAX_STRING_LEN) + "...";
|
||||
// byte array (TODO: other kinds)
|
||||
} else if (obj instanceof Uint8Array && obj.length <= MAX_DUMP_BYTES) {
|
||||
text = dumpRAM(obj, 0, obj.length);
|
||||
// recurse into object? (or function)
|
||||
} else if (typeof obj == 'object' || typeof obj == 'function') {
|
||||
if (this._content != null) {
|
||||
let names = Object.getOwnPropertyNames(obj);
|
||||
if (names.length < MAX_CHILDREN) { // max # of child objects
|
||||
let orphans = new Set(this.children.keys());
|
||||
// visit all children
|
||||
names.forEach((name) => {
|
||||
let childnode = this.children.get(name);
|
||||
if (childnode == null) {
|
||||
childnode = new TreeNode(this, name);
|
||||
this.children.set(name, childnode);
|
||||
}
|
||||
childnode.update(obj[name]);
|
||||
orphans.delete(name);
|
||||
});
|
||||
// remove orphans
|
||||
orphans.forEach((delname) => {
|
||||
let childnode = this.children.get(delname);
|
||||
childnode.remove();
|
||||
this.children.delete(delname);
|
||||
});
|
||||
this._header.classList.add("tree-expanded");
|
||||
this._header.classList.remove("tree-collapsed");
|
||||
} else {
|
||||
text = names.length + " items"; // too many children
|
||||
}
|
||||
} else {
|
||||
this._header.classList.add("tree-collapsed");
|
||||
this._header.classList.remove("tree-expanded");
|
||||
}
|
||||
} else {
|
||||
text = typeof obj; // fallthrough
|
||||
}
|
||||
// change DOM object if needed
|
||||
if (this._inline.innerText != text) {
|
||||
this._inline.innerText = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class TreeViewBase implements ProjectView {
|
||||
root : TreeNode;
|
||||
|
||||
createDiv(parent : HTMLElement) : HTMLElement {
|
||||
var mainnode = new TreeNode(null, null);
|
||||
mainnode.view = this;
|
||||
mainnode._content = parent;
|
||||
this.root = new TreeNode(mainnode, "/");
|
||||
this.root.expanded = true;
|
||||
this.root.getDiv(); // create it
|
||||
this.root._div.style.padding = '0px';
|
||||
return this.root.getDiv(); // should be cached
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.tick();
|
||||
}
|
||||
|
||||
tick() {
|
||||
this.root.update(this.getRootObject());
|
||||
}
|
||||
|
||||
abstract getRootObject() : Object;
|
||||
}
|
||||
|
||||
export class StateBrowserView extends TreeViewBase implements ProjectView {
|
||||
getRootObject() { return platform.saveState(); }
|
||||
}
|
||||
|
||||
export class DebugBrowserView extends TreeViewBase implements ProjectView {
|
||||
getRootObject() { return platform.getDebugTree(); }
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
|
||||
export class AssetEditorView implements ProjectView, pixed.EditorContext {
|
||||
|
@ -785,6 +785,10 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
|
||||
// DEBUGGING
|
||||
|
||||
getDebugTree() {
|
||||
return this.saveState().o;
|
||||
}
|
||||
|
||||
// TODO: bind() a function to avoid depot?
|
||||
saveState() {
|
||||
var state = {
|
||||
|
@ -55,10 +55,9 @@ class GlkImpl {
|
||||
curline: HTMLElement;
|
||||
curstyle: number;
|
||||
reverse: boolean;
|
||||
windows: GlkWindow[];
|
||||
wnd: GlkWindow;
|
||||
waitingfor: "line" | "char" | null;
|
||||
focused = false;
|
||||
exited = false;
|
||||
|
||||
constructor(page: HTMLElement, input: HTMLInputElement) {
|
||||
this.page = page;
|
||||
@ -66,8 +65,7 @@ class GlkImpl {
|
||||
this.reset();
|
||||
}
|
||||
reset() {
|
||||
this.windows = [];
|
||||
this.wnd = null;
|
||||
this.exited = false;
|
||||
this.clear();
|
||||
}
|
||||
clear() {
|
||||
@ -89,6 +87,7 @@ class GlkImpl {
|
||||
// TODO
|
||||
}
|
||||
glk_exit() {
|
||||
this.exited = true;
|
||||
this.flushline();
|
||||
this.addtext("** Game exited **", 1);
|
||||
}
|
||||
@ -681,10 +680,11 @@ class ZmachinePlatform implements Platform {
|
||||
*/
|
||||
|
||||
isRunning(): boolean {
|
||||
return this.zvm != null;
|
||||
return this.zvm != null && !this.glk.exited;
|
||||
}
|
||||
|
||||
advance(novideo?: boolean): number {
|
||||
// TODO?
|
||||
// TODO? we should advance 1 step, whatever that is in ZVM
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -696,17 +696,106 @@ class ZmachinePlatform implements Platform {
|
||||
}
|
||||
showHelp(tool:string, ident?:string) {
|
||||
switch (tool) {
|
||||
case 'inform6': window.open("https://www.inform-fiction.org/manual/html/"); break;
|
||||
case 'inform6': window.open("https://www.inform-fiction.org/manual/html/contents.html"); break;
|
||||
}
|
||||
}
|
||||
getPresets(): Preset[] {
|
||||
return ZMACHINE_PRESETS;
|
||||
}
|
||||
|
||||
// TODO: Z machine is big endian!!
|
||||
inspect(ident:string) {
|
||||
return inspectSymbol(this, ident);
|
||||
}
|
||||
|
||||
getDebugTree() {
|
||||
var root = {};
|
||||
//root['debuginfo'] = sym.debuginfo;
|
||||
if (this.zvm != null) {
|
||||
root['Objects'] = () => this.getRootObjects();
|
||||
root['Globals'] = () => this.getGlobalVariables();
|
||||
}
|
||||
return root;
|
||||
}
|
||||
getObjectName(node) {
|
||||
var objlookup = this.getDebugLookup('object');
|
||||
var name = objlookup[node] || "";
|
||||
name += " (#" + node + ")";
|
||||
return name;
|
||||
}
|
||||
addObjectToTree(tree, child) {
|
||||
let name = this.getObjectName(child);
|
||||
tree[name] = this.getObjectTree(child);
|
||||
}
|
||||
getRootObjects() {
|
||||
var tree = {};
|
||||
// TODO: better way?
|
||||
try {
|
||||
for (let child=0; child<65536; child++) {
|
||||
if (this.zvm.get_parent(child) == 0) {
|
||||
this.addObjectToTree(tree, child);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (!(e instanceof RangeError)) throw e;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
getObjectTree(parentobj: number) {
|
||||
var child = this.zvm.get_child(parentobj);
|
||||
var tree = {};
|
||||
while (child) {
|
||||
this.addObjectToTree(tree, child);
|
||||
child = this.zvm.get_sibling(child);
|
||||
}
|
||||
// add attributes
|
||||
var flags = this.getFlagList(parentobj);
|
||||
if (flags.length) {
|
||||
tree["[attributes]"] = flags.join(' ');
|
||||
}
|
||||
/*
|
||||
var props = this.getPropList(parentobj);
|
||||
if (props.length) {
|
||||
tree["[properties]"] = props.join(' ');
|
||||
}
|
||||
*/
|
||||
return tree;
|
||||
}
|
||||
getFlagList(obj:number) {
|
||||
var attrlookup = this.getDebugLookup('attribute');
|
||||
var set_attrs = [];
|
||||
for (var i=0; i<32; i++) {
|
||||
if (this.zvm.test_attr(obj, i)) {
|
||||
set_attrs.push(attrlookup[i] || "#"+i);
|
||||
}
|
||||
}
|
||||
return set_attrs;
|
||||
}
|
||||
getPropList(obj:number) {
|
||||
var proplookup = this.getDebugLookup('property');
|
||||
var set_props = [];
|
||||
var addr = 0;
|
||||
for (var i=0; i<50; i++) {
|
||||
addr = this.zvm.find_prop(obj, 0, addr);
|
||||
if (addr == 0) break;
|
||||
set_props.push(proplookup[addr] || "%"+addr);
|
||||
}
|
||||
return set_props;
|
||||
}
|
||||
getDebugLookup(key : 'object'|'property'|'attribute'|'constant'|'global-variable') : {} {
|
||||
var debugsym = (this as Platform).debugSymbols;
|
||||
return (debugsym && debugsym.debuginfo && debugsym.debuginfo[key]) || {};
|
||||
}
|
||||
getGlobalVariables() {
|
||||
var globals = this.getDebugLookup('global-variable');
|
||||
var result = {};
|
||||
Object.entries(globals).forEach((entry) => {
|
||||
var addr = parseInt(entry[0]);
|
||||
var name = entry[1] as string;
|
||||
result[name] = this.zvm.m.getUint16(addr);
|
||||
})
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
import { WorkerResult, WorkerFileUpdate, WorkerBuildStep, WorkerMessage, WorkerError, Dependency, SourceLine, CodeListing, CodeListingMap, Segment } from "../common/workertypes";
|
||||
import { WorkerResult, WorkerFileUpdate, WorkerBuildStep, WorkerMessage, WorkerError, Dependency, SourceLine, CodeListing, CodeListingMap, Segment, WorkerOutput } from "../common/workertypes";
|
||||
|
||||
declare var WebAssembly;
|
||||
declare function importScripts(path:string);
|
||||
@ -2397,9 +2397,9 @@ interface XMLNode {
|
||||
|
||||
function parseXMLPoorly(s: string) : XMLNode {
|
||||
var re = /[<]([/]?)([?a-z_-]+)([^>]*)[>]+|(\s*[^<]+)/gi;
|
||||
var m;
|
||||
var i=0;
|
||||
var stack = [];
|
||||
var m : RegExpMatchArray;
|
||||
//var i=0;
|
||||
var stack : XMLNode[] = [];
|
||||
while (m = re.exec(s)) {
|
||||
var [_m0,close,ident,attrs,content] = m;
|
||||
//if (i++<100) console.log(close,ident,attrs,content);
|
||||
@ -2432,7 +2432,7 @@ function compileInform6(step:BuildStep) {
|
||||
lstout += "\n";
|
||||
}
|
||||
}
|
||||
var args = [ '-afnops', '-v5', '-Cu', '-E1', '-k', '+/share/lib', step.path ];
|
||||
var args = [ '-afjnops', '-v5', '-Cu', '-E1', '-k', '+/share/lib', step.path ];
|
||||
var inform = emglobal.inform({
|
||||
instantiateWasm: moduleInstFn('inform'),
|
||||
noInitialRun:true,
|
||||
@ -2454,10 +2454,15 @@ function compileInform6(step:BuildStep) {
|
||||
|
||||
// parse debug XML
|
||||
var symbolmap = {};
|
||||
var entitymap = {'object':{}, 'property':{}, 'constant':{}};
|
||||
var segments : Segment[] = [];
|
||||
var entitymap = {
|
||||
// number -> string
|
||||
'object':{}, 'property':{}, 'attribute':{}, 'constant':{}, 'global-variable':{}, 'routine':{},
|
||||
};
|
||||
var dbgout = FS.readFile("gameinfo.dbg", {encoding:'utf8'});
|
||||
var xmlroot = parseXMLPoorly(dbgout);
|
||||
//console.log(xmlroot);
|
||||
var segtype = "ram";
|
||||
xmlroot.children.forEach((node) => {
|
||||
switch (node.type) {
|
||||
case 'global-variable':
|
||||
@ -2465,34 +2470,26 @@ function compileInform6(step:BuildStep) {
|
||||
var ident = node.children.find((c,v) => c.type=='identifier').text;
|
||||
var address = parseInt(node.children.find((c,v) => c.type=='address').text);
|
||||
symbolmap[ident] = address;
|
||||
entitymap[node.type][address] = ident;
|
||||
break;
|
||||
case 'object':
|
||||
case 'property':
|
||||
case 'attribute':
|
||||
var ident = node.children.find((c,v) => c.type=='identifier').text;
|
||||
var value = parseInt(node.children.find((c,v) => c.type=='value').text);
|
||||
entitymap[node.type][ident] = value;
|
||||
//entitymap[node.type][ident] = value;
|
||||
entitymap[node.type][value] = ident;
|
||||
//symbolmap[ident] = address | 0x1000000;
|
||||
break;
|
||||
case 'story-file-section':
|
||||
var name = node.children.find((c,v) => c.type=='type').text;
|
||||
var address = parseInt(node.children.find((c,v) => c.type=='address').text);
|
||||
var endAddress = parseInt(node.children.find((c,v) => c.type=='end-address').text);
|
||||
if (name == "grammar table") segtype = "rom";
|
||||
segments.push({name:name, start:address, size:endAddress-address, type:segtype});
|
||||
}
|
||||
});
|
||||
// parse segments
|
||||
var segments : Segment[] = [];
|
||||
var seglst = lstout.split("Offsets in story file:")[1];
|
||||
if (seglst) {
|
||||
let curseg : Segment = {name:'Header',start:0x0,size:0x42,type:'rom'};
|
||||
segments.push(curseg);
|
||||
let curtype = 'ram';
|
||||
let re_seg = /([0-9a-f]{5}) (\w+)/g;
|
||||
let m;
|
||||
while (m = re_seg.exec(seglst)) {
|
||||
var start = parseInt(m[1], 16);
|
||||
var name = m[2];
|
||||
if (name == 'Parse') curtype = 'rom';
|
||||
curseg.size = start - curseg.start;
|
||||
curseg = {name:name, start:start, size:0, type:curtype};
|
||||
segments.push(curseg);
|
||||
}
|
||||
}
|
||||
// parse listing
|
||||
var listings : CodeListingMap = {};
|
||||
// 35 +00015 <*> call_vs long_19 location long_424 -> sp
|
||||
var lines = parseListing(lstout, /\s*(\d+)\s+[+]([0-9a-f]+)\s+([<*>]*)\s*(\w+)\s+(.+)/i, -1, 2, 4);
|
||||
@ -2504,10 +2501,11 @@ function compileInform6(step:BuildStep) {
|
||||
errors:errors,
|
||||
symbolmap:symbolmap,
|
||||
segments:segments,
|
||||
//debuginfo:entitymap,
|
||||
debuginfo:entitymap,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
|
||||
var TOOLS = {
|
||||
|
Loading…
Reference in New Issue
Block a user