#!/usr/bin/python #author: Bryan Bishop #date: 2012-01-31 #url: http://romendo.net/stag019/pokedex/reverse.php?source #almost an exact copy of stag019's code? from optparse import OptionParser from copy import copy, deepcopy rom = None #load this later RLE_data = [0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF] method_1_data = \ [ [0x00, 0x01, 0x03, 0x02, 0x06, 0x07, 0x05, 0x04, 0x0C, 0x0D, 0x0F, 0x0E, 0x0A, 0x0B, 0x09, 0x08], [0x08, 0x09, 0x0B, 0x0A, 0x0E, 0x0F, 0x0D, 0x0C, 0x04, 0x05, 0x07, 0x06, 0x02, 0x03, 0x01, 0x00], ] def load_rom(): global rom fh = open("../baserom.gbc", "r") rom = fh.read() fh.close() def writebit(switchram): global compressed, curbyte, curbit if curbit + 1 == 8: curbyte += 1 curbit = 0 compressed[curbyte] |= bit << 7 - curbit def data_packet(bitgroups): for bg in bitgroups: writebit((bg >> 1) & 1) writebit(bg & 1) writebit(0) writebit(0) def finish_text(ram): return [chr(x) for x in ram] def RLE(nums): global RLE_data search = nums + 1 while not (bitcount = RLE_data.find(search)): search -= 1 number = nums - RLE_data[bitcount] [writebit(1) for j in range(bitcount)] writebit(0) [writebit((number >> j) & 1) for j in list(reversed(range(-1, bitcount)))] def interpret_compress(ram1, ram2, interpretation, switchram): global compressed, curbit, curbyte, xrows, xwidth if switchram: ram_1, ram_2 = ram2, ram1 elif not switchram: ram_1, ram_2 = ram1, ram2 if interpretation == 1: method_1(ram1) method_1(ram2) elif interpretation == 2 or interpretation == 3: for i in range(0, xrows * xwidth * 8): ram_2[i] ^= ram_1[i] method_1(ram_1) if interpretation == 3: method_1(ram_2) curbit = 7 curbyte = 0 compressed = [0] * 0x310 compressed[0] = (xrows << 4) | xwidth writebit(switchram) for ram in range(2): type_var = 0 nums = 0 bitgroups = [] for i in range(xrows * xwidth * 32): byte = floor(i / (xwidth * 32)) * xwidth * 8 + i % (xwidth * 8) bit = (floor(i / (xwidth * 8)) * 2) % 8 if ram == True: bitgroup = (ram_2[byte] >> 6 - bit) & 3 else: bitgroup = (ram_1[byte] >> 6 - bit) & 3 if bitgroup == 0 or not bitgroup: if not type_var or type_var == 0: writebit(0) elif type_var == 1: nums += 1 else: data_packet(bitgroups) type_var = 1 bitgroups = [] else: if not type_var or type_var == 0: writebit(1) elif type_var == 1: RLE(nums) type_var = -1 bitgroups.append(bitgroup) nums = 0 if type_var == 1: RLE(nums) else: data_packet(bitgroups) if not ram or ram == 0: if interpretation < 2: writebit(0) else: writebit(1) writebit(interpretation - 2) return compressed[0:curbyte + 1] def compress(data, height, width, interpretation=0, curbit, curbyte, switchram=False): global compressed, curbit, curbyte, xrows, xwidth, interpretation, switchram xrows = height xwidth = width compressed = [0] * 0x310 data = [ord(x) for x in data] ram1 = [0] * 0x188 ram2 = copy(ram1) for i in range(0, xrows * xwidth * 8): ram1[i] = data[i << 1] ram2[i] = data[(i << 1) | 1] if interpretation: compression = interpret_compress(ram1, ram2, interpretation, switchram) else: compression = [0] * 3 for i in range(3): j = i * 2 compression[j] = interpret_compress(ram1, ram2, i + 1, 0) compression[j + 1] = interpret_compress(ram1, ram2, i + 1, 1) min = 0 minid = -1 for id, entry in enumerate(compression): if minid == -1 or count(entry) < min: min = count(entry) minid = id compression = compression[minid] return finish_text(compression) def main(): usage = "usage: %prog image.dat height width [offset [interpretration [switchram]]]" parser = OptionParser(usage) (options, args) = parser.parse_args() if len(args) < 3: parser.error("need input image data from ROM") filename = args[0] height = args[1] width = args[2] offset = "00" if len(args) >= 4: offset = args[3] interpretation = 0 switchram = False if len(args) >= 5: intrepretation = args[4] interpretation = int(interpretation) if interpretation < 1 or interpretation > 3: interpretation = 0 elif len(args) >= 6: switchram = args[5] if width < 1 or width > 7 or height < 1 or height > 7: raise Exception, "error: invalid tile sizes" fh = open(filename, "r") content = fh.read() fh.close() if len(content) != height * width * 16 raise Exception, "file size doesn't equal height by width" data = compress(content, height, width) if offset != "00": data = "PATCH" + pack('H6n', offset, len(data)) #wtf should this do? yourafailure print data if __name__ == "__main__": load_rom() main()