const fs = require('fs'); const path = require('path'); const process = require('process'); const { spawnSync, execSync } = require('child_process'); const { png2gb } = require('./png2gb'); const { string2gb } = require('./string2gb'); const DIR_BUILD = path.resolve('build'); const DIR_GENERATED = path.resolve(DIR_BUILD, 'generated'); const DIR_OBJ = path.resolve(DIR_BUILD, 'obj'); const DIR_SRC = path.resolve('src'); const DIR_GBDK = path.resolve(process.env['GBDKDIR']); const DIR_ASSETS = path.resolve('assets'); const DIR_IMAGES = path.resolve(DIR_ASSETS, 'images'); const FILE_OUT = path.resolve(DIR_BUILD, 'Penny.gb'); const FILE_LINKFILE = path.join(DIR_BUILD, `linkflile.lk`); const LCC = path.join(DIR_GBDK, 'bin', 'lcc'); const LCCFLAGS = `-I${DIR_GENERATED} -I${DIR_SRC}`; const compiledSources = []; // Create build dirs [ DIR_BUILD, DIR_GENERATED, DIR_OBJ ].forEach(d => { if(fs.existsSync(d)) return; fs.mkdirSync(d); }); // Scandir const buildSourceFiles = directory => { const sources = []; fs.readdirSync(directory).forEach(file => { const fullPath = path.join(directory, file); const stats = fs.statSync(fullPath); if(stats.isDirectory()) { sources.push(...buildSourceFiles(fullPath)); return; } if(file.endsWith('.c')) sources.push(fullPath); }); return sources; } const logOut = (out, buffer) => { const str = [ out.stderr, out.stdout ].filter(n => n) .map(n => n.toString()) .filter(n => n) .join('') ; if(!str || !str.length) return; buffer(str); } const compileC = (cFile) => { const fileNameOut = path.basename(cFile, '.c') + '.o'; const fileOut = path.join(DIR_OBJ, fileNameOut); compiledSources.push(path.join(fileNameOut)); if(fs.existsSync(fileOut)) return; let result; try { result = execSync(`${LCC} ${LCCFLAGS} -c -o ${fileOut} ${cFile}`); logOut(result, console.log); } catch(e) { logOut(e, e => { console.error(e); process.exit(1); }); throw e; } } // Generate strings // let dataStringH = '#pragma once\n#include "libs.h"\n'; // let dataStringC = '#include "STRINGS.h"\n'; // Object.entries(GAME_STRINGS).forEach(entry => { // const [ name, str ] = entry; // const { dataH, dataC } = string2gb(str, name); // dataStringH += dataH+'\n', dataStringC += dataC+'\n'; // }); // fs.writeFileSync(path.join(DIR_GENERATED, 'STRINGS.h'), dataStringH); // fs.writeFileSync(path.join(DIR_GENERATED, 'STRINGS.c'), dataStringC); // compileC(path.join(DIR_GENERATED, 'STRINGS.c')); // Gen imagery fs.readdirSync(DIR_IMAGES).forEach(img => { if(!img.endsWith(".png")) return; const { fileC, fileH } = png2gb( path.join(DIR_IMAGES, img), DIR_GENERATED, path.basename(img, '.png').toUpperCase() ); compileC(fileC); }) // Get a list of sources and build each of them prior to linking. const allSources = buildSourceFiles(DIR_SRC); for(let i = 0; i < allSources.length; i++) { compileC(allSources[i]); } // Generate a linkfile. fs.writeFileSync(FILE_LINKFILE, compiledSources.map(cs=>{ return path.join(DIR_OBJ, cs); }).join('\n')); // Compile BIN let result; try { result = execSync(`${LCC} ${LCCFLAGS} -o ${FILE_OUT} -Wl-f${FILE_LINKFILE}`); logOut(result, console.log); } catch(e) { logOut(e, console.error); process.exit(1); }