Example #1
0
def make_maps(args):
    """Compile the stated (or all) tilemaps into .tmap files suitable for
    inclusion within the compressed tilemap banks."""

    charmap = mainscript_text.parse_charmap(args.charmap)

    #We Are Number One but a python script compiles everything
    #YouTube: Our Cancer Has Cancer.
    for i, filename in enumerate(args.filenames):
        objname = os.path.join(args.output,
                               os.path.splitext(filename)[0] + ".tmap")

        with open(filename, "r") as csvfile:
            csvreader = csv.reader(csvfile)
            csv_data = []

            for row in csvreader:
                nrow = []
                for cell in row:
                    try:
                        nrow.append(int(cell, 10))
                    except ValueError:
                        pass

                csv_data.append(nrow)

            print("Compiling " + filename)

            with open(objname, "wb") as objfile:
                objfile.write(encode_tilemap(csv_data))
Example #2
0
def make_maps(args):
    """Compile the stated (or all) tilemaps into .tmap files suitable for
    inclusion within the compressed tilemap banks."""
    
    charmap = mainscript_text.parse_charmap(args.charmap)
    
    #We Are Number One but a python script compiles everything
    #YouTube: Our Cancer Has Cancer.
    for i, filename in enumerate(args.filenames):
        objname = os.path.join(args.output, os.path.splitext(filename)[0] + ".tmap")
        
        with open(filename, "r") as csvfile:
            csvreader = csv.reader(csvfile)
            csv_data = []
            
            for row in csvreader:
                nrow = []
                for cell in row:
                    try:
                        nrow.append(int(cell, 10))
                    except ValueError:
                        pass
                
                csv_data.append(nrow)

            print("Compiling " + filename)
            
            with open(objname, "wb") as objfile:
                objfile.write(encode_tilemap(csv_data))
def asm(args):
    """Generate the ASM for string tables.

    This operation needs to be performed once, plus 

    Generated ASM will be printed to console. This portion of the script is
    intended to be piped into a file."""

    charmap = mainscript_text.parse_charmap(args.charmap)
    tablenames = parse_tablenames(args.tablenames)
    
    for table in tablenames:
        print('SECTION "' + table["symbol"] + ' Section", ' + mainscript_text.format_sectionaddr_rom(mainscript_text.flat(table["basebank"], table["baseaddr"])))
        print(table["symbol"] + '::')
        print('\tINCBIN "' + os.path.join(args.output, table["objname"]).replace("\\", "/") + '"')
        print(table["symbol"] + '_END')
        print('')
Example #4
0
def asm(args):
    """Generate the ASM for string tables.

    This operation needs to be performed once, plus 

    Generated ASM will be printed to console. This portion of the script is
    intended to be piped into a file."""

    charmap = mainscript_text.parse_charmap(args.charmap)
    tablenames = parse_tablenames(args.tablenames)
    
    for table in tablenames:
        print('SECTION "' + table["symbol"] + ' Section", ' + mainscript_text.format_sectionaddr_rom(mainscript_text.flat(table["basebank"], table["baseaddr"])))
        print(table["symbol"] + '::')
        print('\tINCBIN "' + os.path.join(args.output, table["objname"]).replace("\\", "/") + '"')
        print(table["symbol"] + '_END')
        print('')
Example #5
0
def asm(args):
    """Generate an ASM file for the metatables and tables present within the
    compressed tilemap system.
    
    This process needs to be run at least once, to convert the compressed
    tilemap names into imports that the assembler and linker can use. Changes
    to that file can be mirrored into the ASM by re-running this command, or
    manually doing so."""

    charmap = mainscript_text.parse_charmap(args.charmap)
    datas, datas_index, banks, bank_index = parse_mapnames(args.mapnames)

    with open(args.rom, 'rb') as rom:
        #Extract the table so we know what order to reference data.
        metatable = extract_metatable(rom, args.metatable_length,
                                      args.metatable_loc)
        metatable_attribs = extract_metatable(rom, args.metatable_length,
                                              args.metatable_loc_attribs)

        bank_tables = {"tilemap": [], "attrib": []}
        bank_datas = {"tilemap": [], "attrib": []}

        for i, bank in enumerate(metatable):
            this_bank_data, this_bank_table = decompress_bank(
                rom, 0x4000 * bank)
            bank_tables["tilemap"].append(this_bank_table)
            bank_datas["tilemap"].append(this_bank_data)

        for i, bank in enumerate(metatable_attribs):
            this_bank_data, this_bank_table = decompress_bank(
                rom, 0x4000 * bank)
            bank_tables["attrib"].append(this_bank_table)
            bank_datas["attrib"].append(this_bank_data)

        #Generate ASM for the metatables
        for category_name, category_index in list(datas_index.items()):
            if category_name == "attrib":
                print('SECTION "' + category_name + ' Section", ' +
                      mainscript_text.format_sectionaddr_rom(
                          args.metatable_loc_attribs))
                print('RLEAttribmapBanks::')
            elif category_name == "tilemap":
                print(
                    'SECTION "' + category_name + ' Section", ' +
                    mainscript_text.format_sectionaddr_rom(args.metatable_loc))
                print('RLETilemapBanks::')

            for bank_id, bank_table_index in list(category_index.items()):
                bank = banks[bank_index[category_name][bank_id]]
                print('\tdb BANK(' + bank["symbol"] + ')')

            print('')

        print('')

        #Generate ASM for each individual table.
        for category_name, category_index in list(datas_index.items()):
            for bank_id, _ in list(category_index.items()):
                bank = banks[bank_index[category_name][bank_id]]

                rom.seek(bank["flataddr"])

                print('SECTION "' + category_name +
                      ' Bank {0}'.format(bank_id) + '", ' +
                      mainscript_text.format_sectionaddr_rom(bank["flataddr"]))
                print(bank["symbol"] + '::')

                #Print out the table in the order we extracted it from baserom
                for table_index in bank_tables[category_name][bank_id]:
                    #Detect if a table pointer refers to the end of the table
                    is_junk = False

                    if table_index >= len(datas_index[category_name][bank_id]):
                        data_meta = datas[datas_index[category_name][bank_id][
                            table_index - 1]]
                        print('\tdw ' + data_meta["symbol"] + "_END")
                    else:
                        data_meta = datas[datas_index[category_name][bank_id]
                                          [table_index]]
                        print('\tdw ' + data_meta["symbol"])

                print('')

                #Print out all the data blocks in the table.
                for tmap_id, _ in enumerate(
                        bank_datas[category_name][bank_id]):
                    #Prevent spitting out nonexistent data here
                    if tmap_id >= len(datas_index[category_name][bank_id]):
                        continue

                    data_meta = datas[datas_index[category_name][bank_id]
                                      [tmap_id]]

                    print(data_meta["symbol"] + '::')
                    print('\tincbin "' + os.path.join(
                        args.output, data_meta["objname"]).replace("\\", "/") +
                          '"')
                    print(data_meta["symbol"] + '_END')
                    print('')

            print('')
def make_tbl(args):
    charmap = mainscript_text.parse_charmap(args.charmap)
    tablenames = parse_tablenames(args.tablenames)
    
    for table in tablenames:
        #Indexes are compiled in a second pass
        if table["format"] == "index":
            continue
        
        #If filenames are specified, only export banks that are mentioned there
        if len(args.filenames) > 0 and table["objname"] not in args.filenames:
            continue
        
        print("Compiling " + table["filename"])
        
        #Open and parse the data
        with open(os.path.join(args.input, table["filename"]), "r", encoding="utf-8") as csvfile:
            csvreader = csv.reader(csvfile)
            headers = None
            rows = []
            
            for row in csvreader:
                if headers is None:
                    headers = row
                else:
                    rows.append(row)

        #Determine what column we want
        index_col = headers.index("#")
        try:
            str_col = headers.index(args.language)
        except ValueError:
            str_col = index_col
        
        #Pack our strings
        packed_strings = []
        
        baseaddr = table["baseaddr"]
        
        entries = []
        reverse_entries = {}
        
        for i, row in enumerate(rows):
            if str_col >= len(row):
                print("WARNING: ROW {} IS MISSING IT'S TEXT!!!".format(i))
                packed_strings.append(b"")
                continue
            
            packed = mainscript_text.pack_text(row[str_col], specials, charmap[0], None, args.window_width, 1, memory_widths, True)
            
            if "stride" in table:
                if len(packed) > table["stride"]:
                    print("WARNING: Row {} is too long for the current string table stride of {} in table {}.".format(i, table["stride"], table["filename"]))
                    packed = packed[0:table["stride"]]
                else:
                    #Pad the string out with E0s.
                    packed = packed + bytes([0xE0] * (table["stride"] - len(packed)))
            elif b"\xe0" not in packed:
                #Any data beyond an E0 is understood to be trash bytes; thus,
                #it does not recieve the implicit terminator.
                packed = packed + b"\xe0"
            
            packed_strings.append(packed)
            
            reverse_entries[mainscript_text.flat(table["basebank"], baseaddr)] = len(entries)
            entries.append(mainscript_text.flat(table["basebank"], baseaddr))
            
            baseaddr += len(packed)
        
        #Save these for later
        table["entries"] = entries
        table["reverse_entries"] = reverse_entries
        
        #Write the data out to the object files. We're done here!
        if not os.path.exists(os.path.dirname(os.path.join(args.output, table["objname"]))):
            os.makedirs(os.path.dirname(os.path.join(args.output, table["objname"])))
        
        with open(os.path.join(args.output, table["objname"]), "wb") as objfile:
            for line in packed_strings:
                objfile.write(line)
    
    for table in tablenames:
        #Now's the time to compile indexes
        if table["format"] != "index":
            continue
        
        #If filenames are specified, only export banks that are mentioned there
        if len(args.filenames) > 0 and table["objname"] not in args.filenames:
            continue
        
        print("Compiling " + table["filename"])
        
        foreign_ptrs = tablenames[table["foreign_id"]]["entries"]
        packed_strings = []
        
        entries = []
        reverse_entries = {}
        
        #Open and parse the data
        with open(os.path.join(args.input, table["filename"]), "r", encoding="utf-8") as csvfile:
            csvreader = csv.reader(csvfile)
            
            for row in csvreader:
                for cell in row:
                    packed_strings.append(mainscript_text.PTR.pack(foreign_ptrs[int(cell, 10) - 1] % 0x4000 + 0x4000))
        
        #Write the data out to the object files. We're done here!
        with open(os.path.join(args.output, table["objname"]), "wb") as objfile:
            for line in packed_strings:
                objfile.write(line)
def extract(args):
    charmap = mainscript_text.parse_charmap(args.charmap)
    tablenames = parse_tablenames(args.tablenames)

    with open(args.rom, 'rb') as rom:
        #Extract a list of pointers each index is expecting
        #This is used for trash byte detection later
        for table in tablenames:
            if table["format"] != "index":
                continue
            
            try:
                all_ptrs = tablenames[table["foreign_id"]]["expected_ptrs"]
            except KeyError:
                all_ptrs = []
            
            rom.seek(mainscript_text.flat(table["basebank"], table["baseaddr"]))
            
            for i in range(table["count"]):
                ptr = mainscript_text.PTR.unpack(rom.read(2))[0]
                addr = mainscript_text.flat(table["basebank"], ptr)
                
                if addr not in all_ptrs:
                    all_ptrs.append(addr)
            
            all_ptrs.sort()
            tablenames[table["foreign_id"]]["expected_ptrs"] = all_ptrs
        
        for table in tablenames:
            #Indexes are extracted in a second pass
            if table["format"] == "index":
                continue
            
            entries = []
            reverse_entries = {}
            
            try:
                expected_ptrs = table["expected_ptrs"]
            except KeyError:
                expected_ptrs = None

            csvdir = os.path.join(args.input, table["basedir"])
            csvpath = os.path.join(args.input, table["filename"])
            mainscript_text.install_path(csvdir)

            with open(csvpath, "w+", encoding="utf-8") as table_csvfile:
                csvwriter = csv.writer(table_csvfile)
                csvwriter.writerow(["#", args.language])

                if table["format"] == "table":
                    for i in range(table["count"]):
                        rom.seek(mainscript_text.flat(table["basebank"], table["baseaddr"] + i * table["stride"]))
                        reverse_entries[rom.tell()] = len(entries)
                        entries.append(rom.tell())
                        data = extract_string(rom, charmap, table["stride"], expected_ptrs).encode("utf-8")
                        idx = "{0}".format(i + 1).encode("utf-8")
                        csvwriter.writerow([idx, data])
                elif table["format"] == "block":
                    rom.seek(mainscript_text.flat(table["basebank"], table["baseaddr"]))
                    for i in range(table["count"]):
                        reverse_entries[rom.tell()] = len(entries)
                        entries.append(rom.tell())
                        data = extract_string(rom, charmap, None, expected_ptrs).encode("utf-8")
                        idx = "{0}".format(i + 1).encode("utf-8")
                        csvwriter.writerow([idx, data])

            #Save these for later
            table["entries"] = entries
            table["reverse_entries"] = reverse_entries

        #OK, now we can extract the indexes
        for table in tablenames:
            if table["format"] != "index":
                continue

            foreign_ptrs = tablenames[table["foreign_id"]]["reverse_entries"]
            rom.seek(mainscript_text.flat(table["basebank"], table["baseaddr"]))
            
            csvdir = os.path.join(args.input, table["basedir"])
            csvpath = os.path.join(args.input, table["filename"])
            mainscript_text.install_path(csvdir)
            
            with open(csvpath, "w+", encoding="utf-8") as table_csvfile:
                csvwriter = csv.writer(table_csvfile)
                
                pretty_row_length = math.ceil(math.sqrt(table["count"]))
                cur_row = []

                for i in range(table["count"]):
                    ptr = mainscript_text.PTR.unpack(rom.read(2))[0]
                    addr = mainscript_text.flat(table["basebank"], ptr)
                    
                    cur_row.append("{0}".format(foreign_ptrs[addr] + 1).encode("utf-8"))
                    if len(cur_row) >= pretty_row_length:
                        csvwriter.writerow(cur_row)
                        cur_row = []

                if len(cur_row) > 0:
                    csvwriter.writerow(cur_row)
Example #8
0
def make_tbl(args):
    charmap = mainscript_text.parse_charmap(args.charmap)
    tablenames = parse_tablenames(args.tablenames)
    
    for table in tablenames:
        #Indexes are compiled in a second pass
        if table["format"] == "index":
            continue
        
        #If filenames are specified, only export banks that are mentioned there
        if len(args.filenames) > 0 and table["objname"] not in args.filenames:
            continue
        
        print("Compiling " + table["filename"])
        
        #Open and parse the data
        with open(os.path.join(args.input, table["filename"]), "r", encoding="utf-8") as csvfile:
            csvreader = csv.reader(csvfile)
            headers = None
            rows = []
            
            for row in csvreader:
                if headers is None:
                    headers = row
                else:
                    rows.append(row)

        #Determine what column we want
        index_col = headers.index("#")
        try:
            str_col = headers.index(args.language)
        except ValueError:
            str_col = index_col
        
        #Pack our strings
        packed_strings = []
        
        baseaddr = table["baseaddr"]
        
        entries = []
        reverse_entries = {}
        
        for i, row in enumerate(rows):
            if str_col >= len(row):
                print("WARNING: ROW {} IS MISSING IT'S TEXT!!!".format(i))
                packed_strings.append(b"")
                continue
            
            packed = mainscript_text.pack_text(row[str_col], specials, charmap[0], None, args.window_width, 1, memory_widths, True)
            
            if "stride" in table:
                if len(packed) > table["stride"]:
                    print("WARNING: Row {} is too long for the current string table stride of {} in table {}.".format(i, table["stride"], table["filename"]))
                    packed = packed[0:table["stride"]]
                else:
                    #Pad the string out with E0s.
                    packed = packed + bytes([0xE0] * (table["stride"] - len(packed)))
            elif b"\xe0" not in packed:
                #Any data beyond an E0 is understood to be trash bytes; thus,
                #it does not recieve the implicit terminator.
                packed = packed + b"\xe0"
            
            packed_strings.append(packed)
            
            reverse_entries[mainscript_text.flat(table["basebank"], baseaddr)] = len(entries)
            entries.append(mainscript_text.flat(table["basebank"], baseaddr))
            
            baseaddr += len(packed)
        
        #Save these for later
        table["entries"] = entries
        table["reverse_entries"] = reverse_entries
        
        #Write the data out to the object files. We're done here!
        if not os.path.exists(os.path.dirname(os.path.join(args.output, table["objname"]))):
            try:
                os.makedirs(os.path.dirname(os.path.join(args.output, table["objname"])))
            except FileExistsError:
                pass
        
        with open(os.path.join(args.output, table["objname"]), "wb") as objfile:
            for line in packed_strings:
                objfile.write(line)
    
    for table in tablenames:
        #Now's the time to compile indexes
        if table["format"] != "index":
            continue
        
        #If filenames are specified, only export banks that are mentioned there
        if len(args.filenames) > 0 and table["objname"] not in args.filenames:
            continue
        
        print("Compiling " + table["filename"])
        
        foreign_ptrs = tablenames[table["foreign_id"]]["entries"]
        packed_strings = []
        
        entries = []
        reverse_entries = {}
        
        #Open and parse the data
        with open(os.path.join(args.input, table["filename"]), "r", encoding="utf-8") as csvfile:
            csvreader = csv.reader(csvfile)
            
            for row in csvreader:
                for cell in row:
                    packed_strings.append(mainscript_text.PTR.pack(foreign_ptrs[int(cell, 10) - 1] % 0x4000 + 0x4000))
        
        #Write the data out to the object files. We're done here!
        with open(os.path.join(args.output, table["objname"]), "wb") as objfile:
            for line in packed_strings:
                objfile.write(line)
Example #9
0
def extract(args):
    charmap = mainscript_text.parse_charmap(args.charmap)
    tablenames = parse_tablenames(args.tablenames)

    with open(args.rom, 'rb') as rom:
        #Extract a list of pointers each index is expecting
        #This is used for trash byte detection later
        for table in tablenames:
            if table["format"] != "index":
                continue
            
            try:
                all_ptrs = tablenames[table["foreign_id"]]["expected_ptrs"]
            except KeyError:
                all_ptrs = []
            
            rom.seek(mainscript_text.flat(table["basebank"], table["baseaddr"]))
            
            for i in range(table["count"]):
                ptr = mainscript_text.PTR.unpack(rom.read(2))[0]
                addr = mainscript_text.flat(table["basebank"], ptr)
                
                if addr not in all_ptrs:
                    all_ptrs.append(addr)
            
            all_ptrs.sort()
            tablenames[table["foreign_id"]]["expected_ptrs"] = all_ptrs
        
        for table in tablenames:
            #Indexes are extracted in a second pass
            if table["format"] == "index":
                continue
            
            entries = []
            reverse_entries = {}
            
            try:
                expected_ptrs = table["expected_ptrs"]
            except KeyError:
                expected_ptrs = None

            csvdir = os.path.join(args.input, table["basedir"])
            csvpath = os.path.join(args.input, table["filename"])
            mainscript_text.install_path(csvdir)

            with open(csvpath, "w+", encoding="utf-8") as table_csvfile:
                csvwriter = csv.writer(table_csvfile)
                csvwriter.writerow(["#", args.language])

                if table["format"] == "table":
                    for i in range(table["count"]):
                        rom.seek(mainscript_text.flat(table["basebank"], table["baseaddr"] + i * table["stride"]))
                        reverse_entries[rom.tell()] = len(entries)
                        entries.append(rom.tell())
                        data = extract_string(rom, charmap, table["stride"], expected_ptrs).encode("utf-8")
                        idx = "{0}".format(i + 1).encode("utf-8")
                        csvwriter.writerow([idx, data])
                elif table["format"] == "block":
                    rom.seek(mainscript_text.flat(table["basebank"], table["baseaddr"]))
                    for i in range(table["count"]):
                        reverse_entries[rom.tell()] = len(entries)
                        entries.append(rom.tell())
                        data = extract_string(rom, charmap, None, expected_ptrs).encode("utf-8")
                        idx = "{0}".format(i + 1).encode("utf-8")
                        csvwriter.writerow([idx, data])

            #Save these for later
            table["entries"] = entries
            table["reverse_entries"] = reverse_entries

        #OK, now we can extract the indexes
        for table in tablenames:
            if table["format"] != "index":
                continue

            foreign_ptrs = tablenames[table["foreign_id"]]["reverse_entries"]
            rom.seek(mainscript_text.flat(table["basebank"], table["baseaddr"]))
            
            csvdir = os.path.join(args.input, table["basedir"])
            csvpath = os.path.join(args.input, table["filename"])
            mainscript_text.install_path(csvdir)
            
            with open(csvpath, "w+", encoding="utf-8") as table_csvfile:
                csvwriter = csv.writer(table_csvfile)
                
                pretty_row_length = math.ceil(math.sqrt(table["count"]))
                cur_row = []

                for i in range(table["count"]):
                    ptr = mainscript_text.PTR.unpack(rom.read(2))[0]
                    addr = mainscript_text.flat(table["basebank"], ptr)
                    
                    cur_row.append("{0}".format(foreign_ptrs[addr] + 1).encode("utf-8"))
                    if len(cur_row) >= pretty_row_length:
                        csvwriter.writerow(cur_row)
                        cur_row = []

                if len(cur_row) > 0:
                    csvwriter.writerow(cur_row)
Example #10
0
def asm(args):
    """Generate an ASM file for the metatables and tables present within the
    compressed tilemap system.
    
    This process needs to be run at least once, to convert the compressed
    tilemap names into imports that the assembler and linker can use. Changes
    to that file can be mirrored into the ASM by re-running this command, or
    manually doing so."""

    charmap = mainscript_text.parse_charmap(args.charmap)
    datas, datas_index, banks, bank_index = parse_mapnames(args.mapnames)
    
    with open(args.rom, 'rb') as rom:
        #Extract the table so we know what order to reference data.
        metatable = extract_metatable(rom, args.metatable_length, args.metatable_loc)
        metatable_attribs = extract_metatable(rom, args.metatable_length, args.metatable_loc_attribs)

        bank_tables = {"tilemap": [], "attrib": []}
        bank_datas = {"tilemap": [], "attrib": []}

        for i, bank in enumerate(metatable):
            this_bank_data, this_bank_table = decompress_bank(rom, 0x4000 * bank)
            bank_tables["tilemap"].append(this_bank_table)
            bank_datas["tilemap"].append(this_bank_data)

        for i, bank in enumerate(metatable_attribs):
            this_bank_data, this_bank_table = decompress_bank(rom, 0x4000 * bank)
            bank_tables["attrib"].append(this_bank_table)
            bank_datas["attrib"].append(this_bank_data)

        #Generate ASM for the metatables
        for category_name, category_index in list(datas_index.items()):
            if category_name == "attrib":
                print('SECTION "' + category_name + ' Section", ' + mainscript_text.format_sectionaddr_rom(args.metatable_loc_attribs))
                print('RLEAttribmapBanks::')
            elif category_name == "tilemap":
                print('SECTION "' + category_name + ' Section", ' + mainscript_text.format_sectionaddr_rom(args.metatable_loc))
                print('RLETilemapBanks::')

            for bank_id, bank_table_index in list(category_index.items()):
                bank = banks[bank_index[category_name][bank_id]]
                print('\tdb BANK(' + bank["symbol"] + ')')

            print('')

        print('')
        
        #Generate ASM for each individual table.
        for category_name, category_index in list(datas_index.items()):
            for bank_id, _ in list(category_index.items()):
                bank = banks[bank_index[category_name][bank_id]]
                
                rom.seek(bank["flataddr"])
                
                print('SECTION "' + category_name + ' Bank {0}'.format(bank_id) + '", ' + mainscript_text.format_sectionaddr_rom(bank["flataddr"]))
                print(bank["symbol"] + '::')
                
                #Print out the table in the order we extracted it from baserom
                for table_index in bank_tables[category_name][bank_id]:
                    #Detect if a table pointer refers to the end of the table
                    is_junk = False
                    
                    if table_index >= len(datas_index[category_name][bank_id]):
                        data_meta = datas[datas_index[category_name][bank_id][table_index - 1]]
                        print('\tdw ' + data_meta["symbol"] + "_END")
                    else:
                        data_meta = datas[datas_index[category_name][bank_id][table_index]]
                        print('\tdw ' + data_meta["symbol"])
                
                print('')
                
                #Print out all the data blocks in the table.
                for tmap_id, _ in enumerate(bank_datas[category_name][bank_id]):
                    #Prevent spitting out nonexistent data here
                    if tmap_id >= len(datas_index[category_name][bank_id]):
                        continue
                    
                    data_meta = datas[datas_index[category_name][bank_id][tmap_id]]
                    
                    print(data_meta["symbol"] + '::')
                    print('\tincbin "' + os.path.join(args.output, data_meta["objname"]).replace("\\", "/") + '"')
                    print(data_meta["symbol"] + '_END')
                    print('')

            print('')