Exemple #1
0
	def get_binary_palettes(self):
		raw_palette_data = bytearray()
		colors_555 = common.convert_to_555(self.master_palette)

		# Mail and bunny palettes
		raw_palette_data.extend(itertools.chain.from_iterable([common.as_u16(c) for i in range(4) for c in colors_555[0x10*i+1:0x10*i+0x10]]))

		# Glove colors
		raw_palette_data.extend(itertools.chain.from_iterable([common.as_u16(colors_555[0x10*i+0x10]) for i in range(2)]))

		return raw_palette_data
Exemple #2
0
	def inject_into_ROM(self, rom):
		#should work for the combo rom, VT rando, and the (J) rom.  Not sure about the (U) rom...maybe?

		#the sheet needs to be placed directly into address $108000-$10F000
		for i,row in enumerate(itertools.chain(ascii_uppercase, ["AA","AB"])):  #over all 28 rows of the sheet
			for column in range(8):    #over all 8 columns
				image_name = f"{row}{column}"
				if image_name == "AB7":
					#AB7 is special, because the palette block sits there in the PNG, so this can't be actually used
					image_name = "null_block"
				raw_image_data = common.convert_to_4bpp(self.images[image_name], (0,0), (0,0,16,16), None)

				rom.bulk_write_to_snes_address(0x108000+0x400*i+0x40*column,raw_image_data[:0x40],0x40)
				rom.bulk_write_to_snes_address(0x108200+0x400*i+0x40*column,raw_image_data[0x40:],0x40)

		#the palettes need to be placed directly into address $1BD308-$1BD380, not including the transparency or gloves colors
		converted_palette = common.convert_to_555(self.master_palette)
		for i in range(4):
			rom.write_to_snes_address(0x1BD308+0x1E*i,converted_palette[0x10*i+1:0x10*i+0x10],0x0F*"2")
		#the glove colors are placed into $1BEDF5-$1BEDF8
		for i in range(2):
			rom.write_to_snes_address(0x1BEDF5+0x02*i,converted_palette[0x10+0x10*i],2)

		return rom
Exemple #3
0
    def inject_into_ROM(self, spiffy_dict, rom):
        #should work for the combo rom, VT rando
        #should work for the (J) & (U) ROMs but won't automatically include the extra code needed to manage gloves, etc

        #this'll check VT rando Tournament Flag
        tournament_flag = rom.read(0x180213, 2) == 1
        #this'll check combo Tournament Flag
        if rom.type() == "EXHIROM" and not tournament_flag:
            config = rom.read_from_snes_address(0x80FF52, 2)
            fieldvals = {}
            fieldvals["gamemode"] = ["singleworld", "multiworld"]
            fieldvals["z3logic"] = ["normal", "hard"]
            fieldvals["m3logic"] = ["normal", "hard"]
            field = {}
            field["race"] = ((config & (1 << 15)) >> 15) > 0  # 1 bit
            field["keysanity"] = ((config & (0b11 << 13)) >> 13) > 0  # 2 bits
            field["gamemode"] = ((config & (1 << 12)) >> 12)  # 1 bit
            field["z3logic"] = ((config & (0b11 << 10)) >> 10)  # 2 bits
            field["m3logic"] = ((config & (0b11 << 8)) >> 8)  # 2 bits
            field["version"] = {}
            field["version"]["major"] = (
                (config & (0b1111 << 4)) >> 4)  # 4 bits
            field["version"]["minor"] = (
                (config & (0b1111 << 0)) >> 0)  # 4 bits

            field["gamemode"] = fieldvals["gamemode"][field["gamemode"]]
            field["z3logic"] = fieldvals["z3logic"][field["z3logic"]]
            field["m3logic"] = fieldvals["m3logic"][field["m3logic"]]

            tournament_flag = field["race"]

        if not tournament_flag:
            #the sheet needs to be placed directly into address $108000-$10F000
            for i, row in enumerate(
                    itertools.chain(
                        ascii_uppercase,
                        ["AA", "AB"])):  #over all 28 rows of the sheet
                for column in range(8):  #over all 8 columns
                    image_name = f"{row}{column}"
                    if image_name == "AB7":
                        #AB7 is special, because the palette block sits there in the PNG, so this can't be actually used
                        image_name = "null_block"
                    raw_image_data = common.convert_to_4bpp(
                        self.images[image_name], (0, 0), (0, 0, 16, 16), None)

                    rom.bulk_write_to_snes_address(
                        0x108000 + 0x400 * i + 0x40 * column,
                        raw_image_data[:0x40], 0x40)
                    rom.bulk_write_to_snes_address(
                        0x108200 + 0x400 * i + 0x40 * column,
                        raw_image_data[0x40:], 0x40)

            #the palettes need to be placed directly into address $1BD308-$1BD380, not including the transparency or gloves colors
            converted_palette = common.convert_to_555(self.master_palette)
            for i in range(4):
                rom.write_to_snes_address(
                    0x1BD308 + 0x1E * i,
                    converted_palette[0x10 * i + 1:0x10 * i + 0x10],
                    0x0F * "2")
            #the glove colors are placed into $1BEDF5-$1BEDF8
            for i in range(2):
                rom.write_to_snes_address(0x1BEDF5 + 0x02 * i,
                                          converted_palette[0x10 + 0x10 * i],
                                          2)
            if (hex(rom.read_from_snes_address(0x238000, 2))
                    == "0x3702") and (hex(
                        rom.read_from_snes_address(0x23801E, 2)) == "0x3702"):
                # print("v32-compatible credits")
                contiguous = digits + ascii_uppercase + "'"
                letters = {
                    "hi": {
                        " ": "0x9F",
                        '.': "0xA0",
                        '/': "0xA2",
                        ':': "0xA3",
                        '_': "0xA6"
                    },
                    "lo": {
                        " ": "0x9F",
                        '.': "0xC0",
                        '/': "0xC2",
                        ':': "0xC3",
                        '_': "0xC6"
                    }
                }
                for i, ltr in enumerate(itertools.chain(contiguous)):
                    letters["hi"][ltr] = hex(i + 83).upper().replace(
                        "0X", "0x")
                    letters["lo"][ltr] = hex(i + 83 + 38).upper().replace(
                        "0X", "0x")

                msg = {
                    "hi": {
                        "ascii": "",
                        "rom": {
                            "hex": [],
                            "dec": []
                        }
                    },
                    "lo": {
                        "ascii": "",
                        "rom": {
                            "hex": [],
                            "dec": []
                        }
                    }
                }
                author = ""
                author_short = ""
                if "author.name" in self.metadata:
                    author = self.metadata["author.name"]
                if "author.name-short" in self.metadata:
                    author_short = self.metadata["author.name-short"]
                char_class = "a-zA-Z0-9\'\.\/\:\_ "
                pattern = r'^([' + char_class + ']+)$'
                antipattern = r'([^' + char_class + '])'
                linelen = 32
                if len(author) <= linelen:
                    matches = re.match(pattern, author)
                    if matches:
                        author = matches.groups(0)[0]
                    else:
                        author = re.sub(antipattern, "", author)
                if len(author_short) <= linelen:
                    matches = re.match(pattern, author_short)
                    if matches:
                        author_short = matches.groups(0)[0]
                    else:
                        author_short = re.sub(antipattern, "", author_short)
                if len(author_short) > len(author):
                    author = author_short
                author = author.upper()
                lpad = int((linelen - len(author)) / 2) - 2
                author = author.rjust(lpad + len(author)).ljust(linelen)
                for i, ltr in enumerate(itertools.chain(author)):
                    msg["hi"]["ascii"] += ltr
                    msg["lo"]["ascii"] += ltr
                    msg["hi"]["rom"]["hex"].append(letters["hi"][ltr])
                    msg["lo"]["rom"]["hex"].append(letters["lo"][ltr])
                    msg["hi"]["rom"]["dec"].append(int(letters["hi"][ltr], 16))
                    msg["lo"]["rom"]["dec"].append(int(letters["lo"][ltr], 16))
                # print(msg)

                rom.bulk_write_to_snes_address(0x238002,
                                               msg["hi"]["rom"]["dec"], 0x20)
                rom.bulk_write_to_snes_address(0x238020,
                                               msg["lo"]["rom"]["dec"], 0x20)

        else:
            # FIXME: English
            raise AssertionError(f"Cannot inject into a Race/Tournament ROM!")

        return rom
def palettes(sprite):
    data = bytearray()

    all = lambda p: p
    all_rev = lambda p: p[::-1]
    first = lambda p: p[:1]
    index_3 = lambda p: p[3:4]
    first_14 = lambda p: p[:14]
    first_15 = lambda p: p[:15]
    last = lambda p: p[-1:]
    last_15 = lambda p: p[-15:]

    palette_manifest = [
        ("power", "standard", first, [(first_15, range(1))]),
        ("varia", "standard", first, [(first_15, range(1))]),
        ("gravity", "standard", first, [(first_15, range(1))]),
        ("power", "loader", all,
         [(first_15, [0x00, 0x01, 0x48, 0x49, 0x4E, 0x4F, 0x54, 0x55, 0x58])]),
        ("varia", "loader", all,
         [(first_15, [0x00, 0x01, 0x48, 0x49, 0x4E, 0x4F, 0x54, 0x55, 0x58])]),
        ("gravity", "loader", all,
         [(first_15, [0x00, 0x01, 0x48, 0x49, 0x4E, 0x4F, 0x54, 0x55, 0x58])]),
        ("power", "heat", all, [(last_15, range(16))]),
        ("varia", "heat", all, [(last_15, range(16))]),
        ("gravity", "heat", all, [(last_15, range(16))]),
        ("power", "charge", all, [(first_15, range(8))]),
        ("varia", "charge", all, [(first_15, range(8))]),
        ("gravity", "charge", all, [(first_15, range(8))]),
        ("power", "speed boost", all, [(first_15, range(4))]),
        ("varia", "speed boost", all, [(first_15, range(4))]),
        ("gravity", "speed boost", all, [(first_15, range(4))]),
        ("power", "speed squat", all, [(first_15, range(4))]),
        ("varia", "speed squat", all, [(first_15, range(4))]),
        ("gravity", "speed squat", all, [(first_15, range(4))]),
        ("power", "shinespark", all, [(first_15, range(4))]),
        ("varia", "shinespark", all, [(first_15, range(4))]),
        ("gravity", "shinespark", all, [(first_15, range(4))]),
        ("power", "screw attack", all, [(first_15, range(4))]),
        ("varia", "screw attack", all, [(first_15, range(4))]),
        ("gravity", "screw attack", all, [(first_15, range(4))]),
        ("power", "flash", all, [(first_15, range(6))]),
        ("power", "death", all, [(first_15, range(9))]),
        ("power", "hyper", all_rev, [(first_15, range(10))]),
        ("power", "sepia", first, [(first_15, range(1))]),
        ("power", "sepia hurt", first, [(first_15, range(1))]),
        ("power", "xray", all, [(index_3, range(3))]),
        ("power", "door", first, [(index_3, range(1))]),
        ("power", "file select", first, [(first_15, range(1))]),
        ("ship", "intro", first, [(first_15, range(1))]),
        ("ship", "outro", all, [(first_15, range(16))]),
        (
            "ship",
            "standard",
            all,
            [
                (first_14, range(1)),  # first 14 colors
                (last, range(14))
            ]),  # 15th color is underglow
    ]

    for category, pose, palette_set, data_sets in palette_manifest:
        palettes = [
            pal
            for _, pal in palette_set(sprite.get_timed_palette(category, pose))
        ]
        for color_set, indices in data_sets:
            colors_555 = [
                common.convert_to_555(color_set(pal)) for pal in palettes
            ]
            data.extend(
                itertools.chain.from_iterable([
                    common.as_u16(c) for i in indices for c in colors_555[i]
                ]))

    return data