summaryrefslogtreecommitdiff
path: root/extras/analyze_texts.py
blob: 57764204162e83b813968b87547319c56cf0e496 (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
#!/usr/bin/python
#author: Bryan Bishop <kanzure@gmail.com>
#date: 2012-01-06
#analyze texts, how many commands are unknown?
import extract_maps
from pretty_map_headers import map_name_cleaner
from operator import itemgetter
debug = False #set to True to increase logging output

#how many times is each command byte called?
totals = {}
total_text_commands = 0
should_be_total = 0

def get_text_pointer(texts_pointer, text_id):
    if type(texts_pointer) == str: texts_pointer = int(texts_pointer, 16)
    if type(text_id) == str: text_id = int(text_id)

    byte1 = ord(extract_maps.rom[texts_pointer + (2*text_id)])
    byte2 = ord(extract_maps.rom[texts_pointer + (2*text_id) + 1])
    pointer = (byte1 + (byte2 << 8))

    return pointer

def how_many_until(byte, starting):
    index = extract_maps.rom.find(byte, starting)
    return index-starting

def print_command_debug_info(command_byte, text_id, text_pointer, map_id):
    if debug:
        print "byte is " + str(command_byte) + " on text #" + str(text_id) + " at " + hex(text_pointer) + " on map " + str(map_id) + " (" + extract_maps.map_headers[map_id]["name"] + ")"

def parse_text_script(text_pointer, text_id, map_id):
    global total_text_commands
    offset = text_pointer
    commands = {}
    command_counter = 0
    
    end = False
    while not end:
        command = {}
        command_byte = ord(extract_maps.rom[offset])
        
        if  command_byte == 0:
            print_command_debug_info(command_byte, text_id, text_pointer, map_id)

            #read until $57
            jump = how_many_until(str(57), offset)
            end_address = offset + jump

            command = {"type": command_byte,
                       "start_address": offset,
                       "end_address": end_address,
                       "size": jump,
                      }

            offset += end_address + 1
            if not 0x0 in totals.keys(): totals[0x0] = 1
            else: totals[0x0] += 1
            
            end = True
        elif command_byte == 0x17:
            print_command_debug_info(command_byte, text_id, text_pointer, map_id)
            
            #TX_FAR [pointer][bank]
            pointer_byte1 = ord(extract_maps.rom[offset+1])
            pointer_byte2 = ord(extract_maps.rom[offset+2])
            pointer_bank = ord(extract_maps.rom[offset+3])

            pointer = (pointer_byte1 + (pointer_byte2 << 8))
            pointer = extract_maps.calculate_pointer(pointer, pointer_bank)

            command = {"type": command_byte,
                       "start_address": offset,
                       "end_address": offset + 3,
                       "pointer": pointer,
                      }

            offset += 3
            if not 0x17 in totals.keys(): totals[0x17] = 1
            else: totals[0x17] += 1
            end = True
        else:
            if not command_byte in totals.keys(): totals[command_byte] = 1
            else: totals[command_byte] += 1
            
            end = True

        commands[command_counter] = command
        command_counter += 1
    total_text_commands += len(commands)
    return commands

def analyze_texts():
    global should_be_total

    texts = {}
    for map_id in extract_maps.map_headers:
        if map_id in extract_maps.bad_maps: continue #skip
        map2 = extract_maps.map_headers[map_id]
        map2["texts"] = {}
        referenced_texts = map2["referenced_texts"]
        should_be_total += len(referenced_texts)
        texts_pointer = int(map2["texts_pointer"], 16)
        
        #print "Checking texts on... map_id=" + str(map_id) + " and len(referenced_texts)=" + str(len(referenced_texts))
        for text_id in referenced_texts:
            #print "Working on map id=" + str(map2["id"]) + " and text id=" + str(text_id)
            text_pointer = get_text_pointer(texts_pointer, text_id)
            text_pointer = extract_maps.calculate_pointer(text_pointer, int(map2["bank"], 16))
            commands = parse_text_script(text_pointer, text_id, map_id)
            map2["texts"][text_id] = commands

        texts[map_id] = map2["texts"]
        extract_maps.map_headers[map_id]["texts"] = map2["texts"]
    return texts

if __name__ == "__main__":
    extract_maps.load_rom()
    extract_maps.load_map_pointers()
    extract_maps.read_all_map_headers()
    print analyze_texts()

    print "\n\n---- stats ----\n\n"
    
    popular_text_commands = sorted(totals.iteritems(), key=itemgetter(1), reverse=True)
    #convert the first values (command byte) to hex
    for popular_item in popular_text_commands:
        print hex(popular_item[0]) + " was used " + str(popular_item[1]) + " times."
    #print "popular text commands: " + str(popular_text_commands)
    
    print "total text commands: " + str(total_text_commands)
    print "total text scripts: " + str(should_be_total)