import mmap import math def convertOffset(lo, hi, bank): return lo + ((hi << 8) - 0x4000) + (bank * 0x4000 + 0x20 * 0x4000) def signedByteToInt(uByte): return (uByte, uByte - 0x100)[uByte >= 0x80] def getOAMFlagStr(flags): strings = [] if (flags == 0): strings.append('$0') if (flags & 0b111 != 0): strings.append('%{:03b}'.format(flags & 0b111)) if (flags & (1 << 3) != 0): strings.append('(1 << OAM_TILE_BANK)') if (flags & (1 << 4) != 0): strings.append('(1 << OAM_OBP_NUM)') if (flags & (1 << 5) != 0): strings.append('(1 << OAM_X_FLIP)') if (flags & (1 << 6) != 0): strings.append('(1 << OAM_Y_FLIP)') if (flags & (1 << 7) != 0): strings.append('(1 << OAM_PRIORITY)') return ' | '.join(s for s in strings) def getAnimData(): with open('baserom.gbc') as rom: romMap = mmap.mmap(rom.fileno(), 0, access=mmap.ACCESS_READ) offsets = [] for i in range(0xd9): lineOffset = 0x81333 + 4*i lo = romMap[lineOffset] hi = romMap[lineOffset + 1] bank = romMap[lineOffset + 2] offsets.append([convertOffset(lo, hi, bank), i]) animData = {} animFrameTables = {} frameData = {} for offset in offsets: header = romMap[offset[0] : offset[0] + 3] pos = offset[0] + 3 data = [] data.append(romMap[pos : pos + 4]) pos += 4 while (data[-1][0] != 0x00 or data[-1][1] != 0x00): data.append(romMap[pos : pos + 4]) pos += 4 maxFrame = 0 for curFrameData in data: if (curFrameData[0] != 0xff): maxFrame = max(curFrameData[0], maxFrame) frameOffset = convertOffset(header[1], header[2], header[0]) pointers = [] tableAlreadyExists = frameOffset in animFrameTables for i in range(maxFrame + 1): pointers.append(romMap[frameOffset + 2*i : frameOffset + 2*i + 2]) if tableAlreadyExists: if len(pointers) > len(animFrameTables[frameOffset]): if (frameOffset != 0xab066): # special case, seems this is wrong animFrameTables[frameOffset] = pointers else: animFrameTables[frameOffset] = pointers animData[offset[0]] = [header, data, offset[1]] for offset in animFrameTables: curFrameData = [] for ptr in animFrameTables[offset]: curOffset = convertOffset(ptr[0], ptr[1], math.floor(offset / 0x4000 - 0x20)) numTiles = romMap[curOffset] curFrameData.append([curOffset, romMap[curOffset : curOffset + numTiles*4 + 1]]) frameData[offset] = curFrameData return animData, animFrameTables, frameData animData, animFrameTables, frameData = getAnimData() pointerIndices = {} counter = 0 for offset in animFrameTables: pointerIndices[offset] = counter counter += 1 allOffsets = [] for offset in animData: allOffsets.append(offset) for offset in animFrameTables: allOffsets.append(offset) allOffsets = sorted(allOffsets) for offset in allOffsets: size = 0 if offset in animData: header = animData[offset][0] data = animData[offset][1] print('AnimData' + str(animData[offset][2]) + ':: ; ' + "{:0x}".format(offset) + ' (' + "{:0x}".format((math.floor(offset / 0x4000))) + ':' + "{:04x}".format(offset % 0x4000 + 0x4000) + ')') print('\tframe_table ' + 'AnimFrameTable' + str(pointerIndices[convertOffset(header[1], header[2], header[0])])) for curData in data: print('\tframe_data ' + ', '.join(str(signedByteToInt(x)) for x in curData)) size = len(header) + len(data) * 4 if offset in animFrameTables: print('AnimFrameTable' + str(pointerIndices[offset]) + ':: ; ' + "{:0x}".format(offset) + ' (' + "{:0x}".format((math.floor(offset / 0x4000))) + ':' + "{:04x}".format(offset % 0x4000 + 0x4000) + ')') for curFrameData in frameData[offset]: print('\tdw .data_' + "{:0x}".format(curFrameData[0])) size += 2 for curFrameData in frameData[offset]: numTiles = curFrameData[1][0] print() print('.data_' + "{:0x}".format(curFrameData[0])) print('\tdb ' + str(numTiles) + ' ; size') size += 1 for i in range(numTiles): print('\tdb ' + str(signedByteToInt(curFrameData[1][4*i + 1])) + ', ' + str(signedByteToInt(curFrameData[1][4*i + 2])) + ', ' + str(curFrameData[1][4*i + 3]) + ', ' + getOAMFlagStr(curFrameData[1][4*i + 4])) size += 4 print('; ' + "0x{:0x}".format(offset + size)) print() if (offset + size) not in allOffsets: print('\tINCROM ' + "${:0x}".format(offset + size) + ', ') print()