Skip to content

Instantly share code, notes, and snippets.

@zaksabeast
Last active October 27, 2019 18:14
Show Gist options
  • Save zaksabeast/7c1a9898ffd78a9807b2603684e20fe1 to your computer and use it in GitHub Desktop.
Save zaksabeast/7c1a9898ffd78a9807b2603684e20fe1 to your computer and use it in GitHub Desktop.
// Reading transfers from Dream Radar on b2/w2 saves:
// 1. Read the 32 bit value at 0x25E00
// 2. key = ((value * 0x5d588b65) + ((value * 0x6c078965) >> 32)) & 0xFFFFFFFF
// 3. xor the key with every 32 bit value from 0x7F010-0x7F094
// 4. The resulting numbers correspond to Dream Radar transfers - 0 means no Pokemon exists. Dream radar legends are associated with specific numbers (e.g. Dialga is 0x96436763)
const fs = require('fs');
// Check to ensure a save location is provided
if (process.argv.length < 3) {
console.error(`Usage: ${process.argv[0]} ${process.argv[1]} <b2w2 save location>`);
process.exit(2);
}
// Get save location
const saveLocation = process.argv[2];
// Offset and sizes
const SEED_OFFSET = 0x25E00;
const DREAM_RADAR_OFFSET = 0x7F000;
const DREAM_RADAR_SIZE = 0x98;
const DREAM_RADAR_SLOT_AMOUNT = 34;
// Helper functions
const getKey = seed => Number((BigInt(seed) * 0x5d588b65n) + ((BigInt(seed) * 0x6c078965n) >> 32n) & 0xFFFFFFFFn);
const cryptSlot = (view, cipherKey, slot) => {
const slotOffset = (slot * 4) + 0x10;
const encPoke = view.getUint32(slotOffset, true);
return encPoke ^ cipherKey;
}
// Get save and dream radar bytes
const save = new Uint8Array(fs.readFileSync(saveLocation, { encoding: null }));
const dreamRadarBytes = save.slice(DREAM_RADAR_OFFSET, DREAM_RADAR_OFFSET + DREAM_RADAR_SIZE);
// Create views to easily grab little endian 32 bit numbers
const saveView = new DataView(save.buffer);
const dreamRadarView = new DataView(dreamRadarBytes.buffer);
// Get the key
const key = getKey(saveView.getUint32(SEED_OFFSET, true));
// Check if the save has transfers
const hasDreamRadarTransfers = dreamRadarView.getUint32(4, true) === 0;
// Calculate result
const dreamRadarSlots = new Array(DREAM_RADAR_SLOT_AMOUNT).fill(0);
const result = hasDreamRadarTransfers
? dreamRadarSlots.map((_, index) => cryptSlot(dreamRadarView, key, index))
: dreamRadarSlots;
console.log(result);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment