diff --git a/tools/cheat-builder/explain.ts b/tools/cheat-builder/explain.ts new file mode 100644 index 0000000..130fb28 --- /dev/null +++ b/tools/cheat-builder/explain.ts @@ -0,0 +1,128 @@ + +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 "); + 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) ); diff --git a/tools/cheat-builder/make-acl.rs b/tools/cheat-builder/make-acl.rs index f565e59..4d2e3e3 100644 --- a/tools/cheat-builder/make-acl.rs +++ b/tools/cheat-builder/make-acl.rs @@ -613,6 +613,7 @@ fn loadlist() -> Vec<(String,String)> { .expect("JSON was not well-formatted"); if let Value::Object(map) = json_data { + retval.reverse( map.len() ); for (key, value) in map.iter() { if let Value::String(serial) = value { if serial != "????" { @@ -782,4 +783,4 @@ impl<'a> Iterator for Utf8CharIter<'a> { } impl<'a> FusedIterator for Utf8CharIter<'a> {} -*/ \ No newline at end of file +*/