2022-02-21 15:35:52 +00:00
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
|
exports.compileCC65 = exports.linkLD65 = exports.assembleCA65 = void 0;
|
|
|
|
const util_1 = require("../../common/util");
|
|
|
|
const workermain_1 = require("../workermain");
|
|
|
|
/*
|
|
|
|
000000r 1 .segment "CODE"
|
|
|
|
000000r 1 .proc _rasterWait: near
|
|
|
|
000000r 1 ; int main() { return mul2(2); }
|
|
|
|
000000r 1 .dbg line, "main.c", 3
|
|
|
|
000014r 1 .dbg func, "main", "00", extern, "_main"
|
|
|
|
000000r 1 A2 00 ldx #$00
|
|
|
|
00B700 1 BOOT2:
|
|
|
|
00B700 1 A2 01 ldx #1 ;track
|
|
|
|
00B725 1 00 IBLASTDRVN: .byte 0
|
|
|
|
00B726 1 xx xx IBSECSZ: .res 2
|
|
|
|
00BA2F 1 2A 2B E8 2C HEX "2A2BE82C2D2E2F303132F0F133343536"
|
|
|
|
*/
|
2022-06-30 18:34:04 +00:00
|
|
|
function parseCA65Listing(code, symbols, params, dbg, listings) {
|
2022-02-21 15:35:52 +00:00
|
|
|
var segofs = 0;
|
|
|
|
var offset = 0;
|
|
|
|
var dbgLineMatch = /^([0-9A-F]+)([r]?)\s+(\d+)\s+[.]dbg\s+(\w+), "([^"]+)", (.+)/;
|
|
|
|
var funcLineMatch = /"(\w+)", (\w+), "(\w+)"/;
|
|
|
|
var insnLineMatch = /^([0-9A-F]+)([r]?)\s{1,2}(\d+)\s{1,2}([0-9A-Frx ]{11})\s+(.*)/;
|
|
|
|
var segMatch = /[.]segment\s+"(\w+)"/i;
|
2022-06-30 18:34:04 +00:00
|
|
|
var origlines = [];
|
|
|
|
var lines = origlines;
|
2022-02-21 15:35:52 +00:00
|
|
|
var linenum = 0;
|
2022-06-30 18:34:04 +00:00
|
|
|
let curpath = '';
|
2022-02-21 15:35:52 +00:00
|
|
|
// TODO: only does .c functions, not all .s files
|
|
|
|
for (var line of code.split(workermain_1.re_crlf)) {
|
|
|
|
var dbgm = dbgLineMatch.exec(line);
|
|
|
|
if (dbgm && dbgm[1]) {
|
|
|
|
var dbgtype = dbgm[4];
|
|
|
|
offset = parseInt(dbgm[1], 16);
|
2022-06-30 18:34:04 +00:00
|
|
|
curpath = dbgm[5];
|
|
|
|
// new file?
|
|
|
|
if (curpath && listings) {
|
|
|
|
let l = listings[curpath];
|
|
|
|
if (!l)
|
|
|
|
l = listings[curpath] = { lines: [] };
|
|
|
|
lines = l.lines;
|
|
|
|
}
|
2022-02-21 15:35:52 +00:00
|
|
|
if (dbgtype == 'func') {
|
|
|
|
var funcm = funcLineMatch.exec(dbgm[6]);
|
|
|
|
if (funcm) {
|
|
|
|
var funcofs = symbols[funcm[3]];
|
|
|
|
if (typeof funcofs === 'number') {
|
|
|
|
segofs = funcofs - offset;
|
|
|
|
//console.log(funcm[3], funcofs, '-', offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dbg && dbgm && dbgtype == 'line') {
|
2022-06-30 18:34:04 +00:00
|
|
|
//console.log(dbgm[5], dbgm[6], offset, segofs);
|
2022-02-21 15:35:52 +00:00
|
|
|
lines.push({
|
2022-06-30 18:34:04 +00:00
|
|
|
path: dbgm[5],
|
2022-02-21 15:35:52 +00:00
|
|
|
line: parseInt(dbgm[6]),
|
|
|
|
offset: offset + segofs,
|
|
|
|
insns: null
|
|
|
|
});
|
|
|
|
}
|
|
|
|
var linem = insnLineMatch.exec(line);
|
|
|
|
var topfile = linem && linem[3] == '1';
|
|
|
|
if (topfile)
|
|
|
|
linenum++;
|
|
|
|
if (topfile && linem[1]) {
|
|
|
|
var offset = parseInt(linem[1], 16);
|
|
|
|
var insns = linem[4].trim();
|
|
|
|
if (insns.length) {
|
|
|
|
// take back one to honor the long .byte line
|
|
|
|
if (linem[5].length == 0) {
|
|
|
|
linenum--;
|
|
|
|
}
|
|
|
|
else if (!dbg) {
|
|
|
|
lines.push({
|
2022-06-30 18:34:04 +00:00
|
|
|
path: curpath,
|
2022-02-21 15:35:52 +00:00
|
|
|
line: linenum,
|
|
|
|
offset: offset + segofs,
|
|
|
|
insns: insns,
|
|
|
|
iscode: true // TODO: can't really tell unless we parse it
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
var sym = linem[5];
|
|
|
|
var segm = sym && segMatch.exec(sym);
|
|
|
|
if (segm && segm[1]) {
|
|
|
|
var symofs = symbols['__' + segm[1] + '_RUN__'];
|
|
|
|
if (typeof symofs === 'number') {
|
|
|
|
segofs = symofs;
|
|
|
|
//console.log(sym, segofs, symofs, '-', offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (sym.endsWith(':') && !sym.startsWith('@')) {
|
|
|
|
var symofs = symbols[sym.substring(0, sym.length - 1)];
|
|
|
|
if (typeof symofs === 'number') {
|
|
|
|
segofs = symofs - offset;
|
|
|
|
//console.log(sym, segofs, symofs, '-', offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-06-30 18:34:04 +00:00
|
|
|
return origlines;
|
2022-02-21 15:35:52 +00:00
|
|
|
}
|
|
|
|
function assembleCA65(step) {
|
|
|
|
(0, workermain_1.loadNative)("ca65");
|
|
|
|
var errors = [];
|
|
|
|
(0, workermain_1.gatherFiles)(step, { mainFilePath: "main.s" });
|
|
|
|
var objpath = step.prefix + ".o";
|
|
|
|
var lstpath = step.prefix + ".lst";
|
|
|
|
if ((0, workermain_1.staleFiles)(step, [objpath, lstpath])) {
|
|
|
|
var objout, lstout;
|
|
|
|
var CA65 = workermain_1.emglobal.ca65({
|
|
|
|
instantiateWasm: (0, workermain_1.moduleInstFn)('ca65'),
|
|
|
|
noInitialRun: true,
|
|
|
|
//logReadFiles:true,
|
|
|
|
print: workermain_1.print_fn,
|
|
|
|
printErr: (0, workermain_1.makeErrorMatcher)(errors, /(.+?):(\d+): (.+)/, 2, 3, step.path, 1),
|
|
|
|
});
|
|
|
|
var FS = CA65.FS;
|
|
|
|
(0, workermain_1.setupFS)(FS, '65-' + (0, util_1.getRootBasePlatform)(step.platform));
|
|
|
|
(0, workermain_1.populateFiles)(step, FS);
|
|
|
|
(0, workermain_1.fixParamsWithDefines)(step.path, step.params);
|
|
|
|
var args = ['-v', '-g', '-I', '/share/asminc', '-o', objpath, '-l', lstpath, step.path];
|
|
|
|
args.unshift.apply(args, ["-D", "__8BITWORKSHOP__=1"]);
|
|
|
|
if (step.mainfile) {
|
|
|
|
args.unshift.apply(args, ["-D", "__MAIN__=1"]);
|
|
|
|
}
|
|
|
|
(0, workermain_1.execMain)(step, CA65, args);
|
2022-06-30 18:34:04 +00:00
|
|
|
if (errors.length) {
|
|
|
|
// TODO?
|
|
|
|
let listings = {};
|
|
|
|
listings[step.path] = { lines: [], text: (0, workermain_1.getWorkFileAsString)(step.path) };
|
|
|
|
return { errors, listings };
|
|
|
|
}
|
2022-02-21 15:35:52 +00:00
|
|
|
objout = FS.readFile(objpath, { encoding: 'binary' });
|
|
|
|
lstout = FS.readFile(lstpath, { encoding: 'utf8' });
|
|
|
|
(0, workermain_1.putWorkFile)(objpath, objout);
|
|
|
|
(0, workermain_1.putWorkFile)(lstpath, lstout);
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
linktool: "ld65",
|
|
|
|
files: [objpath, lstpath],
|
|
|
|
args: [objpath]
|
|
|
|
};
|
|
|
|
}
|
|
|
|
exports.assembleCA65 = assembleCA65;
|
|
|
|
function linkLD65(step) {
|
2022-06-30 18:34:04 +00:00
|
|
|
var _a;
|
2022-02-21 15:35:52 +00:00
|
|
|
(0, workermain_1.loadNative)("ld65");
|
|
|
|
var params = step.params;
|
|
|
|
(0, workermain_1.gatherFiles)(step);
|
|
|
|
var binpath = "main";
|
|
|
|
if ((0, workermain_1.staleFiles)(step, [binpath])) {
|
|
|
|
var errors = [];
|
|
|
|
var LD65 = workermain_1.emglobal.ld65({
|
|
|
|
instantiateWasm: (0, workermain_1.moduleInstFn)('ld65'),
|
|
|
|
noInitialRun: true,
|
|
|
|
//logReadFiles:true,
|
|
|
|
print: workermain_1.print_fn,
|
|
|
|
printErr: function (s) { errors.push({ msg: s, line: 0 }); }
|
|
|
|
});
|
|
|
|
var FS = LD65.FS;
|
|
|
|
(0, workermain_1.setupFS)(FS, '65-' + (0, util_1.getRootBasePlatform)(step.platform));
|
|
|
|
(0, workermain_1.populateFiles)(step, FS);
|
|
|
|
(0, workermain_1.populateExtraFiles)(step, FS, params.extra_link_files);
|
|
|
|
// populate .cfg file, if it is a custom one
|
|
|
|
if (workermain_1.store.hasFile(params.cfgfile)) {
|
|
|
|
(0, workermain_1.populateEntry)(FS, params.cfgfile, workermain_1.store.getFileEntry(params.cfgfile), null);
|
|
|
|
}
|
|
|
|
var libargs = params.libargs || [];
|
|
|
|
var cfgfile = params.cfgfile;
|
|
|
|
var args = ['--cfg-path', '/share/cfg',
|
|
|
|
'--lib-path', '/share/lib',
|
|
|
|
'-C', cfgfile,
|
|
|
|
'-Ln', 'main.vice',
|
|
|
|
//'--dbgfile', 'main.dbg', // TODO: get proper line numbers
|
|
|
|
'-o', 'main', '-m', 'main.map'].concat(step.args, libargs);
|
|
|
|
//console.log(args);
|
|
|
|
(0, workermain_1.execMain)(step, LD65, args);
|
|
|
|
if (errors.length)
|
|
|
|
return { errors: errors };
|
|
|
|
var aout = FS.readFile("main", { encoding: 'binary' });
|
|
|
|
var mapout = FS.readFile("main.map", { encoding: 'utf8' });
|
|
|
|
var viceout = FS.readFile("main.vice", { encoding: 'utf8' });
|
|
|
|
//var dbgout = FS.readFile("main.dbg", {encoding:'utf8'});
|
|
|
|
(0, workermain_1.putWorkFile)("main", aout);
|
|
|
|
(0, workermain_1.putWorkFile)("main.map", mapout);
|
|
|
|
(0, workermain_1.putWorkFile)("main.vice", viceout);
|
|
|
|
// return unchanged if no files changed
|
|
|
|
if (!(0, workermain_1.anyTargetChanged)(step, ["main", "main.map", "main.vice"]))
|
|
|
|
return;
|
|
|
|
// parse symbol map (TODO: omit segments, constants)
|
|
|
|
var symbolmap = {};
|
|
|
|
for (var s of viceout.split("\n")) {
|
|
|
|
var toks = s.split(" ");
|
|
|
|
if (toks[0] == 'al') {
|
|
|
|
let ident = toks[2].substr(1);
|
|
|
|
if (ident.length != 5 || !ident.startsWith('L')) { // no line numbers
|
|
|
|
let ofs = parseInt(toks[1], 16);
|
|
|
|
symbolmap[ident] = ofs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// build segment map
|
|
|
|
var seg_re = /^__(\w+)_SIZE__$/;
|
|
|
|
// TODO: move to Platform class
|
|
|
|
var segments = [];
|
|
|
|
segments.push({ name: 'CPU Stack', start: 0x100, size: 0x100, type: 'ram' });
|
|
|
|
segments.push({ name: 'CPU Vectors', start: 0xfffa, size: 0x6, type: 'rom' });
|
|
|
|
// TODO: CHR, banks, etc
|
|
|
|
for (let ident in symbolmap) {
|
|
|
|
let m = seg_re.exec(ident);
|
|
|
|
if (m) {
|
|
|
|
let seg = m[1];
|
|
|
|
let segstart = symbolmap['__' + seg + '_RUN__'] || symbolmap['__' + seg + '_START__'];
|
|
|
|
let segsize = symbolmap['__' + seg + '_SIZE__'];
|
|
|
|
let seglast = symbolmap['__' + seg + '_LAST__'];
|
|
|
|
if (segstart >= 0 && segsize > 0 && !seg.startsWith('PRG') && seg != 'RAM') { // TODO
|
|
|
|
var type = null;
|
|
|
|
if (seg.startsWith('CODE') || seg == 'STARTUP' || seg == 'RODATA' || seg.endsWith('ROM'))
|
|
|
|
type = 'rom';
|
|
|
|
else if (seg == 'ZP' || seg == 'DATA' || seg == 'BSS' || seg.endsWith('RAM'))
|
|
|
|
type = 'ram';
|
|
|
|
segments.push({ name: seg, start: segstart, size: segsize, last: seglast, type: type });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// build listings
|
|
|
|
var listings = {};
|
|
|
|
for (var fn of step.files) {
|
|
|
|
if (fn.endsWith('.lst')) {
|
|
|
|
var lstout = FS.readFile(fn, { encoding: 'utf8' });
|
|
|
|
lstout = lstout.split('\n\n')[1] || lstout; // remove header
|
|
|
|
(0, workermain_1.putWorkFile)(fn, lstout);
|
2022-06-30 18:34:04 +00:00
|
|
|
console.log(step);
|
|
|
|
let isECS = ((_a = step.debuginfo) === null || _a === void 0 ? void 0 : _a.entities) != null; // TODO
|
|
|
|
if (isECS) {
|
|
|
|
var asmlines = [];
|
|
|
|
var srclines = parseCA65Listing(lstout, symbolmap, params, true, listings);
|
|
|
|
listings[fn] = {
|
|
|
|
lines: [],
|
|
|
|
text: lstout
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
var asmlines = parseCA65Listing(lstout, symbolmap, params, false);
|
|
|
|
var srclines = parseCA65Listing(lstout, symbolmap, params, true); // TODO: listings param for ecs
|
|
|
|
listings[fn] = {
|
|
|
|
asmlines: srclines.length ? asmlines : null,
|
|
|
|
lines: srclines.length ? srclines : asmlines,
|
|
|
|
text: lstout
|
|
|
|
};
|
|
|
|
}
|
2022-02-21 15:35:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
output: aout,
|
|
|
|
listings: listings,
|
|
|
|
errors: errors,
|
|
|
|
symbolmap: symbolmap,
|
|
|
|
segments: segments
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
exports.linkLD65 = linkLD65;
|
|
|
|
function compileCC65(step) {
|
|
|
|
(0, workermain_1.loadNative)("cc65");
|
|
|
|
var params = step.params;
|
|
|
|
// stderr
|
|
|
|
var re_err1 = /(.*?):(\d+): (.+)/;
|
|
|
|
var errors = [];
|
|
|
|
var errline = 0;
|
|
|
|
function match_fn(s) {
|
|
|
|
console.log(s);
|
|
|
|
var matches = re_err1.exec(s);
|
|
|
|
if (matches) {
|
|
|
|
errline = parseInt(matches[2]);
|
|
|
|
errors.push({
|
|
|
|
line: errline,
|
|
|
|
msg: matches[3],
|
|
|
|
path: matches[1]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(0, workermain_1.gatherFiles)(step, { mainFilePath: "main.c" });
|
|
|
|
var destpath = step.prefix + '.s';
|
|
|
|
if ((0, workermain_1.staleFiles)(step, [destpath])) {
|
|
|
|
var CC65 = workermain_1.emglobal.cc65({
|
|
|
|
instantiateWasm: (0, workermain_1.moduleInstFn)('cc65'),
|
|
|
|
noInitialRun: true,
|
|
|
|
//logReadFiles:true,
|
|
|
|
print: workermain_1.print_fn,
|
|
|
|
printErr: match_fn,
|
|
|
|
});
|
|
|
|
var FS = CC65.FS;
|
|
|
|
(0, workermain_1.setupFS)(FS, '65-' + (0, util_1.getRootBasePlatform)(step.platform));
|
|
|
|
(0, workermain_1.populateFiles)(step, FS);
|
|
|
|
(0, workermain_1.fixParamsWithDefines)(step.path, params);
|
|
|
|
var args = [
|
|
|
|
'-I', '/share/include',
|
|
|
|
'-I', '.',
|
|
|
|
"-D", "__8BITWORKSHOP__",
|
|
|
|
];
|
|
|
|
if (params.define) {
|
|
|
|
params.define.forEach((x) => args.push('-D' + x));
|
|
|
|
}
|
|
|
|
if (step.mainfile) {
|
|
|
|
args.unshift.apply(args, ["-D", "__MAIN__"]);
|
|
|
|
}
|
|
|
|
var customArgs = params.extra_compiler_args || ['-T', '-g', '-Oirs', '-Cl', '-W', '-pointer-sign,-no-effect'];
|
|
|
|
args = args.concat(customArgs, args);
|
|
|
|
args.push(step.path);
|
|
|
|
//console.log(args);
|
|
|
|
(0, workermain_1.execMain)(step, CC65, args);
|
|
|
|
if (errors.length)
|
|
|
|
return { errors: errors };
|
|
|
|
var asmout = FS.readFile(destpath, { encoding: 'utf8' });
|
|
|
|
(0, workermain_1.putWorkFile)(destpath, asmout);
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
nexttool: "ca65",
|
|
|
|
path: destpath,
|
|
|
|
args: [destpath],
|
|
|
|
files: [destpath],
|
|
|
|
};
|
|
|
|
}
|
|
|
|
exports.compileCC65 = compileCC65;
|
|
|
|
//# sourceMappingURL=cc65.js.map
|