diff options
Diffstat (limited to 'extras')
-rw-r--r-- | extras/sprite_helper.py | 251 |
1 files changed, 236 insertions, 15 deletions
diff --git a/extras/sprite_helper.py b/extras/sprite_helper.py index 991f4919..ee7a5f47 100644 --- a/extras/sprite_helper.py +++ b/extras/sprite_helper.py @@ -1,11 +1,10 @@ -from extract_maps import * -spacing = " " -load_rom() -load_map_pointers() -read_all_map_headers() +import extract_maps +spacing = "\t" #provided by sawakita -constants = { +#these were originally used for making the initial_icon_constants +#but the label names in constants.asm have since been edited +initial_icon_constants = { 0x01: ["Hiro", ""], 0x02: ["Rival", ""], 0x03: ["Oak", ""], @@ -80,6 +79,85 @@ constants = { 0x48: ["lying old man", ""], } +#somewhat more recent sprite labels +sprite_constants = { +0x01: "SPRITE_RED", +0x02: "SPRITE_BLUE", +0x03: "SPRITE_OAK", +0x04: "SPRITE_BUG_CATCHER", +0x05: "SPRITE_SLOWBRO", +0x06: "SPRITE_LASS", +0x07: "SPRITE_BLACK_HAIR_BOY_1", +0x08: "SPRITE_LITTLE_GIRL", +0x09: "SPRITE_BIRD", +0x0a: "SPRITE_FAT_BALD_GUY", +0x0b: "SPRITE_GAMBLER", +0x0c: "SPRITE_BLACK_HAIR_BOY_2", +0x0d: "SPRITE_GIRL", +0x0e: "SPRITE_HIKER", +0x0f: "SPRITE_FOULARD_WOMAN", +0x10: "SPRITE_GENTLEMAN", +0x11: "SPRITE_DAISY", +0x12: "SPRITE_BIKER", +0x13: "SPRITE_SAILOR", +0x14: "SPRITE_COOK", +0x15: "SPRITE_BIKE_SHOP_GUY", +0x16: "SPRITE_MR_FUJI", +0x17: "SPRITE_GIOVANNI", +0x18: "SPRITE_ROCKET", +0x19: "SPRITE_MEDIUM", +0x1a: "SPRITE_WAITER", +0x1b: "SPRITE_ERIKA", +0x1c: "SPRITE_MOM_GEISHA", +0x1d: "SPRITE_BRUNETTE_GIRL", +0x1e: "SPRITE_LANCE", +0x1f: "SPRITE_OAK_SCIENTIST_AIDE", +0x20: "SPRITE_OAK_AIDE", +0x21: "SPRITE_ROCKER", +0x22: "SPRITE_SWIMMER", +0x23: "SPRITE_WHITE_PLAYER", +0x24: "SPRITE_GYM_HELPER", +0x25: "SPRITE_OLD_PERSON", +0x26: "SPRITE_MART_GUY", +0x27: "SPRITE_FISHER", +0x28: "SPRITE_OLD_MEDIUM_WOMAN", +0x29: "SPRITE_NURSE", +0x2a: "SPRITE_CABLE_CLUB_WOMAN", +0x2b: "SPRITE_MR_MASTERBALL", +0x2c: "SPRITE_LAPRAS_GIVER", +0x2d: "SPRITE_WARDEN", +0x2e: "SPRITE_SS_CAPTAIN", +0x2f: "SPRITE_FISHER2", +0x30: "SPRITE_BLACKBELT", +0x31: "SPRITE_GUARD", +0x32: "SPRITE_____NOT____USED____", +0x33: "SPRITE_MOM", +0x34: "SPRITE_BALDING_GUY", +0x35: "SPRITE_YOUNG_BOY", +0x36: "SPRITE_GAMEBOY_KID", +0x37: "SPRITE_GAMEBOY_KID_COPY", +0x38: "SPRITE_CLEFAIRY", +0x39: "SPRITE_AGATHA", +0x3a: "SPRITE_BRUNO", +0x3b: "SPRITE_LORELEI", +0x3c: "SPRITE_SEEL", +0x3d: "SPRITE_BALL", +0x3e: "SPRITE_OMANYTE", +0x3f: "SPRITE_BOULDER", +0x40: "SPRITE_PAPER_SHEET", +0x41: "SPRITE_BOOK_MAP_DEX", +0x42: "SPRITE_CLIPBOARD", +0x43: "SPRITE_SNORLAX", +0x44: "SPRITE_OLD_AMBER_COPY", +0x45: "SPRITE_OLD_AMBER", +0x46: "SPRITE_LYING_OLD_MAN_UNUSED_1", +0x47: "SPRITE_LYING_OLD_MAN_UNUSED_2", +0x48: "SPRITE_LYING_OLD_MAN", +} +dont_use = [0x32, 0x44, 0x46, 0x47, 0x37] +#sprites after 0x23 have only one image +#SPRITE_BIKE_SHOP_GUY only has 1 + icons = {} unique_icons = set() todo_sprites = {} @@ -111,8 +189,8 @@ def print_appearances(): icon = icons[icon_id] possible_name = "" - if icon_id in constants.keys(): - possible_name = " (sawakita suggests: " + constants[icon_id][0] + ")" + if icon_id in initial_icon_constants.keys(): + possible_name = " (sawakita suggests: " + initial_icon_constants[icon_id][0] + ")" output += "sprite " + hex(icon_id) + possible_name + ":\n" for appearance in icon: @@ -127,9 +205,9 @@ def insert_todo_sprites(): load_icons() counter = 1 for icon in unique_icons: - if icon not in constants: + if icon not in initial_icon_constants: todo_sprites[icon] = counter - constants[icon] = None + initial_icon_constants[icon] = None counter += 1 def sprite_name_cleaner(badname): @@ -148,8 +226,8 @@ def sprite_namer(): "makes up better constant names for each sprite" insert_todo_sprites() - for sprite_id in constants: - suggestions = constants[sprite_id] + for sprite_id in initial_icon_constants: + suggestions = initial_icon_constants[sprite_id] if suggestions == None: sprites[sprite_id] = "SPRITE_TODO_" + str(todo_sprites[sprite_id]) continue #next please @@ -161,6 +239,8 @@ def sprite_namer(): sprites[sprite_id] = result def sprite_printer(): + """prints out a list of sprite constants to put into constants.asm + it's deprecated- use the names from the current file instead.""" for key in sprites: line_length = len(sprites[key]) + len(" EQU $") + 2 @@ -173,9 +253,150 @@ def sprite_printer(): print sprites[key] + extra + " EQU $" + value -sprite_namer() +def parse_sprite_sheet_pointer_table(): + """parses the bytes making up the pointer table + first two bytes are the pointer + third byte is the number of bytes (1 * 4 tiles * 16 bytes each, or 3 * 4 tiles * 16 bytes per tile) + 1 = 1 pose + 3 = 3 poses, possibly 6 immediately after + $C0 or $40 + fourth byte is the rom bank + + so a quick estimation is that, if it has 3, and there's no other pointer that points to the one after the 3rd & next 3, then assume those next 3 are the 4th, 5th and 6th + """ + rom = extract_maps.rom + ptable_address = 0x17b27 #5:7b27 + ptable_pointers = [] + ptable_sheet_data = {} + + #load up pointers please + for sprite_id in sprite_constants.keys(): + pointer_offset = 0x17b27 + ((sprite_id -1) * 4) + pointer_byte1 = ord(rom[pointer_offset]) + pointer_byte2 = ord(rom[pointer_offset+1]) + partial_pointer = (pointer_byte1 + (pointer_byte2 << 8)) + bank = ord(rom[pointer_offset+3]) + pointer = extract_maps.calculate_pointer(partial_pointer, bank) + ptable_pointers.append(pointer) + + #72 sprite pointers, we're not using id=$32 + for sprite_id in sprite_constants.keys(): + sprite_name = sprite_constants[sprite_id] + + #some basic information about this sprite first + data_entry = {"sprite_id": sprite_id, "sprite_name": sprite_name} + + #calculate where it is in the 0x17b27 pointer table + pointer_offset = 0x17b27 + ((sprite_id -1) * 4) + data_entry["sprite_ptr_table_entry_address"] = pointer_offset + + #actual sprite pointer + pointer_byte1 = ord(rom[pointer_offset]) + pointer_byte2 = ord(rom[pointer_offset+1]) + partial_pointer = (pointer_byte1 + (pointer_byte2 << 8)) + bank = ord(rom[pointer_offset+3]) + pointer = extract_maps.calculate_pointer(partial_pointer, bank) + data_entry["pointer"] = pointer + data_entry["bank"] = bank + + byte_count = ord(rom[pointer_offset+2]) + data_entry["byte_count"] = byte_count + + has_more_text = "" + data_entry["poses"] = 1 + if byte_count == 0xc0: #has at least 3 poses + setter1, setter2, setter3 = False, False, False + data_entry["poses"] = 3 + #let's check if there's possibly more + if not ((byte_count + pointer) in ptable_pointers): #yep, probably (#4) + data_entry["poses"] += 1 + data_entry["byte_count"] += 64 + setter1 = True + if setter1 and not ((byte_count + pointer + 64) in ptable_pointers): #has another (#5) + data_entry["poses"] += 1 + data_entry["byte_count"] += 64 + setter2 = True + if setter2 and not ((byte_count + pointer + 64 + 64) in ptable_pointers): #has a #6 + data_entry["poses"] += 1 + data_entry["byte_count"] += 64 + setter3 = True + + print ("$%.2x " % (sprite_id)) + sprite_name + " has $%.2x bytes" % (byte_count) + " pointing to 0x%.x" % (pointer) + " bank is $%.2x" % (bank) + " with pose_count=" + str(data_entry["poses"]) + + ptable_sheet_data[sprite_id] = data_entry + return ptable_sheet_data + +def pretty_print_sheet_incbins(ptable_sheet_data): + """make things look less awful""" + output = "" + used_addresses = [] + + for sheet_id in ptable_sheet_data: + sheet_data = ptable_sheet_data[sheet_id] + name = sheet_data["sprite_name"].split("SPRITE_")[1].lower().title() + clean_name = name.replace("_", "") + address = sheet_data["pointer"] + byte_count = sheet_data["byte_count"] + + #if not (0x10000 <= address <= 0x12e7f): continue #skip + #if not (0x14180 <= address <= 0x17840): continue #skip + if address in used_addresses: continue #skip + used_addresses.append(address) + + output += clean_name + "Sprite: ; 0x%.x" % (address) + "\n" + #output += spacing + "INCBIN \"baserom.gbc\",$%.x,$%.x - $%.x" % (address, address + byte_count, address) + "\n" + output += spacing + "INCBIN \"gfx/sprites/" + name.lower() + ".2bpp\" ; was $%.x" % (address) + "\n" + + filename = "../gfx/sprites/" + name.lower() + ".2bpp" + #fh = open(filename, "w") + #fh.write(extract_maps.rom[address : address + byte_count]) + #fh.close() + + return output + +def pretty_print_sheet_data(ptable_sheet_data): + """make the pointer table not suck so much""" + output = "SpriteSheetPointerTable: ; 0x17b27\n" + used_addresses = [] + + for sheet_id in ptable_sheet_data: + sheet_data = ptable_sheet_data[sheet_id] + address = sheet_data["pointer"] + checker = False + for x in used_addresses: + if not checker and x[0] == address: + checker = True + clean_name = x[1] + + if not checker: + name = sheet_data["sprite_name"].split("SPRITE_")[1].lower().title() + clean_name = name.replace("_", "") + clean_name += "Sprite" + + byte_count = sheet_data["byte_count"] + if byte_count > 0x40: + byte_count = 0xc0 + + output += "\n\t; " + sprite_constants[sheet_data["sprite_id"]] + "\n" + output += spacing + "dw " + clean_name + "\n" + output += spacing + "db $%.2x ; byte count\n" % (byte_count) + output += spacing + "db BANK(" + clean_name + ")\n" + + used_addresses.append((address, clean_name)) + + output += "; 0x17c47" + return output + if __name__ == "__main__": + extract_maps.load_rom() + #extract_maps.load_map_pointers() + #extract_maps.read_all_map_headers() + + #sprite_namer() #load_icons() #print_appearances() - sprite_printer() - + #sprite_printer() + + ptable_sheet_data = parse_sprite_sheet_pointer_table() + print pretty_print_sheet_incbins(ptable_sheet_data) + print pretty_print_sheet_data(ptable_sheet_data) |