make the build script use 'include' statement instead of a hard-coded '.asm' file list

This commit is contained in:
2026-05-01 17:22:22 +02:00
parent 6920d10089
commit 92ac475d58
6 changed files with 101 additions and 79 deletions

140
build.ts
View File

@@ -1,4 +1,4 @@
#!/usr/bin/env -S deno run --allow-read --allow-run
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run
import { TextLineStream } from "jsr:@std/streams@1.1.0";
@@ -9,25 +9,7 @@ import { TextLineStream } from "jsr:@std/streams@1.1.0";
const instructionLength = 4; // in bytes
const rawDataInstructionLengthPrefix = "U32";
const ppmToAsmScriptPath = './ppmToAsm.ts';
const asmFilePaths = [
"src/consts/arch.asm",
"src/consts/game.asm",
"src/consts/keyboard.asm",
"src/consts/map.asm",
"src/consts/scene.asm",
"src/consts/screen.asm",
"src/consts/sprites.asm",
"src/init.asm",
"src/main.asm",
"src/lib/game.asm",
"src/lib/drawing.asm",
"src/lib/sprite_rotation.asm",
];
const reservedSpacePath = "src/reserved_space.asm";
const ppmToAsmScriptPath = "./ppmToAsm.ts";
const mapPath = "assets/map.ppm";
const spritesPath = {
@@ -117,7 +99,11 @@ class Minifier {
}
}
async function ppmToAsm(mode: "map" | "sprite", label: string, path: string): Promise<string> {
async function ppmToAsm(
mode: "map" | "sprite",
label: string,
path: string,
): Promise<string> {
const command = new Deno.Command(ppmToAsmScriptPath, {
args: [
instructionLength.toString(),
@@ -140,62 +126,55 @@ async function ppmToAsm(mode: "map" | "sprite", label: string, path: string): Pr
return decoder.decode(stdout);
}
async function build(output: WritableStreamDefaultWriter<string>) {
for (const path of asmFilePaths) {
const file = await Deno.open(path);
const readable = file.readable.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream());
async function build(
pwd: string,
path: string,
output: WritableStreamDefaultWriter<string>,
) {
const includeExpressionRegex = /^\s*include\s+([^\s;]+)/;
await output.write(`
;/*******************************
;* ${path}
;*******************************/
`);
const file = await Deno.open(`${pwd}/${path}`);
const readable = file.readable.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream());
for await (const line of readable) {
if (!line.startsWith("include ")) {
await output.write(`${line}\n`);
}
for await (const line of readable) {
const match = line.match(includeExpressionRegex);
if (match === null) {
await output.write(`${line}\n`);
continue;
}
await build(pwd, `${match[1]}.asm`, output);
}
const asmRawRepresentations = await Promise.all([
ppmToAsm("map", "map", mapPath),
...Object.entries(spritesPath).map(([label, path]) => ppmToAsm("sprite", label, path)),
]);
await output.write(asmRawRepresentations.join("\n\n"));
await output.write(`
;
; RESERVED RAM SPACE
;
`);
await output.write(await Deno.readTextFile(reservedSpacePath));
await output.close();
}
function printUsage(into: (message: string) => void) {
into(`Usage:
\tbuild.ts [--minify]
\t\tMerge the hardcoded files and output the result to stdout. The "--minify" option can be used to strip the result of all comments, leading/trailing double whitespaces, empty lines and use the more compact raw data representation.
\tbuild.ts [options...] {file}
\t\tRead the given file and recursively include other '.asm' files to produce a single output.
\tbuild.ts --help
\t\tPrint this message`);
\t\tPrint this message
Options:
\t--minify\tWhen used, the result will be stripped of all comments, leading/trailing double whitespaces, empty lines and use the more compact raw data representation.
\t--ppm \tWhen used, the hardcoded ppm files will be translated to their matching Symfony assembly reprensentation into src/dist.`);
}
/**
* SCRIPT
*/
if (Deno.args.length > 1) {
if (Deno.args.length < 1) {
printUsage(console.error);
Deno.exit(1);
}
let minify = false;
if (Deno.args.length === 1) {
switch (Deno.args[0]) {
let convertPPM = false;
let path: string | undefined = undefined;
Deno.args.forEach((arg, index) => {
switch (arg) {
case "--help":
printUsage(console.log);
Deno.exit(0);
@@ -203,11 +182,42 @@ if (Deno.args.length === 1) {
case "--minify":
minify = true;
break;
case "--ppm":
convertPPM = true;
break;
default:
printUsage(console.error);
Deno.exit(1);
if (index !== Deno.args.length - 1) {
printUsage(console.error);
Deno.exit(1);
}
path = arg;
break;
}
});
if (path === undefined) {
printUsage(console.error);
Deno.exit(1);
}
if (convertPPM) {
await Deno.mkdir(`${Deno.cwd()}/src/dist`, { recursive: true });
const mapPromise = async () => {
const assembly = await ppmToAsm("map", "map", mapPath);
await Deno.writeTextFile(`${Deno.cwd()}/src/dist/map.asm`, assembly);
};
const spritePromises = Object.entries(spritesPath).map(async ([label, path]) => {
const assembly = await ppmToAsm("sprite", label, path);
const filename = path.split("/").pop()?.split('.')[0];
await Deno.writeTextFile(`${Deno.cwd()}/src/dist/${filename}.asm`, assembly);
});
await Promise.all([
mapPromise(),
...spritePromises,
]);
}
const encoder = new TextEncoder();
@@ -217,9 +227,9 @@ const stdoutWritable = new WritableStream<string>({
},
});
if (minify) {
const minifier = new Minifier(stdoutWritable);
await build(minifier.stream.writable.getWriter());
} else {
await build(stdoutWritable.getWriter());
}
const writer = minify
? (new Minifier(stdoutWritable)).stream.writable.getWriter()
: stdoutWritable.getWriter();
await build(`${Deno.cwd()}/src`, path, writer);
await writer.close();