summaryrefslogtreecommitdiff
path: root/tools/extract_anim_data.py
blob: 5569aec86a58851fb6b451d78c5df48da465526c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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()