diff options
Diffstat (limited to 'tools/extract_anim_data.py')
-rw-r--r-- | tools/extract_anim_data.py | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/tools/extract_anim_data.py b/tools/extract_anim_data.py new file mode 100644 index 0000000..0722238 --- /dev/null +++ b/tools/extract_anim_data.py @@ -0,0 +1,136 @@ +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()
\ No newline at end of file |