Last active
October 27, 2019 18:14
-
-
Save zaksabeast/7c1a9898ffd78a9807b2603684e20fe1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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