entries = OrderedDict() with open(f"./text/ptrlists/{l}.txt", "w", encoding="utf-8") as output: output.write(str(list_map[l][1:]) + "\n") count_written = False for version_suffix in roms: with open( f'./game/src/version/{version_suffix}/ptrlist_data.asm', 'w') as datafile_version: datafile_version.write( 'INCLUDE "game/src/version/ptrlist_data.asm"\n') with open(roms[version_suffix], "rb") as rom: rom.seek(addr) # Make the (probably) safe assumption that the end of the table is the pointer # before the first pointer end = utils.rom2realaddr((bank, utils.read_short(rom) - 2)) # Seeing the same pointer twice is an # indicator that we've hit the last actual value in the table rom.seek(end) dummy_pointer = utils.read_short(rom) rom.seek(-4, 1) if utils.read_short(rom) != dummy_pointer: dummy_pointer = -1 rom.seek(addr) ptrs = [] if not count_written: output.write(f"{((end - addr) // 2) + 1}\n") output.write(f"{dummy_pointer}\n")
sys.path.append(os.path.join(os.path.dirname(__file__), 'common')) from common import utils, tilesets nametable = {} namefile = None if os.path.exists("scripts/res/tileset_names.tbl"): nametable = utils.read_table("scripts/res/tileset_names.tbl") else: namefile = open("scripts/res/tileset_names.tbl","w") tiletable = 0x10f0 count = 51 with open("baserom_kabuto.gb", "rb") as rom, open("game/src/gfx/tileset_table.asm", "w") as output: rom.seek(tiletable) ptrs = [utils.read_short(rom) for i in range(0, count)] data = {} for ptr in ptrs: rom.seek(ptr) # Bank 0, no need to convert addresses # (Bank, Pointer, VRAM Offset, Name) if namefile: # We assume the table file not existing is fine nametable[ptr] = "{:04X}".format(ptr) namefile.write("{:04X}={}\n".format(ptr, nametable[ptr])) data[ptr] = (utils.read_byte(rom), utils.read_short(rom), utils.read_short(rom), nametable[ptr]) output.write('INCLUDE "game/src/common/macros.asm"\n\n') output.write('SECTION "Tileset Table", ROM0[${:04X}]\n'.format(tiletable)) output.write('TilesetTable::\n') for i in ptrs: output.write(" dw TilesetInfo{}\n".format(data[i][3])) output.write("TilesetTableEnd::\n"); with open("game/src/gfx/tileset_files.asm", "w") as outputf:
with open(data_file, 'r') as df, open(version_data_file, 'r') as vdf: src = df.read() + vdf.read() for line in src.splitlines(): if line.startswith('SECTION') and f'"Pointer List - {key}"' in line: o = line.lstrip('SECTION ').replace(' ', '').replace('\n','').replace('\r\n','').replace('"','').split(',') #Name ROMX[$OFFSET] BANK[$BANK] bank = int(o[2].replace('BANK','').replace('[','').replace(']','').replace('$','0x'), 16) ptr_table_offset = int(o[1].replace('ROMX','').replace('[','').replace(']','').replace('$','0x'), 16) break else: raise Exception(f"Could not find {key} section in {data_file}") with open(input_file, 'rb') as in_f: is_general = utils.read_byte(in_f) total = utils.read_short(in_f) dummy = utils.read_short(in_f) count = utils.read_short(in_f) # Account for the 'empty' elements empty = bytearray() if total == count else pack("<H", dummy) * (total - count) offsets = [(utils.read_short(in_f), utils.read_short(in_f)) for i in range(0, count)] init_text_offsets = list(map(lambda x: pack("<H", x[0] + (2 * (len(offsets))) + ptr_table_offset + len(empty)), offsets)) # Don't really need to bother with using the length information in master with open(output_path, 'wb') as out_f: if len(offsets): init_text_offsets[0] = bytearray(init_text_offsets[0]) b = reduce( (lambda x, y: x + bytearray(y)), init_text_offsets) out_f.write(b) out_f.write(empty)
'').replace('[', '').replace(']', '').replace('$', '0x'), 16) ptr_table_offset = int( o[1].replace('ROMX', '').replace('[', '').replace(']', '').replace('$', '0x'), 16) break else: raise Exception(f"Could not find {key} section in {data_file}") with open(input_file, 'rb') as in_f: total = utils.read_short(in_f) dummy = utils.read_short(in_f) count = utils.read_short(in_f) # Account for the 'empty' elements empty = bytearray() if total == count else pack("<H", dummy) * (total - count) offsets = [(utils.read_short(in_f), utils.read_short(in_f)) for i in range(0, count)] init_text_offsets = list( map( lambda x: pack( "<H", x[0] + (2 * (len(offsets))) + ptr_table_offset + len(empty)), offsets)
rom_info[2], int) else utils.rom2realaddr(rom_info[2]) bank = utils.real2romaddr(text_ptr_table)[0] entry_count = rom_info[3] with open(filename, 'rb') as rom, open(f"./text/credits/Credits.csv", "w", encoding="utf-8") as fp: writer = csv.writer(fp, lineterminator='\n', delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) writer.writerow(["Pointer", "VRAMOffset", "Original", "Translated"]) rom.seek(text_ptr_table) pointers = [(rom.tell(), utils.read_short(rom)) for i in range(0, entry_count)] class SpecialCharacter(): def __init__(self, symbol, default=0, bts=1, end=False, always_print=False): self.symbol = symbol self.default = default self.bts = bts self.end = end self.always_print = always_print
tileset_metadata = {} common_tilesets = [] unique_pointer_and_tilesets = [] unique_tilesets = [] unique_pointers = [] missing_pointers = [] tileset_alias = {} for version in roms: ver = version[1] realptr_key_map[ver] = OrderedDict() realptr_key_map[ver][terminator_key] = terminator tileset_metadata[ver] = OrderedDict() with open(version[0], "rb") as rom: rom.seek(tiletable) ptrs = [(rom.tell(), utils.read_short(rom)) for i in range(0, count)] rom.seek(utils.rom2realaddr(infotable)) info = [(utils.read_byte(rom), utils.read_short(rom), utils.read_byte(rom)) for i in range(0, count)] i = 0 while i < count: key = ptrs[i][0] ptr = ptrs[i][1] bank = info[i][0] vram = info[i][1] vbank = info[i][2] realptr = utils.rom2realaddr((bank, ptr)) if realptr != terminator_key and realptr not in realptr_key_map[ ver]:
tilesets.get_tileset("dakuten", override_offset=0x0) ]) with open("baserom_parts_collection.gb", "rb") as rom: for l in list_map: addr, term, n, prefixlen = list_map[l] if isinstance(addr, tuple): bank = addr[0] addr = utils.rom2realaddr(addr) else: bank = utils.real2romaddr(addr)[0] rom.seek(addr) with open('text/ptrlists/{}.txt'.format(l), 'w', encoding="utf-8") as output: output.write(f"({term},{prefixlen})\n") ptrs = [utils.read_short(rom) for i in range(0, n)] for ptr in ptrs: rom.seek(utils.rom2realaddr((bank, ptr))) prefix = [utils.read_byte(rom) for i in range(0, prefixlen)] # If the first 2 are 00, there's no data if prefixlen > 0 and prefix[0] == 0x0: b = [] else: b = list(iter(partial(utils.read_byte, rom), term)) # In the case of an empty string, print out at least the terminator # Doing this allows the ptrlist2asm script to properly identify when to actually skip the terminator # (Medarotters with a null prefix shouldn't have a terminator, but empty part descriptions should) if len(b) == 0: b = [term] p = "".join(utils.bin2txt(bytearray(prefix), {})) t = "".join(utils.bin2txt(bytearray(b), tileset))
'\n', '').replace('\r\n', '').replace('"', '').split(',') #Name ROMX[$OFFSET] BANK[$BANK] bank = int( o[2].replace('BANK', '').replace('[', '').replace(']', '').replace( '$', '0x'), 16) ptr_table_offset = int( o[1].replace('ROMX', '').replace('[', '').replace(']', '').replace( '$', '0x'), 16) break else: raise Exception(f"Could not find {key} section in {data_file}") with open(input_file, 'rb') as in_f: count = utils.read_short(in_f) offsets = [(utils.read_short(in_f), utils.read_short(in_f)) for i in range(0, count)] init_text_offsets = list( map( lambda x: pack("<H", x[0] + (2 * (len(offsets))) + ptr_table_offset), offsets) ) # Don't really need to bother with using the length information in master with open(output_path, 'wb') as out_f: init_text_offsets[0] = bytearray(init_text_offsets[0]) b = reduce((lambda x, y: x + bytearray(y)), init_text_offsets) out_f.write(b) out_f.write( in_f.read() ) # The rest of the file is the actual text, so just read it entirely
text_shifted_pointers = {} text_unused = {} for info in rom_info: filename = info[0] suffix = info[1] txt_bank_ptr = info[2] txt_tbl_ptr = info[3] entry_count = info[4] with open(filename, 'rb') as rom: rom.seek(txt_bank_ptr) banks = [utils.read_byte(rom) for i in range(0,entry_count)] rom.seek(txt_tbl_ptr) text_ptrs = list(zip(banks, [utils.read_short(rom) for i in range(0, entry_count)])) text_table_ptrs[suffix] = (txt_bank_ptr, txt_tbl_ptr, text_ptrs) class SpecialCharacter(): def __init__(self, symbol, default=0, bts=1, end=False, names=None, always_print=False, print_control_code=True, parser=None): self.symbol = symbol self.default = default self.bts = bts self.end = end self.names = names self.always_print = always_print if not parser: parser = { 0: lambda x: None, 1: utils.read_byte, 2: utils.read_short }[self.bts] self.print_control_code = print_control_code self.parser = parser
text_unused = {} for info in rom_info: filename = info[0] suffix = info[1] txt_bank_ptr = info[2] txt_tbl_ptr = info[3] entry_count = info[4] with open(filename, 'rb') as rom: rom.seek(txt_bank_ptr) banks = [utils.read_byte(rom) for i in range(0, entry_count)] rom.seek(txt_tbl_ptr) text_ptrs = list( zip(banks, [utils.read_short(rom) for i in range(0, entry_count)])) text_table_ptrs[suffix] = (txt_bank_ptr, txt_tbl_ptr, text_ptrs) class SpecialCharacter(): def __init__(self, symbol, default=0, bts=1, end=False, names=None, always_print=False, print_control_code=True, parser=None): self.symbol = symbol self.default = default
name_table[int(p, 16)] = n for info in rom_info: filename = info[0] suffix = info[1] txt_bank_ptr = info[2] txt_tbl_ptr = info[3] entry_count = info[4] with open(filename, 'rb') as rom: rom.seek(txt_bank_ptr) banks = [utils.read_byte(rom) for i in range(0, entry_count)] rom.seek(txt_tbl_ptr) text_ptrs = list( zip(banks, [utils.read_short(rom) for i in range(0, entry_count)])) with open("./game/src/data/text_tables.asm", "w") as f: f.write( f'INCLUDE "build/dialog/text_table_constants_{{GAMEVERSION}}.asm"\n\n' ) for i, entry in enumerate([t for t in text_ptrs if t[0] != 0]): f.write( f'SECTION "TextSection{i}", ROMX[${entry[1]:04x}], BANK[${entry[0]:02x}]\n' ) f.write(f'TextSection{i}:\n') f.write(f' INCBIN cTextSection{i}\n\n') f.write( f'SECTION "Dialog Text Tables", ROM0[${txt_bank_ptr:04x}]\n') f.write(f'TextTableBanks:: ; 0x{txt_bank_ptr:04x}\n')
# tilemap bank is 1e (0x78000) BANK_SIZE = 0x4000 BANK = 0x1e BASE = 0x4000 BASE_ADDR = utils.rom2realaddr((BANK, BASE)) MAX_ADDR = BASE_ADDR + BANK_SIZE - 1 tilemap_ptr = {} tilemap_bytes = {} tilemap_files = [] TERMINATOR = 0 with open("baserom_parts_collection.gb", "rb") as rom: rom.seek(BASE_ADDR) ptr = utils.read_short(rom) tilemap_ptr[0] = ptr end = utils.rom2realaddr((BANK, ptr)) i = 1 while rom.tell() < end: # The first tilemap is where the table should end tilemap_ptr[i] = utils.read_short(rom) i += 1 TERMINATOR = tilemap_ptr[ i - 1] # A bit of a hack, but the last pointer is effectively a 'null', even though there's a list entry pointing to it ptrfile = None ptrtable = {} tileset_file = None tileset_table = {}
nametable = utils.read_table(meta_tilemap_names_file, keystring=True) else: namefile = open(meta_tilemap_names_file, "w") default_version = roms[0] tilemap_tables = None try: with open(default_version[0], "rb") as rom: rom.seek(map_bank_table) tilemap_banks = [ utils.read_byte(rom) for i in range(0, map_table_count) ] rom.seek(map_addr_table) tilemap_addrs = [ utils.read_short(rom) for i in range(0, map_table_count) ] # The tilemap locations are in the same place in both versions tilemap_tables = list(zip(tilemap_banks, tilemap_addrs)) tilemap_data = {} # [version] -> [identifier] -> (realaddr, data) duplicate_map = {} # [version] -> [identifier] -> identity version_specific_ids = set() basename_map = OrderedDict() version_suffixes = [i[1] for i in roms] for versionidx, version in enumerate(roms): rom_filename = version[0] ver = version[1] tilemap_data[versionidx] = OrderedDict()