79 lines
2.6 KiB
JavaScript

const {Worker, isMainThread, parentPort, workerData} = require("worker_threads");
const readCht = require("./cht");
const { readFile, access } = require("fs/promises");
const ncpu = require("os").availableParallelism();
const trimcheat = (dat, info, order) => {
let parts = [], start = 0, done = false;
while (!done) {
let pos = dat.indexOf("[GameInfo]", start);
if (pos > 0) {
pos = dat.indexOf("[", pos + "[GameInfo]".length);
if (pos > 0) {
parts.push(dat.slice(start, pos));
start = pos;
}
else {
parts.push(dat.slice(start, dat.length));
done = true;
}
}
else {
parts.push(dat.slice(start, dat.length));
done = true;
}
}
return parts.map(tr => readCht(tr, info, order));
}
const loadcheat = async (order, serial, title, file) => {
if( false == await access(file).catch( e => false ) ) {
return Promise.resolve();
}
try {
const chtfile = await readFile(file);
const cheats = chtfile.toString("utf-8");
let cheat = null;
if (cheats.indexOf("[GameInfo]") != cheats.lastIndexOf("[GameInfo]"))
cheat = trimcheat(cheats, { serial }, order);
else cheat = [readCht(cheats, { serial }, order)];
return { serial, cheat }
}
catch (e) {
console.log("bad cheat: %s[order=%d]\n%s", title, order, e.stack)
return { serial }
};
}
if( isMainThread ) {
module.exports = ncpu > 3 ? function(list) {
const nPerThread = Math.ceil(list.length / ncpu);
const results = new Array(ncpu);
let n = 0;
return new Promise( ok => {
const workers = new Array(ncpu).fill(0).map( (_,i) => {
const sublist = list.slice(i * nPerThread, (i+1) * nPerThread);
const worker = new Worker(__filename, { workerData: sublist });
worker.once("message", msg => {
results[i] = msg;
worker.unref();
if( ++n == ncpu ) ok(results.flat());
});
} );
});
} : list => Promise.all( list.map( game => {
const [order, serial, title] = game;
const file = `./gba/${order}.u8`;
return loadcheat(order, serial, title ?? order, file);
} ) );
}
else {
const list = workerData;
Promise.all( list.map( game => {
const [order, serial, title] = game;
const file = `./gba/${order}.u8`;
return loadcheat(order, serial, title ?? order, file);
} ) ).then( res => parentPort.postMessage(res) );
}