// Diagnostic copy only. Never overwrite the metadata consumed by the game. const fs = require('node:fs'); const crypto = require('node:crypto'); const [source, destination] = process.argv.slice(2); if (!source || !destination || require('node:path').resolve(source) === require('node:path').resolve(destination)) throw new Error('Specify separate source and diagnostic output files.'); const input = fs.readFileSync(source); const header = Buffer.from(input.subarray(0, 256)); header.fill(0, 0xc0, 0xc4); header.fill(0, 0xc8, 0xcc); if (crypto.createHash('sha256').update(header).digest('hex') !== '2af65a04fe43613b66fafbe269264a6ec2b4c834304db272f0df68e7503b59e2') throw new Error('Not the verified 20230825 header.'); // Standard v27 section order. Each pair is the offset/size FIELD POSITION // in the shuffled header, not a hardcoded section address. const fields = [ [0x2c,0xbc], [0xc8,0xc0], [0xe8,0xc4], [0x20,0xa8], [0x24,0x68], [0x44,0xb0], [0x64,0xec], [0xf0,0x04], [0x38,0x3c], [0x28,0x80], [0xa0,0x50], [0xf8,0xd4], [0xe0,0x5c], [0x08,0x00], [0x18,0x58], [0x4c,0xb4], [0x30,0x9c], [0x34,0x98], [0x6c,0x8c], [0x14,0x48], [0xd8,0xcc], [0x0c,0xb8], [0x88,0x70], [0x7c,0xd0], [0xa4,0x90], [0x78,0x94], [0xe4,0xf4], [0x54,0x40], [0xfc,0x10], [0x74,0x84], [0xac,0xdc] ]; const output = Buffer.from(input); output.writeUInt32LE(0xfab11baf, 0); output.writeUInt32LE(27, 4); for (let i=0; i input.length) throw new Error(`Section ${i} out of bounds`); output.writeUInt32LE(offset, 8+i*8); output.writeUInt32LE(size, 12+i*8); } if (!input.subarray(256).equals(output.subarray(256))) throw new Error('Payload changed'); // This release also places invalid generic-container indices in each image's // synthetic type. Those types cannot have generic parameters. Repair // only verified module rows in the tooling copy; game metadata is untouched. const types = output.readUInt32LE(8 + 19*8); const typeCount = output.readUInt32LE(12 + 19*8) / 88; const images = output.readUInt32LE(8 + 20*8); const imageCount = output.readUInt32LE(12 + 20*8) / 40; const strings = output.readUInt32LE(24); if (imageCount !== 305 || typeCount !== 42537 || output.subarray(strings+42, strings+51).toString() !== '\0') throw new Error('Unexpected August type/image structure'); const modules = new Set(); for (let i=0; i= typeCount || modules.has(index) || output.readUInt32LE(p+84) !== 0x02000001 || output.readInt32LE(p) !== 0 || output.readInt32LE(p+24) < 6673) throw new Error(`Unexpected module row for image ${i}`); modules.add(index); output.writeInt32LE(42, p); output.writeInt32LE(-1, p+24); } for (let i=0; i= 6673) throw new Error(`Invalid generic container on type ${i}`); } fs.writeFileSync(destination, output); console.log(`Wrote tooling copy: ${destination}; normalized header and ${modules.size} synthetic module rows.`);