mirror of
https://gitee.com/anod/open_agb_firm.git
synced 2025-05-06 05:44:11 +08:00
129 lines
5.2 KiB
TypeScript
129 lines
5.2 KiB
TypeScript
|
|
const fs = require('fs');
|
|
|
|
const align = (t, b) => t % b == 0 ? t : t + b - t % b;
|
|
|
|
const getSerial = (buffer: Buffer, offset: number, base1: number, base2: number) => {
|
|
if( offset >= base2 ){
|
|
let n = Math.floor( (offset-base2) / 8 );
|
|
let c = (base1-8) / 3;
|
|
for(let i=0; i < c; ++i ){
|
|
let a = buffer.readUInt16LE(base1 + i*2);
|
|
let b = buffer.readUInt16LE(base1 + i*2 + 2);
|
|
if( a <= n && n < b ){
|
|
let start = 8 + i * 3;
|
|
let str = String.fromCharCode( buffer[start], buffer[start+1], buffer[start+2] );
|
|
return [str, i];
|
|
}
|
|
}
|
|
return ["????", -1];
|
|
} else if( offset >= base1 && offset < base2 - 2 ) {
|
|
let n = offset - base1;
|
|
n = Math.floor( n/2 );
|
|
let start = 8 + n * 3;
|
|
let str = String.fromCharCode( buffer[start], buffer[start+1], buffer[start+2] );
|
|
return [str, n];
|
|
}
|
|
else return ["????", -1];
|
|
}
|
|
|
|
const describe = (buffer: Buffer, offset: number) => {
|
|
console.info(`error at ${offset}`);
|
|
let n = buffer.readUInt16LE(4);
|
|
let serialbase = 8;
|
|
let offsetbase = serialbase + 3*n;
|
|
let cheatbase = offsetbase + 2 * (n+1);
|
|
let cheatcnt = buffer.readUInt16LE(cheatbase-2);
|
|
let expandbase = align( cheatbase + 8 * cheatcnt, 32 );
|
|
let serial = "????", entry = -1;
|
|
if( offset >= offsetbase ) [serial, entry] = getSerial(buffer, offset, offsetbase, cheatbase);
|
|
|
|
console.debug("is it right? %d - %d - %d - %d", serialbase, offsetbase, cheatbase, align(expandbase, 32));
|
|
if( offset < serialbase ){ // 属于HEAD数据
|
|
if( offset < 4){
|
|
console.log("INSIDE MAGIC NUMBER");
|
|
console.log("ACL?");
|
|
console.log(new Array(offset).fill(" ").join("")+"^");
|
|
}
|
|
else if( offset < 6 ){
|
|
console.log("INSIDE SERIAL LENGTH");
|
|
console.log(n.toString(16).padStart(4, '0'));
|
|
console.log(new Array(5 - offset).fill(" ").join("")+" ^");
|
|
}
|
|
else {
|
|
console.log("INSIDE MAX CHEAT PARAGRAPH");
|
|
n = buffer.readUInt16LE(6);
|
|
console.log(n.toString(16).padStart(4, '0'));
|
|
console.log(new Array(7 - offset).fill(" ").join("")+" ^");
|
|
}
|
|
}
|
|
else if( offset < offsetbase ){
|
|
let start = serialbase + Math.floor( (offset-serialbase)/3 ) * 3;
|
|
console.log("INSITDE SERIAL COLLECTIONS", "index =", Math.floor( (offset-serialbase)/3 ));
|
|
console.log( String.fromCharCode( buffer[start], buffer[start+1], buffer[start+2] ) );
|
|
console.log( new Array(offset-start).fill(" ").join("")+"^" );
|
|
}
|
|
else if( offset < cheatbase ){
|
|
let start = offsetbase + Math.floor( (offset-offsetbase)/2 ) * 2;
|
|
console.log("INSITDE SERIAL EXTENSIONS", "index =", Math.floor( (offset-offsetbase)/2 ), "serial(3) =", serial);
|
|
if( offset > offsetbase+1 ){
|
|
n = buffer.readUInt16LE(start-2);
|
|
console.log(n.toString(16).padStart(4, "0"), " <<< ", getSerial(buffer, offset-2, offsetbase, cheatbase)[0]);
|
|
}
|
|
n = buffer.readUInt16LE(start);
|
|
console.log(n.toString(16).padStart(4, '0') );
|
|
console.log(new Array(offset - start).fill(" ").join("")+" ^");
|
|
}
|
|
else if( offset < expandbase ){
|
|
if( offset < cheatbase + cheatcnt * 8 ){
|
|
let start = cheatbase + Math.floor( (offset-cheatbase) / 8 ) * 8;
|
|
let entstart = buffer.readUInt16LE( offsetbase + entry*2 ), h, l;
|
|
entstart = cheatbase + entstart * 8;
|
|
console.log("INSITDE CHEAT SEGMENTS", "index =", Math.floor( (offset-cheatbase)/8 ), "serial(3) =", serial);
|
|
while( entstart < start ){
|
|
h = buffer.readUInt32LE(entstart);
|
|
l = buffer.readUInt32LE(entstart+4);
|
|
console.log(h.toString(16).padStart(8, '0') + " " + l.toString(16).padStart(8, '0'));
|
|
entstart += 8;
|
|
}
|
|
h = buffer.readUInt32LE(start);
|
|
l = buffer.readUInt32LE(start+4);
|
|
console.log(h.toString(16).padStart(8, '0') + " " + l.toString(16).padStart(8, '0'));
|
|
if( offset - start < 4 ){
|
|
console.log(new Array(3 - (offset - start)).fill(" ").join("")+" ^");
|
|
}
|
|
else console.log(new Array(12 - (offset - start)).fill(" ").join("")+" ^");
|
|
}
|
|
else {
|
|
console.log("INSITDE CHEAT SEGMENTS PADDING" );
|
|
}
|
|
}
|
|
else if( offset < buffer.length ){
|
|
console.log("INSIDE CHEAT BINARY");
|
|
// 1 index from cheatbase
|
|
// 2 index from offsetbase
|
|
// 3 get offset for cheat bin
|
|
// 4 show for entry size/entry record/string table/index table/code table
|
|
}
|
|
else {
|
|
console.error("INVALID POSITION AT %d", offset);
|
|
}
|
|
}
|
|
|
|
const main = (argv: string[]) => {
|
|
if( argv.length < 2 ) {
|
|
console.info("Usage: explain <file1> <file2>");
|
|
return;
|
|
}
|
|
const first: Buffer = fs.readFileSync(argv[0]);
|
|
const second: Buffer = fs.readFileSync(argv[1]);
|
|
|
|
let diff = 0;
|
|
for(; first[diff] === second[diff]; diff++);
|
|
describe(first,diff);
|
|
console.log("------------------");
|
|
describe(second,diff);
|
|
}
|
|
|
|
main( process.argv.slice(2) );
|