2017-01-09 21:28:20 +00:00
|
|
|
|
2021-08-15 15:10:01 +00:00
|
|
|
import type { WorkerResult, WorkerBuildStep, WorkerMessage, WorkerError, SourceLine, WorkerErrorResult, WorkingStore } from "../common/workertypes";
|
|
|
|
import { getBasePlatform, getRootBasePlatform } from "../common/util";
|
2018-10-05 13:47:15 +00:00
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
/// <reference types="emscripten" />
|
|
|
|
export interface EmscriptenModule {
|
2021-07-30 23:21:50 +00:00
|
|
|
callMain: (args: string[]) => void;
|
|
|
|
FS : any; // TODO
|
|
|
|
}
|
|
|
|
|
2018-10-05 13:47:15 +00:00
|
|
|
declare function importScripts(path:string);
|
|
|
|
declare function postMessage(msg);
|
|
|
|
|
2019-09-29 18:41:29 +00:00
|
|
|
const ENVIRONMENT_IS_WEB = typeof window === 'object';
|
|
|
|
const ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
|
2021-08-12 18:51:10 +00:00
|
|
|
export const emglobal : any = ENVIRONMENT_IS_WORKER ? self : ENVIRONMENT_IS_WEB ? window : global;
|
2019-09-29 18:41:29 +00:00
|
|
|
|
2021-07-17 20:53:07 +00:00
|
|
|
// simple CommonJS module loader
|
|
|
|
// TODO: relative paths for dependencies
|
|
|
|
if (!emglobal['require']) {
|
|
|
|
emglobal['require'] = (modpath: string) => {
|
|
|
|
if (modpath.endsWith('.js')) modpath = modpath.slice(-3);
|
|
|
|
var modname = modpath.split('/').slice(-1)[0];
|
|
|
|
var hasNamespace = emglobal[modname] != null;
|
|
|
|
console.log('@@@ require', modname, modpath, hasNamespace);
|
|
|
|
if (!hasNamespace) {
|
|
|
|
exports = {};
|
|
|
|
importScripts(`${modpath}.js`);
|
|
|
|
}
|
|
|
|
if (emglobal[modname] == null) {
|
|
|
|
emglobal[modname] = exports; // TODO: always put in global scope?
|
|
|
|
}
|
|
|
|
return emglobal[modname]; // TODO
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-10 04:44:17 +00:00
|
|
|
// WebAssembly module cache
|
|
|
|
// TODO: leaks memory even when disabled...
|
|
|
|
var _WASM_module_cache = {};
|
2020-07-13 22:15:48 +00:00
|
|
|
var CACHE_WASM_MODULES = true; // if false, use asm.js only
|
|
|
|
|
2021-07-07 04:18:46 +00:00
|
|
|
// TODO: which modules need this?
|
|
|
|
var wasmMemory;
|
2021-08-12 18:51:10 +00:00
|
|
|
export function getWASMMemory() {
|
2021-07-07 04:18:46 +00:00
|
|
|
if (wasmMemory == null) {
|
|
|
|
wasmMemory = new WebAssembly.Memory({
|
2021-07-07 16:06:22 +00:00
|
|
|
'initial': 1024, // 64MB
|
|
|
|
'maximum': 16384, // 1024MB
|
2021-07-07 04:18:46 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
return wasmMemory;
|
|
|
|
}
|
|
|
|
|
2018-10-05 13:47:15 +00:00
|
|
|
function getWASMModule(module_id:string) {
|
2018-07-10 04:44:17 +00:00
|
|
|
var module = _WASM_module_cache[module_id];
|
|
|
|
if (!module) {
|
|
|
|
starttime();
|
|
|
|
module = new WebAssembly.Module(wasmBlob[module_id]);
|
|
|
|
if (CACHE_WASM_MODULES) {
|
|
|
|
_WASM_module_cache[module_id] = module;
|
|
|
|
delete wasmBlob[module_id];
|
|
|
|
}
|
|
|
|
endtime("module creation " + module_id);
|
|
|
|
}
|
|
|
|
return module;
|
|
|
|
}
|
|
|
|
// function for use with instantiateWasm
|
2021-08-12 18:51:10 +00:00
|
|
|
export function moduleInstFn(module_id:string) {
|
2018-07-10 04:44:17 +00:00
|
|
|
return function(imports,ri) {
|
|
|
|
var mod = getWASMModule(module_id);
|
|
|
|
var inst = new WebAssembly.Instance(mod, imports);
|
|
|
|
ri(inst);
|
|
|
|
return inst.exports;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 18:25:24 +00:00
|
|
|
//
|
|
|
|
|
2017-01-26 05:09:57 +00:00
|
|
|
var PLATFORM_PARAMS = {
|
2018-12-05 19:05:10 +00:00
|
|
|
'vcs': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6502',
|
2018-12-05 19:05:10 +00:00
|
|
|
code_start: 0x1000,
|
|
|
|
code_size: 0xf000,
|
|
|
|
data_start: 0x80,
|
|
|
|
data_size: 0x80,
|
2021-03-04 14:20:00 +00:00
|
|
|
wiz_rom_ext: '.a26',
|
2021-03-23 17:22:48 +00:00
|
|
|
wiz_inc_dir: '2600',
|
|
|
|
extra_link_files: ['atari2600.cfg'],
|
|
|
|
cfgfile: 'atari2600.cfg',
|
2018-12-05 19:05:10 +00:00
|
|
|
},
|
2017-01-26 05:09:57 +00:00
|
|
|
'mw8080bw': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2017-01-26 05:09:57 +00:00
|
|
|
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': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2017-01-26 05:09:57 +00:00
|
|
|
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': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2017-01-26 05:09:57 +00:00
|
|
|
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': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2017-02-15 21:03:52 +00:00
|
|
|
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
|
|
|
},
|
2019-08-06 19:36:28 +00:00
|
|
|
'williams': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6809',
|
2019-08-06 19:36:28 +00:00
|
|
|
code_start: 0x0,
|
|
|
|
rom_size: 0xc000,
|
|
|
|
data_start: 0x9800,
|
|
|
|
data_size: 0x2800,
|
|
|
|
stack_end: 0xc000,
|
2022-02-18 17:53:33 +00:00
|
|
|
set_stack_end: 0xc000,
|
2020-06-08 21:36:33 +00:00
|
|
|
extra_link_files: ['williams.scr', 'libcmoc-crt-vec.a', 'libcmoc-std-vec.a'],
|
|
|
|
extra_link_args: ['-swilliams.scr', '-lcmoc-crt-vec', '-lcmoc-std-vec'],
|
2022-02-18 17:53:33 +00:00
|
|
|
extra_compile_files: ['assert.h','cmoc.h','stdarg.h','stdlib.h'],
|
|
|
|
//extra_compile_args: ['--vectrex'],
|
2022-02-15 02:35:42 +00:00
|
|
|
},
|
|
|
|
'williams-defender': {
|
|
|
|
arch: '6809',
|
|
|
|
code_start: 0x0,
|
|
|
|
rom_size: 0xc000,
|
|
|
|
data_start: 0x9800,
|
|
|
|
data_size: 0x2800,
|
|
|
|
stack_end: 0xc000,
|
2019-08-06 19:36:28 +00:00
|
|
|
},
|
2017-01-29 21:06:05 +00:00
|
|
|
'williams-z80': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2017-01-29 21:06:05 +00:00
|
|
|
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': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
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
|
|
|
},
|
2019-04-24 20:56:53 +00:00
|
|
|
'vector-ataricolor': { //TODO
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6502',
|
2019-12-19 00:47:40 +00:00
|
|
|
define: ['__VECTOR__'],
|
2019-04-24 20:56:53 +00:00
|
|
|
cfgfile: 'vector-color.cfg',
|
2022-01-29 17:38:44 +00:00
|
|
|
libargs: ['crt0.o', 'none.lib'],
|
2019-04-24 20:56:53 +00:00
|
|
|
extra_link_files: ['crt0.o', 'vector-color.cfg'],
|
|
|
|
},
|
2017-04-02 18:54:51 +00:00
|
|
|
'sound_williams-z80': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2017-04-02 18:54:51 +00:00
|
|
|
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': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2017-04-29 15:31:11 +00:00
|
|
|
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': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2017-05-02 13:09:53 +00:00
|
|
|
rom_start: 0x8000,
|
|
|
|
code_start: 0x8100,
|
|
|
|
rom_size: 0x8000,
|
|
|
|
data_start: 0x7000,
|
2017-05-01 11:37:48 +00:00
|
|
|
data_size: 0x400,
|
|
|
|
stack_end: 0x8000,
|
2019-08-17 18:12:14 +00:00
|
|
|
extra_preproc_args: ['-I', '/share/include/coleco', '-D', 'CV_CV'],
|
2018-11-28 15:31:07 +00:00
|
|
|
extra_link_args: ['-k', '/share/lib/coleco', '-l', 'libcv', '-l', 'libcvu', 'crt0.rel'],
|
|
|
|
},
|
2019-08-17 18:12:14 +00:00
|
|
|
'msx': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2019-08-17 18:12:14 +00:00
|
|
|
rom_start: 0x4000,
|
|
|
|
code_start: 0x4000,
|
|
|
|
rom_size: 0x8000,
|
|
|
|
data_start: 0xc000,
|
|
|
|
data_size: 0x3000,
|
|
|
|
stack_end: 0xffff,
|
|
|
|
extra_link_args: ['crt0-msx.rel'],
|
|
|
|
extra_link_files: ['crt0-msx.rel', 'crt0-msx.lst'],
|
2021-03-04 16:22:12 +00:00
|
|
|
wiz_sys_type: 'z80',
|
|
|
|
wiz_inc_dir: 'msx',
|
2019-08-17 18:12:14 +00:00
|
|
|
},
|
|
|
|
'msx-libcv': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2019-08-17 18:12:14 +00:00
|
|
|
rom_start: 0x4000,
|
|
|
|
code_start: 0x4000,
|
|
|
|
rom_size: 0x8000,
|
|
|
|
data_start: 0xc000,
|
|
|
|
data_size: 0x3000,
|
|
|
|
stack_end: 0xffff,
|
|
|
|
extra_preproc_args: ['-I', '.', '-D', 'CV_MSX'],
|
|
|
|
extra_link_args: ['-k', '.', '-l', 'libcv-msx', '-l', 'libcvu-msx', 'crt0-msx.rel'],
|
|
|
|
extra_link_files: ['libcv-msx.lib', 'libcvu-msx.lib', 'crt0-msx.rel', 'crt0-msx.lst'],
|
|
|
|
extra_compile_files: ['cv.h','cv_graphics.h','cv_input.h','cv_sound.h','cv_support.h','cvu.h','cvu_c.h','cvu_compression.h','cvu_f.h','cvu_graphics.h','cvu_input.h','cvu_sound.h'],
|
|
|
|
},
|
2018-11-29 22:40:53 +00:00
|
|
|
'sms-sg1000-libcv': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2018-11-28 15:31:07 +00:00
|
|
|
rom_start: 0x0000,
|
|
|
|
code_start: 0x0100,
|
|
|
|
rom_size: 0xc000,
|
|
|
|
data_start: 0xc000,
|
|
|
|
data_size: 0x400,
|
|
|
|
stack_end: 0xe000,
|
|
|
|
extra_preproc_args: ['-I', '.', '-D', 'CV_SMS'],
|
|
|
|
extra_link_args: ['-k', '.', '-l', 'libcv-sms', '-l', 'libcvu-sms', 'crt0-sms.rel'],
|
|
|
|
extra_link_files: ['libcv-sms.lib', 'libcvu-sms.lib', 'crt0-sms.rel', 'crt0-sms.lst'],
|
|
|
|
extra_compile_files: ['cv.h','cv_graphics.h','cv_input.h','cv_sound.h','cv_support.h','cvu.h','cvu_c.h','cvu_compression.h','cvu_f.h','cvu_graphics.h','cvu_input.h','cvu_sound.h'],
|
2017-05-01 11:37:48 +00:00
|
|
|
},
|
2018-07-27 17:39:09 +00:00
|
|
|
'nes': { //TODO
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6502',
|
2019-12-19 00:47:40 +00:00
|
|
|
define: ['__NES__'],
|
2019-08-21 15:14:30 +00:00
|
|
|
cfgfile: 'neslib2.cfg',
|
2019-05-14 16:01:54 +00:00
|
|
|
libargs: ['crt0.o', 'nes.lib', 'neslib2.lib',
|
2019-03-13 18:52:30 +00:00
|
|
|
'-D', 'NES_MAPPER=0', // NROM
|
|
|
|
'-D', 'NES_PRG_BANKS=2', // 2 16K PRG banks
|
2019-02-21 19:19:29 +00:00
|
|
|
'-D', 'NES_CHR_BANKS=1', // 1 CHR bank
|
2019-02-10 16:04:31 +00:00
|
|
|
'-D', 'NES_MIRRORING=0', // horizontal mirroring
|
2018-08-14 20:28:29 +00:00
|
|
|
],
|
2019-08-21 15:14:30 +00:00
|
|
|
extra_link_files: ['crt0.o', 'neslib2.lib', 'neslib2.cfg', 'nesbanked.cfg'],
|
2021-03-04 14:20:00 +00:00
|
|
|
wiz_rom_ext: '.nes',
|
2018-07-27 17:39:09 +00:00
|
|
|
},
|
2017-12-30 17:48:30 +00:00
|
|
|
'apple2': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6502',
|
2019-12-19 00:47:40 +00:00
|
|
|
define: ['__APPLE2__'],
|
2022-01-24 19:26:11 +00:00
|
|
|
cfgfile: 'apple2.cfg',
|
2019-12-18 17:20:15 +00:00
|
|
|
libargs: [ '--lib-path', '/share/target/apple2/drv', '-D', '__EXEHDR__=0', 'apple2.lib'],
|
2018-08-06 20:23:19 +00:00
|
|
|
__CODE_RUN__: 16384,
|
2018-09-25 23:46:24 +00:00
|
|
|
code_start: 0x803,
|
2017-12-30 17:48:30 +00:00
|
|
|
},
|
2018-06-18 08:12:52 +00:00
|
|
|
'apple2-e': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6502',
|
2019-12-19 00:47:40 +00:00
|
|
|
define: ['__APPLE2__'],
|
2018-06-18 08:12:52 +00:00
|
|
|
cfgfile: 'apple2.cfg',
|
|
|
|
libargs: ['apple2.lib'],
|
2018-06-20 08:06:18 +00:00
|
|
|
},
|
2021-07-27 16:26:49 +00:00
|
|
|
'atari8-800xl.disk': {
|
2021-07-25 02:45:55 +00:00
|
|
|
arch: '6502',
|
|
|
|
define: ['__ATARI__'],
|
|
|
|
cfgfile: 'atari.cfg',
|
|
|
|
libargs: ['atari.lib'],
|
|
|
|
fastbasic_cfgfile: 'fastbasic-cart.cfg',
|
|
|
|
},
|
2021-07-27 16:26:49 +00:00
|
|
|
'atari8-800xl': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6502',
|
2019-12-19 00:47:40 +00:00
|
|
|
define: ['__ATARI__'],
|
2018-06-22 06:24:52 +00:00
|
|
|
cfgfile: 'atari-cart.cfg',
|
2020-07-28 20:06:49 +00:00
|
|
|
libargs: ['atari.lib', '-D', '__CARTFLAGS__=4'],
|
2021-07-25 02:45:55 +00:00
|
|
|
fastbasic_cfgfile: 'fastbasic-cart.cfg',
|
2018-06-22 06:24:52 +00:00
|
|
|
},
|
2022-08-30 02:00:52 +00:00
|
|
|
'atari8-800': {
|
|
|
|
arch: '6502',
|
|
|
|
define: ['__ATARI__'],
|
|
|
|
cfgfile: 'atari-cart.cfg',
|
|
|
|
libargs: ['atari.lib', '-D', '__CARTFLAGS__=4'],
|
|
|
|
fastbasic_cfgfile: 'fastbasic-cart.cfg',
|
|
|
|
},
|
2018-06-20 08:06:18 +00:00
|
|
|
'atari8-5200': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6502',
|
2019-12-19 00:47:40 +00:00
|
|
|
define: ['__ATARI5200__'],
|
2018-06-21 18:15:05 +00:00
|
|
|
cfgfile: 'atari5200.cfg',
|
2020-07-28 20:06:49 +00:00
|
|
|
libargs: ['atari5200.lib', '-D', '__CARTFLAGS__=255'],
|
2021-07-25 02:45:55 +00:00
|
|
|
fastbasic_cfgfile: 'fastbasic-cart.cfg',
|
2018-06-22 06:24:52 +00:00
|
|
|
},
|
2017-11-11 19:45:32 +00:00
|
|
|
'verilog': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'verilog',
|
2020-12-16 16:48:33 +00:00
|
|
|
extra_compile_files: ['8bitworkshop.v'],
|
2017-11-11 19:45:32 +00:00
|
|
|
},
|
2018-08-27 21:31:49 +00:00
|
|
|
'astrocade': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2018-08-27 21:31:49 +00:00
|
|
|
code_start: 0x2000,
|
2018-09-03 13:37:17 +00:00
|
|
|
rom_size: 0x2000,
|
2018-09-02 14:48:43 +00:00
|
|
|
data_start: 0x4e10,
|
2018-09-03 13:37:17 +00:00
|
|
|
data_size: 0x1f0,
|
|
|
|
stack_end: 0x5000,
|
|
|
|
},
|
|
|
|
'astrocade-arcade': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2018-09-03 13:37:17 +00:00
|
|
|
code_start: 0x0000,
|
|
|
|
rom_size: 0x4000,
|
|
|
|
data_start: 0x7de0,
|
|
|
|
data_size: 0x220,
|
|
|
|
stack_end: 0x8000,
|
2018-08-27 21:31:49 +00:00
|
|
|
},
|
2018-09-05 02:28:12 +00:00
|
|
|
'astrocade-bios': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2018-09-05 02:28:12 +00:00
|
|
|
code_start: 0x0000,
|
|
|
|
rom_size: 0x2000,
|
|
|
|
data_start: 0x4fce,
|
|
|
|
data_size: 50,
|
|
|
|
stack_end: 0x4fce,
|
|
|
|
},
|
2019-08-06 03:47:23 +00:00
|
|
|
'atari7800': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6502',
|
2019-12-19 00:47:40 +00:00
|
|
|
define: ['__ATARI7800__'],
|
2019-08-06 03:47:23 +00:00
|
|
|
cfgfile: 'atari7800.cfg',
|
2022-01-29 17:38:44 +00:00
|
|
|
libargs: ['crt0.o', 'none.lib'],
|
2019-08-14 12:56:45 +00:00
|
|
|
extra_link_files: ['crt0.o', 'atari7800.cfg'],
|
2019-08-06 03:47:23 +00:00
|
|
|
},
|
2019-08-19 17:42:32 +00:00
|
|
|
'c64': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6502',
|
2019-12-19 00:47:40 +00:00
|
|
|
define: ['__CBM__', '__C64__'],
|
2019-12-18 17:20:15 +00:00
|
|
|
cfgfile: 'c64.cfg', // SYS 2061
|
2019-08-19 17:42:32 +00:00
|
|
|
libargs: ['c64.lib'],
|
|
|
|
//extra_link_files: ['c64-cart.cfg'],
|
|
|
|
},
|
2022-02-23 19:36:44 +00:00
|
|
|
'vic20': {
|
|
|
|
arch: '6502',
|
|
|
|
define: ['__CBM__', '__VIC20__'],
|
|
|
|
cfgfile: 'vic20.cfg',
|
|
|
|
libargs: ['vic20.lib'],
|
|
|
|
//extra_link_files: ['c64-cart.cfg'],
|
|
|
|
},
|
2019-08-21 01:34:01 +00:00
|
|
|
'kim1': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6502',
|
2019-08-21 01:34:01 +00:00
|
|
|
},
|
2020-06-09 01:26:57 +00:00
|
|
|
'vectrex': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: '6809',
|
2020-06-09 01:26:57 +00:00
|
|
|
code_start: 0x0,
|
|
|
|
rom_size: 0x8000,
|
|
|
|
data_start: 0xc880,
|
|
|
|
data_size: 0x380,
|
|
|
|
stack_end: 0xcc00,
|
2020-06-09 15:05:46 +00:00
|
|
|
extra_compile_files: ['assert.h','cmoc.h','stdarg.h','vectrex.h','stdlib.h','bios.h'],
|
2020-06-09 01:26:57 +00:00
|
|
|
extra_link_files: ['vectrex.scr', 'libcmoc-crt-vec.a', 'libcmoc-std-vec.a'],
|
2020-06-09 15:05:46 +00:00
|
|
|
extra_compile_args: ['--vectrex'],
|
2020-06-09 01:26:57 +00:00
|
|
|
extra_link_args: ['-svectrex.scr', '-lcmoc-crt-vec', '-lcmoc-std-vec'],
|
|
|
|
},
|
2020-06-14 01:28:58 +00:00
|
|
|
'x86': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'x86',
|
2020-07-01 23:16:38 +00:00
|
|
|
},
|
|
|
|
'zx': {
|
2021-03-04 16:22:12 +00:00
|
|
|
arch: 'z80',
|
2020-07-02 17:33:22 +00:00
|
|
|
code_start: 0x5ccb,
|
2021-11-22 16:49:16 +00:00
|
|
|
rom_size: 0xff58-0x5ccb,
|
2020-07-02 17:33:22 +00:00
|
|
|
data_start: 0xf000,
|
2021-11-22 16:49:16 +00:00
|
|
|
data_size: 0xfe00-0xf000,
|
|
|
|
stack_end: 0xff58,
|
|
|
|
extra_link_args: ['crt0-zx.rel'],
|
|
|
|
extra_link_files: ['crt0-zx.rel', 'crt0-zx.lst'],
|
2021-03-04 16:22:12 +00:00
|
|
|
},
|
|
|
|
'devel-6502': {
|
|
|
|
arch: '6502',
|
2020-10-17 19:34:08 +00:00
|
|
|
cfgfile: 'devel-6502.cfg',
|
2022-01-29 17:38:44 +00:00
|
|
|
libargs: ['crt0.o', 'none.lib'],
|
2020-10-17 19:34:08 +00:00
|
|
|
extra_link_files: ['crt0.o', 'devel-6502.cfg'],
|
2021-03-04 16:22:12 +00:00
|
|
|
},
|
2021-11-22 16:49:16 +00:00
|
|
|
// https://github.com/cpcitor/cpc-dev-tool-chain
|
2021-12-01 21:08:33 +00:00
|
|
|
'cpc.rslib': {
|
2021-11-22 16:49:16 +00:00
|
|
|
arch: 'z80',
|
|
|
|
code_start: 0x4000,
|
|
|
|
rom_size: 0xb100-0x4000,
|
|
|
|
data_start: 0xb100,
|
|
|
|
data_size: 0xb100-0xc000,
|
|
|
|
stack_end: 0xc000,
|
|
|
|
extra_compile_files: ['cpcrslib.h'],
|
|
|
|
extra_link_args: ['crt0-cpc.rel', 'cpcrslib.lib'],
|
|
|
|
extra_link_files: ['crt0-cpc.rel', 'crt0-cpc.lst', 'cpcrslib.lib', 'cpcrslib.lst'],
|
|
|
|
},
|
2021-12-01 21:08:33 +00:00
|
|
|
// https://lronaldo.github.io/cpctelera/ (TODO)
|
|
|
|
'cpc': {
|
|
|
|
arch: 'z80',
|
|
|
|
code_start: 0x4000,
|
|
|
|
rom_size: 0xb100-0x4000,
|
|
|
|
data_start: 0xb100,
|
|
|
|
data_size: 0xb100-0xc000,
|
|
|
|
stack_end: 0xc000,
|
|
|
|
extra_compile_files: ['cpctelera.h'],
|
|
|
|
extra_link_args: ['crt0-cpc.rel', 'cpctelera.lib'],
|
|
|
|
extra_link_files: ['crt0-cpc.rel', 'crt0-cpc.lst', 'cpctelera.lib', 'cpctelera.lst'],
|
|
|
|
},
|
2017-01-26 05:09:57 +00:00
|
|
|
};
|
|
|
|
|
2018-11-30 17:37:00 +00:00
|
|
|
PLATFORM_PARAMS['sms-sms-libcv'] = PLATFORM_PARAMS['sms-sg1000-libcv'];
|
2022-08-29 03:16:17 +00:00
|
|
|
PLATFORM_PARAMS['sms-gg-libcv'] = PLATFORM_PARAMS['sms-sms-libcv'];
|
2018-11-19 14:10:13 +00:00
|
|
|
|
2018-07-10 04:44:17 +00:00
|
|
|
var _t1;
|
2021-08-12 18:51:10 +00:00
|
|
|
export function starttime() { _t1 = new Date(); }
|
|
|
|
export function endtime(msg) { var _t2 = new Date(); console.log(msg, _t2.getTime() - _t1.getTime(), "ms"); }
|
2017-11-07 21:41:07 +00:00
|
|
|
|
2018-06-25 04:52:40 +00:00
|
|
|
/// working file store and build steps
|
|
|
|
|
2018-10-05 13:47:15 +00:00
|
|
|
type FileData = string | Uint8Array;
|
|
|
|
|
|
|
|
type FileEntry = {
|
|
|
|
path: string
|
|
|
|
encoding: string
|
|
|
|
data: FileData
|
|
|
|
ts: number
|
|
|
|
};
|
|
|
|
|
|
|
|
type BuildOptions = {
|
2018-12-15 18:14:40 +00:00
|
|
|
mainFilePath : string,
|
2021-07-12 17:29:50 +00:00
|
|
|
processFn?: (s:string, d:FileData) => FileData
|
2018-10-05 13:47:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// TODO
|
2021-08-08 18:40:19 +00:00
|
|
|
export type BuildStepResult = WorkerResult | WorkerNextToolResult;
|
|
|
|
|
|
|
|
export interface WorkerNextToolResult {
|
|
|
|
nexttool?: string
|
|
|
|
linktool?: string
|
|
|
|
path?: string
|
|
|
|
args: string[]
|
|
|
|
files: string[]
|
|
|
|
bblines?: boolean
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export interface BuildStep extends WorkerBuildStep {
|
2018-10-05 13:47:15 +00:00
|
|
|
files? : string[]
|
|
|
|
args? : string[]
|
|
|
|
nextstep? : BuildStep
|
|
|
|
linkstep? : BuildStep
|
|
|
|
params?
|
2021-08-08 18:40:19 +00:00
|
|
|
result? : BuildStepResult
|
2018-10-05 13:47:15 +00:00
|
|
|
code?
|
|
|
|
prefix?
|
|
|
|
maxts?
|
2022-02-24 15:47:34 +00:00
|
|
|
debuginfo?
|
2018-10-05 13:47:15 +00:00
|
|
|
};
|
|
|
|
|
2021-07-30 23:21:50 +00:00
|
|
|
///
|
|
|
|
|
2021-08-15 15:10:01 +00:00
|
|
|
export class FileWorkingStore implements WorkingStore {
|
2021-07-30 23:21:50 +00:00
|
|
|
workfs : {[path:string]:FileEntry} = {};
|
|
|
|
workerseq : number = 0;
|
2021-09-15 14:52:08 +00:00
|
|
|
items : {};
|
2021-07-30 23:21:50 +00:00
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this.reset();
|
|
|
|
}
|
|
|
|
reset() {
|
|
|
|
this.workfs = {};
|
|
|
|
this.newVersion();
|
|
|
|
}
|
|
|
|
currentVersion() {
|
|
|
|
return this.workerseq;
|
|
|
|
}
|
|
|
|
newVersion() {
|
|
|
|
let ts = new Date().getTime();
|
|
|
|
if (ts <= this.workerseq)
|
|
|
|
ts = ++this.workerseq;
|
|
|
|
return ts;
|
|
|
|
}
|
|
|
|
putFile(path:string, data:FileData) : FileEntry {
|
|
|
|
var encoding = (typeof data === 'string') ? 'utf8' : 'binary';
|
|
|
|
var entry = this.workfs[path];
|
|
|
|
if (!entry || !compareData(entry.data, data) || entry.encoding != encoding) {
|
|
|
|
this.workfs[path] = entry = {path:path, data:data, encoding:encoding, ts:this.newVersion()};
|
|
|
|
console.log('+++', entry.path, entry.encoding, entry.data.length, entry.ts);
|
|
|
|
}
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
hasFile(path: string) {
|
|
|
|
return this.workfs[path] != null;
|
|
|
|
}
|
|
|
|
getFileData(path:string) : FileData {
|
|
|
|
return this.workfs[path] && this.workfs[path].data;
|
|
|
|
}
|
|
|
|
getFileAsString(path:string) : string {
|
|
|
|
let data = this.getFileData(path);
|
|
|
|
if (data != null && typeof data !== 'string')
|
|
|
|
throw new Error(`${path}: expected string`)
|
|
|
|
return data as string; // TODO
|
|
|
|
}
|
|
|
|
getFileEntry(path:string) : FileEntry {
|
|
|
|
return this.workfs[path];
|
|
|
|
}
|
2021-08-15 15:10:01 +00:00
|
|
|
setItem(key: string, value: object) {
|
|
|
|
this.items[key] = value;
|
|
|
|
}
|
2021-07-30 23:21:50 +00:00
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export var store = new FileWorkingStore();
|
2021-07-30 23:21:50 +00:00
|
|
|
|
|
|
|
///
|
|
|
|
|
2021-08-15 15:10:01 +00:00
|
|
|
function errorResult(msg: string) : WorkerErrorResult {
|
|
|
|
return { errors:[{ line:0, msg:msg }]};
|
|
|
|
}
|
|
|
|
|
2021-07-30 23:21:50 +00:00
|
|
|
class Builder {
|
|
|
|
steps : BuildStep[] = [];
|
|
|
|
startseq : number = 0;
|
|
|
|
|
|
|
|
// returns true if file changed during this build step
|
|
|
|
wasChanged(entry:FileEntry) : boolean {
|
|
|
|
return entry.ts > this.startseq;
|
|
|
|
}
|
2021-08-12 23:19:39 +00:00
|
|
|
async executeBuildSteps() : Promise<WorkerResult> {
|
2021-07-30 23:21:50 +00:00
|
|
|
this.startseq = store.currentVersion();
|
|
|
|
var linkstep : BuildStep = null;
|
|
|
|
while (this.steps.length) {
|
|
|
|
var step = this.steps.shift(); // get top of array
|
|
|
|
var platform = step.platform;
|
|
|
|
var toolfn = TOOLS[step.tool];
|
|
|
|
if (!toolfn) throw Error("no tool named " + step.tool);
|
|
|
|
step.params = PLATFORM_PARAMS[getBasePlatform(platform)];
|
|
|
|
try {
|
2021-08-12 23:19:39 +00:00
|
|
|
step.result = await toolfn(step);
|
2021-07-30 23:21:50 +00:00
|
|
|
} catch (e) {
|
|
|
|
console.log("EXCEPTION", e, e.stack);
|
2021-08-15 15:10:01 +00:00
|
|
|
return errorResult(e+""); // TODO: catch errors already generated?
|
2021-07-30 23:21:50 +00:00
|
|
|
}
|
|
|
|
if (step.result) {
|
2021-08-08 18:40:19 +00:00
|
|
|
(step.result as any).params = step.params; // TODO: type check
|
2022-02-24 15:47:34 +00:00
|
|
|
if (step.debuginfo) {
|
|
|
|
let r = step.result as any; // TODO
|
|
|
|
if (!r.debuginfo) r.debuginfo = {};
|
|
|
|
Object.assign(r.debuginfo, step.debuginfo);
|
|
|
|
}
|
2021-07-30 23:21:50 +00:00
|
|
|
// errors? return them
|
2021-08-08 18:40:19 +00:00
|
|
|
if ('errors' in step.result && step.result.errors.length) {
|
2021-07-30 23:21:50 +00:00
|
|
|
applyDefaultErrorPath(step.result.errors, step.path);
|
|
|
|
return step.result;
|
|
|
|
}
|
|
|
|
// if we got some output, return it immediately
|
2021-08-08 18:40:19 +00:00
|
|
|
if ('output' in step.result && step.result.output) {
|
2021-07-30 23:21:50 +00:00
|
|
|
return step.result;
|
|
|
|
}
|
|
|
|
// combine files with a link tool?
|
2021-08-08 18:40:19 +00:00
|
|
|
if ('linktool' in step.result) {
|
2022-02-24 15:47:34 +00:00
|
|
|
// add to existing link step
|
2021-07-30 23:21:50 +00:00
|
|
|
if (linkstep) {
|
|
|
|
linkstep.files = linkstep.files.concat(step.result.files);
|
|
|
|
linkstep.args = linkstep.args.concat(step.result.args);
|
|
|
|
} else {
|
|
|
|
linkstep = {
|
|
|
|
tool:step.result.linktool,
|
|
|
|
platform:platform,
|
|
|
|
files:step.result.files,
|
|
|
|
args:step.result.args
|
|
|
|
};
|
|
|
|
}
|
2022-02-24 15:47:34 +00:00
|
|
|
linkstep.debuginfo = step.debuginfo; // TODO: multiple debuginfos
|
2021-07-30 23:21:50 +00:00
|
|
|
}
|
|
|
|
// process with another tool?
|
2021-08-08 18:40:19 +00:00
|
|
|
if ('nexttool' in step.result) {
|
|
|
|
var asmstep : BuildStep = {
|
|
|
|
tool: step.result.nexttool,
|
|
|
|
platform: platform,
|
|
|
|
...step.result
|
|
|
|
}
|
2021-07-30 23:21:50 +00:00
|
|
|
this.steps.push(asmstep);
|
|
|
|
}
|
|
|
|
// process final step?
|
|
|
|
if (this.steps.length == 0 && linkstep) {
|
|
|
|
this.steps.push(linkstep);
|
|
|
|
linkstep = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-12 23:19:39 +00:00
|
|
|
async handleMessage(data: WorkerMessage) : Promise<WorkerResult> {
|
2021-07-30 23:21:50 +00:00
|
|
|
this.steps = [];
|
|
|
|
// file updates
|
|
|
|
if (data.updates) {
|
2021-08-15 15:10:01 +00:00
|
|
|
data.updates.forEach((u) => store.putFile(u.path, u.data));
|
|
|
|
}
|
|
|
|
// object update
|
|
|
|
if (data.setitems) {
|
|
|
|
data.setitems.forEach((i) => store.setItem(i.key, i.value));
|
2021-07-30 23:21:50 +00:00
|
|
|
}
|
|
|
|
// build steps
|
|
|
|
if (data.buildsteps) {
|
|
|
|
this.steps.push.apply(this.steps, data.buildsteps);
|
|
|
|
}
|
|
|
|
// single-file
|
|
|
|
if (data.code) {
|
2021-08-15 15:10:01 +00:00
|
|
|
this.steps.push(data as BuildStep); // TODO: remove cast
|
2021-07-30 23:21:50 +00:00
|
|
|
}
|
|
|
|
// execute build steps
|
|
|
|
if (this.steps.length) {
|
2021-08-12 23:19:39 +00:00
|
|
|
var result = await this.executeBuildSteps();
|
2021-07-30 23:21:50 +00:00
|
|
|
return result ? result : {unchanged:true};
|
|
|
|
}
|
|
|
|
// TODO: cache results
|
|
|
|
// message not recognized
|
|
|
|
console.log("Unknown message",data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var builder = new Builder();
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
|
|
function applyDefaultErrorPath(errors:WorkerError[], path:string) {
|
|
|
|
if (!path) return;
|
|
|
|
for (var i=0; i<errors.length; i++) {
|
|
|
|
var err = errors[i];
|
|
|
|
if (!err.path && err.line) err.path = path;
|
|
|
|
}
|
|
|
|
}
|
2018-06-25 14:43:15 +00:00
|
|
|
|
2018-10-05 13:47:15 +00:00
|
|
|
function compareData(a:FileData, b:FileData) : boolean {
|
2018-06-25 14:43:15 +00:00
|
|
|
if (a.length != b.length) return false;
|
2020-08-05 04:48:29 +00:00
|
|
|
if (typeof a === 'string' && typeof b === 'string') {
|
|
|
|
return a == b;
|
|
|
|
} else {
|
2018-06-25 14:43:15 +00:00
|
|
|
for (var i=0; i<a.length; i++) {
|
|
|
|
//if (a[i] != b[i]) console.log('differ at byte',i,a[i],b[i]);
|
|
|
|
if (a[i] != b[i]) return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2018-06-25 04:52:40 +00:00
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function putWorkFile(path:string, data:FileData) {
|
2021-07-30 23:21:50 +00:00
|
|
|
return store.putFile(path, data);
|
2018-06-28 03:26:23 +00:00
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function getWorkFileAsString(path:string) : string {
|
2021-07-30 23:21:50 +00:00
|
|
|
return store.getFileAsString(path);
|
2018-11-28 16:10:24 +00:00
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function populateEntry(fs, path:string, entry:FileEntry, options:BuildOptions) {
|
2018-12-15 18:14:40 +00:00
|
|
|
var data = entry.data;
|
2021-07-12 17:29:50 +00:00
|
|
|
if (options && options.processFn) {
|
|
|
|
data = options.processFn(path, data);
|
|
|
|
}
|
2019-04-26 19:38:34 +00:00
|
|
|
// create subfolders
|
|
|
|
var toks = path.split('/');
|
|
|
|
if (toks.length > 1) {
|
|
|
|
for (var i=0; i<toks.length-1; i++)
|
|
|
|
try {
|
|
|
|
fs.mkdir(toks[i]);
|
|
|
|
} catch (e) { }
|
|
|
|
}
|
|
|
|
// write file
|
2018-12-15 18:14:40 +00:00
|
|
|
fs.writeFile(path, data, {encoding:entry.encoding});
|
2021-07-30 23:21:50 +00:00
|
|
|
var time = new Date(entry.ts);
|
|
|
|
fs.utime(path, time, time);
|
2018-06-28 00:26:22 +00:00
|
|
|
console.log("<<<", path, entry.data.length);
|
2018-06-25 14:43:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// can call multiple times (from populateFiles)
|
2021-08-12 18:51:10 +00:00
|
|
|
export function gatherFiles(step:BuildStep, options?:BuildOptions) : number {
|
2018-06-25 14:43:15 +00:00
|
|
|
var maxts = 0;
|
|
|
|
if (step.files) {
|
|
|
|
for (var i=0; i<step.files.length; i++) {
|
|
|
|
var path = step.files[i];
|
2021-07-30 23:21:50 +00:00
|
|
|
var entry = store.workfs[path];
|
2018-12-15 18:14:40 +00:00
|
|
|
if (!entry) {
|
|
|
|
throw new Error("No entry for path '" + path + "'");
|
|
|
|
} else {
|
|
|
|
maxts = Math.max(maxts, entry.ts);
|
|
|
|
}
|
2018-06-25 14:43:15 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-28 00:26:22 +00:00
|
|
|
else if (step.code) {
|
2018-10-05 13:47:15 +00:00
|
|
|
var path = step.path ? step.path : options.mainFilePath; // TODO: what if options null
|
2019-11-13 20:45:18 +00:00
|
|
|
if (!path) throw Error("need path or mainFilePath");
|
2018-06-25 04:52:40 +00:00
|
|
|
var code = step.code;
|
|
|
|
var entry = putWorkFile(path, code);
|
|
|
|
step.path = path;
|
2018-06-25 14:43:15 +00:00
|
|
|
step.files = [path];
|
|
|
|
maxts = entry.ts;
|
2018-06-25 04:52:40 +00:00
|
|
|
}
|
|
|
|
else if (step.path) {
|
|
|
|
var path = step.path;
|
2021-07-30 23:21:50 +00:00
|
|
|
var entry = store.workfs[path];
|
2018-06-25 14:43:15 +00:00
|
|
|
maxts = entry.ts;
|
|
|
|
step.files = [path];
|
2018-06-25 04:52:40 +00:00
|
|
|
}
|
|
|
|
if (step.path && !step.prefix) {
|
2021-06-12 16:29:49 +00:00
|
|
|
step.prefix = getPrefix(step.path);
|
2018-06-25 04:52:40 +00:00
|
|
|
}
|
2018-06-25 14:43:15 +00:00
|
|
|
step.maxts = maxts;
|
|
|
|
return maxts;
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function getPrefix(s : string) : string {
|
2021-06-12 16:29:49 +00:00
|
|
|
var pos = s.lastIndexOf('.');
|
|
|
|
return (pos > 0) ? s.substring(0, pos) : s;
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function populateFiles(step:BuildStep, fs, options?:BuildOptions) {
|
2018-06-25 14:43:15 +00:00
|
|
|
gatherFiles(step, options);
|
2019-11-13 20:45:18 +00:00
|
|
|
if (!step.files) throw Error("call gatherFiles() first");
|
2018-06-25 14:43:15 +00:00
|
|
|
for (var i=0; i<step.files.length; i++) {
|
|
|
|
var path = step.files[i];
|
2021-07-30 23:21:50 +00:00
|
|
|
populateEntry(fs, path, store.workfs[path], options);
|
2018-06-25 14:43:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function populateExtraFiles(step:BuildStep, fs, extrafiles) {
|
2018-08-14 20:28:29 +00:00
|
|
|
if (extrafiles) {
|
|
|
|
for (var i=0; i<extrafiles.length; i++) {
|
|
|
|
var xfn = extrafiles[i];
|
2019-08-23 00:53:48 +00:00
|
|
|
// is this file cached?
|
2021-07-30 23:21:50 +00:00
|
|
|
if (store.workfs[xfn]) {
|
|
|
|
fs.writeFile(xfn, store.workfs[xfn].data, {encoding:'binary'});
|
2019-08-23 00:53:48 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// fetch from network
|
2019-04-03 21:00:05 +00:00
|
|
|
var xpath = "lib/" + getBasePlatform(step.platform) + "/" + xfn;
|
2018-08-14 20:28:29 +00:00
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.responseType = 'arraybuffer';
|
2021-07-17 20:53:07 +00:00
|
|
|
xhr.open("GET", PWORKER+xpath, false); // synchronous request
|
2018-08-14 20:28:29 +00:00
|
|
|
xhr.send(null);
|
|
|
|
if (xhr.response && xhr.status == 200) {
|
|
|
|
var data = new Uint8Array(xhr.response);
|
|
|
|
fs.writeFile(xfn, data, {encoding:'binary'});
|
2019-08-23 00:53:48 +00:00
|
|
|
putWorkFile(xfn, data);
|
2018-08-15 04:43:52 +00:00
|
|
|
console.log(":::",xfn,data.length);
|
2018-08-14 20:28:29 +00:00
|
|
|
} else {
|
|
|
|
throw Error("Could not load extra file " + xpath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function staleFiles(step:BuildStep, targets:string[]) {
|
2019-11-13 20:45:18 +00:00
|
|
|
if (!step.maxts) throw Error("call populateFiles() first");
|
2018-06-28 03:26:23 +00:00
|
|
|
// see if any target files are more recent than inputs
|
2018-06-25 14:43:15 +00:00
|
|
|
for (var i=0; i<targets.length; i++) {
|
2021-07-30 23:21:50 +00:00
|
|
|
var entry = store.workfs[targets[i]];
|
2018-06-25 14:43:15 +00:00
|
|
|
if (!entry || step.maxts > entry.ts)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
console.log("unchanged", step.maxts, targets);
|
|
|
|
return false;
|
2018-06-25 04:52:40 +00:00
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function anyTargetChanged(step:BuildStep, targets:string[]) {
|
2019-11-13 20:45:18 +00:00
|
|
|
if (!step.maxts) throw Error("call populateFiles() first");
|
2018-06-28 04:57:06 +00:00
|
|
|
// see if any target files are more recent than inputs
|
|
|
|
for (var i=0; i<targets.length; i++) {
|
2021-07-30 23:21:50 +00:00
|
|
|
var entry = store.workfs[targets[i]];
|
2018-06-28 04:57:06 +00:00
|
|
|
if (!entry || entry.ts > step.maxts)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
console.log("unchanged", step.maxts, targets);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function execMain(step:BuildStep, mod, args:string[]) {
|
2018-06-25 04:52:40 +00:00
|
|
|
starttime();
|
2020-06-08 21:36:33 +00:00
|
|
|
var run = mod.callMain || mod.run; // TODO: run?
|
2019-12-07 23:20:01 +00:00
|
|
|
run(args);
|
2018-06-25 04:52:40 +00:00
|
|
|
endtime(step.tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// asm.js / WASM / filesystem loading
|
|
|
|
|
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
|
|
|
|
2018-10-05 13:47:15 +00:00
|
|
|
const PSRC = "../../src/";
|
|
|
|
const PWORKER = PSRC+"worker/";
|
|
|
|
|
2017-01-10 08:18:54 +00:00
|
|
|
// load filesystems for CC65 and others asynchronously
|
2018-10-05 13:47:15 +00:00
|
|
|
function loadFilesystem(name:string) {
|
2017-01-06 00:14:12 +00:00
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.responseType = 'blob';
|
2018-10-05 13:47:15 +00:00
|
|
|
xhr.open("GET", PWORKER+"fs/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';
|
2018-10-05 13:47:15 +00:00
|
|
|
xhr.open("GET", PWORKER+"fs/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
|
|
|
}
|
|
|
|
|
2021-07-17 20:53:07 +00:00
|
|
|
var loaded = {};
|
2021-08-12 18:51:10 +00:00
|
|
|
export function load(modulename:string, debug?:boolean) {
|
2017-11-05 18:34:00 +00:00
|
|
|
if (!loaded[modulename]) {
|
2018-10-05 13:47:15 +00:00
|
|
|
importScripts(PWORKER+'asmjs/'+modulename+(debug?"."+debug+".js":".js"));
|
2017-11-05 18:34:00 +00:00
|
|
|
loaded[modulename] = 1;
|
|
|
|
}
|
|
|
|
}
|
2021-08-12 18:51:10 +00:00
|
|
|
export function loadWASM(modulename:string, debug?:boolean) {
|
2017-11-05 18:34:00 +00:00
|
|
|
if (!loaded[modulename]) {
|
2018-10-05 13:47:15 +00:00
|
|
|
importScripts(PWORKER+"wasm/" + modulename+(debug?"."+debug+".js":".js"));
|
2017-11-05 18:34:00 +00:00
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.responseType = 'arraybuffer';
|
2018-10-05 13:47:15 +00:00
|
|
|
xhr.open("GET", PWORKER+"wasm/"+modulename+".wasm", false); // synchronous request
|
2017-11-05 18:34:00 +00:00
|
|
|
xhr.send(null);
|
|
|
|
if (xhr.response) {
|
2018-07-10 04:44:17 +00:00
|
|
|
wasmBlob[modulename] = new Uint8Array(xhr.response);
|
2019-03-14 15:20:50 +00:00
|
|
|
console.log("Loaded " + modulename + ".wasm (" + wasmBlob[modulename].length + " bytes)");
|
2017-11-05 18:34:00 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-08-12 18:51:10 +00:00
|
|
|
export function loadNative(modulename:string) {
|
2017-11-07 21:41:07 +00:00
|
|
|
// detect WASM
|
2018-07-10 05:09:10 +00:00
|
|
|
if (CACHE_WASM_MODULES && typeof WebAssembly === 'object') {
|
2017-11-07 21:41:07 +00:00
|
|
|
loadWASM(modulename);
|
|
|
|
} else {
|
|
|
|
load(modulename);
|
|
|
|
}
|
|
|
|
}
|
2017-11-05 18:34:00 +00:00
|
|
|
|
2017-01-10 08:18:54 +00:00
|
|
|
// mount the filesystem at /share
|
2021-08-12 18:51:10 +00:00
|
|
|
export function setupFS(FS, name:string) {
|
2019-03-13 18:52:30 +00:00
|
|
|
var WORKERFS = FS.filesystems['WORKERFS'];
|
2022-01-29 17:38:44 +00:00
|
|
|
if (name === '65-vector') name = '65-none'; // TODO
|
|
|
|
if (name === '65-atari7800') name = '65-none'; // TODO
|
|
|
|
if (name === '65-devel') name = '65-none'; // TODO
|
|
|
|
if (name === '65-vcs') name = '65-none'; // TODO
|
2019-11-13 20:45:18 +00:00
|
|
|
if (!fsMeta[name]) throw Error("No filesystem for '" + name + "'");
|
2017-01-06 00:14:12 +00:00
|
|
|
FS.mkdir('/share');
|
2018-08-06 15:20:55 +00:00
|
|
|
FS.mount(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');
|
2018-08-06 15:20:55 +00:00
|
|
|
// fix for slow Blob operations by caching typed arrays
|
|
|
|
// https://github.com/kripken/emscripten/blob/incoming/src/library_workerfs.js
|
2019-08-09 15:42:36 +00:00
|
|
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=349304#c30
|
2018-08-06 15:20:55 +00:00
|
|
|
var reader = WORKERFS.reader;
|
|
|
|
var blobcache = {};
|
|
|
|
WORKERFS.stream_ops.read = function (stream, buffer, offset, length, position) {
|
|
|
|
if (position >= stream.node.size) return 0;
|
|
|
|
var contents = blobcache[stream.path];
|
|
|
|
if (!contents) {
|
|
|
|
var ab = reader.readAsArrayBuffer(stream.node.contents);
|
|
|
|
contents = blobcache[stream.path] = new Uint8Array(ab);
|
|
|
|
}
|
|
|
|
if (position + length > contents.length)
|
|
|
|
length = contents.length - position;
|
|
|
|
for (var i=0; i<length; i++) {
|
|
|
|
buffer[offset+i] = contents[position+i];
|
|
|
|
}
|
|
|
|
return length;
|
|
|
|
};
|
2017-01-06 00:14:12 +00:00
|
|
|
}
|
2016-12-16 01:21:51 +00:00
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export var print_fn = function(s:string) {
|
2017-01-12 16:22:27 +00:00
|
|
|
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
|
2021-08-12 18:51:10 +00:00
|
|
|
export const re_msvc = /[/]*([^( ]+)\s*[(](\d+)[)]\s*:\s*(.+?):\s*(.*)/;
|
|
|
|
export const re_msvc2 = /\s*(at)\s+(\d+)\s*(:)\s*(.*)/;
|
2018-06-19 22:42:02 +00:00
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function msvcErrorMatcher(errors:WorkerError[]) {
|
2018-10-05 13:47:15 +00:00
|
|
|
return function(s:string) {
|
2018-06-19 22:42:02 +00:00
|
|
|
var matches = re_msvc.exec(s) || re_msvc2.exec(s);
|
|
|
|
if (matches) {
|
|
|
|
var errline = parseInt(matches[2]);
|
|
|
|
errors.push({
|
|
|
|
line:errline,
|
2018-08-18 00:46:55 +00:00
|
|
|
path:matches[1],
|
2018-10-05 13:47:15 +00:00
|
|
|
//type:matches[3],
|
2018-06-19 22:42:02 +00:00
|
|
|
msg:matches[4]
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
console.log(s);
|
|
|
|
}
|
2017-01-13 02:21:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function makeErrorMatcher(errors:WorkerError[], regex, iline:number, imsg:number, mainpath:string, ifilename?:number) {
|
2017-01-23 21:21:45 +00:00
|
|
|
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,
|
2018-08-18 00:46:55 +00:00
|
|
|
msg:matches[imsg],
|
2018-12-15 18:14:40 +00:00
|
|
|
path:ifilename ? matches[ifilename] : mainpath
|
2017-01-23 21:21:45 +00:00
|
|
|
});
|
2017-11-13 05:24:19 +00:00
|
|
|
} else {
|
2018-07-03 03:55:38 +00:00
|
|
|
console.log("??? "+s);
|
2017-01-23 21:21:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function extractErrors(regex, strings:string[], path:string, iline, imsg, ifilename) {
|
2017-01-23 21:21:45 +00:00
|
|
|
var errors = [];
|
2019-03-23 00:26:47 +00:00
|
|
|
var matcher = makeErrorMatcher(errors, regex, iline, imsg, path, ifilename);
|
2017-01-23 21:21:45 +00:00
|
|
|
for (var i=0; i<strings.length; i++) {
|
|
|
|
matcher(strings[i]);
|
|
|
|
}
|
|
|
|
return errors;
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export const re_crlf = /\r?\n/;
|
2020-07-10 18:25:34 +00:00
|
|
|
// 1 %line 16+1 hello.asm
|
2021-08-12 18:51:10 +00:00
|
|
|
export const re_lineoffset = /\s*(\d+)\s+[%]line\s+(\d+)\+(\d+)\s+(.+)/;
|
2018-08-28 17:59:12 +00:00
|
|
|
|
2022-02-22 15:40:05 +00:00
|
|
|
export function parseListing(code:string,
|
|
|
|
lineMatch, iline:number, ioffset:number, iinsns:number, icycles?:number,
|
|
|
|
funcMatch?, segMatch?) : SourceLine[] {
|
2019-06-11 13:39:45 +00:00
|
|
|
var lines : SourceLine[] = [];
|
2020-07-10 18:25:34 +00:00
|
|
|
var lineofs = 0;
|
2022-02-22 15:40:05 +00:00
|
|
|
var segment = '';
|
|
|
|
var func = '';
|
|
|
|
var funcbase = 0;
|
2020-07-06 23:53:20 +00:00
|
|
|
code.split(re_crlf).forEach((line, lineindex) => {
|
2022-02-22 15:40:05 +00:00
|
|
|
let segm = segMatch && segMatch.exec(line);
|
|
|
|
if (segm) { segment = segm[1]; }
|
|
|
|
let funcm = funcMatch && funcMatch.exec(line);
|
|
|
|
if (funcm) { funcbase = parseInt(funcm[1],16); func = funcm[2]; }
|
|
|
|
|
2017-01-14 02:31:04 +00:00
|
|
|
var linem = lineMatch.exec(line);
|
|
|
|
if (linem && linem[1]) {
|
2020-07-06 23:53:20 +00:00
|
|
|
var linenum = iline < 0 ? lineindex : parseInt(linem[iline]);
|
2017-01-15 03:46:12 +00:00
|
|
|
var offset = parseInt(linem[ioffset], 16);
|
|
|
|
var insns = linem[iinsns];
|
2019-06-11 13:39:45 +00:00
|
|
|
var cycles : number = icycles ? parseInt(linem[icycles]) : null;
|
|
|
|
var iscode = cycles > 0;
|
2017-01-14 02:31:04 +00:00
|
|
|
if (insns) {
|
|
|
|
lines.push({
|
2022-02-22 15:40:05 +00:00
|
|
|
line: linenum + lineofs,
|
|
|
|
offset: offset - funcbase,
|
|
|
|
insns,
|
|
|
|
cycles,
|
|
|
|
iscode,
|
|
|
|
segment,
|
|
|
|
func
|
2017-01-14 02:31:04 +00:00
|
|
|
});
|
|
|
|
}
|
2020-07-10 18:25:34 +00:00
|
|
|
} else {
|
|
|
|
let m = re_lineoffset.exec(line);
|
|
|
|
// TODO: check filename too
|
|
|
|
if (m) {
|
|
|
|
lineofs = parseInt(m[2]) - parseInt(m[1]) - parseInt(m[3]);
|
|
|
|
}
|
2017-01-14 02:31:04 +00:00
|
|
|
}
|
2020-07-06 23:53:20 +00:00
|
|
|
});
|
2017-01-14 02:31:04 +00:00
|
|
|
return lines;
|
|
|
|
}
|
|
|
|
|
2022-02-22 15:40:05 +00:00
|
|
|
export function parseSourceLines(code:string, lineMatch, offsetMatch, funcMatch?, segMatch?) {
|
2017-01-15 18:31:52 +00:00
|
|
|
var lines = [];
|
|
|
|
var lastlinenum = 0;
|
2022-02-22 15:40:05 +00:00
|
|
|
var segment = '';
|
|
|
|
var func = '';
|
|
|
|
var funcbase = 0;
|
2018-08-28 17:59:12 +00:00
|
|
|
for (var line of code.split(re_crlf)) {
|
2022-02-22 15:40:05 +00:00
|
|
|
let segm = segMatch && segMatch.exec(line);
|
|
|
|
if (segm) { segment = segm[1]; }
|
|
|
|
let funcm = funcMatch && funcMatch.exec(line);
|
|
|
|
if (funcm) { funcbase = parseInt(funcm[1],16); func = funcm[2]; }
|
|
|
|
|
2017-01-15 18:31:52 +00:00
|
|
|
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({
|
2022-02-22 15:40:05 +00:00
|
|
|
line: lastlinenum,
|
|
|
|
offset: offset - funcbase,
|
|
|
|
segment,
|
|
|
|
func
|
2017-01-15 18:31:52 +00:00
|
|
|
});
|
|
|
|
lastlinenum = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return lines;
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function setupStdin(fs, code:string) {
|
2017-01-13 02:21:35 +00:00
|
|
|
var i = 0;
|
|
|
|
fs.init(
|
|
|
|
function() { return i<code.length ? code.charCodeAt(i++) : null; }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function fixParamsWithDefines(path:string, params){
|
2019-03-13 18:52:30 +00:00
|
|
|
var libargs = params.libargs;
|
2019-02-15 18:54:15 +00:00
|
|
|
if (path && libargs) {
|
|
|
|
var code = getWorkFileAsString(path);
|
|
|
|
if (code) {
|
2019-05-22 01:39:37 +00:00
|
|
|
var oldcfgfile = params.cfgfile;
|
2019-02-15 18:54:15 +00:00
|
|
|
var ident2index = {};
|
|
|
|
// find all lib args "IDENT=VALUE"
|
|
|
|
for (var i=0; i<libargs.length; i++) {
|
|
|
|
var toks = libargs[i].split('=');
|
|
|
|
if (toks.length == 2) {
|
|
|
|
ident2index[toks[0]] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// find #defines and replace them
|
2019-05-22 01:39:37 +00:00
|
|
|
var re = /^[;]?#define\s+(\w+)\s+(\S+)/gmi; // TODO: empty string?
|
2019-02-15 18:54:15 +00:00
|
|
|
var m;
|
|
|
|
while (m = re.exec(code)) {
|
|
|
|
var ident = m[1];
|
|
|
|
var value = m[2];
|
|
|
|
var index = ident2index[ident];
|
|
|
|
if (index >= 0) {
|
|
|
|
libargs[index] = ident + "=" + value;
|
2019-03-13 18:52:30 +00:00
|
|
|
console.log('Using libargs', index, libargs[index]);
|
|
|
|
// TODO: MMC3 mapper switch
|
|
|
|
if (ident == 'NES_MAPPER' && value == '4') {
|
|
|
|
params.cfgfile = 'nesbanked.cfg';
|
2019-05-22 01:39:37 +00:00
|
|
|
console.log("using config file", params.cfgfile);
|
2019-03-13 18:52:30 +00:00
|
|
|
}
|
2019-05-22 01:39:37 +00:00
|
|
|
} else if (ident == 'CFGFILE' && value) {
|
|
|
|
params.cfgfile = value;
|
|
|
|
} else if (ident == 'LIBARGS' && value) {
|
|
|
|
params.libargs = value.split(',').filter((s) => { return s!=''; });
|
|
|
|
console.log('Using libargs', params.libargs);
|
2021-07-15 17:54:19 +00:00
|
|
|
} else if (ident == 'CC65_FLAGS' && value) {
|
|
|
|
params.extra_compiler_args = value.split(',').filter((s) => { return s!=''; });
|
|
|
|
console.log('Using compiler flags', params.extra_compiler_args);
|
2019-02-15 18:54:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-13 02:21:35 +00:00
|
|
|
|
2018-11-22 17:28:50 +00:00
|
|
|
function makeCPPSafe(s:string) : string {
|
|
|
|
return s.replace(/[^A-Za-z0-9_]/g,'_');
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function preprocessMCPP(step:BuildStep, filesys:string) {
|
2017-01-22 14:35:04 +00:00
|
|
|
load("mcpp");
|
2018-08-12 23:59:08 +00:00
|
|
|
var platform = step.platform;
|
2019-02-25 21:04:15 +00:00
|
|
|
var params = PLATFORM_PARAMS[getBasePlatform(platform)];
|
2017-05-02 13:09:53 +00:00
|
|
|
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 = [];
|
2018-08-18 00:46:55 +00:00
|
|
|
var match_fn = makeErrorMatcher(errors, /<stdin>:(\d+): (.+)/, 1, 2, step.path);
|
2021-07-30 23:21:50 +00:00
|
|
|
var MCPP : EmscriptenModule = emglobal.mcpp({
|
2017-01-22 14:35:04 +00:00
|
|
|
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
|
|
|
});
|
2021-07-30 23:21:50 +00:00
|
|
|
var FS = MCPP.FS;
|
2019-12-11 03:19:12 +00:00
|
|
|
if (filesys) setupFS(FS, filesys);
|
2018-08-12 23:59:08 +00:00
|
|
|
populateFiles(step, FS);
|
2018-11-28 15:31:07 +00:00
|
|
|
populateExtraFiles(step, FS, params.extra_compile_files);
|
2018-06-25 04:52:40 +00:00
|
|
|
// TODO: make configurable by other compilers
|
2017-05-02 13:09:53 +00:00
|
|
|
var args = [
|
2017-01-23 21:21:45 +00:00
|
|
|
"-D", "__8BITWORKSHOP__",
|
2017-02-20 23:50:29 +00:00
|
|
|
"-D", "__SDCC_z80",
|
2018-11-22 17:28:50 +00:00
|
|
|
"-D", makeCPPSafe(platform.toUpperCase()),
|
2017-01-23 21:21:45 +00:00
|
|
|
"-I", "/share/include",
|
|
|
|
"-Q",
|
2018-08-12 23:59:08 +00:00
|
|
|
step.path, "main.i"];
|
2018-11-29 23:55:20 +00:00
|
|
|
if (step.mainfile) {
|
|
|
|
args.unshift.apply(args, ["-D", "__MAIN__"]);
|
|
|
|
}
|
2022-08-29 03:16:17 +00:00
|
|
|
let platform_def = (platform.toUpperCase() as any).replaceAll(/[^a-zA-Z0-9]/g,'_');
|
|
|
|
args.unshift.apply(args, ["-D", `__PLATFORM_${platform_def}__`]);
|
2017-05-02 13:09:53 +00:00
|
|
|
if (params.extra_preproc_args) {
|
|
|
|
args.push.apply(args, params.extra_preproc_args);
|
|
|
|
}
|
2021-07-30 23:21:50 +00:00
|
|
|
execMain(step, MCPP, args);
|
2018-06-25 04:52:40 +00:00
|
|
|
if (errors.length)
|
|
|
|
return {errors:errors};
|
|
|
|
var iout = FS.readFile("main.i", {encoding:'utf8'});
|
|
|
|
iout = iout.replace(/^#line /gm,'\n# ');
|
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"
|
2019-03-23 00:26:47 +00:00
|
|
|
var errors = extractErrors(/([^:]+):(\d+): (.+)/, errout.split("\n"), step.path, 2, 3, 1);
|
2017-01-29 21:06:05 +00:00
|
|
|
if (errors.length == 0) {
|
2021-08-15 15:10:01 +00:00
|
|
|
errors = errorResult(errout).errors;
|
2017-01-29 21:06:05 +00:00
|
|
|
}
|
|
|
|
return {errors: errors};
|
2017-01-23 21:21:45 +00:00
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
//
|
2017-01-22 14:35:04 +00:00
|
|
|
}
|
|
|
|
return {code:iout};
|
|
|
|
}
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
export function setupRequireFunction() {
|
2018-11-21 16:53:33 +00:00
|
|
|
var exports = {};
|
|
|
|
exports['jsdom'] = {
|
|
|
|
JSDOM: function(a,b) {
|
|
|
|
this.window = {};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
emglobal['require'] = (modname:string) => {
|
2021-06-28 20:36:47 +00:00
|
|
|
console.log('require',modname,exports[modname]!=null);
|
2018-11-21 16:53:33 +00:00
|
|
|
return exports[modname];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-28 14:10:59 +00:00
|
|
|
////////////////////////////
|
|
|
|
|
2021-08-12 18:51:10 +00:00
|
|
|
import * as misc from './tools/misc'
|
|
|
|
import * as cc65 from './tools/cc65'
|
|
|
|
import * as dasm from './tools/dasm'
|
|
|
|
import * as sdcc from './tools/sdcc'
|
|
|
|
import * as verilog from './tools/verilog'
|
|
|
|
import * as m6809 from './tools/m6809'
|
|
|
|
import * as m6502 from './tools/m6502'
|
|
|
|
import * as z80 from './tools/z80'
|
|
|
|
import * as x86 from './tools/x86'
|
|
|
|
import * as arm from './tools/arm'
|
2021-08-12 23:19:39 +00:00
|
|
|
import * as script from './tools/script'
|
2022-01-29 17:34:26 +00:00
|
|
|
import * as ecs from './tools/ecs'
|
2021-08-12 18:51:10 +00:00
|
|
|
|
2017-01-15 03:46:12 +00:00
|
|
|
var TOOLS = {
|
2021-08-12 18:51:10 +00:00
|
|
|
'dasm': dasm.assembleDASM,
|
2018-06-28 00:26:22 +00:00
|
|
|
//'acme': assembleACME,
|
|
|
|
//'plasm': compilePLASMA,
|
2021-08-12 18:51:10 +00:00
|
|
|
'cc65': cc65.compileCC65,
|
|
|
|
'ca65': cc65.assembleCA65,
|
|
|
|
'ld65': cc65.linkLD65,
|
2018-06-28 00:26:22 +00:00
|
|
|
//'z80asm': assembleZ80ASM,
|
|
|
|
//'sccz80': compileSCCZ80,
|
2021-08-12 18:51:10 +00:00
|
|
|
'sdasz80': sdcc.assembleSDASZ80,
|
|
|
|
'sdldz80': sdcc.linkSDLDZ80,
|
|
|
|
'sdcc': sdcc.compileSDCC,
|
|
|
|
'xasm6809': m6809.assembleXASM6809,
|
|
|
|
'cmoc': m6809.compileCMOC,
|
|
|
|
'lwasm': m6809.assembleLWASM,
|
|
|
|
'lwlink': m6809.linkLWLINK,
|
2018-06-25 04:52:40 +00:00
|
|
|
//'naken': assembleNAKEN,
|
2021-08-12 18:51:10 +00:00
|
|
|
'verilator': verilog.compileVerilator,
|
|
|
|
'yosys': verilog.compileYosys,
|
|
|
|
'jsasm': verilog.compileJSASMStep,
|
|
|
|
'zmac': z80.assembleZMAC,
|
|
|
|
'nesasm': m6502.assembleNESASM,
|
|
|
|
'smlrc': x86.compileSmallerC,
|
|
|
|
'yasm': x86.assembleYASM,
|
|
|
|
'bataribasic': dasm.compileBatariBasic,
|
|
|
|
'markdown': misc.translateShowdown,
|
|
|
|
'inform6': misc.compileInform6,
|
|
|
|
'merlin32': m6502.assembleMerlin32,
|
|
|
|
'fastbasic': m6502.compileFastBasic,
|
|
|
|
'basic': misc.compileBASIC,
|
|
|
|
'silice': verilog.compileSilice,
|
|
|
|
'wiz': misc.compileWiz,
|
|
|
|
'armips': arm.assembleARMIPS,
|
|
|
|
'vasmarm': arm.assembleVASMARM,
|
2022-01-29 17:34:26 +00:00
|
|
|
//'js': script.runJavascript,
|
|
|
|
'ecs': ecs.assembleECS,
|
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',
|
2022-02-23 19:36:44 +00:00
|
|
|
'cc65-vic20': '65-vic20',
|
|
|
|
'ca65-vic20': '65-vic20',
|
2018-06-20 07:09:37 +00:00
|
|
|
'cc65-nes': '65-nes',
|
|
|
|
'ca65-nes': '65-nes',
|
|
|
|
'cc65-atari8': '65-atari8',
|
|
|
|
'ca65-atari8': '65-atari8',
|
2022-01-29 17:38:44 +00:00
|
|
|
'cc65-vector': '65-none',
|
|
|
|
'ca65-vector': '65-none',
|
|
|
|
'cc65-atari7800': '65-none',
|
|
|
|
'ca65-atari7800': '65-none',
|
|
|
|
'cc65-devel': '65-none',
|
|
|
|
'ca65-devel': '65-none',
|
|
|
|
'ca65-vcs': '65-none',
|
2017-01-23 21:21:45 +00:00
|
|
|
'sdasz80': 'sdcc',
|
|
|
|
'sdcc': 'sdcc',
|
2018-06-24 05:01:38 +00:00
|
|
|
'sccz80': 'sccz80',
|
2018-11-20 17:31:19 +00:00
|
|
|
'bataribasic': '2600basic',
|
2020-07-06 23:53:20 +00:00
|
|
|
'inform6': 'inform',
|
2020-07-29 00:14:42 +00:00
|
|
|
'fastbasic': '65-atari8',
|
2020-12-16 16:48:33 +00:00
|
|
|
'silice': 'Silice',
|
2021-03-04 14:20:00 +00:00
|
|
|
'wiz': 'wiz',
|
2022-02-21 15:24:03 +00:00
|
|
|
'ecs-vcs': '65-none', // TODO: support multiple platforms
|
|
|
|
'ecs-nes': '65-nes', // TODO: support multiple platforms
|
2022-08-25 20:52:04 +00:00
|
|
|
'ecs-c64': '65-c64', // TODO: support multiple platforms
|
2017-01-23 21:21:45 +00:00
|
|
|
}
|
|
|
|
|
2021-08-14 16:06:49 +00:00
|
|
|
//const waitFor = delay => new Promise(resolve => setTimeout(resolve, delay)); // for testing
|
2021-08-12 23:19:39 +00:00
|
|
|
|
|
|
|
async function handleMessage(data : WorkerMessage) : Promise<WorkerResult> {
|
2018-06-25 14:43:15 +00:00
|
|
|
// preload file system
|
2018-03-03 02:16:25 +00:00
|
|
|
if (data.preload) {
|
|
|
|
var fs = TOOL_PRELOADFS[data.preload];
|
2020-10-17 19:34:08 +00:00
|
|
|
if (!fs && data.platform)
|
|
|
|
fs = TOOL_PRELOADFS[data.preload+'-'+getBasePlatform(data.platform)];
|
2018-06-20 07:09:37 +00:00
|
|
|
if (!fs && data.platform)
|
2019-04-03 21:00:05 +00:00
|
|
|
fs = TOOL_PRELOADFS[data.preload+'-'+getRootBasePlatform(data.platform)];
|
2018-06-20 07:09:37 +00:00
|
|
|
if (fs && !fsMeta[fs])
|
|
|
|
loadFilesystem(fs);
|
2017-01-23 21:21:45 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-06-25 21:51:07 +00:00
|
|
|
// clear filesystem? (TODO: buildkey)
|
|
|
|
if (data.reset) {
|
2021-07-30 23:21:50 +00:00
|
|
|
store.reset();
|
2018-06-25 21:51:07 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-07-30 23:21:50 +00:00
|
|
|
return builder.handleMessage(data);
|
2018-03-03 02:16:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ENVIRONMENT_IS_WORKER) {
|
2021-08-12 23:19:39 +00:00
|
|
|
var lastpromise = null;
|
|
|
|
onmessage = async function(e) {
|
|
|
|
await lastpromise; // wait for previous message to complete
|
|
|
|
lastpromise = handleMessage(e.data);
|
|
|
|
var result = await lastpromise;
|
|
|
|
lastpromise = null;
|
2018-03-03 02:16:25 +00:00
|
|
|
if (result) {
|
2021-08-15 15:10:01 +00:00
|
|
|
try {
|
|
|
|
postMessage(result);
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e);
|
|
|
|
postMessage(errorResult(`${e}`));
|
|
|
|
}
|
2018-03-03 02:16:25 +00:00
|
|
|
}
|
2017-01-06 00:14:12 +00:00
|
|
|
}
|
2016-12-16 01:21:51 +00:00
|
|
|
}
|