Skip to content

Instantly share code, notes, and snippets.

@kamronbatman
Created May 1, 2022 17:28
Show Gist options
  • Save kamronbatman/610e0e6cf9b171c9d8c44dc75a022523 to your computer and use it in GitHub Desktop.
Save kamronbatman/610e0e6cf9b171c9d8c44dc75a022523 to your computer and use it in GitHub Desktop.
Pokemon Gen 4 PCD -> WC in JS
const fs = require('fs');
const path = require('path');
function mu32(a, b) {
var ah = (a >> 16) & 0xffff, al = a & 0xffff;
var bh = (b >> 16) & 0xffff, bl = b & 0xffff;
var high = ((ah * bl) + (al * bh)) & 0xffff;
return (((high << 16)>>>0) + (al * bl)) & 0xffffffff;
}
function LCRNG(seed) {
return (mu32(seed, 0x41C64E6D) + 0x00006073) >>> 0;
}
function ShuffleArray(pkmBuffer, shiftValue) {
const blockPositions = [
[0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3, 1, 1, 2, 3, 2, 3],
[1, 1, 2, 3, 2, 3, 0, 0, 0, 0, 0, 0, 2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2],
[2, 3, 1, 1, 3, 2, 2, 3, 1, 1, 3, 2, 0, 0, 0, 0, 0, 0, 3, 2, 3, 2, 1, 1],
[3, 2, 3, 2, 1, 1, 3, 2, 3, 2, 1, 1, 3, 2, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0],
];
const newBlocks = [pkmBuffer.slice(0, 8)];
for (let block = 0; block < 4; block += 1) {
const position = 32 * blockPositions[block][shiftValue];
newBlocks.push(pkmBuffer.slice(8 + position, 8 + (position + 32)));
}
newBlocks.push(pkmBuffer.slice(136, 236));
return Buffer.concat(newBlocks);
}
function getPKM(pcdBuffer) {
if (pcdBuffer.readUInt8(0) !== 1) {
return pcdBuffer;
}
const pkmBuffer = pcdBuffer.slice(8, 244);
const pv = pkmBuffer.readUInt32LE(0);
const chk = pkmBuffer.readUInt16LE(6);
const shiftvalue = ((pv & 0x3E000) >> 0xD) % 24;
let seed = chk;
const decrypted = Buffer.alloc(236);
decrypted.writeUInt32LE(pv, 0);
decrypted.writeUInt32LE(pkmBuffer.readUInt32LE(4), 4);
// Decrypt
for (let i = 8; i < 236; i += 2) {
if (i === 136) {
seed = pv;
}
seed = LCRNG(seed);
decrypted.writeUInt16LE((pkmBuffer.readUInt16LE(i)) ^ (seed >>> 0x10), i);
}
return Buffer.concat([pcdBuffer.slice(0, 8), ShuffleArray(decrypted, shiftvalue), pcdBuffer.slice(244, pcdBuffer.length)]);
}
function getPKMFromPCD(dir) {
const paths = fs.readdirSync(dir);
fs.mkdirSync(path.join(dir, '/wcs/'));
for (let i = 0; i < paths.length; i++) {
if (paths[i].endsWith('.pcd')) {
const pcdBuffer = fs.readFileSync(paths[i]);
const pkmBuffer = getPKM(pcdBuffer);
fs.writeFileSync(path.join(dir, '/wcs/', paths[i].substring(0, paths[i].length - 4) + '.wc4'), pkmBuffer);
}
}
}
getPKMFromPCD('./');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment