mirror of
https://gitee.com/anod/open_agb_firm.git
synced 2025-05-05 21:34:11 +08:00
Compare commits
3 Commits
491141bf94
...
3ad07f892f
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3ad07f892f | ||
![]() |
15694de28c | ||
![]() |
5ebede3a4e |
@ -1,10 +1,27 @@
|
||||
const { readFile, writeFile } = require("fs/promises");
|
||||
const transform = require("./worker");
|
||||
const fastly = process.env.OAFCHT_NO_ITER==='1';
|
||||
|
||||
const loadlist = async () => {
|
||||
const datfile = await readFile("./serial.json");
|
||||
const datas = JSON.parse(datfile.toString());
|
||||
return Object.entries(datas).filter(n => n[1] != "????");
|
||||
// 避免使用迭代器方法,减少CPU(已走过performance对比流程)
|
||||
// ---------------原来的代码在这里------------------
|
||||
if( fastly === false ){
|
||||
return Object.entries(datas).filter(n => n[1] != "????");
|
||||
}
|
||||
// ---------------修改的代码在这里------------------
|
||||
else {
|
||||
const entries = Object.entries(datas);
|
||||
const retval = new Array(entries.length);
|
||||
let l = 0;
|
||||
for( let i=0; i < entries.length; ++i ){
|
||||
if( entries[i][1] !== "????" ) retval[l++] = entries[i];
|
||||
}
|
||||
retval.length = l;
|
||||
return retval;
|
||||
}
|
||||
// ---------------修改的代码完结处------------------
|
||||
}
|
||||
|
||||
const format = valid => {
|
||||
@ -32,9 +49,10 @@ const format = valid => {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
const getnametable = list => list.reduce((r, { serial, cheat }, idx, arr) => {
|
||||
// 避免使用迭代器方法,减少CPU(已走过performance对比流程)
|
||||
// ---------------原来的代码在这里------------------
|
||||
const getnametable = fastly === false ? 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 (size1 > 0 && r[2] - r[1].at(size1 - 1) > r[3])
|
||||
@ -50,9 +68,37 @@ const format = valid => {
|
||||
r[1] = concat(r[1], [r[2]]);
|
||||
}
|
||||
return r;
|
||||
}, [concat(new Uint8Array(concatUnit), []), concat(new Uint16Array(concatUnit), []), 0, 0, ""]);
|
||||
}, [concat(new Uint8Array(concatUnit), []), concat(new Uint16Array(concatUnit), []), 0, 0, ""])
|
||||
// ---------------修改的代码在这里------------------
|
||||
: list => {
|
||||
const ret = [concat(new Uint8Array(concatUnit), []), concat(new Uint16Array(concatUnit), []), 0, 0, ""];
|
||||
const {length} = list;
|
||||
for( let idx=0; idx < length; ++idx ){
|
||||
const { serial, cheat } = list[idx];
|
||||
const val = serial.slice(0, -1);
|
||||
const size1 = size.get(ret[1]);
|
||||
if( val != ret[4] ){
|
||||
if( size1 > 0 && ret[2] - ret[1].at(size1 - 1) > ret[3] )
|
||||
ret[3] = ret[2] - ret[1].at(size1 - 1);
|
||||
ret[0] = concat(ret[0], enc.encode(val))
|
||||
ret[1] = concat(ret[1], [ret[2]]);
|
||||
ret[4] = val;
|
||||
}
|
||||
ret[2] = ret[2] + cheat.length;
|
||||
if( idx + 1 == length ){
|
||||
if( ret[2] - ret[1].at(size1 - 1) > ret[3] )
|
||||
ret[3] = ret[2] - ret[1].at(size1 - 1);
|
||||
ret[1] = concat(ret[1], [ret[2]]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
// ---------------修改的代码完结处------------------
|
||||
|
||||
const expandcheat = (list, base) => list.reduce((r, { cheat, serial }) => {
|
||||
|
||||
// 避免使用迭代器方法,减少CPU(已走过performance对比流程)
|
||||
// ---------------原来的代码在这里------------------
|
||||
const expandcheat = fastly === false ? (list, base) => list.reduce((r, { cheat, serial }) => {
|
||||
const val = serial.charCodeAt(3);
|
||||
return cheat.reduce((r, { id, bin }) => {
|
||||
const off = r[2] + size.get(r[1]);
|
||||
@ -60,7 +106,23 @@ const format = valid => {
|
||||
r[1] = concat(r[1], bin);
|
||||
return r;
|
||||
}, r);
|
||||
}, [concat(new Uint32Array(concatUnit), []), concat(new Uint8Array(concatUnit), []), align(base, 32)]);
|
||||
}, [concat(new Uint32Array(concatUnit), []), concat(new Uint8Array(concatUnit), []), align(base, 32)])
|
||||
// ---------------修改的代码在这里------------------
|
||||
: (list, base) => {
|
||||
const ret = [concat(new Uint32Array(concatUnit), []), concat(new Uint8Array(concatUnit), []), align(base, 32)];
|
||||
const {length} = list;
|
||||
for( let idx=0; idx < length; ++idx ){
|
||||
const { cheat, serial } = list[idx];
|
||||
const val = serial.charCodeAt(3);
|
||||
for( const { id, bin } of cheat ){
|
||||
const off = ret[2] + size.get(ret[1]);
|
||||
ret[0] = concat(ret[0], [val | (off << 3), id])
|
||||
ret[1] = concat(ret[1], bin);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
// ---------------修改的代码完结处------------------
|
||||
|
||||
const linkbuffer = (arr, ...l) => {
|
||||
for (let i of l) {
|
||||
@ -106,15 +168,42 @@ const start = async () => {
|
||||
let list = await loadlist();
|
||||
let roms = await transform(list);
|
||||
console.log(`all rom has ${roms.length} and time ${performance.now() - begin}`);
|
||||
roms = Object.entries(roms.reduce((r, data) => {
|
||||
if (!data) return r;
|
||||
// 避免使用迭代器方法,减少CPU(已走过performance对比流程)
|
||||
// ---------------原来的代码在这里------------------
|
||||
if( fastly === false ){
|
||||
roms = Object.entries(roms.reduce((r, data) => {
|
||||
if (!data) return r;
|
||||
|
||||
const { serial, cheat } = data;
|
||||
if (!cheat || cheat.length == 0) return r;
|
||||
if (serial in r) r[serial] = [...r[serial], ...cheat];
|
||||
else r[serial] = cheat;
|
||||
return r;
|
||||
}, {})).map(([serial, cheat]) => ({ serial, cheat }));
|
||||
}
|
||||
// ---------------修改的代码在这里------------------
|
||||
else
|
||||
{
|
||||
const res = new Array(6400), idx = {};
|
||||
let l = 0;
|
||||
for( let i=0; i < roms.length; ++i ){
|
||||
const data = roms[i];
|
||||
if( !data ) continue;
|
||||
|
||||
const { serial, cheat } = data;
|
||||
if (!cheat || cheat.length == 0) return r;
|
||||
if (serial in r) r[serial] = [...r[serial], ...cheat];
|
||||
else r[serial] = cheat;
|
||||
return r;
|
||||
}, {})).map(([serial, cheat]) => ({ serial, cheat }));
|
||||
const { serial, cheat } = data;
|
||||
if( !cheat || cheat.length == 0 ) continue;
|
||||
|
||||
const cheats = idx[serial] ? idx[serial] : [];
|
||||
cheats.push(...cheat);
|
||||
if( !idx[serial] ){
|
||||
idx[serial] = cheats;
|
||||
res[l++] = { serial, cheat: cheats };
|
||||
}
|
||||
}
|
||||
res.length = l;
|
||||
roms = res;
|
||||
}
|
||||
// ---------------修改的代码完结处------------------
|
||||
|
||||
const content = await format( roms );
|
||||
await writeFile( "gba.acl", content );
|
||||
|
@ -18,7 +18,8 @@ const nine = "9".charCodeAt();
|
||||
const a = "a".charCodeAt();
|
||||
const f = "f".charCodeAt();
|
||||
const conv = new TextEncoder();
|
||||
const fastly = process.env.OAFCHT_NO_REUSE==='1';
|
||||
const noiter = process.env.OAFCHT_NO_ITER==='1';
|
||||
const noreuse = process.env.OAFCHT_NO_REUSE==='1';
|
||||
|
||||
/**
|
||||
* 这个函数做了一些数据复用处理,能省下来一点文件容量
|
||||
@ -50,7 +51,8 @@ const findIndex = (t, tr, tlen) => {
|
||||
const read = (cht, info, order) => {
|
||||
let state = WAIT_LOCK, token = [], line = 1;
|
||||
|
||||
let locks = [], currlock = null, retval = [];
|
||||
let locks = [], currlock = null
|
||||
const retval = [];
|
||||
|
||||
const token_str = () => { const r = token.join(""); return (token = [], r); }
|
||||
const error = msg => { throw new SyntaxError(`${msg} at line: ${line} in lock ${currlock?.name}`) }
|
||||
@ -223,34 +225,78 @@ const assembleCheat = (list, dup, hole) => {
|
||||
else if (0 == (n & 0xf000000)) return (n & 0xffff) | 0x3000000;
|
||||
else return n;
|
||||
};
|
||||
const addrval = list.reduce((r, command) => {
|
||||
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 = 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) {
|
||||
arr.push({ addr, value, count: 1 });// cnt addr value
|
||||
}
|
||||
else {
|
||||
let cur = arr.at(-1);
|
||||
if (cur.value == value) {
|
||||
++cur.count;
|
||||
// 避免使用迭代器方法,减少CPU(已走过performance对比流程)
|
||||
// ---------------原来的代码在这里------------------
|
||||
const addrval = new Map();
|
||||
if( noiter === false ){
|
||||
list.forEach((command) => {
|
||||
let addr = fromTaddr(command[0]);
|
||||
let len = command.length - 1;
|
||||
for( let pos=0; pos < len; ++pos) {
|
||||
addrval.set(addr+pos, parseInt(command[pos+1], 16))
|
||||
}
|
||||
});
|
||||
}
|
||||
// ---------------修改的代码在这里------------------
|
||||
else {
|
||||
for( let i=0; i < list.length; ++i ){
|
||||
const command = list[i];
|
||||
const addr = fromTaddr(command[0]);
|
||||
const len = command.length - 1;
|
||||
for( let pos=0; pos < len; ++pos) {
|
||||
addrval.set(addr+pos, parseInt(command[pos+1], 16));
|
||||
}
|
||||
else arr.push({ addr, value, count: 1 });
|
||||
}
|
||||
return arr;
|
||||
}, []);
|
||||
return Uint32Array.from(blocks.reduce((r, block) => {
|
||||
r.push( block.addr );
|
||||
r.push( (block.count << 8) | block.value )
|
||||
return r;
|
||||
}, []))
|
||||
}
|
||||
// ---------------修改的代码完结处------------------
|
||||
const ordered = Array.from(addrval).sort((a, b) => a[0] - b[0]);
|
||||
// 避免使用迭代器方法,减少CPU(已走过performance对比流程)
|
||||
// ---------------原来的代码在这里------------------
|
||||
if( noiter === false ){
|
||||
const blocks = ordered.reduce((arr, [addr, value]) => {
|
||||
dup.set(addr, hole);
|
||||
if (arr.length == 0) {
|
||||
arr.push({ addr, value, count: 1 });// cnt addr value
|
||||
}
|
||||
else {
|
||||
let cur = arr.at(-1);
|
||||
if (cur.value == value && cur.addr + cur.count == addr) {
|
||||
++cur.count;
|
||||
}
|
||||
else arr.push({ addr, value, count: 1 });
|
||||
}
|
||||
return arr;
|
||||
}, []);
|
||||
return Uint32Array.from(blocks.reduce((r, block) => {
|
||||
r.push( block.addr );
|
||||
r.push( (block.count << 8) | block.value )
|
||||
return r;
|
||||
}, []));
|
||||
}
|
||||
// ---------------修改的代码在这里------------------
|
||||
else {
|
||||
const blocks = new Array();
|
||||
let curr = null;
|
||||
for( let i=0; i < ordered.length; ++i ){
|
||||
const [addr, value] = ordered[i];
|
||||
dup.set(addr, hole);
|
||||
if( !curr ) {
|
||||
curr = { addr, value, count: 1 };
|
||||
}
|
||||
else {
|
||||
if( curr.value == value && curr.addr + curr.count == addr ) {
|
||||
++curr.count;
|
||||
}
|
||||
else {
|
||||
blocks.push( curr.addr, (curr.count << 8) | curr.value );
|
||||
curr = { addr, value, count: 1 };
|
||||
}
|
||||
}
|
||||
}
|
||||
if( curr ) blocks.push( curr.addr, (curr.count << 8) | curr.value );
|
||||
return Uint32Array.from(blocks);
|
||||
}
|
||||
// ---------------修改的代码完结处------------------
|
||||
}
|
||||
|
||||
const pack = (entlist, strlist, idxlist, cmdlist, xvalue) => {
|
||||
@ -337,15 +383,15 @@ const lade = (list, info, order) => {
|
||||
size.str = len;
|
||||
return off;
|
||||
};
|
||||
const ut_addtr = fastly ? (() => {
|
||||
const ut_addtr = noreuse ? (() => {
|
||||
const cache = {};
|
||||
return tr => {// 不要直接ut_pushtr,因为有些秘籍会撑爆字符串表
|
||||
if (cache[tr] != undefined) return cache[tr];
|
||||
else {
|
||||
const code = conv.encode(tr);
|
||||
const off = findIndex(strtable, code, size.str);
|
||||
if( off >= 0 ) cache[tr] = off;
|
||||
return off < 0 ? ut_pushtr(code) : off;
|
||||
const off = ut_pushtr(code);
|
||||
cache[tr] = off;
|
||||
return off;
|
||||
}
|
||||
}
|
||||
})() : tr => {
|
||||
@ -353,7 +399,20 @@ const lade = (list, info, order) => {
|
||||
const off = findIndex(strtable, code, size.str);
|
||||
return off < 0 ? ut_pushtr(code) : off;
|
||||
};
|
||||
return list.map(ut_addtr);
|
||||
// 避免使用迭代器方法,减少CPU(已走过performance对比流程)
|
||||
// ---------------原来的代码在这里------------------
|
||||
if( noiter === false ){
|
||||
return list.map(ut_addtr);
|
||||
}
|
||||
// ---------------修改的代码在这里------------------
|
||||
else {
|
||||
let res = new Array(list.length);
|
||||
for( let i=0; i < list.length; ++i ){
|
||||
res[i] = ut_addtr(list[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// ---------------修改的代码完结处------------------
|
||||
}
|
||||
|
||||
const addStrIndex = list => {
|
||||
@ -399,19 +458,42 @@ const lade = (list, info, order) => {
|
||||
|
||||
// pack
|
||||
let holedup = new Map();
|
||||
let entbytelist = enttable.map(entry => {
|
||||
let { id, data } = entry;
|
||||
if (id < 0x10000) { // 收集str
|
||||
let idxlist = id == 0 ? addString( data ) : addString(data.length > 1 ? data : []); // length==1就是开启
|
||||
let location = addStrIndex(idxlist);
|
||||
return Uint32Array.of(id, location, idxlist.length);
|
||||
// 避免使用迭代器方法,减少CPU(已走过performance对比流程)
|
||||
// ---------------原来的代码在这里------------------
|
||||
let entbytelist;
|
||||
if( noiter === false ){
|
||||
entbytelist = enttable.map(entry => {
|
||||
let { id, data } = entry;
|
||||
if (id < 0x10000) { // 收集str
|
||||
let idxlist = id == 0 ? addString( data ) : addString(data.length > 1 ? data : []); // length==1就是开启
|
||||
let location = addStrIndex(idxlist);
|
||||
return Uint32Array.of(id, location, idxlist.length);
|
||||
}
|
||||
else {
|
||||
let armbytecode = assembleCheat(data, holedup, id & 0xffff);
|
||||
let location = addCommand(armbytecode);
|
||||
return Uint32Array.of(id, location, armbytecode.length);
|
||||
}
|
||||
});
|
||||
}
|
||||
// ---------------修改的代码在这里------------------
|
||||
else {
|
||||
entbytelist = new Array(enttable.length);
|
||||
for( let i=0; i < enttable.length; i++ ){
|
||||
let { id, data } = enttable[i];
|
||||
if (id < 0x10000) {
|
||||
let idxlist = id == 0 ? addString( data ) : addString(data.length > 1 ? data : []); // length==1就是开启
|
||||
let location = addStrIndex(idxlist);
|
||||
entbytelist[i] = Uint32Array.of(id, location, idxlist.length);
|
||||
}
|
||||
else {
|
||||
let armbytecode = assembleCheat(data, holedup, id & 0xffff);
|
||||
let location = addCommand(armbytecode);
|
||||
entbytelist[i] = Uint32Array.of(id, location, armbytecode.length);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let armbytecode = assembleCheat(data, holedup, id & 0xffff);
|
||||
let location = addCommand(armbytecode);
|
||||
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);
|
||||
|
@ -3,6 +3,21 @@ const {Worker, isMainThread, parentPort, workerData} = require("worker_threads")
|
||||
const readCht = require("./cht");
|
||||
const { readFileSync } = require("fs");
|
||||
const ncpu = require("os").availableParallelism();
|
||||
const fastly = process.env.OAFCHT_NO_ITER==='1';
|
||||
|
||||
const handlelist = fastly === false ? list => list.map( game => {
|
||||
const [order, serial, title] = game;
|
||||
const file = `./gba/${order}.u8`;
|
||||
return loadcheat(order, serial, title ?? order, file);
|
||||
}) : list => {
|
||||
const res = new Array(list.length);
|
||||
for( let i=0; i < list.length; i++ ) {
|
||||
const [order, serial, title] = list[i];
|
||||
const file = `./gba/${order}.u8`;
|
||||
res[i] = loadcheat(order, serial, title ?? order, file) ;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
const loadcheat = (order, serial, title, file) => {
|
||||
try {
|
||||
@ -32,11 +47,7 @@ if( isMainThread ) {
|
||||
});
|
||||
} );
|
||||
});
|
||||
} : list => Promise.resolve( list.map( game => {
|
||||
const [order, serial, title] = game;
|
||||
const file = `./gba/${order}.u8`;
|
||||
return loadcheat(order, serial, title ?? order, file);
|
||||
} ) );
|
||||
} : list => Promise.resolve( handlelist(list) );
|
||||
}
|
||||
else {
|
||||
const list = workerData;
|
||||
@ -45,11 +56,5 @@ else {
|
||||
const file = `./gba/${order}.u8`;
|
||||
return loadcheat(order, serial, title ?? order, file);
|
||||
} ) ).then( res => parentPort.postMessage(res) );*/
|
||||
parentPort.postMessage(
|
||||
list.map( game => {
|
||||
const [order, serial, title] = game;
|
||||
const file = `./gba/${order}.u8`;
|
||||
return loadcheat(order, serial, title ?? order, file);
|
||||
})
|
||||
);
|
||||
parentPort.postMessage( handlelist(list) );
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user