mirror of
https://gitee.com/anod/open_agb_firm.git
synced 2025-05-06 13:54:09 +08:00
对打包acl的代码做了优化的修bug。曾经50秒的打包时间如今只需4秒了
This commit is contained in:
parent
519264b053
commit
e97d8006a1
@ -4,10 +4,6 @@ const fs = require("fs");
|
|||||||
const { readFile, writeFile, access } = require("fs/promises");
|
const { readFile, writeFile, access } = require("fs/promises");
|
||||||
|
|
||||||
const loadlist = async () => {
|
const loadlist = async () => {
|
||||||
/* const datfile = await readFile("./list.dat");
|
|
||||||
const records = readxml( datfile.toString("utf-8") );
|
|
||||||
const inform = rec => [rec.attributes.name.slice(0,4), rec.children[1].attributes.serial||"????", rec.attributes.name.slice(7)]
|
|
||||||
return records.children.filter( rec => rec.name=="game" && rec.attributes.name.charAt()!="x" ).map( inform );*/
|
|
||||||
const datfile = await readFile("./serial.json");
|
const datfile = await readFile("./serial.json");
|
||||||
const datas = JSON.parse(datfile.toString());
|
const datas = JSON.parse(datfile.toString());
|
||||||
return Object.entries(datas).filter(n => n[1] != "????");
|
return Object.entries(datas).filter(n => n[1] != "????");
|
||||||
@ -55,47 +51,64 @@ const loadcheat = async (order, serial, title, file) => {
|
|||||||
const format = valid => {
|
const format = valid => {
|
||||||
valid.sort((a, b) => a.serial.localeCompare(b.serial));
|
valid.sort((a, b) => a.serial.localeCompare(b.serial));
|
||||||
console.info(`valid rom has ${valid.length}`);
|
console.info(`valid rom has ${valid.length}`);
|
||||||
valid.forEach( ({serial, cheat}) => console.debug(`${cheat.length} in ${serial}`) );
|
|
||||||
|
|
||||||
const enc = new TextEncoder();
|
const enc = new TextEncoder();
|
||||||
|
const size = Symbol("length");
|
||||||
|
const concatUnit = 10240;
|
||||||
const align = (n, base) => base * Math.floor((n + base - 1) / base);
|
const align = (n, base) => base * Math.floor((n + base - 1) / base);
|
||||||
const concat = (a, b) => {
|
const concat = (a, b) => {
|
||||||
const n = new ( Object.getPrototypeOf(a).constructor )( a.length+b.length );
|
let len = (a[size] || 0) + b.length;
|
||||||
n.set( a, 0 )
|
if (len > a.length) {
|
||||||
n.set( b, 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;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
a.set(b, a[size]);
|
||||||
|
a[size] = len;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
const getnametable = list => list.reduce((r, { serial, cheat }, idx, arr) => {
|
const getnametable = list => list.reduce((r, { serial, cheat }, idx, arr) => {
|
||||||
const val = serial.slice(0, -1);
|
const val = serial.slice(0, -1);
|
||||||
if (val != r[4]) {
|
if (val != r[4]) {
|
||||||
if( r[1].length > 0 && r[2] - r[1].at(-1) > r[3] )
|
if (r[1][size] > 0 && r[2] - r[1].at(r[1][size] - 1) > r[3])
|
||||||
r[3] = r[2] - r[1].at(-1);
|
r[3] = r[2] - r[1].at(r[1][size] - 1);
|
||||||
r[0] = concat(r[0], enc.encode(val))
|
r[0] = concat(r[0], enc.encode(val))
|
||||||
r[1] = concat(r[1], [r[2]]);
|
r[1] = concat(r[1], [r[2]]);
|
||||||
r[4] = val;
|
r[4] = val;
|
||||||
}
|
}
|
||||||
r[2] = r[2] + cheat.length;
|
r[2] = r[2] + cheat.length;
|
||||||
if (idx + 1 == arr.length) {
|
if (idx + 1 == arr.length) {
|
||||||
if( r[2] - r[1].at(-1) > r[3] )
|
if (r[2] - r[1].at(r[1][size] - 1) > r[3])
|
||||||
r[3] = r[2] - r[1].at(-1);
|
r[3] = r[2] - r[1].at(r[1][size] - 1);
|
||||||
r[1] = concat(r[1], [r[2]]);
|
r[1] = concat(r[1], [r[2]]);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}, [new Uint8Array(), new Uint16Array(), 0, 0, ""] );
|
}, [concat(new Uint8Array(concatUnit), []), concat(new Uint16Array(concatUnit), []), 0, 0, ""]);
|
||||||
|
|
||||||
const expandcheat = (list, base) => list.reduce((r, { cheat, serial }) => {
|
const expandcheat = (list, base) => list.reduce((r, { cheat, serial }) => {
|
||||||
const val = serial.charCodeAt(3);
|
const val = serial.charCodeAt(3);
|
||||||
const [c, e] = cheat.reduce( (r,{id, bin}) => {
|
return cheat.reduce((r, { id, bin }) => {
|
||||||
const off = r[2] + r[1].length;
|
const off = r[2] + r[1][size];
|
||||||
r[0] = concat(r[0], [val | (off << 3), id])
|
r[0] = concat(r[0], [val | (off << 3), id])
|
||||||
r[1] = concat(r[1], bin);
|
r[1] = concat(r[1], bin);
|
||||||
return r;
|
return r;
|
||||||
}, r);
|
}, r);
|
||||||
return [c, e, r[2]];
|
}, [concat(new Uint32Array(concatUnit), []), concat(new Uint8Array(concatUnit), []), align(base, 32)]);
|
||||||
}, [new Uint32Array(), new Uint8Array(), align(base, 32)] );
|
|
||||||
|
|
||||||
const [sers, offs, chtc, maxl] = getnametable( valid );
|
const linkbuffer = (arr, ...l) => {
|
||||||
const [cheats, expanded] = expandcheat( valid, 8+sers.length+offs.length*2+chtc*8 );
|
for (let i of l) {
|
||||||
|
const arrBa = arr[i];
|
||||||
|
arr[i] = arrBa.slice(0, arrBa[size]);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [sers, offs, chtc, maxl] = linkbuffer(getnametable(valid), 0, 1);
|
||||||
|
const [cheats, expanded] = linkbuffer(expandcheat(valid, 8 + sers.length + offs.length * 2 + chtc * 8), 0, 1);
|
||||||
console.info(`name: ${sers.length} cheats: ${chtc} maxl: ${maxl}`);
|
console.info(`name: ${sers.length} cheats: ${chtc} maxl: ${maxl}`);
|
||||||
|
|
||||||
const serialbase = 8;
|
const serialbase = 8;
|
||||||
|
Binary file not shown.
@ -16,17 +16,19 @@ const a = "a".charCodeAt();
|
|||||||
const f = "f".charCodeAt();
|
const f = "f".charCodeAt();
|
||||||
const conv = new TextEncoder();
|
const conv = new TextEncoder();
|
||||||
|
|
||||||
const findIndex = (t, tr) => {
|
const findIndex = (t, tr, tlen) => {
|
||||||
const tlen = t.length, rlen = tr.length;
|
const rlen = tr.length, limit = tlen - rlen;
|
||||||
for( let i=0; i+rlen < tlen; ++i ){
|
for (let i = 0; i < limit; ++i) {
|
||||||
let eq = true;
|
if (t[i + rlen] != 0) continue;
|
||||||
for( j=0; j < rlen; ++j ){
|
|
||||||
if( t[i+j] != tr[j] ){
|
let eq = true, j = 0, k = i + j;
|
||||||
|
for (; j < rlen; ++j, ++k) {
|
||||||
|
if (t[k] != tr[j]) {
|
||||||
eq = false;
|
eq = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( eq && t[i+rlen]==0 ) return i;
|
if (eq) return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -155,8 +157,7 @@ const read = (cht, info, order) => {
|
|||||||
if ((zero <= digit && digit <= nine) ||
|
if ((zero <= digit && digit <= nine) ||
|
||||||
(a <= digit && digit <= f) ||
|
(a <= digit && digit <= f) ||
|
||||||
currlock.name.toLowerCase() == "gameinfo" ||
|
currlock.name.toLowerCase() == "gameinfo" ||
|
||||||
currlock.hole.toLowerCase() == "text" )
|
currlock.hole.toLowerCase() == "text") {
|
||||||
{
|
|
||||||
token.push(digit);
|
token.push(digit);
|
||||||
}
|
}
|
||||||
else error(`error occur ${ch}[${digit}] on ${STATE[state]}`);
|
else error(`error occur ${ch}[${digit}] on ${STATE[state]}`);
|
||||||
@ -211,7 +212,7 @@ const pack = (entlist, strlist, idxlist, cmdlist, xvalue) => {
|
|||||||
const strbase = 2 + entlist.length * entrysize;
|
const strbase = 2 + entlist.length * entrysize;
|
||||||
const idxbase = strbase + strlist.buffer.byteLength;
|
const idxbase = strbase + strlist.buffer.byteLength;
|
||||||
const cmdbase = idxbase + idxlist.buffer.byteLength;
|
const cmdbase = idxbase + idxlist.buffer.byteLength;
|
||||||
const size = cmdbase + cmdlist.buffer.byteLength;;
|
const size = cmdbase + cmdlist.buffer.byteLength;
|
||||||
let result = new ArrayBuffer(align(size, 32));
|
let result = new ArrayBuffer(align(size, 32));
|
||||||
|
|
||||||
// entry count
|
// entry count
|
||||||
@ -269,21 +270,29 @@ const lade = (list, info, order) => {
|
|||||||
|
|
||||||
enttable.sort((a, b) => a.id - b.id);
|
enttable.sort((a, b) => a.id - b.id);
|
||||||
|
|
||||||
let strtable = Uint8Array.of(); // 保存字符串常量
|
let strtable = new Uint8Array(1024); // 保存字符串常量
|
||||||
let idxtable = Uint16Array.of(); // 从字符串常量索引出来的字符串列表
|
let idxtable = new Uint16Array(128); // 从字符串常量索引出来的字符串列表
|
||||||
let cmdtable = Uint32Array.of(); // 保存选项对应指令
|
let cmdtable = new Uint32Array(4096); // 保存选项对应指令
|
||||||
|
const size = {"str": 0, "cmd": 0, idx: 0};
|
||||||
const addString = list => {
|
const addString = list => {
|
||||||
const ut_pushtr = tr => {
|
const ut_pushtr = tr => {
|
||||||
const off = strtable.length;
|
const off = size.str;
|
||||||
let nt = new Uint8Array( off+tr.length+1 );
|
const len = off + tr.length + 1;
|
||||||
|
if (len > strtable.length) {
|
||||||
|
let nt = new Uint8Array(Math.min(strtable.length * 2, off + tr.length + 1024));
|
||||||
nt.set(strtable, 0);
|
nt.set(strtable, 0);
|
||||||
nt.set(tr, off);
|
nt.set(tr, off);
|
||||||
strtable = nt;
|
strtable = nt;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strtable.set(tr, off);
|
||||||
|
}
|
||||||
|
size.str = len;
|
||||||
return off;
|
return off;
|
||||||
};
|
};
|
||||||
const ut_addtr = tr => {
|
const ut_addtr = tr => {
|
||||||
const code = conv.encode(tr);
|
const code = conv.encode(tr);
|
||||||
const off = findIndex( strtable, code );
|
const off = findIndex(strtable, code, size.str);
|
||||||
return off < 0 ? ut_pushtr(code) : off;
|
return off < 0 ? ut_pushtr(code) : off;
|
||||||
};
|
};
|
||||||
return list.map(ut_addtr);
|
return list.map(ut_addtr);
|
||||||
@ -292,22 +301,38 @@ const lade = (list, info, order) => {
|
|||||||
const addStrIndex = list => {
|
const addStrIndex = list => {
|
||||||
if (list.length == 0) return 0;
|
if (list.length == 0) return 0;
|
||||||
|
|
||||||
if( strtable.length > 0xffff ) throw new RangeError(`string table is too big.`);
|
if (size.str > 0xffff) throw new RangeError(`string table is too big.`);
|
||||||
let ret = idxtable.buffer.byteLength;
|
|
||||||
let nt = new Uint16Array( idxtable.length + list.length );
|
const ret = size.idx;
|
||||||
|
const len = ret + list.length;
|
||||||
|
if( len > idxtable.length )
|
||||||
|
{
|
||||||
|
let nt = new Uint16Array( Math.max( len+128, idxtable.length * 2 ) );
|
||||||
nt.set(idxtable, 0);
|
nt.set(idxtable, 0);
|
||||||
nt.set( list, idxtable.length );
|
nt.set(list, ret);
|
||||||
idxtable = nt;
|
idxtable = nt;
|
||||||
return ret;
|
}
|
||||||
|
else {
|
||||||
|
idxtable.set( list, ret );
|
||||||
|
}
|
||||||
|
size.idx = len;
|
||||||
|
return ret * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const addCommand = list => {
|
const addCommand = list => {
|
||||||
let ret = cmdtable.buffer.byteLength;
|
const ret = size.cmd;
|
||||||
let nt = new Uint32Array( cmdtable.length + list.length );
|
const len = ret + list.length;
|
||||||
nt.set( cmdtable, 0 );
|
if (len > cmdtable.length) {
|
||||||
nt.set( list, cmdtable.length );
|
let n = new Uint32Array(Math.max(cmdtable.length * 8, len));
|
||||||
cmdtable = nt;
|
n.set(cmdtable, 0);
|
||||||
return ret;
|
n.set(list, ret);
|
||||||
|
cmdtable = n;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cmdtable.set(list, ret);
|
||||||
|
}
|
||||||
|
size.cmd = len;
|
||||||
|
return ret * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enttable.length > 0xffff) {
|
if (enttable.length > 0xffff) {
|
||||||
@ -319,7 +344,7 @@ const lade = (list, info, order) => {
|
|||||||
let entbytelist = enttable.map(entry => {
|
let entbytelist = enttable.map(entry => {
|
||||||
let { id, data } = entry;
|
let { id, data } = entry;
|
||||||
if (id < 0x10000) { // 收集str
|
if (id < 0x10000) { // 收集str
|
||||||
let idxlist = addString(data.length > 1 ? data : []); // length==1就是开启
|
let idxlist = id == 0 ? addString( data ) : addString(data.length > 1 ? data : []); // length==1就是开启
|
||||||
let location = addStrIndex(idxlist);
|
let location = addStrIndex(idxlist);
|
||||||
return Uint32Array.of(id, location, idxlist.length);
|
return Uint32Array.of(id, location, idxlist.length);
|
||||||
}
|
}
|
||||||
@ -329,6 +354,9 @@ const lade = (list, info, order) => {
|
|||||||
return Uint32Array.of(id, location, armbytecode.length);
|
return Uint32Array.of(id, location, armbytecode.length);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
cmdtable = cmdtable.slice(0, size.cmd);
|
||||||
|
strtable = strtable.slice(0, size.str);
|
||||||
|
idxtable = idxtable.slice(0, size.idx);
|
||||||
|
|
||||||
let n = info.serial.split("").reduce((r, v) => (v.charCodeAt() | r << 8), 0);
|
let n = info.serial.split("").reduce((r, v) => (v.charCodeAt() | r << 8), 0);
|
||||||
let xv = cmdtable.reduce((r, v) => r ^ v, n);
|
let xv = cmdtable.reduce((r, v) => r ^ v, n);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user