poketcg/tools/extract_anim_data.py
2022-09-18 11:55:56 -05:00

137 lines
4.9 KiB
Python

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()