diff --git a/src/emu.js b/src/emu.js index 8c32cd50..f851695c 100644 --- a/src/emu.js +++ b/src/emu.js @@ -469,6 +469,12 @@ var Base6502Platform = function() { this.cpuStateToLongString = function(c) { return cpuStateToLongString_6502(c); } + this.getToolForFilename = function(fn) { + if (fn.endsWith(".pla")) return "plasm"; + if (fn.endsWith(".c")) return "cc65"; + if (fn.endsWith(".s")) return "ca65"; + return "dasm"; + } } function dumpRAM(ram, ramofs, ramlen) { @@ -619,4 +625,14 @@ var BaseZ80Platform = function() { this.cpuStateToLongString = function(c) { return cpuStateToLongString_Z80(c); } + this.getToolForFilename = function(fn) { + if (fn.endsWith(".c")) return "sdcc"; + return "z80asm"; + } +} + +function padBytes(data, len) { + var r = new RAM(len); + r.mem.set(data); + return r.mem; } diff --git a/src/platform/spaceinv.js b/src/platform/spaceinv.js index fefb3acb..9e639d0d 100644 --- a/src/platform/spaceinv.js +++ b/src/platform/spaceinv.js @@ -177,7 +177,7 @@ var SpaceInvadersPlatform = function(mainElement) { } this.loadROM = function(title, data) { - rom = data; + rom = padBytes(data, 0x2000); self.reset(); } diff --git a/src/platform/vcs.js b/src/platform/vcs.js index c912190e..a9eace28 100644 --- a/src/platform/vcs.js +++ b/src/platform/vcs.js @@ -113,6 +113,9 @@ var VCSPlatform = function() { var ram = self.getRAMForState(state); return "\n" + dumpRAM(ram, 0x80, 0x80); } + this.getToolForFilename = function(fn) { + return "dasm"; + } }; PLATFORMS['vcs'] = VCSPlatform; diff --git a/src/ui.js b/src/ui.js index d1f6c792..3a99936e 100644 --- a/src/ui.js +++ b/src/ui.js @@ -202,7 +202,7 @@ function _shareFile(e) { $.post({ url: 'share.php', data: { - 'platform':'vcs', /// TODO + 'platform':platform_id, 'filename':current_preset_id.split('/').pop(), 'text':text, }, @@ -275,16 +275,9 @@ function updateSelector() { }); } -function getToolForFilename(fn) { - if (fn.endsWith(".pla")) return "plasm"; - if (fn.endsWith(".c")) return "cc65"; - if (fn.endsWith(".s")) return "ca65"; - if (fn.endsWith(".asm")) return "z80asm"; - return "dasm"; -} - function setCode(text) { - worker.postMessage({code:text, tool:getToolForFilename(current_preset_id)}); + worker.postMessage({code:text, platform:platform_id, + tool:platform.getToolForFilename(current_preset_id)}); } function arrayCompare(a,b) { @@ -301,10 +294,10 @@ function arrayCompare(a,b) { worker.onmessage = function(e) { // errors? var toolbar = $("#controls_top"); - if (e.data.listing.errors.length > 0) { + if (e.data.errors.length > 0) { toolbar.addClass("has-errors"); editor.clearGutter("gutter-info"); - for (info of e.data.listing.errors) { + for (info of e.data.errors) { var div = document.createElement("div"); div.setAttribute("class", "tooltipbox tooltiperror"); div.style.color = '#ff3333'; // TODO @@ -342,7 +335,7 @@ worker.onmessage = function(e) { editor.clearGutter("gutter-clock"); offset2line = {}; line2offset = {}; - for (var info of e.data.listing.lines) { + 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); diff --git a/src/worker/workermain.js b/src/worker/workermain.js index 7b6792be..803bc71b 100644 --- a/src/worker/workermain.js +++ b/src/worker/workermain.js @@ -72,14 +72,14 @@ var print_fn = function(s) { } // test.c(6) : warning 85: in function main unreferenced local variable : 'x' -var re_msvc = /(.*?)[(](\d+)[)]\s*:\s*(\w+)\s*(\d+):\s*(.*)/; +var re_msvc = /(.*?)[(](\d+)[)]\s*:\s*(\w+)\s*(\d+):\s*(.*)/; +var re_msvc2 = /\s*at\s+(\d+)\s*:\s*(.*)/; var msvc_errors; function match_msvc(s) { - var matches = re_msvc.exec(s); - console.log(s, matches); + var matches = re_msvc.exec(s) || re_msvc2.exec(s); if (matches) { - errline = parseInt(matches[1]); + var errline = parseInt(matches[1]); msvc_errors.push({ line:errline, msg:matches[2] @@ -87,22 +87,19 @@ function match_msvc(s) { } } -function parseListing(code, lineMatch) { +function parseListing(code, lineMatch, iline, ioffset, iinsns) { var lines = []; for (var line of code.split(/\r?\n/)) { var linem = lineMatch.exec(line); if (linem && linem[1]) { - var linenum = parseInt(linem[1]); - var filename = linem[2]; - var offset = parseInt(linem[3], 16); - var insns = linem[4]; - var restline = linem[5]; + var linenum = parseInt(linem[iline]); + var offset = parseInt(linem[ioffset], 16); + var insns = linem[iinsns]; if (insns) { lines.push({ line:linenum, offset:offset, insns:insns, - iscode:restline[0] != '.' }); } } @@ -193,7 +190,8 @@ function assembleDASM(code) { return { exitstatus:Module.EXITSTATUS, output:aout.slice(2), - listing:listing, + lines:listing.lines, + errors:listing.errors, intermediate:{listing:alst}, }; } @@ -224,16 +222,17 @@ function assembleACME(code) { // TODO: --msvc Module.callMain(["-o", "a.out", "-r", "a.rpt", "-l", "a.sym", "--setpc", "24576", "main.a"]); if (errors.length) { - return {listing:{errors:errors}}; + return {errors:errors}; } var aout = FS.readFile("a.out"); var alst = FS.readFile("a.rpt", {'encoding':'utf8'}); var asym = FS.readFile("a.sym", {'encoding':'utf8'}); - var listing = parseDASMListing(alst, {}); + var listing = parseDASMListing(alst, {}); // TODO return { exitstatus:Module.EXITSTATUS, output:aout, - listing:listing, + lines:listing.lines, + errors:listing.errors, intermediate:{listing:alst, symbols:asym}, }; } @@ -281,7 +280,7 @@ function compilePLASMA(code) { Module.callMain(["-A"]); outstr = "INTERP = $e044\n" + outstr; // TODO if (errors.length) { - return {listing:{errors:errors}}; + return {errors:errors}; } return assembleACME(outstr); } @@ -317,8 +316,6 @@ function parseCA65Listing(code, mapfile) { function assemblelinkCA65(code, platform, warnings) { load("ca65"); load("ld65"); - if (!platform) - platform = 'apple2'; // TODO var objout, lstout; { var CA65 = ca65({ @@ -350,10 +347,12 @@ function assemblelinkCA65(code, platform, warnings) { '-t', platform, '-o', 'main', '-m', 'main.map', 'main.o', platform+'.lib']); var aout = FS.readFile("main", {encoding:'binary'}); var mapout = FS.readFile("main.map", {encoding:'utf8'}); + var listing = parseCA65Listing(lstout, mapout); return { exitstatus:LD65.EXITSTATUS, output:aout.slice(4), - listing:parseCA65Listing(lstout, mapout), + lines:listing.lines, + errors:listing.errors, intermediate:{listing:lstout, map:mapout}, }; } @@ -361,8 +360,6 @@ function assemblelinkCA65(code, platform, warnings) { function compileCC65(code, platform) { load("cc65"); - if (!platform) - platform = 'apple2'; // TODO // stderr var re_err1 = /.*?(\d+).*?: (.+)/; var errors = []; @@ -392,14 +389,12 @@ function compileCC65(code, platform) { var asmout = FS.readFile("main.s", {encoding:'utf8'}); return assemblelinkCA65(asmout, platform, errors); } catch(e) { - return {listing:{errors:errors}}; + return {errors:errors}; } } -function assembleZ80ASM(code, platform) { +function assembleZ80ASM(code, platform, ccompile) { load("z80asm"); - if (!platform) - platform = 'apple2'; // TODO var Module = z80asm({ noInitialRun:true, //logReadFiles:true, @@ -412,15 +407,17 @@ function assembleZ80ASM(code, platform) { //setupFS(FS); // changes for dialect code = code.replace(".optsdcc -mz80",""); + code = code.replace(/^(\w+)\s*=/gim,"DEFC $1 ="); code = code.replace(/\tXREF /gi,"\tEXTERN "); code = code.replace(/\tXDEF /gi,"\tPUBLIC "); + //console.log(code.split("\n")); FS.writeFile("main.asm", code); try { Module.callMain(["-b", "-s", "-l", "-m", "main.asm"]); try { var aerr = FS.readFile("main.err", {'encoding':'utf8'}); // TODO if (aerr.length) { - return {listing:{errors:extractErrors(aerr.split("\n"), /.+? line (\d+): (.+)/)}}; + return {errors:extractErrors(aerr.split("\n"), /.+? line (\d+): (.+)/)}; } // Warning at file 'test.asm' line 9: 'XREF' is deprecated, use 'EXTERN' instead } catch (e) { @@ -436,14 +433,13 @@ l_main00101 = 0003, L: test */ var amap = FS.readFile("main.map", {'encoding':'utf8'}); // TODO var aout = FS.readFile("main.bin", {'encoding':'binary'}); - var listing = parseDASMListing(alst, {}); // TODO + var asmlines = parseListing(alst, /(\d+)(\s+)([0-9A-F]+)\s+([0-9A-F][0-9A-F ]*[0-9A-F])\s+([A-Z_.].+)/i, 1, 2, 3); + var srclines = parseListing(alst, /(\d+)\s+([0-9A-F]+)\s+;[(]null[)]:(\d+)/i, 3, 2, 1); return { exitstatus:Module.EXITSTATUS, output:aout, - listing:{ - errors:[], - lines:parseListing(alst, /(\d+)(\s+)([0-9A-F]+)\s+([0-9A-F][0-9A-F ]*[0-9A-F])\s+([A-Z_.].+)/i) - }, + errors:[], + lines:ccompile ? srclines : asmlines, intermediate:{listing:alst, mapfile:amap}, }; } catch (e) { @@ -470,14 +466,17 @@ function compileSDCC(code, platform) { '-mz80', '--asm=z80asm', '-o', 'test.asm']); try { var asmout = FS.readFile("test.asm", {encoding:'utf8'}); - return assembleZ80ASM(asmout, platform, msvc_errors); + var result = assembleZ80ASM(asmout, platform, true); + result.errors = result.errors.concat(msvc_errors); + return result; } catch(e) { - return {listing:{errors:msvc_errors}}; + return {errors:msvc_errors}; } } -var tools = { +var TOOLS = { 'dasm': assembleDASM, + 'acme': assembleACME, 'plasm': compilePLASMA, 'cc65': compileCC65, 'ca65': assemblelinkCA65, @@ -488,7 +487,7 @@ var tools = { onmessage = function(e) { var code = e.data.code; var platform = e.data.platform; - var toolfn = tools[e.data.tool]; + var toolfn = TOOLS[e.data.tool]; if (!toolfn) throw "no tool named " + e.data.tool; var result = toolfn(code, platform); if (result) { diff --git a/test/cli/worker.js b/test/cli/worker.js index 46439293..3d192e6b 100644 --- a/test/cli/worker.js +++ b/test/cli/worker.js @@ -59,40 +59,46 @@ global.postMessage = null; includeInThisContext("src/worker/workermain.js"); -function compile(tool, code, callback, outlen, nlines, nerrors) { +function compile(tool, code, platform, callback, outlen, nlines, nerrors) { global.postMessage = function(msg) { - if (msg.listing.errors && msg.listing.errors.length) { - console.log(msg.listing.errors); - assert.equal(nerrors, msg.listing.errors.length, "errors"); + if (msg.errors && msg.errors.length) { + console.log(msg.errors); + assert.equal(nerrors, msg.errors.length, "errors"); } else { assert.equal(nerrors||0, 0, "errors"); assert.equal(msg.output.length, outlen, "output binary"); - assert.equal(msg.listing.lines.length, nlines, "listing lines"); + assert.equal(msg.lines.length, nlines, "listing lines"); } callback(null, msg); }; global.onmessage({ - data:{code:code, tool:tool} + data:{code:code, platform:platform, tool:tool} }); } describe('Worker', function() { it('should assemble DASM', function(done) { - compile('dasm', '\tprocessor 6502\n\torg $f000\nfoo lda #0\n', done, 2, 1); + compile('dasm', '\tprocessor 6502\n\torg $f000\nfoo lda #0\n', 'vcs', done, 2, 1); + }); + it('should assemble ACME', function(done) { + compile('acme', 'foo: lda #0\n', 'vcs', done, 2, 0); // TODO }); it('should compile PLASMA', function(done) { - compile('plasm', 'word x = 0', done, 5, 0); + compile('plasm', 'word x = 0', 'apple2', done, 5, 0); }); it('should compile CC65', function(done) { - compile('cc65', '#include \nint main() {\nint x=1;\nprintf("%d",x);\nreturn x+2;\n}', done, 2947, 4); + compile('cc65', '#include \nint main() {\nint x=1;\nprintf("%d",x);\nreturn x+2;\n}', 'apple2', done, 2947, 4); }); it('should NOT assemble Z80ASM', function(done) { - compile('z80asm', 'ddwiuweq', done, 0, 0, 1); + compile('z80asm', 'ddwiuweq', 'none', done, 0, 0, 1); }); it('should assemble Z80ASM', function(done) { - compile('z80asm', '\tMODULE test\n\tXREF _puts\n\tld hl,$0000\n\tret\n', done, 4, 2, 0); + compile('z80asm', '\tMODULE test\n\tXREF _puts\n\tld hl,$0000\n\tret\n', 'none', done, 4, 2, 0); + }); + it('should NOT compile SDCC', function(done) { + compile('sdcc', 'foobar', 'none', done, 0, 0, 1); }); it('should compile SDCC', function(done) { - compile('sdcc', 'int main(int argc) {\nint x=1; int y=2;\nreturn x+y+argc;\n}', done, 16, 8, 0); + compile('sdcc', 'int main(int argc) {\nint x=1; int y=2;\nreturn x+y+argc;\n}', 'none', done, 16, 2, 0); }); });