2017-01-06 00:14:12 +00:00
|
|
|
"use strict";
|
2017-01-09 21:28:20 +00:00
|
|
|
|
2017-01-26 05:09:57 +00:00
|
|
|
var PLATFORM_PARAMS = {
|
|
|
|
'mw8080bw': {
|
|
|
|
code_start: 0x0,
|
2017-05-02 13:09:53 +00:00
|
|
|
rom_size: 0x2000,
|
2017-01-26 05:09:57 +00:00
|
|
|
data_start: 0x2000,
|
|
|
|
data_size: 0x400,
|
2017-04-22 01:56:49 +00:00
|
|
|
stack_end: 0x2400,
|
2017-01-26 05:09:57 +00:00
|
|
|
},
|
|
|
|
'vicdual': {
|
|
|
|
code_start: 0x0,
|
2017-05-02 13:09:53 +00:00
|
|
|
rom_size: 0x4020,
|
2017-02-18 22:50:51 +00:00
|
|
|
data_start: 0xe400,
|
2017-01-26 05:09:57 +00:00
|
|
|
data_size: 0x400,
|
2017-04-22 01:56:49 +00:00
|
|
|
stack_end: 0xe800,
|
2017-01-26 05:09:57 +00:00
|
|
|
},
|
|
|
|
'galaxian': {
|
|
|
|
code_start: 0x0,
|
2017-05-02 13:09:53 +00:00
|
|
|
rom_size: 0x4000,
|
2017-01-26 05:09:57 +00:00
|
|
|
data_start: 0x4000,
|
|
|
|
data_size: 0x400,
|
2017-04-22 01:56:49 +00:00
|
|
|
stack_end: 0x4800,
|
2017-01-26 05:09:57 +00:00
|
|
|
},
|
2017-02-15 21:03:52 +00:00
|
|
|
'galaxian-scramble': {
|
|
|
|
code_start: 0x0,
|
2017-05-02 13:09:53 +00:00
|
|
|
rom_size: 0x5020,
|
2017-02-15 21:03:52 +00:00
|
|
|
data_start: 0x4000,
|
|
|
|
data_size: 0x400,
|
2017-04-22 01:56:49 +00:00
|
|
|
stack_end: 0x4800,
|
2017-02-15 21:03:52 +00:00
|
|
|
},
|
2017-01-29 21:06:05 +00:00
|
|
|
'williams-z80': {
|
|
|
|
code_start: 0x0,
|
2017-05-02 13:09:53 +00:00
|
|
|
rom_size: 0x9800,
|
2017-03-28 16:22:33 +00:00
|
|
|
data_start: 0x9800,
|
|
|
|
data_size: 0x2800,
|
2017-04-22 01:56:49 +00:00
|
|
|
stack_end: 0xc000,
|
2017-01-29 21:06:05 +00:00
|
|
|
},
|
2017-02-05 04:19:54 +00:00
|
|
|
'vector-z80color': {
|
2017-02-01 18:21:17 +00:00
|
|
|
code_start: 0x0,
|
2017-05-02 13:09:53 +00:00
|
|
|
rom_size: 0x8000,
|
2017-02-05 04:19:54 +00:00
|
|
|
data_start: 0xe000,
|
|
|
|
data_size: 0x2000,
|
2017-04-22 01:56:49 +00:00
|
|
|
stack_end: 0x0,
|
2017-02-01 18:21:17 +00:00
|
|
|
},
|
2017-04-02 18:54:51 +00:00
|
|
|
'sound_williams-z80': {
|
|
|
|
code_start: 0x0,
|
2017-05-02 13:09:53 +00:00
|
|
|
rom_size: 0x4000,
|
2017-04-02 18:54:51 +00:00
|
|
|
data_start: 0x4000,
|
2017-04-15 04:12:21 +00:00
|
|
|
data_size: 0x400,
|
2017-04-22 01:56:49 +00:00
|
|
|
stack_end: 0x8000,
|
2017-04-02 18:54:51 +00:00
|
|
|
},
|
2017-04-29 15:31:11 +00:00
|
|
|
'base_z80': {
|
|
|
|
code_start: 0x0,
|
2017-05-02 13:09:53 +00:00
|
|
|
rom_size: 0x8000,
|
2017-04-29 15:31:11 +00:00
|
|
|
data_start: 0x8000,
|
|
|
|
data_size: 0x8000,
|
|
|
|
stack_end: 0x0,
|
|
|
|
},
|
2017-05-01 11:37:48 +00:00
|
|
|
'coleco': {
|
2017-05-02 13:09:53 +00:00
|
|
|
rom_start: 0x8000,
|
|
|
|
code_start: 0x8100,
|
2018-06-18 08:12:52 +00:00
|
|
|
code_offset: 0x8147, // TODO: right after cv_start()
|
2017-05-02 13:09:53 +00:00
|
|
|
rom_size: 0x8000,
|
|
|
|
data_start: 0x7000,
|
2017-05-01 11:37:48 +00:00
|
|
|
data_size: 0x400,
|
|
|
|
stack_end: 0x8000,
|
2017-05-21 03:40:05 +00:00
|
|
|
extra_preproc_args: ['-I', '/share/include/coleco'],
|
|
|
|
extra_link_args: ['-k', '/share/lib/coleco',
|
2017-05-21 21:34:57 +00:00
|
|
|
'-l', 'libcv', '-l', 'libcvu', '/share/lib/coleco/crt0.rel',
|
|
|
|
//'-l', 'comp.lib', '-l', 'cvlib.lib', '-l', 'getput.lib', '/share/lib/coleco/crtcv.rel',
|
2017-05-21 03:40:05 +00:00
|
|
|
'main.rel'],
|
2017-05-01 11:37:48 +00:00
|
|
|
},
|
2017-05-21 21:34:57 +00:00
|
|
|
'nes-conio': {
|
|
|
|
cfgfile: 'nes.cfg',
|
2018-06-18 08:12:52 +00:00
|
|
|
define: '__NES__',
|
2017-05-21 21:34:57 +00:00
|
|
|
libargs: ['nes.lib'],
|
|
|
|
},
|
|
|
|
'nes-lib': {
|
|
|
|
define: '__NES__',
|
|
|
|
cfgfile: 'neslib.cfg',
|
|
|
|
libargs: ['neslib.lib', 'nes.lib'],
|
|
|
|
},
|
2017-12-30 17:48:30 +00:00
|
|
|
'apple2': {
|
|
|
|
define: '__APPLE2__',
|
2018-06-20 07:09:37 +00:00
|
|
|
cfgfile: 'apple2-hgr.cfg',
|
2017-12-30 17:48:30 +00:00
|
|
|
libargs: ['apple2.lib'],
|
2018-06-21 18:15:05 +00:00
|
|
|
code_offset: 0x803, // TODO: parse segment list
|
2017-12-30 17:48:30 +00:00
|
|
|
},
|
2018-06-18 08:12:52 +00:00
|
|
|
'apple2-e': {
|
|
|
|
define: '__APPLE2__',
|
|
|
|
cfgfile: 'apple2.cfg',
|
|
|
|
libargs: ['apple2.lib'],
|
2018-06-20 08:06:18 +00:00
|
|
|
},
|
2018-06-22 06:24:52 +00:00
|
|
|
'atari8-800': {
|
|
|
|
define: '__ATARI__',
|
|
|
|
cfgfile: 'atari-cart.cfg',
|
|
|
|
libargs: ['atari.lib'],
|
|
|
|
code_offset: 0xa000, // TODO
|
|
|
|
},
|
2018-06-20 08:06:18 +00:00
|
|
|
'atari8-5200': {
|
2018-06-21 18:15:05 +00:00
|
|
|
define: '__ATARI5200__',
|
|
|
|
cfgfile: 'atari5200.cfg',
|
2018-06-20 08:06:18 +00:00
|
|
|
libargs: ['atari5200.lib'],
|
2018-06-22 06:24:52 +00:00
|
|
|
code_offset: 0x4000, // TODO
|
|
|
|
},
|
|
|
|
'c64': {
|
|
|
|
define: '__C64__',
|
|
|
|
cfgfile: 'c64.cfg',
|
|
|
|
libargs: ['c64.lib'],
|
|
|
|
code_offset: 0x4000, // TODO
|
2018-06-18 08:12:52 +00:00
|
|
|
},
|
2017-11-11 19:45:32 +00:00
|
|
|
'verilog': {
|
|
|
|
},
|
2017-01-26 05:09:57 +00:00
|
|
|
};
|
|
|
|
|
2017-01-10 08:18:54 +00:00
|
|
|
// shim out window and document objects for security
|
|
|
|
// https://github.com/mbostock/d3/issues/1053
|
|
|
|
var noop = function() { return new Function(); };
|
|
|
|
var window = noop();
|
|
|
|
window.CSSStyleDeclaration = noop();
|
|
|
|
window.CSSStyleDeclaration.setProperty = noop();
|
|
|
|
window.Element = noop();
|
|
|
|
window.Element.setAttribute = noop();
|
|
|
|
window.Element.setAttributeNS = noop();
|
|
|
|
window.navigator = noop();
|
|
|
|
var document = noop();
|
|
|
|
document.documentElement = noop();
|
|
|
|
document.documentElement.style = noop();
|
|
|
|
|
2017-11-07 21:41:07 +00:00
|
|
|
var _t1, _t2;
|
|
|
|
function starttime() { _t1 = new Date(); }
|
|
|
|
function endtime(msg) { _t2 = new Date(); console.log(msg, _t2.getTime() - _t1.getTime(), "ms"); }
|
|
|
|
|
2017-01-23 21:21:45 +00:00
|
|
|
var fsMeta = {};
|
|
|
|
var fsBlob = {};
|
2017-11-05 18:34:00 +00:00
|
|
|
var wasmBlob = {};
|
2017-01-23 21:21:45 +00:00
|
|
|
|
2017-01-10 08:18:54 +00:00
|
|
|
// load filesystems for CC65 and others asynchronously
|
2017-01-23 21:21:45 +00:00
|
|
|
function loadFilesystem(name) {
|
2017-01-06 00:14:12 +00:00
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.responseType = 'blob';
|
2017-01-23 21:21:45 +00:00
|
|
|
xhr.open("GET", "fs"+name+".data", false); // synchronous request
|
2017-01-06 00:14:12 +00:00
|
|
|
xhr.send(null);
|
2017-01-23 21:21:45 +00:00
|
|
|
fsBlob[name] = xhr.response;
|
2017-01-06 00:14:12 +00:00
|
|
|
xhr = new XMLHttpRequest();
|
|
|
|
xhr.responseType = 'json';
|
2017-01-23 21:21:45 +00:00
|
|
|
xhr.open("GET", "fs"+name+".js.metadata", false); // synchronous request
|
2017-01-06 00:14:12 +00:00
|
|
|
xhr.send(null);
|
2017-01-23 21:21:45 +00:00
|
|
|
fsMeta[name] = xhr.response;
|
|
|
|
console.log("Loaded "+name+" filesystem", fsMeta[name].files.length, 'files', fsBlob[name].size, 'bytes');
|
2017-01-06 00:14:12 +00:00
|
|
|
}
|
|
|
|
|
2017-11-05 18:34:00 +00:00
|
|
|
var loaded = {}
|
|
|
|
function load(modulename, debug) {
|
|
|
|
if (!loaded[modulename]) {
|
|
|
|
importScripts(modulename+(debug?"."+debug+".js":".js"));
|
|
|
|
loaded[modulename] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function loadWASM(modulename, debug) {
|
|
|
|
if (!loaded[modulename]) {
|
|
|
|
importScripts("wasm/" + modulename+(debug?"."+debug+".js":".js"));
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.responseType = 'arraybuffer';
|
|
|
|
xhr.open("GET", "wasm/"+modulename+".wasm", false); // synchronous request
|
|
|
|
xhr.send(null);
|
|
|
|
if (xhr.response) {
|
|
|
|
wasmBlob[modulename] = xhr.response; //new Uint8Array(xhr.response);
|
|
|
|
console.log("Loaded " + modulename + ".wasm");
|
|
|
|
loaded[modulename] = 1;
|
|
|
|
} else {
|
2018-03-03 02:41:56 +00:00
|
|
|
throw Error("Could not load WASM file " + modulename + ".wasm");
|
2017-11-05 18:34:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-07 21:41:07 +00:00
|
|
|
function loadNative(modulename, debug) {
|
|
|
|
// detect WASM
|
|
|
|
if (typeof WebAssembly === 'object') {
|
|
|
|
loadWASM(modulename);
|
|
|
|
return wasmBlob['sdcc'];
|
|
|
|
} else {
|
|
|
|
load(modulename);
|
|
|
|
}
|
|
|
|
}
|
2017-11-05 18:34:00 +00:00
|
|
|
|
2017-04-12 02:46:06 +00:00
|
|
|
var ATARI_CFG =
|
2017-04-23 13:03:05 +00:00
|
|
|
"FEATURES {\nSTARTADDRESS: default = $9000;\n}\n"
|
2017-04-12 02:46:06 +00:00
|
|
|
+ "MEMORY {\n"
|
2017-04-23 13:03:05 +00:00
|
|
|
+ " ZP: file = \"\", start = $82, size = $7E, type = rw, define = yes;\n"
|
|
|
|
+ " RAM: file = \"\", start = $0200, size = $1e00, define = yes;\n"
|
|
|
|
+ " ROM: file = %O, start = $9000, size = $7000;\n"
|
|
|
|
+ " ROMV: file = %O, start = $FFFA, size = $0006, fill = yes;\n"
|
2017-04-12 02:46:06 +00:00
|
|
|
+ "}\n"
|
|
|
|
+ "SEGMENTS {\n"
|
2017-04-23 13:03:05 +00:00
|
|
|
+ "ZEROPAGE: load = ZP, type = zp, define = yes;\n"
|
|
|
|
+ " STARTUP: load = ROM, type = ro, define = yes;\n"
|
|
|
|
+ " ONCE: load = ROM, type = ro, define = yes;\n"
|
|
|
|
+ " CODE: load = ROM, type = ro, define = yes;\n"
|
|
|
|
+ " DATA: load = RAM, type = rw, define = yes, run = RAM;\n"
|
|
|
|
+ " INIT: load = RAM, type = rw, define = yes;\n"
|
|
|
|
+ " BSS: load = RAM, type = bss, define = yes;\n"
|
|
|
|
+ " HEAP: load = RAM, type = bss, optional = yes;\n"
|
|
|
|
+ " RODATA: load = ROM, type = ro;\n"
|
|
|
|
+ "}\n"
|
|
|
|
+ "FEATURES {\n"
|
|
|
|
+ " CONDES: segment = STARTUP,\n"
|
|
|
|
+ " type = constructor,\n"
|
|
|
|
+ " label = __CONSTRUCTOR_TABLE__,\n"
|
|
|
|
+ " count = __CONSTRUCTOR_COUNT__;\n"
|
|
|
|
+ " CONDES: segment = STARTUP,\n"
|
|
|
|
+ " type = destructor,\n"
|
|
|
|
+ " label = __DESTRUCTOR_TABLE__,\n"
|
|
|
|
+ " count = __DESTRUCTOR_COUNT__;\n"
|
2017-04-12 02:46:06 +00:00
|
|
|
+ "}\n"
|
|
|
|
+ "SYMBOLS {\n"
|
2017-04-23 13:03:05 +00:00
|
|
|
+ " __STACKSIZE__: type = weak, value = $0400;\n"
|
|
|
|
+ " __LC_LAST__: type = weak, value = $0400;\n"
|
|
|
|
+ " __LC_START__: type = weak, value = $0400;\n"
|
2017-04-12 02:46:06 +00:00
|
|
|
+ "}\n"
|
2017-04-23 13:03:05 +00:00
|
|
|
;
|
|
|
|
/*
|
2017-04-12 02:46:06 +00:00
|
|
|
+ "MEMORY {\n"
|
|
|
|
+ " ZP: file = \"\", define = yes, start = $0082, size = $007E;\n"
|
|
|
|
+ " MAIN: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S;\n"
|
|
|
|
+ "}\n"
|
|
|
|
+ "SEGMENTS {\n"
|
|
|
|
+ " ZEROPAGE: load = ZP, type = zp, optional = yes;\n"
|
|
|
|
+ " EXTZP: load = ZP, type = zp, optional = yes;\n"
|
|
|
|
+ " STARTUP: load = MAIN, type = ro, define = yes, optional = yes;\n"
|
|
|
|
+ " LOWCODE: load = MAIN, type = ro, define = yes, optional = yes;\n"
|
|
|
|
+ " ONCE: load = MAIN, type = ro, optional = yes;\n"
|
|
|
|
+ " CODE: load = MAIN, type = ro, define = yes;\n"
|
|
|
|
+ " RODATA: load = MAIN, type = ro, optional = yes;\n"
|
|
|
|
+ " DATA: load = MAIN, type = rw, optional = yes;\n"
|
|
|
|
+ " BSS: load = MAIN, type = bss, define = yes, optional = yes;\n"
|
|
|
|
+ " INIT: load = MAIN, type = bss, optional = yes;\n"
|
|
|
|
+ "}\n"
|
|
|
|
+ "FEATURES {\n"
|
|
|
|
+ " CONDES: type = constructor,\n"
|
|
|
|
+ " label = __CONSTRUCTOR_TABLE__,\n"
|
|
|
|
+ " count = __CONSTRUCTOR_COUNT__,\n"
|
|
|
|
+ " segment = ONCE;\n"
|
|
|
|
+ " CONDES: type = destructor,\n"
|
|
|
|
+ " label = __DESTRUCTOR_TABLE__,\n"
|
|
|
|
+ " count = __DESTRUCTOR_COUNT__,\n"
|
|
|
|
+ " segment = RODATA;\n"
|
|
|
|
+ " CONDES: type = interruptor,\n"
|
|
|
|
+ " label = __INTERRUPTOR_TABLE__,\n"
|
|
|
|
+ " count = __INTERRUPTOR_COUNT__,\n"
|
|
|
|
+ " segment = RODATA,\n"
|
|
|
|
+ " import = __CALLIRQ__;\n"
|
|
|
|
+ "}\n";
|
|
|
|
*/
|
|
|
|
|
2017-01-10 08:18:54 +00:00
|
|
|
// mount the filesystem at /share
|
2017-01-23 21:21:45 +00:00
|
|
|
function setupFS(FS, name) {
|
2017-01-06 00:14:12 +00:00
|
|
|
FS.mkdir('/share');
|
|
|
|
FS.mount(FS.filesystems['WORKERFS'], {
|
2017-01-23 21:21:45 +00:00
|
|
|
packages: [{ metadata: fsMeta[name], blob: fsBlob[name] }]
|
2017-01-06 00:14:12 +00:00
|
|
|
}, '/share');
|
2017-04-12 02:46:06 +00:00
|
|
|
FS.writeFile("/vector-ataricolor.cfg", ATARI_CFG);
|
2017-01-06 00:14:12 +00:00
|
|
|
}
|
2016-12-16 01:21:51 +00:00
|
|
|
|
2017-01-04 21:07:59 +00:00
|
|
|
var DASM_MAIN_FILENAME = "main.a";
|
|
|
|
var DASM_PREAMBLE = "\tprocessor 6502\n";
|
|
|
|
var DASM_PREAMBLE_LINES = 1;
|
2016-12-16 01:21:51 +00:00
|
|
|
|
2017-01-12 16:22:27 +00:00
|
|
|
var print_fn = function(s) {
|
|
|
|
console.log(s);
|
|
|
|
//console.log(new Error().stack);
|
|
|
|
}
|
2017-01-06 00:14:12 +00:00
|
|
|
|
2017-01-13 02:21:35 +00:00
|
|
|
// test.c(6) : warning 85: in function main unreferenced local variable : 'x'
|
2017-01-16 15:35:19 +00:00
|
|
|
// main.a (4): error: Unknown Mnemonic 'xxx'.
|
2017-01-22 14:35:04 +00:00
|
|
|
// at 2: warning 190: ISO C forbids an empty source file
|
2017-01-16 15:35:19 +00:00
|
|
|
var re_msvc = /([^(]+)\s*[(](\d+)[)]\s*:\s*(.+?):\s*(.*)/;
|
|
|
|
var re_msvc2 = /\s*(at)\s+(\d+)\s*(:)\s*(.*)/;
|
2018-06-19 22:42:02 +00:00
|
|
|
|
|
|
|
function msvcErrorMatcher(errors) {
|
|
|
|
return function(s) {
|
|
|
|
var matches = re_msvc.exec(s) || re_msvc2.exec(s);
|
|
|
|
if (matches) {
|
|
|
|
var errline = parseInt(matches[2]);
|
|
|
|
errors.push({
|
|
|
|
line:errline,
|
|
|
|
file:matches[1],
|
|
|
|
type:matches[3],
|
|
|
|
msg:matches[4]
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
console.log(s);
|
|
|
|
}
|
2017-01-13 02:21:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-23 21:21:45 +00:00
|
|
|
function makeErrorMatcher(errors, regex, iline, imsg) {
|
|
|
|
return function(s) {
|
|
|
|
var matches = regex.exec(s);
|
|
|
|
if (matches) {
|
|
|
|
errors.push({
|
2017-11-13 05:24:19 +00:00
|
|
|
line:parseInt(matches[iline]) || 1,
|
2017-01-23 21:21:45 +00:00
|
|
|
msg:matches[imsg]
|
|
|
|
});
|
2017-11-13 05:24:19 +00:00
|
|
|
} else {
|
|
|
|
console.log(s);
|
2017-01-23 21:21:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function extractErrors(regex, strings) {
|
|
|
|
var errors = [];
|
|
|
|
var matcher = makeErrorMatcher(errors, regex, 1, 2);
|
|
|
|
for (var i=0; i<strings.length; i++) {
|
|
|
|
matcher(strings[i]);
|
|
|
|
}
|
|
|
|
return errors;
|
|
|
|
}
|
|
|
|
|
2018-06-18 08:12:52 +00:00
|
|
|
function parseListing(code, lineMatch, iline, ioffset, iinsns, origin) {
|
2017-01-14 02:31:04 +00:00
|
|
|
var lines = [];
|
2018-06-18 08:12:52 +00:00
|
|
|
origin |= 0;
|
2017-01-14 02:31:04 +00:00
|
|
|
for (var line of code.split(/\r?\n/)) {
|
|
|
|
var linem = lineMatch.exec(line);
|
|
|
|
if (linem && linem[1]) {
|
2017-01-15 03:46:12 +00:00
|
|
|
var linenum = parseInt(linem[iline]);
|
|
|
|
var offset = parseInt(linem[ioffset], 16);
|
|
|
|
var insns = linem[iinsns];
|
2017-01-14 02:31:04 +00:00
|
|
|
if (insns) {
|
|
|
|
lines.push({
|
|
|
|
line:linenum,
|
2018-06-18 08:12:52 +00:00
|
|
|
offset:offset + origin,
|
2017-01-14 02:31:04 +00:00
|
|
|
insns:insns,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return lines;
|
|
|
|
}
|
|
|
|
|
2018-06-18 08:12:52 +00:00
|
|
|
function parseSourceLines(code, lineMatch, offsetMatch, origin) {
|
2017-01-15 18:31:52 +00:00
|
|
|
var lines = [];
|
|
|
|
var lastlinenum = 0;
|
2018-06-18 08:12:52 +00:00
|
|
|
origin |= 0;
|
2017-01-15 18:31:52 +00:00
|
|
|
for (var line of code.split(/\r?\n/)) {
|
|
|
|
var linem = lineMatch.exec(line);
|
|
|
|
if (linem && linem[1]) {
|
|
|
|
lastlinenum = parseInt(linem[1]);
|
|
|
|
} else if (lastlinenum) {
|
|
|
|
var linem = offsetMatch.exec(line);
|
|
|
|
if (linem && linem[1]) {
|
|
|
|
var offset = parseInt(linem[1], 16);
|
|
|
|
lines.push({
|
|
|
|
line:lastlinenum,
|
2018-06-18 08:12:52 +00:00
|
|
|
offset:offset + origin,
|
2017-01-15 18:31:52 +00:00
|
|
|
});
|
|
|
|
lastlinenum = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return lines;
|
|
|
|
}
|
|
|
|
|
2017-01-04 21:07:59 +00:00
|
|
|
function parseDASMListing(code, unresolved) {
|
2016-12-16 01:21:51 +00:00
|
|
|
// 4 08ee a9 00 start lda #01workermain.js:23:5
|
2017-01-16 15:35:19 +00:00
|
|
|
var lineMatch = /\s*(\d+)\s+(\S+)\s+([0-9a-f]+)\s+([0-9a-f][0-9a-f ]+)?\s+(.+)?/;
|
2016-12-16 01:21:51 +00:00
|
|
|
var equMatch = /\bequ\b/;
|
|
|
|
var errors = [];
|
|
|
|
var lines = [];
|
|
|
|
var lastline = 0;
|
|
|
|
for (var line of code.split(/\r?\n/)) {
|
|
|
|
var linem = lineMatch.exec(line);
|
|
|
|
if (linem && linem[1]) {
|
2017-01-04 21:07:59 +00:00
|
|
|
var linenum = parseInt(linem[1]) - DASM_PREAMBLE_LINES;
|
2016-12-16 01:21:51 +00:00
|
|
|
var filename = linem[2];
|
|
|
|
var offset = parseInt(linem[3], 16);
|
|
|
|
var insns = linem[4];
|
|
|
|
var restline = linem[5];
|
|
|
|
// inside of main file?
|
2017-01-04 21:07:59 +00:00
|
|
|
if (filename == DASM_MAIN_FILENAME) {
|
2016-12-16 01:21:51 +00:00
|
|
|
if (insns && !restline.match(equMatch)) {
|
|
|
|
lines.push({
|
|
|
|
line:linenum,
|
|
|
|
offset:offset,
|
|
|
|
insns:insns,
|
|
|
|
iscode:restline[0] != '.'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
lastline = linenum;
|
|
|
|
} else {
|
|
|
|
// inside of macro or include file
|
2017-01-16 15:35:19 +00:00
|
|
|
if (insns && linem[3] && lastline>0) {
|
2016-12-16 01:21:51 +00:00
|
|
|
lines.push({
|
|
|
|
line:lastline+1,
|
|
|
|
offset:offset,
|
|
|
|
insns:null
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// TODO: check filename too
|
|
|
|
// TODO: better symbol test (word boundaries)
|
2017-01-03 15:43:40 +00:00
|
|
|
for (var key in unresolved) {
|
2016-12-16 01:21:51 +00:00
|
|
|
var pos = restline ? restline.indexOf(key) : line.indexOf(key);
|
|
|
|
if (pos >= 0) {
|
|
|
|
errors.push({
|
|
|
|
line:linenum,
|
|
|
|
msg:"Unresolved symbol '" + key + "'"
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-01-16 15:35:19 +00:00
|
|
|
var errm = re_msvc.exec(line);
|
2016-12-16 01:21:51 +00:00
|
|
|
if (errm) {
|
|
|
|
errors.push({
|
2017-01-16 15:35:19 +00:00
|
|
|
line:parseInt(errm[2]),
|
|
|
|
msg:errm[4]
|
2016-12-16 01:21:51 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {lines:lines, errors:errors};
|
|
|
|
}
|
|
|
|
|
2017-01-04 21:07:59 +00:00
|
|
|
function assembleDASM(code) {
|
2017-01-14 02:31:04 +00:00
|
|
|
load("dasm");
|
2016-12-16 01:21:51 +00:00
|
|
|
var re_usl = /(\w+)\s+0000\s+[?][?][?][?]/;
|
|
|
|
var unresolved = {};
|
2017-01-06 00:14:12 +00:00
|
|
|
function match_fn(s) {
|
2016-12-16 01:21:51 +00:00
|
|
|
var matches = re_usl.exec(s);
|
|
|
|
if (matches) {
|
|
|
|
unresolved[matches[1]] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var Module = DASM({
|
|
|
|
noInitialRun:true,
|
2017-01-06 00:14:12 +00:00
|
|
|
print:match_fn
|
2016-12-16 01:21:51 +00:00
|
|
|
});
|
|
|
|
var FS = Module['FS'];
|
2017-01-04 21:07:59 +00:00
|
|
|
FS.writeFile(DASM_MAIN_FILENAME, DASM_PREAMBLE + code);
|
2017-01-16 15:35:19 +00:00
|
|
|
Module.callMain([DASM_MAIN_FILENAME, "-la.lst"/*, "-v3", "-sa.sym"*/]);
|
2016-12-16 01:21:51 +00:00
|
|
|
var aout = FS.readFile("a.out");
|
|
|
|
var alst = FS.readFile("a.lst", {'encoding':'utf8'});
|
2017-01-16 15:35:19 +00:00
|
|
|
//var asym = FS.readFile("a.sym", {'encoding':'utf8'});
|
2017-01-04 21:07:59 +00:00
|
|
|
var listing = parseDASMListing(alst, unresolved);
|
2017-01-10 08:18:54 +00:00
|
|
|
return {
|
|
|
|
output:aout.slice(2),
|
2017-01-15 03:46:12 +00:00
|
|
|
lines:listing.lines,
|
|
|
|
errors:listing.errors,
|
2017-01-10 08:18:54 +00:00
|
|
|
intermediate:{listing:alst},
|
|
|
|
};
|
2017-01-04 21:07:59 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 00:14:12 +00:00
|
|
|
// TODO: not quite done
|
2017-01-04 21:07:59 +00:00
|
|
|
function assembleACME(code) {
|
2017-01-14 02:31:04 +00:00
|
|
|
load("acme");
|
2017-01-10 08:18:54 +00:00
|
|
|
// stderr
|
|
|
|
var re_err2 = /(Error|Warning) - File (.+?), line (\d+) ([^:]+) (.*)/;
|
|
|
|
var errors = [];
|
|
|
|
var errline = 0;
|
2017-01-06 00:14:12 +00:00
|
|
|
function match_fn(s) {
|
2017-01-10 08:18:54 +00:00
|
|
|
var matches = re_err2.exec(s);
|
2017-01-04 21:07:59 +00:00
|
|
|
if (matches) {
|
2017-01-10 08:18:54 +00:00
|
|
|
errors.push({
|
|
|
|
line:1, // TODO: parseInt(matches[3]),
|
|
|
|
msg:matches[0] // TODO: matches[5]
|
|
|
|
});
|
2017-01-04 21:07:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
var Module = ACME({
|
|
|
|
noInitialRun:true,
|
2017-01-10 08:18:54 +00:00
|
|
|
print:match_fn,
|
|
|
|
printErr:match_fn
|
2017-01-04 21:07:59 +00:00
|
|
|
});
|
|
|
|
var FS = Module['FS'];
|
|
|
|
FS.writeFile("main.a", code);
|
2017-01-13 02:21:35 +00:00
|
|
|
// TODO: --msvc
|
2017-01-04 21:07:59 +00:00
|
|
|
Module.callMain(["-o", "a.out", "-r", "a.rpt", "-l", "a.sym", "--setpc", "24576", "main.a"]);
|
2017-01-10 08:18:54 +00:00
|
|
|
if (errors.length) {
|
2017-01-15 03:46:12 +00:00
|
|
|
return {errors:errors};
|
2017-01-10 08:18:54 +00:00
|
|
|
}
|
2017-01-04 21:07:59 +00:00
|
|
|
var aout = FS.readFile("a.out");
|
2017-01-13 02:21:35 +00:00
|
|
|
var alst = FS.readFile("a.rpt", {'encoding':'utf8'});
|
|
|
|
var asym = FS.readFile("a.sym", {'encoding':'utf8'});
|
2017-01-15 03:46:12 +00:00
|
|
|
var listing = parseDASMListing(alst, {}); // TODO
|
2017-01-10 08:18:54 +00:00
|
|
|
return {
|
|
|
|
output:aout,
|
2017-01-15 03:46:12 +00:00
|
|
|
lines:listing.lines,
|
|
|
|
errors:listing.errors,
|
2017-01-10 08:18:54 +00:00
|
|
|
intermediate:{listing:alst, symbols:asym},
|
|
|
|
};
|
2016-12-16 01:21:51 +00:00
|
|
|
}
|
|
|
|
|
2017-01-13 02:21:35 +00:00
|
|
|
function setupStdin(fs, code) {
|
|
|
|
var i = 0;
|
|
|
|
fs.init(
|
|
|
|
function() { return i<code.length ? code.charCodeAt(i++) : null; }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-01-04 21:07:59 +00:00
|
|
|
function compilePLASMA(code) {
|
2017-01-14 02:31:04 +00:00
|
|
|
load("plasm");
|
2017-01-10 08:18:54 +00:00
|
|
|
// stdout
|
2017-01-04 21:07:59 +00:00
|
|
|
var outstr = "";
|
|
|
|
function out_fn(s) { outstr += s; outstr += "\n"; }
|
2017-01-10 08:18:54 +00:00
|
|
|
// stderr
|
|
|
|
var re_err1 = /\s*(\d+):.*/;
|
|
|
|
var re_err2 = /Error: (.*)/;
|
|
|
|
var errors = [];
|
|
|
|
var errline = 0;
|
|
|
|
function match_fn(s) {
|
|
|
|
var matches = re_err1.exec(s);
|
|
|
|
if (matches) {
|
|
|
|
errline = parseInt(matches[1]);
|
|
|
|
}
|
|
|
|
matches = re_err2.exec(s);
|
|
|
|
if (matches) {
|
|
|
|
errors.push({
|
|
|
|
line:errline,
|
|
|
|
msg:matches[1]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2017-01-04 21:07:59 +00:00
|
|
|
var Module = PLASM({
|
|
|
|
noInitialRun:true,
|
|
|
|
noFSInit:true,
|
2017-01-10 08:18:54 +00:00
|
|
|
print:out_fn,
|
|
|
|
printErr:match_fn,
|
2017-01-04 21:07:59 +00:00
|
|
|
});
|
|
|
|
var FS = Module['FS'];
|
|
|
|
var output = [];
|
2017-01-13 02:21:35 +00:00
|
|
|
setupStdin(FS, code);
|
|
|
|
//FS.writeFile("main.pla", code);
|
2017-01-04 21:07:59 +00:00
|
|
|
Module.callMain(["-A"]);
|
2018-06-19 22:42:02 +00:00
|
|
|
// TODO: have to make dummy 4-byte header so start ends up @ $803
|
|
|
|
outstr = "\tnop\n\tnop\n\tnop\n\tnop\n" + outstr;
|
|
|
|
// set code base and INTERP address
|
|
|
|
outstr = "* = $7FF\n" + outstr;
|
2017-01-09 21:28:20 +00:00
|
|
|
outstr = "INTERP = $e044\n" + outstr; // TODO
|
2017-01-10 08:18:54 +00:00
|
|
|
if (errors.length) {
|
2017-01-15 03:46:12 +00:00
|
|
|
return {errors:errors};
|
2017-01-10 08:18:54 +00:00
|
|
|
}
|
2018-06-19 22:42:02 +00:00
|
|
|
console.log(outstr);
|
2017-01-04 21:07:59 +00:00
|
|
|
return assembleACME(outstr);
|
|
|
|
}
|
|
|
|
|
2017-01-10 08:18:54 +00:00
|
|
|
function parseCA65Listing(code, mapfile) {
|
|
|
|
// CODE 00603E 00637C 00033F 00001
|
|
|
|
var mapMatch = /^CODE\s+([0-9A-F]+)/m.exec(mapfile);
|
2018-06-19 22:42:02 +00:00
|
|
|
var codeofs = 0x6000; // TODO
|
2017-01-10 08:18:54 +00:00
|
|
|
if (mapMatch) {
|
|
|
|
var codeofs = parseInt(mapMatch[1], 16);
|
|
|
|
}
|
2017-01-06 00:14:12 +00:00
|
|
|
// .dbg line, "main.c", 1
|
|
|
|
var dbgLineMatch = /([0-9a-fA-F]+)([r]?)\s+(\d+)\s+[.]dbg\s+line,\s+\S+,\s+(\d+)/;
|
|
|
|
var errors = [];
|
|
|
|
var lines = [];
|
|
|
|
var lastlinenum = 0;
|
|
|
|
for (var line of code.split(/\r?\n/)) {
|
|
|
|
var linem = dbgLineMatch.exec(line);
|
|
|
|
if (linem && linem[1]) {
|
|
|
|
var offset = parseInt(linem[1], 16);
|
|
|
|
var linenum = parseInt(linem[4]);
|
|
|
|
lines.push({
|
|
|
|
line:linenum,
|
2017-01-10 08:18:54 +00:00
|
|
|
offset:offset + codeofs,
|
2017-01-06 00:14:12 +00:00
|
|
|
insns:null
|
|
|
|
});
|
|
|
|
//console.log(linem, lastlinenum, lines[lines.length-1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {lines:lines, errors:errors};
|
|
|
|
}
|
|
|
|
|
2017-11-15 00:12:52 +00:00
|
|
|
function assemblelinkCA65(code, platform) {
|
2017-05-21 21:34:57 +00:00
|
|
|
var params = PLATFORM_PARAMS[platform];
|
|
|
|
if (!params) throw Error("Platform not supported: " + platform);
|
2017-11-07 21:41:07 +00:00
|
|
|
loadNative("ca65");
|
|
|
|
loadNative("ld65");
|
2018-06-19 22:42:02 +00:00
|
|
|
var errors = [];
|
2017-01-06 00:14:12 +00:00
|
|
|
var objout, lstout;
|
|
|
|
{
|
|
|
|
var CA65 = ca65({
|
2017-11-07 21:41:07 +00:00
|
|
|
wasmBinary: wasmBlob['ca65'],
|
2017-01-06 00:14:12 +00:00
|
|
|
noInitialRun:true,
|
2017-01-10 08:18:54 +00:00
|
|
|
//logReadFiles:true,
|
2017-01-06 00:14:12 +00:00
|
|
|
print:print_fn,
|
2018-06-19 22:42:02 +00:00
|
|
|
printErr:msvcErrorMatcher(errors),
|
2017-01-06 00:14:12 +00:00
|
|
|
});
|
|
|
|
var FS = CA65['FS'];
|
2018-06-20 07:09:37 +00:00
|
|
|
setupFS(FS, '65-'+platform.split('-')[0]);
|
2017-01-06 00:14:12 +00:00
|
|
|
FS.writeFile("main.s", code, {encoding:'utf8'});
|
2017-11-07 21:41:07 +00:00
|
|
|
starttime();
|
2017-01-06 00:14:12 +00:00
|
|
|
CA65.callMain(['-v', '-g', '-I', '/share/asminc', '-l', 'main.lst', "main.s"]);
|
2017-11-07 21:41:07 +00:00
|
|
|
endtime("assemble");
|
2018-06-19 22:42:02 +00:00
|
|
|
try {
|
|
|
|
objout = FS.readFile("main.o", {encoding:'binary'});
|
|
|
|
lstout = FS.readFile("main.lst", {encoding:'utf8'});
|
|
|
|
} catch (e) {
|
2018-06-22 06:24:52 +00:00
|
|
|
errors.push({line:1, msg:e+""});
|
2018-06-19 22:42:02 +00:00
|
|
|
return {errors:errors}; // TODO
|
|
|
|
}
|
|
|
|
if (errors.length)
|
|
|
|
return {errors:errors};
|
2017-01-06 00:14:12 +00:00
|
|
|
}{
|
|
|
|
var LD65 = ld65({
|
2017-11-07 21:41:07 +00:00
|
|
|
wasmBinary: wasmBlob['ld65'],
|
2017-01-06 00:14:12 +00:00
|
|
|
noInitialRun:true,
|
2017-01-10 08:18:54 +00:00
|
|
|
//logReadFiles:true,
|
2017-01-06 00:14:12 +00:00
|
|
|
print:print_fn,
|
2018-06-19 22:42:02 +00:00
|
|
|
printErr:makeErrorMatcher(errors, /[(](\d+)[)]: (.+)/, 1, 2),
|
2017-01-06 00:14:12 +00:00
|
|
|
});
|
|
|
|
var FS = LD65['FS'];
|
2017-04-12 02:46:06 +00:00
|
|
|
var cfgfile = '/' + platform + '.cfg';
|
2018-06-20 07:09:37 +00:00
|
|
|
setupFS(FS, '65-'+platform.split('-')[0]);
|
2017-01-06 00:14:12 +00:00
|
|
|
FS.writeFile("main.o", objout, {encoding:'binary'});
|
2017-05-21 21:34:57 +00:00
|
|
|
var libargs = params.libargs;
|
2017-11-07 21:41:07 +00:00
|
|
|
starttime();
|
2018-06-20 04:13:19 +00:00
|
|
|
LD65.callMain(['--cfg-path', '/share/cfg',
|
|
|
|
'--lib-path', '/share/lib',
|
2018-06-22 06:24:52 +00:00
|
|
|
'--lib-path', '/share/target/apple2/drv', // TODO
|
|
|
|
'-D', '__EXEHDR__=0', // TODO
|
2017-05-21 21:34:57 +00:00
|
|
|
'-C', params.cfgfile,
|
2018-06-21 18:15:05 +00:00
|
|
|
'-Ln', 'main.vice',
|
2017-05-18 02:33:56 +00:00
|
|
|
//'--dbgfile', 'main.dbg',
|
2017-05-21 21:34:57 +00:00
|
|
|
'-o', 'main', '-m', 'main.map', 'main.o'].concat(libargs));
|
2017-11-07 21:41:07 +00:00
|
|
|
endtime("link");
|
2017-05-18 02:33:56 +00:00
|
|
|
if (errors.length) {
|
2018-06-19 22:42:02 +00:00
|
|
|
return {errors:errors};
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
var aout = FS.readFile("main", {encoding:'binary'});
|
|
|
|
var mapout = FS.readFile("main.map", {encoding:'utf8'});
|
2018-06-21 18:15:05 +00:00
|
|
|
var viceout = FS.readFile("main.vice", {encoding:'utf8'});
|
2018-06-19 22:42:02 +00:00
|
|
|
} catch (e) {
|
2018-06-22 06:24:52 +00:00
|
|
|
errors.push({line:1, msg:e+""});
|
|
|
|
return {errors:errors}; // TODO
|
2017-05-18 02:33:56 +00:00
|
|
|
}
|
2017-01-15 03:46:12 +00:00
|
|
|
var listing = parseCA65Listing(lstout, mapout);
|
2017-04-23 13:03:05 +00:00
|
|
|
//console.log(lstout);
|
|
|
|
//console.log(mapout);
|
2018-06-19 06:08:18 +00:00
|
|
|
var srclines = parseSourceLines(lstout, /[.]dbg\s+line, "main[.]c", (\d+)/i, /^\s*([0-9A-F]+)r/i, params.code_offset);
|
2018-06-21 18:15:05 +00:00
|
|
|
// parse symbol map (TODO: omit segments, constants)
|
|
|
|
var symbolmap = {};
|
|
|
|
for (var s of viceout.split("\n")) {
|
|
|
|
var toks = s.split(" ");
|
|
|
|
if (toks[0] == 'al') {
|
|
|
|
symbolmap[toks[2].substr(1)] = parseInt(toks[1], 16);
|
|
|
|
}
|
|
|
|
}
|
2017-01-10 08:18:54 +00:00
|
|
|
return {
|
2017-05-18 02:33:56 +00:00
|
|
|
output:aout.slice(0),
|
2017-01-15 03:46:12 +00:00
|
|
|
lines:listing.lines,
|
2017-05-18 02:33:56 +00:00
|
|
|
srclines:srclines,
|
2017-01-15 03:46:12 +00:00
|
|
|
errors:listing.errors,
|
2018-06-21 18:15:05 +00:00
|
|
|
symbolmap:symbolmap,
|
|
|
|
intermediate:{listing:lstout+"\n"+mapout+"\n"+viceout, map:mapout, symbols:viceout}, // TODO
|
2017-01-10 08:18:54 +00:00
|
|
|
};
|
2017-01-06 00:14:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function compileCC65(code, platform) {
|
2017-05-21 21:34:57 +00:00
|
|
|
var params = PLATFORM_PARAMS[platform];
|
|
|
|
if (!params) throw Error("Platform not supported: " + platform);
|
2017-01-14 02:31:04 +00:00
|
|
|
load("cc65");
|
2017-01-10 08:18:54 +00:00
|
|
|
// stderr
|
|
|
|
var re_err1 = /.*?(\d+).*?: (.+)/;
|
|
|
|
var errors = [];
|
|
|
|
var errline = 0;
|
|
|
|
function match_fn(s) {
|
2017-02-01 18:21:17 +00:00
|
|
|
console.log(s);
|
2017-01-10 08:18:54 +00:00
|
|
|
var matches = re_err1.exec(s);
|
|
|
|
if (matches) {
|
|
|
|
errline = parseInt(matches[1]);
|
|
|
|
errors.push({
|
|
|
|
line:errline,
|
|
|
|
msg:matches[2]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2017-01-06 00:14:12 +00:00
|
|
|
var CC65 = cc65({
|
|
|
|
noInitialRun:true,
|
2017-01-10 08:18:54 +00:00
|
|
|
//logReadFiles:true,
|
2017-01-06 00:14:12 +00:00
|
|
|
print:print_fn,
|
2017-01-10 08:18:54 +00:00
|
|
|
printErr:match_fn,
|
2017-01-06 00:14:12 +00:00
|
|
|
});
|
|
|
|
var FS = CC65['FS'];
|
2018-06-20 07:09:37 +00:00
|
|
|
setupFS(FS, '65-'+platform.split('-')[0]);
|
2017-01-06 00:14:12 +00:00
|
|
|
FS.writeFile("main.c", code, {encoding:'utf8'});
|
2017-11-07 21:41:07 +00:00
|
|
|
starttime();
|
2017-05-21 21:34:57 +00:00
|
|
|
CC65.callMain(['-T', '-g', /*'-Cl',*/
|
2017-05-18 02:33:56 +00:00
|
|
|
'-Oirs',
|
|
|
|
'-I', '/share/include',
|
2017-05-21 21:34:57 +00:00
|
|
|
'-D' + params.define,
|
2017-05-18 02:33:56 +00:00
|
|
|
"main.c"]);
|
2017-11-07 21:41:07 +00:00
|
|
|
endtime("compile");
|
2017-01-10 08:18:54 +00:00
|
|
|
try {
|
|
|
|
var asmout = FS.readFile("main.s", {encoding:'utf8'});
|
2017-04-23 13:03:05 +00:00
|
|
|
//console.log(asmout);
|
2017-04-12 02:46:06 +00:00
|
|
|
var result = assemblelinkCA65(asmout, platform, errors);
|
2018-06-21 18:15:05 +00:00
|
|
|
//result.asmlines = result.lines;
|
|
|
|
//result.lines = result.srclines;
|
2017-04-12 02:46:06 +00:00
|
|
|
result.srclines = null;
|
|
|
|
return result;
|
2017-01-10 08:18:54 +00:00
|
|
|
} catch(e) {
|
2017-01-15 03:46:12 +00:00
|
|
|
return {errors:errors};
|
2017-01-10 08:18:54 +00:00
|
|
|
}
|
2017-01-06 00:14:12 +00:00
|
|
|
}
|
|
|
|
|
2017-01-16 04:47:12 +00:00
|
|
|
function assembleZ80ASM(code, platform) {
|
2017-01-14 02:31:04 +00:00
|
|
|
load("z80asm");
|
2018-06-24 05:01:38 +00:00
|
|
|
var params = PLATFORM_PARAMS[platform];
|
|
|
|
if (!params) throw Error("Platform not supported: " + platform);
|
2017-01-13 02:21:35 +00:00
|
|
|
var Module = z80asm({
|
|
|
|
noInitialRun:true,
|
|
|
|
//logReadFiles:true,
|
|
|
|
print:print_fn,
|
2018-06-24 05:01:38 +00:00
|
|
|
printErr:function() {},
|
2017-02-15 21:03:52 +00:00
|
|
|
TOTAL_MEMORY:256*1024*1024,
|
2017-01-13 02:21:35 +00:00
|
|
|
});
|
|
|
|
var FS = Module['FS'];
|
|
|
|
//setupFS(FS);
|
|
|
|
// changes for dialect
|
2018-06-24 05:01:38 +00:00
|
|
|
//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 ");
|
2017-01-13 02:21:35 +00:00
|
|
|
FS.writeFile("main.asm", code);
|
|
|
|
try {
|
2018-06-24 05:01:38 +00:00
|
|
|
Module.callMain(["-b", "-s", "-l", "-m", "-g",
|
|
|
|
"--origin=" + params.code_start.toString(16),
|
|
|
|
"main.asm"]);
|
2017-01-13 02:21:35 +00:00
|
|
|
try {
|
|
|
|
var aerr = FS.readFile("main.err", {'encoding':'utf8'}); // TODO
|
2017-01-14 02:31:04 +00:00
|
|
|
if (aerr.length) {
|
2017-01-23 21:21:45 +00:00
|
|
|
return {errors:extractErrors(/.+? line (\d+): (.+)/, aerr.split("\n"))};
|
2017-01-14 02:31:04 +00:00
|
|
|
}
|
2017-01-13 02:21:35 +00:00
|
|
|
// Warning at file 'test.asm' line 9: 'XREF' is deprecated, use 'EXTERN' instead
|
|
|
|
} catch (e) {
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
77 0000 ;test.c:5: return 0;
|
|
|
|
78 0000 21 00 00 ld hl,$0000
|
|
|
|
*/
|
|
|
|
var alst = FS.readFile("main.lst", {'encoding':'utf8'}); // TODO
|
|
|
|
/*
|
|
|
|
_main = 0000, G: test
|
|
|
|
l_main00101 = 0003, L: test
|
|
|
|
*/
|
|
|
|
var amap = FS.readFile("main.map", {'encoding':'utf8'}); // TODO
|
|
|
|
var aout = FS.readFile("main.bin", {'encoding':'binary'});
|
2018-06-19 22:42:02 +00:00
|
|
|
var asmlines = parseListing(alst, /^(\d+)\s+([0-9A-F]+)\s+([0-9A-F][0-9A-F ]*[0-9A-F])\s+/i, 1, 2, 3); // TODO: , params.rom_start|0);
|
2017-01-15 18:31:52 +00:00
|
|
|
var srclines = parseListing(alst, /^(\d+)\s+([0-9A-F]+)\s+;[(]null[)]:(\d+)/i, 3, 2, 1);
|
2017-01-13 02:21:35 +00:00
|
|
|
return {
|
|
|
|
output:aout,
|
2017-01-15 03:46:12 +00:00
|
|
|
errors:[],
|
2017-01-16 04:47:12 +00:00
|
|
|
lines:asmlines,
|
|
|
|
srclines:srclines,
|
2017-01-13 02:21:35 +00:00
|
|
|
intermediate:{listing:alst, mapfile:amap},
|
|
|
|
};
|
|
|
|
} catch (e) {
|
2017-01-14 02:31:04 +00:00
|
|
|
throw (e);
|
2017-01-13 02:21:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-24 05:01:38 +00:00
|
|
|
function compileSCCZ80(code, platform) {
|
|
|
|
var preproc = preprocessMCPP(code, platform, 'sccz80');
|
|
|
|
if (preproc.errors) return preproc;
|
|
|
|
else code = preproc.code;
|
|
|
|
|
|
|
|
var params = PLATFORM_PARAMS[platform];
|
|
|
|
if (!params) throw Error("Platform not supported: " + platform);
|
|
|
|
var errors = [];
|
|
|
|
var errorMatcher = makeErrorMatcher(errors, /sccz80:[^ ]+ L:(\d+) (.+)/, 1, 2);
|
|
|
|
|
|
|
|
load('sccz80');
|
|
|
|
//sccz80:hello.c L:1 Error:Can't open include file
|
|
|
|
var SCCZ80 = sccz80({
|
|
|
|
wasmBinary: wasmBlob['sccz80'],
|
|
|
|
noInitialRun:true,
|
|
|
|
//noFSInit:true,
|
|
|
|
print:errorMatcher,
|
|
|
|
printErr:errorMatcher,
|
|
|
|
TOTAL_MEMORY:256*1024*1024,
|
|
|
|
});
|
|
|
|
var FS = SCCZ80['FS'];
|
|
|
|
//setupStdin(FS, code);
|
|
|
|
setupFS(FS, 'sccz80');
|
|
|
|
code = code.replace('__asm', '#asm').replace('__endasm', '#endasm;');
|
|
|
|
FS.writeFile("main.i", code, {encoding:'utf8'});
|
|
|
|
var args = ['-ext=asm', '-opt-code-speed', '-mz80', '-standard-escape-chars', 'main.i', '-o', 'main.asm'];
|
|
|
|
if (params.extra_compile_args) {
|
|
|
|
args.push.apply(args, params.extra_compile_args);
|
|
|
|
}
|
|
|
|
starttime();
|
|
|
|
SCCZ80.callMain(args);
|
|
|
|
endtime("compile");
|
|
|
|
// TODO: preprocessor errors w/ correct file
|
|
|
|
if (errors.length /* && nwarnings < msvc_errors.length*/) {
|
|
|
|
return {errors:errors};
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
var asmout = FS.readFile("main.asm", {encoding:'utf8'});
|
|
|
|
//asmout = " .area _HOME\n .area _CODE\n .area _INITIALIZER\n .area _DATA\n .area _INITIALIZED\n .area _BSEG\n .area _BSS\n .area _HEAP\n" + asmout;
|
|
|
|
//asmout = asmout.replace(".area _INITIALIZER",".area _CODE");
|
|
|
|
asmout = asmout.replace('INCLUDE "', ';;;INCLUDE "')
|
|
|
|
} catch (e) {
|
|
|
|
errors.push({line:1, msg:e+""});
|
|
|
|
return {errors:errors};
|
|
|
|
}
|
|
|
|
var warnings = errors;
|
|
|
|
try {
|
|
|
|
var result = assembleZ80ASM(asmout, platform, true);
|
|
|
|
} catch (e) {
|
|
|
|
errors.push({line:1, msg:e+""});
|
|
|
|
return {errors:errors};
|
|
|
|
}
|
|
|
|
result.asmlines = result.lines;
|
|
|
|
result.lines = result.srclines;
|
|
|
|
result.srclines = null;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-01-15 18:31:52 +00:00
|
|
|
function hexToArray(s, ofs) {
|
|
|
|
var buf = new ArrayBuffer(s.length/2);
|
|
|
|
var arr = new Uint8Array(buf);
|
|
|
|
for (var i=0; i<arr.length; i++) {
|
|
|
|
arr[i] = parseInt(s.slice(i*2+ofs,i*2+ofs+2), 16);
|
|
|
|
}
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
2017-05-02 13:09:53 +00:00
|
|
|
function parseIHX(ihx, rom_start, rom_size) {
|
|
|
|
var output = new Uint8Array(new ArrayBuffer(rom_size));
|
2017-01-15 18:31:52 +00:00
|
|
|
for (var s of ihx.split("\n")) {
|
|
|
|
if (s[0] == ':') {
|
|
|
|
var arr = hexToArray(s, 1);
|
|
|
|
var count = arr[0];
|
2017-05-02 13:09:53 +00:00
|
|
|
var address = (arr[1]<<8) + arr[2] - rom_start;
|
2017-01-15 18:31:52 +00:00
|
|
|
var rectype = arr[3];
|
|
|
|
if (rectype == 0) {
|
|
|
|
for (var i=0; i<count; i++) {
|
|
|
|
var b = arr[4+i];
|
|
|
|
output[i+address] = b;
|
|
|
|
}
|
|
|
|
} else if (rectype == 1) {
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-16 04:47:12 +00:00
|
|
|
function assemblelinkSDASZ80(code, platform) {
|
2017-11-07 21:41:07 +00:00
|
|
|
loadNative("sdasz80");
|
|
|
|
loadNative("sdldz80");
|
2017-01-15 18:31:52 +00:00
|
|
|
var objout, lstout, symout;
|
|
|
|
var params = PLATFORM_PARAMS[platform];
|
|
|
|
if (!params) throw Error("Platform not supported: " + platform);
|
2018-06-19 22:42:02 +00:00
|
|
|
var errors = [];
|
2017-01-15 18:31:52 +00:00
|
|
|
{
|
2017-01-22 14:35:04 +00:00
|
|
|
//?ASxxxx-Error-<o> in line 1 of main.asm null
|
|
|
|
// <o> .org in REL area or directive / mnemonic error
|
|
|
|
var match_asm_re = / <\w> (.+)/; // TODO
|
|
|
|
function match_asm_fn(s) {
|
|
|
|
var matches = match_asm_re.exec(s);
|
2017-01-15 18:31:52 +00:00
|
|
|
if (matches) {
|
2017-01-22 14:35:04 +00:00
|
|
|
var errline = parseInt(matches[2]);
|
2018-06-19 22:42:02 +00:00
|
|
|
errors.push({
|
2017-01-15 18:31:52 +00:00
|
|
|
line:1, // TODO: errline,
|
|
|
|
msg:matches[1]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var ASZ80 = sdasz80({
|
2017-11-07 21:41:07 +00:00
|
|
|
wasmBinary: wasmBlob['sdasz80'],
|
2017-01-15 18:31:52 +00:00
|
|
|
noInitialRun:true,
|
|
|
|
//logReadFiles:true,
|
2017-01-22 14:35:04 +00:00
|
|
|
print:match_asm_fn,
|
|
|
|
printErr:match_asm_fn,
|
2017-01-15 18:31:52 +00:00
|
|
|
});
|
|
|
|
var FS = ASZ80['FS'];
|
|
|
|
FS.writeFile("main.asm", code, {encoding:'utf8'});
|
2017-11-07 21:41:07 +00:00
|
|
|
starttime();
|
2017-01-15 18:31:52 +00:00
|
|
|
ASZ80.callMain(['-plosgffwy', 'main.asm']);
|
2017-11-07 21:41:07 +00:00
|
|
|
endtime("assemble");
|
2018-06-19 22:42:02 +00:00
|
|
|
if (errors.length) {
|
|
|
|
return {errors:errors};
|
2017-01-15 18:31:52 +00:00
|
|
|
}
|
|
|
|
objout = FS.readFile("main.rel", {encoding:'utf8'});
|
|
|
|
lstout = FS.readFile("main.lst", {encoding:'utf8'});
|
2017-01-16 04:47:12 +00:00
|
|
|
//symout = FS.readFile("main.sym", {encoding:'utf8'});
|
2017-01-15 18:31:52 +00:00
|
|
|
}{
|
2017-01-22 14:35:04 +00:00
|
|
|
//?ASlink-Warning-Undefined Global '__divsint' referenced by module 'main'
|
|
|
|
var match_aslink_re = /\?ASlink-(\w+)-(.+)/;
|
|
|
|
function match_aslink_fn(s) {
|
|
|
|
var matches = match_aslink_re.exec(s);
|
|
|
|
if (matches) {
|
2018-06-19 22:42:02 +00:00
|
|
|
errors.push({
|
2017-01-22 14:35:04 +00:00
|
|
|
line:1,
|
|
|
|
msg:matches[2]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2017-05-02 13:09:53 +00:00
|
|
|
var updateListing = !params.extra_link_args;
|
2017-01-15 18:31:52 +00:00
|
|
|
var LDZ80 = sdldz80({
|
2017-11-07 21:41:07 +00:00
|
|
|
wasmBinary: wasmBlob['sdldz80'],
|
2017-01-15 18:31:52 +00:00
|
|
|
noInitialRun:true,
|
|
|
|
//logReadFiles:true,
|
2017-01-22 14:35:04 +00:00
|
|
|
print:match_aslink_fn,
|
|
|
|
printErr:match_aslink_fn,
|
2017-01-15 18:31:52 +00:00
|
|
|
});
|
|
|
|
var FS = LDZ80['FS'];
|
2017-01-23 21:21:45 +00:00
|
|
|
setupFS(FS, 'sdcc');
|
2017-01-15 18:31:52 +00:00
|
|
|
FS.writeFile("main.rel", objout, {encoding:'utf8'});
|
2017-05-02 13:09:53 +00:00
|
|
|
if (updateListing) {
|
|
|
|
FS.writeFile("main.lst", lstout, {encoding:'utf8'});
|
|
|
|
}
|
|
|
|
var args = ['-mjwxy'+(updateListing?'u':''),
|
|
|
|
'-i', 'main.ihx',
|
2017-01-15 18:31:52 +00:00
|
|
|
'-b', '_CODE=0x'+params.code_start.toString(16),
|
|
|
|
'-b', '_DATA=0x'+params.data_start.toString(16),
|
2017-01-23 21:21:45 +00:00
|
|
|
'-k', '/share/lib/z80',
|
2017-05-02 13:09:53 +00:00
|
|
|
'-l', 'z80'];
|
|
|
|
if (params.extra_link_args) {
|
|
|
|
args.push.apply(args, params.extra_link_args);
|
|
|
|
} else {
|
|
|
|
args.push('main.rel');
|
|
|
|
}
|
2017-11-07 21:41:07 +00:00
|
|
|
starttime();
|
2017-05-02 13:09:53 +00:00
|
|
|
LDZ80.callMain(args);
|
2017-11-07 21:41:07 +00:00
|
|
|
endtime("link");
|
2017-01-15 18:31:52 +00:00
|
|
|
var hexout = FS.readFile("main.ihx", {encoding:'utf8'});
|
|
|
|
var mapout = FS.readFile("main.noi", {encoding:'utf8'});
|
2017-05-02 13:09:53 +00:00
|
|
|
var rstout = updateListing ? FS.readFile("main.rst", {encoding:'utf8'}) : lstout;
|
2017-01-16 04:47:12 +00:00
|
|
|
//var dbgout = FS.readFile("main.cdb", {encoding:'utf8'});
|
2017-01-15 18:31:52 +00:00
|
|
|
// 0000 21 02 00 [10] 52 ld hl, #2
|
2018-06-18 08:12:52 +00:00
|
|
|
// TODO: use map to find code_offset
|
|
|
|
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, params.code_offset); //, 5, 3);
|
|
|
|
var srclines = parseSourceLines(lstout, /^\s+\d+ ;<stdin>:(\d+):/i, /^\s*([0-9A-F]{4})/i, params.code_offset);
|
2017-01-16 04:47:12 +00:00
|
|
|
// parse symbol map
|
|
|
|
var symbolmap = {};
|
|
|
|
for (var s of mapout.split("\n")) {
|
|
|
|
var toks = s.split(" ");
|
2017-04-22 01:56:49 +00:00
|
|
|
if (toks[0] == 'DEF' && !toks[1].startsWith("A$main$")) {
|
|
|
|
symbolmap[toks[1]] = parseInt(toks[2], 16);
|
2017-01-16 04:47:12 +00:00
|
|
|
}
|
|
|
|
}
|
2017-01-15 18:31:52 +00:00
|
|
|
return {
|
2017-05-02 13:09:53 +00:00
|
|
|
output:parseIHX(hexout, params.rom_start?params.rom_start:params.code_start, params.rom_size),
|
2017-01-16 04:47:12 +00:00
|
|
|
lines:asmlines,
|
|
|
|
srclines:srclines,
|
2018-06-19 22:42:02 +00:00
|
|
|
errors:errors, // TODO?
|
2017-04-22 01:56:49 +00:00
|
|
|
symbolmap:symbolmap,
|
2017-01-23 21:21:45 +00:00
|
|
|
intermediate:{listing:rstout},
|
2017-01-15 18:31:52 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-05 18:34:00 +00:00
|
|
|
var sdcc;
|
2017-01-13 02:21:35 +00:00
|
|
|
function compileSDCC(code, platform) {
|
2018-06-24 05:01:38 +00:00
|
|
|
var preproc = preprocessMCPP(code, platform, 'sdcc');
|
2017-01-22 14:35:04 +00:00
|
|
|
if (preproc.errors) return preproc;
|
|
|
|
else code = preproc.code;
|
|
|
|
|
2017-01-15 18:31:52 +00:00
|
|
|
var params = PLATFORM_PARAMS[platform];
|
|
|
|
if (!params) throw Error("Platform not supported: " + platform);
|
2018-06-19 22:42:02 +00:00
|
|
|
var errors = [];
|
2017-11-05 18:34:00 +00:00
|
|
|
|
2017-11-07 21:41:07 +00:00
|
|
|
loadNative('sdcc');
|
2017-01-13 02:21:35 +00:00
|
|
|
var SDCC = sdcc({
|
2017-11-07 16:45:20 +00:00
|
|
|
wasmBinary: wasmBlob['sdcc'],
|
2017-01-13 02:21:35 +00:00
|
|
|
noInitialRun:true,
|
|
|
|
noFSInit:true,
|
|
|
|
print:print_fn,
|
2018-06-19 22:42:02 +00:00
|
|
|
printErr:msvcErrorMatcher(errors),
|
2017-03-15 14:11:28 +00:00
|
|
|
TOTAL_MEMORY:256*1024*1024,
|
2017-01-13 02:21:35 +00:00
|
|
|
});
|
|
|
|
var FS = SDCC['FS'];
|
|
|
|
setupStdin(FS, code);
|
2017-01-23 21:21:45 +00:00
|
|
|
setupFS(FS, 'sdcc');
|
2017-01-13 02:21:35 +00:00
|
|
|
//FS.writeFile("main.c", code, {encoding:'utf8'});
|
2017-05-02 13:09:53 +00:00
|
|
|
var args = ['--vc', '--std-sdcc99', '-mz80', //'-Wall',
|
2017-01-22 14:35:04 +00:00
|
|
|
'--c1mode', // '--debug',
|
|
|
|
//'-S', 'main.c',
|
2017-11-07 16:45:20 +00:00
|
|
|
//'--asm=sdasz80',
|
|
|
|
//'--reserve-regs-iy',
|
2017-02-18 22:50:51 +00:00
|
|
|
'--less-pedantic',
|
2017-04-15 04:12:21 +00:00
|
|
|
///'--fomit-frame-pointer',
|
2017-02-20 23:50:29 +00:00
|
|
|
'--opt-code-speed',
|
2017-11-14 20:56:03 +00:00
|
|
|
//'--oldralloc', // TODO: does this make it fater?
|
2017-04-15 04:12:21 +00:00
|
|
|
//'--cyclomatic',
|
|
|
|
//'--nooverlay','--nogcse','--nolabelopt','--noinvariant','--noinduction','--nojtbound','--noloopreverse','--no-peep','--nolospre',
|
2017-05-02 13:09:53 +00:00
|
|
|
'-o', 'main.asm'];
|
|
|
|
if (params.extra_compile_args) {
|
|
|
|
args.push.apply(args, params.extra_compile_args);
|
|
|
|
}
|
2017-11-07 21:41:07 +00:00
|
|
|
starttime();
|
2017-05-02 13:09:53 +00:00
|
|
|
SDCC.callMain(args);
|
2017-11-07 21:41:07 +00:00
|
|
|
endtime("compile");
|
2017-02-20 23:50:29 +00:00
|
|
|
// TODO: preprocessor errors w/ correct file
|
2018-06-19 22:42:02 +00:00
|
|
|
if (errors.length /* && nwarnings < msvc_errors.length*/) {
|
|
|
|
return {errors:errors};
|
2017-01-13 02:21:35 +00:00
|
|
|
}
|
2017-01-29 21:06:05 +00:00
|
|
|
try {
|
|
|
|
var asmout = FS.readFile("main.asm", {encoding:'utf8'});
|
2017-02-18 22:50:51 +00:00
|
|
|
asmout = " .area _HOME\n .area _CODE\n .area _INITIALIZER\n .area _DATA\n .area _INITIALIZED\n .area _BSEG\n .area _BSS\n .area _HEAP\n" + asmout;
|
|
|
|
//asmout = asmout.replace(".area _INITIALIZER",".area _CODE");
|
2017-01-29 21:06:05 +00:00
|
|
|
} catch (e) {
|
2018-06-19 22:42:02 +00:00
|
|
|
errors.push({line:1, msg:e+""});
|
|
|
|
return {errors:errors};
|
2017-01-29 21:06:05 +00:00
|
|
|
}
|
2018-06-19 22:42:02 +00:00
|
|
|
var warnings = errors;
|
2017-02-01 18:21:17 +00:00
|
|
|
try {
|
|
|
|
var result = assemblelinkSDASZ80(asmout, platform, true);
|
|
|
|
} catch (e) {
|
2018-06-19 22:42:02 +00:00
|
|
|
errors.push({line:1, msg:e+""});
|
|
|
|
return {errors:errors};
|
2017-02-01 18:21:17 +00:00
|
|
|
}
|
2017-01-16 04:47:12 +00:00
|
|
|
result.asmlines = result.lines;
|
|
|
|
result.lines = result.srclines;
|
|
|
|
result.srclines = null;
|
2017-01-15 18:31:52 +00:00
|
|
|
return result;
|
2017-01-13 02:21:35 +00:00
|
|
|
}
|
|
|
|
|
2017-01-21 13:13:36 +00:00
|
|
|
function assembleXASM6809(code, platform) {
|
|
|
|
load("xasm6809");
|
|
|
|
var origin = 0; // TODO: configurable
|
|
|
|
var alst = "";
|
|
|
|
var lasterror = null;
|
2018-06-19 22:42:02 +00:00
|
|
|
var errors = [];
|
2017-01-21 13:13:36 +00:00
|
|
|
function match_fn(s) {
|
|
|
|
alst += s;
|
|
|
|
alst += "\n";
|
|
|
|
if (lasterror) {
|
|
|
|
var line = parseInt(s.slice(0,5));
|
2018-06-19 22:42:02 +00:00
|
|
|
errors.push({
|
2017-01-21 13:13:36 +00:00
|
|
|
line:line,
|
|
|
|
msg:lasterror
|
|
|
|
});
|
|
|
|
lasterror = null;
|
|
|
|
}
|
|
|
|
else if (s.startsWith("***** ")) {
|
|
|
|
lasterror = s.slice(6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var Module = xasm6809({
|
|
|
|
noInitialRun:true,
|
|
|
|
//logReadFiles:true,
|
|
|
|
print:match_fn,
|
|
|
|
printErr:print_fn
|
|
|
|
});
|
|
|
|
var FS = Module['FS'];
|
|
|
|
//setupFS(FS);
|
|
|
|
FS.writeFile("main.asm", code);
|
|
|
|
Module.callMain(["-c", "-l", "-s", "-y", "-o=main.bin", "main.asm"]);
|
|
|
|
try {
|
|
|
|
var aout = FS.readFile("main.bin", {encoding:'binary'});
|
|
|
|
// 00001 0000 [ 2] 1048 asld
|
2018-06-18 08:12:52 +00:00
|
|
|
var asmlines = parseListing(alst, /^\s*([0-9A-F]+)\s+([0-9A-F]+)\s+\[([0-9 ]+)\]\s+(\d+) (.*)/i, 1, 2, 4, params.code_offset); //, 5, 3);
|
2017-01-21 13:13:36 +00:00
|
|
|
return {
|
|
|
|
output:aout,
|
2018-06-19 22:42:02 +00:00
|
|
|
errors:errors,
|
2017-01-21 13:13:36 +00:00
|
|
|
lines:asmlines,
|
|
|
|
intermediate:{listing:alst},
|
|
|
|
};
|
|
|
|
} catch(e) {
|
2018-06-19 22:42:02 +00:00
|
|
|
return {errors:errors}; // TODO
|
2017-01-21 13:13:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-24 05:01:38 +00:00
|
|
|
function preprocessMCPP(code, platform, toolname) {
|
2017-01-22 14:35:04 +00:00
|
|
|
load("mcpp");
|
2017-05-02 13:09:53 +00:00
|
|
|
var params = PLATFORM_PARAMS[platform];
|
|
|
|
if (!params) throw Error("Platform not supported: " + platform);
|
2017-01-23 21:21:45 +00:00
|
|
|
// <stdin>:2: error: Can't open include file "foo.h"
|
|
|
|
var errors = [];
|
|
|
|
var match_fn = makeErrorMatcher(errors, /<stdin>:(\d+): (.+)/, 1, 2);
|
2017-01-22 14:35:04 +00:00
|
|
|
var MCPP = mcpp({
|
|
|
|
noInitialRun:true,
|
|
|
|
noFSInit:true,
|
|
|
|
print:print_fn,
|
2017-01-23 21:21:45 +00:00
|
|
|
printErr:match_fn,
|
2017-01-22 14:35:04 +00:00
|
|
|
});
|
|
|
|
var FS = MCPP['FS'];
|
2018-06-24 05:01:38 +00:00
|
|
|
setupFS(FS, toolname);
|
2017-01-22 14:35:04 +00:00
|
|
|
FS.writeFile("main.c", code, {encoding:'utf8'});
|
2017-05-02 13:09:53 +00:00
|
|
|
var args = [
|
2017-01-23 21:21:45 +00:00
|
|
|
"-D", "__8BITWORKSHOP__",
|
2017-01-29 21:06:05 +00:00
|
|
|
"-D", platform.toUpperCase().replace('-','_'),
|
2017-02-20 23:50:29 +00:00
|
|
|
"-D", "__SDCC_z80",
|
2017-01-23 21:21:45 +00:00
|
|
|
"-I", "/share/include",
|
|
|
|
"-Q",
|
2017-05-02 13:09:53 +00:00
|
|
|
"main.c", "main.i"];
|
|
|
|
if (params.extra_preproc_args) {
|
|
|
|
args.push.apply(args, params.extra_preproc_args);
|
|
|
|
}
|
|
|
|
MCPP.callMain(args);
|
2017-01-22 14:35:04 +00:00
|
|
|
try {
|
2017-01-23 21:21:45 +00:00
|
|
|
var iout = FS.readFile("main.i", {encoding:'utf8'});
|
|
|
|
iout = iout.replace(/^#line /gm,'\n# ');
|
2017-01-22 14:35:04 +00:00
|
|
|
} catch (e) {
|
2017-01-23 21:21:45 +00:00
|
|
|
errors.push({line:1, msg:e+""});
|
2017-01-22 14:35:04 +00:00
|
|
|
}
|
2017-01-23 21:21:45 +00:00
|
|
|
try {
|
|
|
|
var errout = FS.readFile("mcpp.err", {encoding:'utf8'});
|
|
|
|
if (errout.length) {
|
|
|
|
// //main.c:2: error: Can't open include file "stdiosd.h"
|
2017-01-29 21:06:05 +00:00
|
|
|
var errors = extractErrors(/[^:]+:(\d+): (.+)/, errout.split("\n"));
|
|
|
|
if (errors.length == 0) {
|
|
|
|
errors = [{line:1, msg:errout}];
|
|
|
|
}
|
|
|
|
return {errors: errors};
|
2017-01-23 21:21:45 +00:00
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
//
|
2017-01-22 14:35:04 +00:00
|
|
|
}
|
|
|
|
return {code:iout};
|
|
|
|
}
|
|
|
|
|
2017-04-27 11:48:59 +00:00
|
|
|
function assembleNAKEN(code, platform) {
|
|
|
|
load("naken_asm");
|
|
|
|
var errors = [];
|
|
|
|
var match_fn = makeErrorMatcher(errors, /Error: (.+) at (.+):(\d+)/, 3, 1);
|
|
|
|
var Module = naken_asm({
|
|
|
|
noInitialRun:true,
|
|
|
|
//logReadFiles:true,
|
|
|
|
print:match_fn,
|
|
|
|
printErr:print_fn
|
|
|
|
});
|
|
|
|
var FS = Module['FS'];
|
|
|
|
//setupFS(FS);
|
|
|
|
FS.writeFile("main.asm", code);
|
|
|
|
Module.callMain(["-l", "-b", "main.asm"]);
|
|
|
|
try {
|
|
|
|
var aout = FS.readFile("out.bin", {encoding:'binary'});
|
|
|
|
var alst = FS.readFile("out.lst", {encoding:'utf8'});
|
|
|
|
//console.log(alst);
|
|
|
|
// 0x0000: 77 ld (hl),a cycles: 4
|
2018-06-18 08:12:52 +00:00
|
|
|
var asmlines = parseListing(alst, /^0x([0-9a-f]+):\s+([0-9a-f]+)\s+(.+)cycles: (\d+)/i, 0, 1, 2); //, 3);
|
2017-04-27 11:48:59 +00:00
|
|
|
return {
|
|
|
|
output:aout,
|
|
|
|
errors:errors,
|
|
|
|
lines:asmlines,
|
|
|
|
intermediate:{listing:alst},
|
|
|
|
};
|
|
|
|
} catch(e) {
|
|
|
|
return {errors:errors};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-14 14:33:15 +00:00
|
|
|
function detectModuleName(code) {
|
2017-11-28 02:08:19 +00:00
|
|
|
var m = /\bmodule\s+(\w+_top)\b/.exec(code)
|
|
|
|
|| /\bmodule\s+(top)\b/.exec(code)
|
|
|
|
|| /\bmodule\s+(\w+)\b/.exec(code);
|
2017-11-14 14:33:15 +00:00
|
|
|
return m ? m[1] : null;
|
|
|
|
}
|
|
|
|
|
2017-11-20 01:32:58 +00:00
|
|
|
function detectTopModuleName(code) {
|
|
|
|
var topmod = detectModuleName(code) || "top";
|
|
|
|
var m = /\bmodule\s+(\w+?_top)/.exec(code);
|
|
|
|
if (m && m[1]) topmod = m[1];
|
|
|
|
m = /\bmodule\s+(\w+?_top)/.exec(code);
|
|
|
|
if (m && m[1]) topmod = m[1];
|
|
|
|
return topmod;
|
|
|
|
}
|
|
|
|
|
2018-02-21 19:32:11 +00:00
|
|
|
function writeDependencies(depends, FS, errors, callback) {
|
2017-11-15 00:12:52 +00:00
|
|
|
if (depends) {
|
|
|
|
for (var i=0; i<depends.length; i++) {
|
|
|
|
var d = depends[i];
|
2018-02-21 19:32:11 +00:00
|
|
|
var text;
|
2018-02-07 00:07:40 +00:00
|
|
|
if (d.text) {
|
2018-02-21 19:32:11 +00:00
|
|
|
text = d.text;
|
2018-02-14 20:58:38 +00:00
|
|
|
} else {
|
|
|
|
// load from network (hopefully cached)
|
|
|
|
// TODO: get from indexeddb?
|
|
|
|
var path = '../../presets/' + d.prefix + '/' + d.filename;
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.open("GET", path, false); // synchronous request
|
|
|
|
xhr.send(null);
|
|
|
|
if (xhr.response) {
|
2018-02-21 19:32:11 +00:00
|
|
|
text = xhr.response;
|
2018-02-14 20:58:38 +00:00
|
|
|
} else {
|
|
|
|
console.log("Could not load " + path);
|
|
|
|
}
|
2018-02-07 00:07:40 +00:00
|
|
|
}
|
2018-02-21 19:32:11 +00:00
|
|
|
if (callback)
|
|
|
|
text = callback(d, text);
|
2018-03-02 05:15:33 +00:00
|
|
|
if (text && FS)
|
2018-02-21 19:32:11 +00:00
|
|
|
FS.writeFile(d.filename, text, {encoding:'utf8'});
|
2017-11-15 00:12:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-15 00:26:40 +00:00
|
|
|
function parseMIF(s) {
|
|
|
|
var lines = s.split('\n');
|
|
|
|
var words = [];
|
|
|
|
for (var i=0; i<lines.length; i++) {
|
|
|
|
var l = lines[i];
|
|
|
|
var toks = l.split(/[;\s+]+/);
|
|
|
|
if (toks.length == 5 && toks[2] == ":") {
|
|
|
|
var addr = parseInt(toks[1], 16);
|
|
|
|
var value = parseInt(toks[3], 16);
|
|
|
|
words[addr] = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return words;
|
|
|
|
}
|
|
|
|
|
|
|
|
function compileCASPR(code, platform, options) {
|
|
|
|
loadNative("caspr");
|
|
|
|
var errors = [];
|
|
|
|
var match_fn = makeErrorMatcher(errors, /(ERROR|FATAL) - (.+)/, 2, 2);
|
|
|
|
var caspr_mod = caspr({
|
|
|
|
wasmBinary:wasmBlob['caspr'],
|
|
|
|
noInitialRun:true,
|
|
|
|
print:print_fn,
|
|
|
|
printErr:match_fn,
|
|
|
|
});
|
|
|
|
var FS = caspr_mod['FS'];
|
|
|
|
FS.writeFile("main.asm", code);
|
2018-02-15 18:31:32 +00:00
|
|
|
var arch = code.match(/^[.]arch\s+(\w+)/m);
|
|
|
|
var deps = [{prefix:'verilog',filename:arch[1]+'.cfg'}]; // TODO: parse file for ".arch femto8"
|
2018-02-15 00:26:40 +00:00
|
|
|
writeDependencies(deps, FS, errors);
|
|
|
|
try {
|
|
|
|
starttime();
|
|
|
|
caspr_mod.callMain(["main.asm"]);
|
|
|
|
endtime("compile");
|
|
|
|
var miffile = FS.readFile("main.mif", {encoding:'utf8'});
|
|
|
|
return {
|
|
|
|
errors:errors,
|
|
|
|
output:parseMIF(miffile),
|
|
|
|
intermediate:{listing:miffile},
|
|
|
|
lines:[]};
|
|
|
|
} catch(e) {
|
|
|
|
errors.push({line:0,msg:e.message});
|
|
|
|
return {errors:errors}; // TODO
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-03 02:41:56 +00:00
|
|
|
var jsasm_module_top;
|
|
|
|
var jsasm_module_output;
|
|
|
|
var jsasm_module_key;
|
|
|
|
|
2018-03-02 05:15:33 +00:00
|
|
|
function compileJSASM(asmcode, platform, options, is_inline) {
|
2018-02-18 05:12:09 +00:00
|
|
|
load("assembler");
|
|
|
|
var asm = new Assembler();
|
2018-03-02 05:15:33 +00:00
|
|
|
var includes = [];
|
2018-03-23 21:05:08 +00:00
|
|
|
asm.loadJSON = function(filename) {
|
2018-02-18 05:12:09 +00:00
|
|
|
// TODO: what if it comes from dependencies?
|
|
|
|
var path = '../../presets/' + platform + '/' + filename;
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.responseType = 'json';
|
|
|
|
xhr.open("GET", path, false); // synchronous request
|
|
|
|
xhr.send(null);
|
|
|
|
return xhr.response;
|
|
|
|
};
|
2018-03-02 05:15:33 +00:00
|
|
|
asm.loadInclude = function(filename) {
|
|
|
|
if (!filename.startsWith('"') || !filename.endsWith('"'))
|
|
|
|
return 'Expected filename in "double quotes"';
|
|
|
|
filename = filename.substr(1, filename.length-2);
|
|
|
|
includes.push(filename);
|
|
|
|
};
|
2018-03-03 03:39:32 +00:00
|
|
|
var loaded_module = false;
|
2018-03-02 05:15:33 +00:00
|
|
|
asm.loadModule = function(top_module) {
|
|
|
|
// TODO: cache module
|
|
|
|
// compile last file in list
|
2018-03-03 03:39:32 +00:00
|
|
|
loaded_module = true;
|
2018-03-03 02:41:56 +00:00
|
|
|
var key = top_module + '/' + includes;
|
|
|
|
if (key != jsasm_module_key) {
|
2018-03-03 03:39:32 +00:00
|
|
|
jsasm_module_key = key;
|
2018-03-03 02:41:56 +00:00
|
|
|
jsasm_module_top = top_module;
|
|
|
|
var main_filename = includes[includes.length-1];
|
|
|
|
var code = '`include "' + main_filename + '"\n';
|
|
|
|
code += "/* module " + top_module + " */\n";
|
|
|
|
var voutput = compileVerilator(code, platform, options);
|
|
|
|
if (voutput.errors.length)
|
|
|
|
return voutput.errors[0].msg;
|
|
|
|
jsasm_module_output = voutput;
|
|
|
|
}
|
2018-03-02 05:15:33 +00:00
|
|
|
}
|
2018-02-18 05:12:09 +00:00
|
|
|
var result = asm.assembleFile(asmcode);
|
2018-03-03 03:39:32 +00:00
|
|
|
if (loaded_module && jsasm_module_output) {
|
2018-03-02 05:15:33 +00:00
|
|
|
var asmout = result.output;
|
2018-03-03 02:41:56 +00:00
|
|
|
result.output = jsasm_module_output.output;
|
2018-03-02 05:15:33 +00:00
|
|
|
result.output.program_rom = asmout;
|
|
|
|
// cpu_platform__DOT__program_rom
|
2018-03-03 02:41:56 +00:00
|
|
|
result.output.program_rom_variable = jsasm_module_top + "__DOT__program_rom";
|
2018-03-02 05:15:33 +00:00
|
|
|
}
|
2018-02-18 05:12:09 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-02-21 19:32:11 +00:00
|
|
|
function compileInlineASM(code, platform, options, errors, asmlines) {
|
2018-02-18 05:12:09 +00:00
|
|
|
code = code.replace(/__asm\b([\s\S]+?)\b__endasm\b/g, function(s,asmcode,index) {
|
|
|
|
var firstline = code.substr(0,index).match(/\n/g).length;
|
2018-03-02 05:15:33 +00:00
|
|
|
var asmout = compileJSASM(asmcode, platform, options, true);
|
2018-02-15 00:26:40 +00:00
|
|
|
if (asmout.errors && asmout.errors.length) {
|
2018-02-21 19:32:11 +00:00
|
|
|
for (var i=0; i<asmout.errors.length; i++) {
|
|
|
|
asmout.errors[i].line += firstline;
|
|
|
|
errors.push(asmout.errors[i]);
|
|
|
|
}
|
2018-02-15 00:26:40 +00:00
|
|
|
return "";
|
|
|
|
} else if (asmout.output) {
|
|
|
|
var s = "";
|
|
|
|
var out = asmout.output;
|
|
|
|
for (var i=0; i<out.length; i++) {
|
|
|
|
if (i>0) s += ",";
|
2018-02-18 05:12:09 +00:00
|
|
|
s += 0|out[i];
|
2018-02-15 00:26:40 +00:00
|
|
|
}
|
2018-02-28 03:35:42 +00:00
|
|
|
if (asmlines) {
|
2018-03-02 05:15:33 +00:00
|
|
|
var al = asmout.lines;
|
2018-02-28 03:35:42 +00:00
|
|
|
for (var i=0; i<al.length; i++) {
|
|
|
|
al[i].line += firstline;
|
|
|
|
asmlines.push(al[i]);
|
|
|
|
}
|
|
|
|
}
|
2018-02-15 00:26:40 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
});
|
2018-02-21 19:32:11 +00:00
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
|
|
|
function compileVerilator(code, platform, options) {
|
|
|
|
loadNative("verilator_bin");
|
|
|
|
load("verilator2js");
|
|
|
|
var errors = [];
|
|
|
|
var asmlines = [];
|
|
|
|
code = compileInlineASM(code, platform, options, errors, asmlines);
|
2017-11-15 00:12:52 +00:00
|
|
|
var match_fn = makeErrorMatcher(errors, /%(.+?): (.+?:)?(\d+)?[:]?\s*(.+)/i, 3, 4);
|
2017-11-11 19:45:32 +00:00
|
|
|
var verilator_mod = verilator_bin({
|
|
|
|
wasmBinary:wasmBlob['verilator_bin'],
|
|
|
|
noInitialRun:true,
|
|
|
|
print:print_fn,
|
|
|
|
printErr:match_fn,
|
|
|
|
});
|
2017-11-20 01:32:58 +00:00
|
|
|
var topmod = detectTopModuleName(code);
|
2017-11-11 19:45:32 +00:00
|
|
|
var FS = verilator_mod['FS'];
|
2017-11-13 05:24:19 +00:00
|
|
|
FS.writeFile(topmod+".v", code);
|
2018-02-21 19:32:11 +00:00
|
|
|
writeDependencies(options.dependencies, FS, errors, function(d, code) {
|
2018-02-28 03:35:42 +00:00
|
|
|
return compileInlineASM(code, platform, options, errors, null);
|
2018-02-21 19:32:11 +00:00
|
|
|
});
|
2017-11-11 19:45:32 +00:00
|
|
|
starttime();
|
2018-02-26 21:42:20 +00:00
|
|
|
try {
|
|
|
|
verilator_mod.callMain(["--cc", "-O3", "-DEXT_INLINE_ASM", "-DTOPMOD__"+topmod,
|
|
|
|
"-Wall", "-Wno-DECLFILENAME", "-Wno-UNUSED", '--report-unoptflat',
|
|
|
|
"--x-assign", "fast", "--noassert", "--pins-bv", "33",
|
|
|
|
"--top-module", topmod, topmod+".v"]);
|
|
|
|
} catch (e) {
|
|
|
|
errors.push({line:0,msg:"Compiler internal error: " + e});
|
|
|
|
}
|
2017-11-11 19:45:32 +00:00
|
|
|
endtime("compile");
|
2018-02-09 16:59:52 +00:00
|
|
|
if (errors.length) {
|
|
|
|
return {errors:errors};
|
|
|
|
}
|
2017-11-11 19:45:32 +00:00
|
|
|
try {
|
2017-11-13 05:24:19 +00:00
|
|
|
var h_file = FS.readFile("obj_dir/V"+topmod+".h", {encoding:'utf8'});
|
|
|
|
var cpp_file = FS.readFile("obj_dir/V"+topmod+".cpp", {encoding:'utf8'});
|
2017-11-11 19:45:32 +00:00
|
|
|
var rtn = translateVerilatorOutputToJS(h_file, cpp_file);
|
|
|
|
rtn.errors = errors;
|
|
|
|
rtn.lines = [];// TODO
|
|
|
|
rtn.intermediate = {listing:h_file + cpp_file};
|
2018-02-18 05:12:09 +00:00
|
|
|
rtn.lines = asmlines;
|
2017-11-11 19:45:32 +00:00
|
|
|
return rtn;
|
|
|
|
} catch(e) {
|
2017-11-13 05:24:19 +00:00
|
|
|
console.log(e);
|
2017-11-11 19:45:32 +00:00
|
|
|
return {errors:errors};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-20 01:32:58 +00:00
|
|
|
function compileYosys(code, platform, options) {
|
|
|
|
loadNative("yosys");
|
|
|
|
var errors = [];
|
2017-11-29 01:48:27 +00:00
|
|
|
var match_fn = makeErrorMatcher(errors, /ERROR: (.+?) in line (.+?[.]v):(\d+)[: ]+(.+)/i, 3, 4);
|
2017-11-20 01:32:58 +00:00
|
|
|
starttime();
|
|
|
|
var yosys_mod = yosys({
|
|
|
|
wasmBinary:wasmBlob['yosys'],
|
|
|
|
noInitialRun:true,
|
|
|
|
print:print_fn,
|
|
|
|
printErr:match_fn,
|
|
|
|
});
|
|
|
|
endtime("create module");
|
|
|
|
var topmod = detectTopModuleName(code);
|
|
|
|
var FS = yosys_mod['FS'];
|
|
|
|
FS.writeFile(topmod+".v", code);
|
|
|
|
writeDependencies(options.dependencies, FS, errors);
|
|
|
|
starttime();
|
2017-11-29 01:48:27 +00:00
|
|
|
try {
|
|
|
|
yosys_mod.callMain(["-q", "-o", topmod+".json", "-S", topmod+".v"]);
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e);
|
|
|
|
endtime("compile");
|
|
|
|
return {errors:errors};
|
|
|
|
}
|
2017-11-20 01:32:58 +00:00
|
|
|
endtime("compile");
|
2018-02-03 20:20:56 +00:00
|
|
|
//TODO: filename in errors
|
2017-11-20 01:32:58 +00:00
|
|
|
if (errors.length) return {errors:errors};
|
|
|
|
try {
|
|
|
|
var json_file = FS.readFile(topmod+".json", {encoding:'utf8'});
|
|
|
|
var json = JSON.parse(json_file);
|
|
|
|
console.log(json);
|
|
|
|
return {yosys_json:json, errors:errors};
|
|
|
|
} catch(e) {
|
|
|
|
console.log(e);
|
|
|
|
return {errors:errors};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-15 03:46:12 +00:00
|
|
|
var TOOLS = {
|
2017-01-04 21:07:59 +00:00
|
|
|
'dasm': assembleDASM,
|
2017-01-15 03:46:12 +00:00
|
|
|
'acme': assembleACME,
|
2017-01-04 21:07:59 +00:00
|
|
|
'plasm': compilePLASMA,
|
2017-01-06 00:14:12 +00:00
|
|
|
'cc65': compileCC65,
|
|
|
|
'ca65': assemblelinkCA65,
|
2017-01-13 02:21:35 +00:00
|
|
|
'z80asm': assembleZ80ASM,
|
2017-01-15 18:31:52 +00:00
|
|
|
'sdasz80': assemblelinkSDASZ80,
|
2017-01-13 02:21:35 +00:00
|
|
|
'sdcc': compileSDCC,
|
2017-01-21 13:13:36 +00:00
|
|
|
'xasm6809': assembleXASM6809,
|
2017-04-27 11:48:59 +00:00
|
|
|
'naken': assembleNAKEN,
|
2017-11-11 19:45:32 +00:00
|
|
|
'verilator': compileVerilator,
|
2017-11-20 01:32:58 +00:00
|
|
|
'yosys': compileYosys,
|
2018-02-15 00:26:40 +00:00
|
|
|
'caspr': compileCASPR,
|
2018-03-02 05:15:33 +00:00
|
|
|
'jsasm': compileJSASM,
|
2018-06-24 05:01:38 +00:00
|
|
|
'sccz80': compileSCCZ80,
|
2017-01-04 21:07:59 +00:00
|
|
|
}
|
2016-12-16 01:21:51 +00:00
|
|
|
|
2017-01-23 21:21:45 +00:00
|
|
|
var TOOL_PRELOADFS = {
|
2018-06-20 07:09:37 +00:00
|
|
|
'cc65-apple2': '65-apple2',
|
|
|
|
'ca65-apple2': '65-apple2',
|
|
|
|
'cc65-c64': '65-c64',
|
|
|
|
'ca65-c64': '65-c64',
|
|
|
|
'cc65-nes': '65-nes',
|
|
|
|
'ca65-nes': '65-nes',
|
|
|
|
'cc65-atari8': '65-atari8',
|
|
|
|
'ca65-atari8': '65-atari8',
|
2017-01-23 21:21:45 +00:00
|
|
|
'sdasz80': 'sdcc',
|
|
|
|
'sdcc': 'sdcc',
|
2018-06-24 05:01:38 +00:00
|
|
|
'sccz80': 'sccz80',
|
2017-01-23 21:21:45 +00:00
|
|
|
}
|
|
|
|
|
2018-03-03 02:16:25 +00:00
|
|
|
function handleMessage(data) {
|
|
|
|
if (data.preload) {
|
|
|
|
var fs = TOOL_PRELOADFS[data.preload];
|
2018-06-20 07:09:37 +00:00
|
|
|
if (!fs && data.platform)
|
|
|
|
fs = TOOL_PRELOADFS[data.preload+'-'+data.platform.split('-')[0]];
|
|
|
|
if (fs && !fsMeta[fs])
|
|
|
|
loadFilesystem(fs);
|
2017-01-23 21:21:45 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// (code,platform,tool)
|
2018-03-03 02:16:25 +00:00
|
|
|
var code = data.code;
|
|
|
|
var platform = data.platform;
|
|
|
|
var toolfn = TOOLS[data.tool];
|
|
|
|
if (!toolfn) throw "no tool named " + data.tool;
|
|
|
|
var dependencies = data.dependencies;
|
|
|
|
var result = toolfn(code, platform, data);
|
2017-04-22 01:56:49 +00:00
|
|
|
result.params = PLATFORM_PARAMS[platform];
|
2018-03-03 02:16:25 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function';
|
|
|
|
var ENVIRONMENT_IS_WEB = typeof window === 'object';
|
|
|
|
var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
|
|
|
|
|
|
|
|
if (ENVIRONMENT_IS_WORKER) {
|
|
|
|
onmessage = function(e) {
|
|
|
|
var result = handleMessage(e.data);
|
|
|
|
if (result) {
|
|
|
|
postMessage(result);
|
|
|
|
}
|
2017-01-06 00:14:12 +00:00
|
|
|
}
|
2016-12-16 01:21:51 +00:00
|
|
|
}
|