From 11fc96d891c04d6c9a8006f2681ac9da9c0404ed Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Thu, 21 Feb 2019 16:47:25 -0500 Subject: [PATCH] started on Memory Map view --- css/ui.css | 19 ++++++++++++++ src/project.ts | 8 +++++- src/ui.ts | 5 ++++ src/views.ts | 53 +++++++++++++++++++++++++++++++++++++++- src/worker/workermain.ts | 10 +++++--- src/workertypes.ts | 3 +++ 6 files changed, 93 insertions(+), 5 deletions(-) diff --git a/css/ui.css b/css/ui.css index efe53510..f34a7d5a 100644 --- a/css/ui.css +++ b/css/ui.css @@ -403,3 +403,22 @@ div.markdown th { .alert { z-index:2; } +.segment { + border: 2px solid rgba(0,0,0,0.2); + border-radius:8px; + color: #333; + background-color:#999; +} +.segment.segment-ram { + background-color:#aaffaa; +} +.segment.segment-rom { + background-color:#ddddff; + padding-top:1em; + padding-bottom:1em; +} +.segment-offset { + font-family: "Andale Mono", "Menlo", "Lucida Console", monospace; + font-size: 12pt; + color:#66dd66; +} diff --git a/src/project.ts b/src/project.ts index f5afba38..9e14c1b1 100644 --- a/src/project.ts +++ b/src/project.ts @@ -1,6 +1,6 @@ "use strict"; -import { FileData, Dependency, SourceLine, SourceFile, CodeListing, CodeListingMap, WorkerError, WorkerResult } from "./workertypes"; +import { FileData, Dependency, SourceLine, SourceFile, CodeListing, CodeListingMap, WorkerError, Segment, WorkerResult } from "./workertypes"; import { getFilenameForPath, getFilenamePrefix, getFolderForPath, isProbablyBinary } from "./util"; type BuildResultCallback = (result:WorkerResult) => void; @@ -12,6 +12,7 @@ type GetRemoteCallback = any; // TODO (path:string, (text:string) => FileData) = export class CodeProject { filedata : {[path:string]:FileData} = {}; listings : CodeListingMap; + segments : Segment[]; mainpath : string; pendingWorkerMessages = 0; tools_preloaded = {}; @@ -298,6 +299,11 @@ export class CodeProject { lst.assemblyfile = new SourceFile(lst.asmlines, lst.text); } } + // save and sort segment list + this.segments = data.segments; + if (this.segments) { + this.segments.sort((a,b) => {return a.start-b.start}); + } } getListings() : CodeListingMap { diff --git a/src/ui.ts b/src/ui.ts index e91df95c..092f095e 100644 --- a/src/ui.ts +++ b/src/ui.ts @@ -194,6 +194,11 @@ function refreshWindowList() { return new Views.MemoryView(); }); } + if (current_project.segments) { + addWindowItem("#memmap", "Memory Map", function() { + return new Views.MemoryMapView(); + }); + } } // can pass integer or string id diff --git a/src/views.ts b/src/views.ts index 2da0f79b..d18ce55a 100644 --- a/src/views.ts +++ b/src/views.ts @@ -3,7 +3,7 @@ import $ = require("jquery"); //import CodeMirror = require("codemirror"); import { CodeProject } from "./project"; -import { SourceFile, WorkerError } from "./workertypes"; +import { SourceFile, WorkerError, Segment } from "./workertypes"; import { Platform, EmuState } from "./baseplatform"; import { hex, lpad, rpad } from "./util"; import { CodeAnalyzer } from "./analysis"; @@ -772,3 +772,54 @@ export class BinaryFileView implements ProjectView { getPath() { return this.path; } } + +/// + +export class MemoryMapView implements ProjectView { + maindiv : JQuery; + + createDiv(parent : HTMLElement) { + this.maindiv = $("
"); + //div.setAttribute("class", "memdump"); + $(parent).append(this.maindiv); + this.refresh(); + return this.maindiv[0]; + } + + addSegment(seg : Segment) { + var offset = $('
'); + offset.text('$'+hex(seg.start,4)); + var segdiv = $('
'); + if (seg.last) + segdiv.text(seg.name+" ("+(seg.last-seg.start)+" / "+seg.size+" bytes used)"); + else + segdiv.text(seg.name+" ("+seg.size+" bytes)"); + if (seg.size >= 256) { + var pad = (Math.log(seg.size) - Math.log(256)) * 0.5; + segdiv.css('padding-top', pad+'em'); + segdiv.css('padding-bottom', pad+'em'); + } + if (seg.type) { + segdiv.addClass('segment-'+seg.type); + } + var row = $('
').append(offset, segdiv); + var container = $('
').append(row); + this.maindiv.append(container); + } + + refresh() { + this.maindiv.empty(); + var segments = current_project.segments; + if (segments) { + var curofs = 0; + for (var seg of segments) { + var used = seg.last ? (seg.last-seg.start) : seg.size; + if (curofs != seg.start) + this.addSegment({name:'',start:curofs, size:seg.start-curofs}); + this.addSegment(seg); + curofs = seg.start + used; + } + } + } + +} diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts index 9aa17561..9a2c22a3 100644 --- a/src/worker/workermain.ts +++ b/src/worker/workermain.ts @@ -886,7 +886,8 @@ function linkLD65(step:BuildStep) { } } // build segment map - var segments = {}; + var segments = []; + segments.push({name:'Stack',start:0x100,size:0x100,type:'ram'}); for (let ident in symbolmap) { let m = seg_re.exec(ident); if (m) { @@ -894,8 +895,11 @@ function linkLD65(step:BuildStep) { let segstart = symbolmap['__'+seg+'_RUN__'] || symbolmap['__'+seg+'_START__']; let segsize = symbolmap['__'+seg+'_SIZE__']; let seglast = symbolmap['__'+seg+'_LAST__']; - if (segstart >= 0 && segsize > 0) { - segments[seg] = {start:segstart, size:segsize, last:seglast}; + if (segstart >= 0 && segsize > 0 && seg != 'PRG' && seg != 'RAM') { // TODO + var type = null; + if (seg == 'CODE' || seg == 'STARTUP' || seg == 'RODATA') type = 'rom'; + else if (seg == 'ZP' || seg == 'RAM' || seg == 'DATA' || seg == 'BSS') type = 'ram'; + segments.push({name:seg, start:segstart, size:segsize, last:seglast, type:type}); } } } diff --git a/src/workertypes.ts b/src/workertypes.ts index 4085561a..ea67eef4 100644 --- a/src/workertypes.ts +++ b/src/workertypes.ts @@ -91,12 +91,15 @@ export type VerilogOutput = 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, }