mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-12-22 12:30:01 +00:00
SourceFile object; moved styles to css/codemirror.css
This commit is contained in:
parent
6f09dd9634
commit
0fca237979
@ -347,3 +347,70 @@ div.CodeMirror-dragcursors {
|
||||
|
||||
/* Help users use markselection to safely style text background */
|
||||
span.CodeMirror-selectedtext { background: none; }
|
||||
|
||||
/****************************************************************/
|
||||
/* Based on mbonaci's Brackets mbo theme */
|
||||
/* https://github.com/mbonaci/global/blob/master/Mbo.tmTheme */
|
||||
/* Create your own: http://tmtheme-editor.herokuapp.com */
|
||||
/****************************************************************/
|
||||
|
||||
.cm-s-mbo.CodeMirror { background: #2c2c2c; color: #ffffec; }
|
||||
.cm-s-mbo div.CodeMirror-selected { background: #716C62; }
|
||||
.cm-s-mbo .CodeMirror-line::selection, .cm-s-mbo .CodeMirror-line > span::selection, .cm-s-mbo .CodeMirror-line > span > span::selection { background: rgba(113, 108, 98, .99); }
|
||||
.cm-s-mbo .CodeMirror-line::-moz-selection, .cm-s-mbo .CodeMirror-line > span::-moz-selection, .cm-s-mbo .CodeMirror-line > span > span::-moz-selection { background: rgba(113, 108, 98, .99); }
|
||||
.cm-s-mbo .CodeMirror-gutters { background: #4e4e4e; border-right: 0px; }
|
||||
.cm-s-mbo .CodeMirror-guttermarker { color: white; }
|
||||
.cm-s-mbo .CodeMirror-guttermarker-subtle { color: grey; }
|
||||
.cm-s-mbo .CodeMirror-linenumber { color: #dadada; }
|
||||
.cm-s-mbo .CodeMirror-cursor { border-left: 1px solid #ffffec; }
|
||||
|
||||
.cm-s-mbo span.cm-comment { color: #95958a; }
|
||||
.cm-s-mbo span.cm-atom { color: #00a8c6; }
|
||||
.cm-s-mbo span.cm-number { color: #00a8c6; }
|
||||
|
||||
.cm-s-mbo span.cm-property, .cm-s-mbo span.cm-attribute { color: #9ddfe9; }
|
||||
.cm-s-mbo span.cm-keyword { color: #ffb928; }
|
||||
.cm-s-mbo span.cm-string { color: #ffcf6c; }
|
||||
.cm-s-mbo span.cm-string.cm-property { color: #ffffec; }
|
||||
|
||||
.cm-s-mbo span.cm-variable { color: #ffffec; }
|
||||
.cm-s-mbo span.cm-variable-2 { color: #00a8c6; }
|
||||
.cm-s-mbo span.cm-variable-3 { color: #ffb928; }
|
||||
.cm-s-mbo span.cm-def { color: #ffff88; }
|
||||
.cm-s-mbo span.cm-bracket { color: #fffffc; font-weight: bold; }
|
||||
.cm-s-mbo span.cm-tag { color: #9ddfe9; }
|
||||
.cm-s-mbo span.cm-link { color: #f54b07; }
|
||||
.cm-s-mbo span.cm-error { border-bottom: #636363; color: #ffffec; }
|
||||
.cm-s-mbo span.cm-qualifier { color: #ffffec; }
|
||||
|
||||
.cm-s-mbo .CodeMirror-activeline-background { background: #494b41; }
|
||||
.cm-s-mbo .CodeMirror-matchingbracket { color: #33ff33 !important; }
|
||||
.cm-s-mbo .CodeMirror-matchingtag { background: rgba(255, 255, 255, .37); }
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
.cm-s-cobalt.CodeMirror { background: #002240; color: white; }
|
||||
.cm-s-cobalt div.CodeMirror-selected { background: #b36539; }
|
||||
.cm-s-cobalt .CodeMirror-line::selection, .cm-s-cobalt .CodeMirror-line > span::selection, .cm-s-cobalt .CodeMirror-line > span > span::selection { background: rgba(179, 101, 57, .99); }
|
||||
.cm-s-cobalt .CodeMirror-line::-moz-selection, .cm-s-cobalt .CodeMirror-line > span::-moz-selection, .cm-s-cobalt .CodeMirror-line > span > span::-moz-selection { background: rgba(179, 101, 57, .99); }
|
||||
.cm-s-cobalt .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
|
||||
.cm-s-cobalt .CodeMirror-guttermarker { color: #ffee80; }
|
||||
.cm-s-cobalt .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
|
||||
.cm-s-cobalt .CodeMirror-linenumber { color: #d0d0d0; }
|
||||
.cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white; }
|
||||
|
||||
.cm-s-cobalt span.cm-comment { color: #ccc; }
|
||||
.cm-s-cobalt span.cm-atom { color: #845dc4; }
|
||||
.cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; }
|
||||
.cm-s-cobalt span.cm-keyword { color: #ffee80; }
|
||||
.cm-s-cobalt span.cm-string { color: #3ad900; }
|
||||
.cm-s-cobalt span.cm-meta { color: #ff9d00; }
|
||||
.cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; }
|
||||
.cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; }
|
||||
.cm-s-cobalt span.cm-bracket { color: #d8d8d8; }
|
||||
.cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }
|
||||
.cm-s-cobalt span.cm-link { color: #845dc4; }
|
||||
.cm-s-cobalt span.cm-error { color: #9d1e15; }
|
||||
|
||||
.cm-s-cobalt .CodeMirror-activeline-background { background: #003399; }
|
||||
.cm-s-cobalt .CodeMirror-matchingbracket { outline:1px solid grey;color:white !important; }
|
||||
|
@ -257,10 +257,11 @@ canvas.pixelated {
|
||||
<script src="bootstrap/js/bootstrap-tour.min.js"></script>
|
||||
|
||||
<script src="codemirror/lib/codemirror.js"></script>
|
||||
<script src="codemirror/mode/clike/clike.js"></script>
|
||||
<script src="codemirror/mode/6502/6502.js"></script>
|
||||
<script src="codemirror/mode/z80/z80.js"></script>
|
||||
<link rel="stylesheet" href="css/codemirror.css">
|
||||
<link rel="stylesheet" href="codemirror/theme/mbo.css">
|
||||
<link rel="stylesheet" href="codemirror/theme/cobalt.css">
|
||||
<script src="codemirror/addon/edit/matchbrackets.js"></script>
|
||||
<script src="codemirror/addon/search/search.js"></script>
|
||||
<script src="codemirror/addon/search/searchcursor.js"></script>
|
||||
<script src="codemirror/addon/search/jumpToLine.js"></script>
|
||||
|
119
src/ui.js
119
src/ui.js
@ -61,31 +61,64 @@ var FileStore = function(storage, prefix) {
|
||||
}
|
||||
}
|
||||
|
||||
var SourceFile = function(lines, text) {
|
||||
lines = lines || [];
|
||||
this.text = text;
|
||||
this.offset2line = {};
|
||||
this.line2offset = {};
|
||||
for (var info of lines) {
|
||||
if (info.offset >= 0) {
|
||||
this.offset2line[info.offset] = info.line;
|
||||
this.line2offset[info.line] = info.offset;
|
||||
}
|
||||
}
|
||||
this.findLineForOffset = function(PC) {
|
||||
if (this.offset2line) {
|
||||
for (var i=0; i<256; i++) {
|
||||
var line = this.offset2line[PC];
|
||||
if (line >= 0) {
|
||||
return line;
|
||||
}
|
||||
PC--;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
var TOOL_TO_SOURCE_STYLE = {
|
||||
'dasm': '6502',
|
||||
'acme': '6502',
|
||||
'cc65': 'text/x-csrc',
|
||||
'ca65': '6502',
|
||||
'z80asm': 'z80',
|
||||
'sdasz80': 'z80',
|
||||
'sdcc': 'text/x-csrc',
|
||||
}
|
||||
|
||||
var worker = new Worker("./src/worker/workermain.js");
|
||||
var current_output = null;
|
||||
var current_preset_index = -1; // TODO: use URL
|
||||
var current_preset_id = null;
|
||||
var offset2line = null;
|
||||
var line2offset = null;
|
||||
var assemblyfile = null;
|
||||
var sourcefile = null;
|
||||
var pcvisits;
|
||||
var trace_pending_at_pc;
|
||||
var store;
|
||||
|
||||
var CODE = 'code1';
|
||||
var editor = CodeMirror(document.getElementById('editor'), {
|
||||
mode: '6502',
|
||||
theme: 'mbo',
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
tabSize: 8,
|
||||
gutters: ["CodeMirror-linenumbers", "gutter-offset", "gutter-bytes", "gutter-clock", "gutter-info"],
|
||||
});
|
||||
var disasmview = CodeMirror(document.getElementById('disassembly'), {
|
||||
mode: '6502',
|
||||
mode: 'z80',
|
||||
theme: 'cobalt',
|
||||
tabSize: 8,
|
||||
readOnly: true,
|
||||
styleActiveLine: true,
|
||||
gutters: ["gutter-offset", "gutter-bytes", "gutter-clock", "gutter-info"],
|
||||
styleActiveLine: true
|
||||
});
|
||||
|
||||
editor.on('changes', function(ed, changeobj) {
|
||||
@ -111,10 +144,13 @@ function updatePreset(current_preset_id, text) {
|
||||
}
|
||||
}
|
||||
|
||||
function loadCode(text) {
|
||||
function loadCode(text, fileid) {
|
||||
editor.setValue(text);
|
||||
current_output = null;
|
||||
setCode(text);
|
||||
setLastPreset(fileid);
|
||||
var tool = platform.getToolForFilename(fileid);
|
||||
editor.setOption("mode", tool && TOOL_TO_SOURCE_STYLE[tool]);
|
||||
}
|
||||
|
||||
function loadFile(fileid, filename, index) {
|
||||
@ -122,8 +158,7 @@ function loadFile(fileid, filename, index) {
|
||||
current_preset_index = index;
|
||||
var text = store.loadFile(fileid)|| "";
|
||||
if (text) {
|
||||
loadCode(text);
|
||||
setLastPreset(fileid);
|
||||
loadCode(text, fileid);
|
||||
} else if (!text && index >= 0) {
|
||||
filename += ".a";
|
||||
console.log("Loading preset", fileid, filename, index, PRESETS[index]);
|
||||
@ -131,14 +166,12 @@ function loadFile(fileid, filename, index) {
|
||||
console.log("Fetching", filename);
|
||||
$.get( filename, function( text ) {
|
||||
console.log("GET",text.length,'bytes');
|
||||
loadCode(text);
|
||||
setLastPreset(fileid);
|
||||
loadCode(text, fileid);
|
||||
}, 'text');
|
||||
}
|
||||
} else {
|
||||
$.get( "presets/"+platform_id+"/skeleton.a", function( text ) {
|
||||
loadCode(text);
|
||||
setLastPreset(fileid);
|
||||
loadCode(text, fileid);
|
||||
updatePreset(fileid, text);
|
||||
}, 'text');
|
||||
}
|
||||
@ -294,6 +327,10 @@ function arrayCompare(a,b) {
|
||||
worker.onmessage = function(e) {
|
||||
// errors?
|
||||
var toolbar = $("#controls_top");
|
||||
sourcefile = new SourceFile(e.data.lines);
|
||||
if (e.data.asmlines) {
|
||||
assemblyfile = new SourceFile(e.data.asmlines, e.data.intermediate.listing);
|
||||
}
|
||||
if (e.data.errors.length > 0) {
|
||||
toolbar.addClass("has-errors");
|
||||
editor.clearGutter("gutter-info");
|
||||
@ -333,14 +370,10 @@ worker.onmessage = function(e) {
|
||||
editor.clearGutter("gutter-bytes");
|
||||
editor.clearGutter("gutter-offset");
|
||||
editor.clearGutter("gutter-clock");
|
||||
offset2line = {};
|
||||
line2offset = {};
|
||||
for (var info of e.data.lines) {
|
||||
if (info.offset >= 0) {
|
||||
var textel = document.createTextNode(hex(info.offset,4));
|
||||
editor.setGutterMarker(info.line-1, "gutter-offset", textel);
|
||||
offset2line[info.offset] = info.line;
|
||||
line2offset[info.line] = info.offset;
|
||||
}
|
||||
if (info.insns) {
|
||||
var insnstr = info.insns.length > 8 ? ("...") : info.insns;
|
||||
@ -363,19 +396,6 @@ worker.onmessage = function(e) {
|
||||
trace_pending_at_pc = null;
|
||||
}
|
||||
|
||||
function findLineForOffset(PC) {
|
||||
if (offset2line) {
|
||||
for (var i=0; i<256; i++) {
|
||||
var line = offset2line[PC];
|
||||
if (line >= 0) {
|
||||
return line;
|
||||
}
|
||||
PC--;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function setCurrentLine(line) {
|
||||
editor.setSelection({line:line,ch:0}, {line:line-1,ch:0}, {scroll:true});
|
||||
}
|
||||
@ -437,7 +457,7 @@ function setupBreakpoint() {
|
||||
platform.setupDebug(function(state) {
|
||||
lastDebugState = state;
|
||||
var PC = state.c.PC;
|
||||
var line = findLineForOffset(PC);
|
||||
var line = sourcefile.findLineForOffset(PC);
|
||||
if (line >= 0) {
|
||||
console.log("BREAKPOINT", hex(PC), line);
|
||||
setCurrentLine(line);
|
||||
@ -477,7 +497,7 @@ function getCurrentLine() {
|
||||
|
||||
function runToCursor() {
|
||||
setupBreakpoint();
|
||||
var line = getCurrentLine();
|
||||
var line = sourcefile.getCurrentLine();
|
||||
var pc = line2offset[line];
|
||||
if (pc >= 0) {
|
||||
console.log("Run to", line, pc.toString(16));
|
||||
@ -691,16 +711,29 @@ function showLoopTimingForCurrentLine() {
|
||||
}
|
||||
*/
|
||||
|
||||
function jumpToLine(ed, i) {
|
||||
var t = ed.charCoords({line: i, ch: 0}, "local").top;
|
||||
var middleHeight = ed.getScrollerElement().offsetHeight / 2;
|
||||
ed.scrollTo(null, t - middleHeight - 5);
|
||||
}
|
||||
|
||||
function updateDisassembly() {
|
||||
var div = $("#disassembly");
|
||||
if (div.is(':visible')) {
|
||||
disasmview.clearGutter("gutter-info");
|
||||
disasmview.clearGutter("gutter-bytes");
|
||||
disasmview.clearGutter("gutter-offset");
|
||||
disasmview.clearGutter("gutter-clock");
|
||||
var state = lastDebugState || platform.saveState();
|
||||
var mem = state.b;
|
||||
var pc = state.c.PC;
|
||||
if (assemblyfile && assemblyfile.text) {
|
||||
disasmview.setValue(assemblyfile.text);
|
||||
if (platform.getDebugCallback()) {
|
||||
var lineno = assemblyfile.findLineForOffset(pc);
|
||||
if (lineno) {
|
||||
disasmview.setCursor(lineno-1, 0);
|
||||
jumpToLine(disasmview, lineno-1);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
var gutters = [];
|
||||
var selline = 0;
|
||||
// TODO: not perfect disassembler
|
||||
@ -711,7 +744,7 @@ function updateDisassembly() {
|
||||
var disasm = platform.disassemble(mem, start, end, pcvisits);
|
||||
var s = "";
|
||||
for (a in disasm) {
|
||||
var srclinenum = offset2line[a];
|
||||
var srclinenum = sourcefile.offset2line[a];
|
||||
if (srclinenum) {
|
||||
var srcline = editor.getLine(srclinenum-1);
|
||||
if (srcline && srcline.trim().length) {
|
||||
@ -728,16 +761,8 @@ function updateDisassembly() {
|
||||
}
|
||||
var text = disassemble(pc-96, pc) + disassemble(pc, pc+96);
|
||||
disasmview.setValue(text);
|
||||
/*
|
||||
for (var i=0; i<gutters.length; i++) {
|
||||
var g = gutters[i];
|
||||
if (g[0]) disasmview.setGutterMarker(i, "gutter-offset", hex(g[0]));
|
||||
}
|
||||
*/
|
||||
disasmview.setCursor(selline, 0);
|
||||
// TODO: need to refresh when viewport changes
|
||||
var scrinfo = disasmview.getScrollInfo();
|
||||
disasmview.scrollTo(0, (scrinfo.height-scrinfo.clientHeight)/2);
|
||||
jumpToLine(disasmview, selline);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,6 @@ var document = noop();
|
||||
document.documentElement = noop();
|
||||
document.documentElement.style = noop();
|
||||
|
||||
|
||||
// load filesystems for CC65 and others asynchronously
|
||||
var fsMeta, fsBlob;
|
||||
{
|
||||
@ -210,7 +209,6 @@ function assembleDASM(code) {
|
||||
var alst = FS.readFile("a.lst", {'encoding':'utf8'});
|
||||
var listing = parseDASMListing(alst, unresolved);
|
||||
return {
|
||||
exitstatus:Module.EXITSTATUS,
|
||||
output:aout.slice(2),
|
||||
lines:listing.lines,
|
||||
errors:listing.errors,
|
||||
@ -251,7 +249,6 @@ function assembleACME(code) {
|
||||
var asym = FS.readFile("a.sym", {'encoding':'utf8'});
|
||||
var listing = parseDASMListing(alst, {}); // TODO
|
||||
return {
|
||||
exitstatus:Module.EXITSTATUS,
|
||||
output:aout,
|
||||
lines:listing.lines,
|
||||
errors:listing.errors,
|
||||
@ -369,7 +366,6 @@ function assemblelinkCA65(code, platform, warnings) {
|
||||
var mapout = FS.readFile("main.map", {encoding:'utf8'});
|
||||
var listing = parseCA65Listing(lstout, mapout);
|
||||
return {
|
||||
exitstatus:LD65.EXITSTATUS,
|
||||
output:aout.slice(4),
|
||||
lines:listing.lines,
|
||||
errors:listing.errors,
|
||||
@ -412,7 +408,7 @@ function compileCC65(code, platform) {
|
||||
}
|
||||
}
|
||||
|
||||
function assembleZ80ASM(code, platform, ccompile) {
|
||||
function assembleZ80ASM(code, platform) {
|
||||
load("z80asm");
|
||||
var origin = 0; // TODO: configurable
|
||||
var Module = z80asm({
|
||||
@ -454,11 +450,10 @@ l_main00101 = 0003, L: test
|
||||
var asmlines = parseListing(alst, /^(\d+)\s+([0-9A-F]+)\s+([0-9A-F][0-9A-F ]*[0-9A-F])\s+/i, 1, 2, 3, 4);
|
||||
var srclines = parseListing(alst, /^(\d+)\s+([0-9A-F]+)\s+;[(]null[)]:(\d+)/i, 3, 2, 1);
|
||||
return {
|
||||
exitstatus:Module.EXITSTATUS,
|
||||
output:aout,
|
||||
errors:[],
|
||||
lines:ccompile ? srclines : asmlines,
|
||||
listing:ccompile ? asmlines : null,
|
||||
lines:asmlines,
|
||||
srclines:srclines,
|
||||
intermediate:{listing:alst, mapfile:amap},
|
||||
};
|
||||
} catch (e) {
|
||||
@ -504,7 +499,7 @@ function parseIHX(ihx, code_start, code_size) {
|
||||
}
|
||||
}
|
||||
|
||||
function assemblelinkSDASZ80(code, platform, ccompile) {
|
||||
function assemblelinkSDASZ80(code, platform) {
|
||||
load("sdasz80");
|
||||
load("sdldz80");
|
||||
var objout, lstout, symout;
|
||||
@ -538,7 +533,7 @@ function assemblelinkSDASZ80(code, platform, ccompile) {
|
||||
}
|
||||
objout = FS.readFile("main.rel", {encoding:'utf8'});
|
||||
lstout = FS.readFile("main.lst", {encoding:'utf8'});
|
||||
symout = FS.readFile("main.sym", {encoding:'utf8'});
|
||||
//symout = FS.readFile("main.sym", {encoding:'utf8'});
|
||||
}{
|
||||
var LDZ80 = sdldz80({
|
||||
noInitialRun:true,
|
||||
@ -557,19 +552,26 @@ function assemblelinkSDASZ80(code, platform, ccompile) {
|
||||
'main.rel']);
|
||||
var hexout = FS.readFile("main.ihx", {encoding:'utf8'});
|
||||
var mapout = FS.readFile("main.noi", {encoding:'utf8'});
|
||||
var dbgout = FS.readFile("main.cdb", {encoding:'utf8'});
|
||||
//var dbgout = FS.readFile("main.cdb", {encoding:'utf8'});
|
||||
// 0000 21 02 00 [10] 52 ld hl, #2
|
||||
// TODO: offset by start address?
|
||||
var asmlines = parseListing(lstout, /^\s*([0-9A-F]+)\s+([0-9A-F][0-9A-F r]*[0-9A-F])\s+\[([0-9 ]+)\]\s+(\d+) (.*)/i, 4, 1, 2, 5, 3);
|
||||
var srclines = parseSourceLines(lstout, /^\s+\d+ ;\(null\):(\d+):/i, /^\s*([0-9A-F]{4})/i);
|
||||
console.log(lstout); // TODO
|
||||
// parse symbol map
|
||||
var symbolmap = {};
|
||||
for (var s of mapout.split("\n")) {
|
||||
var toks = s.split(" ");
|
||||
if (s[0] == 'DEF') {
|
||||
symbolmap[s[1]] = s[2];
|
||||
}
|
||||
}
|
||||
return {
|
||||
exitstatus:LDZ80.EXITSTATUS,
|
||||
output:parseIHX(hexout, params.code_start, params.code_size),
|
||||
lines:ccompile ? srclines : asmlines,
|
||||
listing:ccompile ? asmlines : null,
|
||||
lines:asmlines,
|
||||
srclines:srclines,
|
||||
errors:msvc_errors, // TODO?
|
||||
intermediate:{listing:lstout, map:mapout, symbols:symout, debug:dbgout},
|
||||
symbolmap:symbolmap,
|
||||
intermediate:{listing:lstout},
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -589,7 +591,7 @@ function compileSDCC(code, platform) {
|
||||
setupFS(FS);
|
||||
//FS.writeFile("main.c", code, {encoding:'utf8'});
|
||||
msvc_errors = [];
|
||||
SDCC.callMain(['--vc', '--c1mode', '--std-sdcc99', '-mz80',
|
||||
SDCC.callMain(['--vc', '--c1mode', '--std-sdcc99', '-mz80', '-Wall',
|
||||
'--debug',
|
||||
//'--asm=z80asm',
|
||||
'--fomit-frame-pointer', '--opt-code-speed',
|
||||
@ -599,8 +601,12 @@ function compileSDCC(code, platform) {
|
||||
} catch(e) {
|
||||
return {errors:msvc_errors};
|
||||
}
|
||||
var warnings = msvc_errors;
|
||||
var result = assemblelinkSDASZ80(asmout, platform, true);
|
||||
result.errors = result.errors.concat(msvc_errors);
|
||||
result.asmlines = result.lines;
|
||||
result.lines = result.srclines;
|
||||
result.srclines = null;
|
||||
result.errors = result.errors.concat(warnings);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user