def pokemon_translate(self, src): u"""Translates a raw block of text to readable unicode, using the encryption from the Gen IV Pokémon games. These blocks actually contain a list of multiple strings. The whole list is returned. """ pokemon_junk = pokemon_encrypted_text_struct.parse(src) # <3 LoadingNOW for the original source # Decrypt the header # It's encrypted with some XOR shenanigans and 16-bit math. key = cap_to_bits(pokemon_junk.key * 0x02fd, 16) for i in range(pokemon_junk.count): curkey = cap_to_bits(key * (i + 1), 16) curkey = curkey | (curkey << 16) pokemon_junk.header[i].offset ^= curkey pokemon_junk.header[i].length ^= curkey # Translate this garbage, decrypting with this rotating key strings = [] for i, header in enumerate(pokemon_junk.header): dest_chars = [] offset = header.offset length = header.length key = ((i + 1) * 0x91bd3) & 0xffff for pos in xrange(length): # Characters are two bytes; get them and fix endianness n = (ord(src[offset + pos * 2 + 1]) << 8) \ | ord(src[offset + pos * 2]) n ^= key dest_chars.append(unichr(n)) # Rotate key key = (key + 0x493d) & 0xffff dest_string = u''.join(dest_chars) strings.append(self.escape_control_chars(self.pokemon_decode_string(dest_string))) return strings
def pixel_generator(): # Unmask the sprite data for word, mask in izip(word_iterator(rahc.data, 16), mask_generator()): unmasked = word ^ mask # This is 16 bits, and there are four bits per pixel, so we # have four pixels for _ in range(4): yield cap_to_bits(unmasked, 4) unmasked >>= 4
def mask_generator(): key = (word_iterator(rahc.data[0:2], 16)).next() while True: yield key key = cap_to_bits(key * mult + add, 16)