diff --git a/tools/cheat-builder/build.js b/tools/cheat-builder/build.js index a0f7665..cb31425 100644 --- a/tools/cheat-builder/build.js +++ b/tools/cheat-builder/build.js @@ -12,38 +12,41 @@ const format = valid => { console.info(`valid rom has ${valid.length}`); const enc = new TextEncoder(); - const size = Symbol("length"); + //const size = Symbol("length"); const concatUnit = 10240; const align = (n, base) => base * Math.floor((n + base - 1) / base); + const size = new WeakMap() const concat = (a, b) => { - let len = (a[size] || 0) + b.length; + const sizea = size.get(a); + let len = (sizea || 0) + b.length; if (len > a.length) { let n = new (Object.getPrototypeOf(a).constructor)(align(len, concatUnit) * 2); n.set(a, 0); - n.set(b, a[size]); - n[size] = len; + n.set(b, sizea); + size.set(n, len); return n; } else { - a.set(b, a[size]); - a[size] = len; + a.set(b, sizea); + size.set(a, len); return a; } } const getnametable = list => list.reduce((r, { serial, cheat }, idx, arr) => { const val = serial.slice(0, -1); //console.log("looping", val, r[4], r[2], cheat.length) + const size1 = size.get(r[1]); if (val != r[4]) { - if (r[1][size] > 0 && r[2] - r[1].at(r[1][size] - 1) > r[3]) - r[3] = r[2] - r[1].at(r[1][size] - 1); + if (size1 > 0 && r[2] - r[1].at(size1 - 1) > r[3]) + r[3] = r[2] - r[1].at(size1 - 1); r[0] = concat(r[0], enc.encode(val)) r[1] = concat(r[1], [r[2]]); r[4] = val; } r[2] = r[2] + cheat.length; if (idx + 1 == arr.length) { - if (r[2] - r[1].at(r[1][size] - 1) > r[3]) - r[3] = r[2] - r[1].at(r[1][size] - 1); + if (r[2] - r[1].at(size1 - 1) > r[3]) + r[3] = r[2] - r[1].at(size1 - 1); r[1] = concat(r[1], [r[2]]); } return r; @@ -52,7 +55,7 @@ const format = valid => { const expandcheat = (list, base) => list.reduce((r, { cheat, serial }) => { const val = serial.charCodeAt(3); return cheat.reduce((r, { id, bin }) => { - const off = r[2] + r[1][size]; + const off = r[2] + size.get(r[1]); r[0] = concat(r[0], [val | (off << 3), id]) r[1] = concat(r[1], bin); return r; @@ -62,7 +65,7 @@ const format = valid => { const linkbuffer = (arr, ...l) => { for (let i of l) { const arrBa = arr[i]; - arr[i] = arrBa.slice(0, arrBa[size]); + arr[i] = arrBa.slice(0, size.get(arrBa)); } return arr; } diff --git a/tools/cheat-builder/cht.js b/tools/cheat-builder/cht.js index 6602464..ea98d2c 100644 --- a/tools/cheat-builder/cht.js +++ b/tools/cheat-builder/cht.js @@ -10,8 +10,9 @@ const NEED_PART = 8 const STATE = ["", "WAIT_LOCK", "READ_LOCK", "WAIT_HOLE", "READ_HOLE", "WAIT_KEY", "READ_KEY"] const PASSHOLE = ["text", "off"] -const space = " ".charCodeAt(); -const tab = "\t".charCodeAt(); +const space = " "; +const tab = "\t"; +const hex = "0123456789abcdef"; const zero = "0".charCodeAt(); const nine = "9".charCodeAt(); const a = "a".charCodeAt(); @@ -40,8 +41,7 @@ const read = (cht, info, order) => { let locks = [], currlock = null, retval = []; - const merge_str = String.fromCharCode.bind(String); - const token_str = () => { const r = merge_str.apply(null, token); return (token.length = 0, r); } + const token_str = () => { const r = token.join(""); return (token = [], r); } const error = msg => { throw new SyntaxError(`${msg} at line: ${line} in lock ${currlock?.name}`) } const incr = ch => { switch (ch) { @@ -101,7 +101,7 @@ const read = (cht, info, order) => { currlock.keys = [new Array()]; } else if (state == READ_LOCK) { - token.push(ch.charCodeAt()); + token.push(ch); } else if (state == WAIT_PART) {} else if (state == NEED_PART) state = WAIT_PART; @@ -119,7 +119,7 @@ const read = (cht, info, order) => { state = READ_KEY; } else if (state == READ_LOCK) { - token.push(ch.charCodeAt()); + token.push(ch); } else if (state == WAIT_PART) {} else if (state == NEED_PART) state = WAIT_PART; @@ -131,7 +131,7 @@ const read = (cht, info, order) => { currlock.keys.push(new Array()); } else if (state == READ_LOCK) { - token.push(ch.charCodeAt()); + token.push(ch); } else if (state == READ_HOLE) {// MULTILINE KEY let { name, cmd } = currlock.holes.pop(); @@ -159,29 +159,22 @@ const read = (cht, info, order) => { break; case " ": if (state == READ_LOCK || state == READ_HOLE) { - token.push(ch.charCodeAt()); - } - else if (state == READ_KEY) { - if (currlock.name.toLowerCase() == "gameinfo") { - token.push(ch.charCodeAt()); - } + token.push(ch); } + else if (state == READ_KEY) {} else if (state == WAIT_PART) {} else if (state == NEED_PART) state = WAIT_PART; break; default: if (state == READ_LOCK || state == READ_HOLE) { - token.push(ch.charCodeAt()); + token.push(ch); } else if (state == READ_KEY) { - let digit = ch.toLowerCase().charCodeAt(); - if ((zero <= digit && digit <= nine) || - (a <= digit && digit <= f) || - currlock.name.toLowerCase() == "gameinfo" || + if (hex.includes(ch.toLowerCase()) || currlock.hole.toLowerCase() == "text") { - token.push(digit); + token.push(ch); } - else error(`error occur ${ch}[${digit}] on ${STATE[state]}`); + else error(`error occur ${ch}[${ch.charCodeAt()}] on ${STATE[state]}`); } else if (state == WAIT_PART) {} else if (state == NEED_PART) state = WAIT_PART; @@ -218,16 +211,14 @@ const assembleCheat = (list, dup, hole) => { else return n; }; const addrval = list.reduce((r, command) => { - let [taddr, ...vals] = command; - let addr = fromTaddr(taddr); - vals.forEach((val, pos) => { - let dest = addr + pos; - let value = parseInt(val, 16); - r.set(dest, value); - }); + let addr = fromTaddr(command[0]); + let len = command.length - 1; + for( let pos=0; pos < len; ++pos) { + r.set(addr+pos, parseInt(command[pos+1], 16)) + } return r; }, new Map()); - const ordered = [...addrval].sort((a, b) => a[0] - b[0]); + const ordered = Array.from(addrval).sort((a, b) => a[0] - b[0]); const blocks = ordered.reduce((arr, [addr, value]) => { dup.set(addr, hole); if (arr.length == 0) { @@ -242,7 +233,11 @@ const assembleCheat = (list, dup, hole) => { } return arr; }, []); - return Uint32Array.from(blocks.reduce((r, block) => [...r, block.addr, (block.count << 8) | block.value], [])) + return Uint32Array.from(blocks.reduce((r, block) => { + r.push( block.addr ); + r.push( (block.count << 8) | block.value ) + return r; + }, [])) } const pack = (entlist, strlist, idxlist, cmdlist, xvalue) => { diff --git a/tools/cheat-builder/worker.js b/tools/cheat-builder/worker.js index 65458d3..2ecb31f 100644 --- a/tools/cheat-builder/worker.js +++ b/tools/cheat-builder/worker.js @@ -1,24 +1,17 @@ const {Worker, isMainThread, parentPort, workerData} = require("worker_threads"); const readCht = require("./cht"); -const { accessSync, readFileSync } = require("fs"); +const { readFileSync } = require("fs"); const ncpu = require("os").availableParallelism(); const loadcheat = (order, serial, title, file) => { - try{ - accessSync( file ); - } - catch( e ) { - return {serial} - } - try { const chtfile = readFileSync(file, {encoding: "utf-8"}); const cheat = readCht(chtfile, { serial }, order); return { serial, cheat } } catch (e) { - console.log("bad cheat: %s[order=%d]\n%s", title, order, e.stack) + //console.log("bad cheat: %s[order=%d]\n%s", title, order, e.stack) return { serial } } }