Freestyler, rock the microphone

Straight from the top of my dome
Freestyler, rock the microphone
Carry on with the freestyler

I got to throw on and go on
You know I got to flow on, selectors on ya radio play us
'Cause we're friendly for ozone, but that's not all so hold on
Tight as I rock the mic right, oh, excuse me, pardon
As I synchronize with the analysed upcoming vibes
The session, let there be a lesson, question
You carry protection or will your heart go on
Like Celine Dion, Karma Chameleon
This commit is contained in:
Lucy 2024-09-02 21:48:35 +02:00
parent 0c9d1a472f
commit 49daaf1da8
4 changed files with 936 additions and 139 deletions

673
Fusion_Palette_Shuffle.py Normal file
View file

@ -0,0 +1,673 @@
# Source Generated with Decompyle++
# File: Fusion_Palette_Shuffle.pyc (Python 3.8)
import struct
import random
import sys
from pathlib import Path
from MFOR import file_hash
tileset_fixes = {
4640526: 575,
4640528: 735,
4640530: 863,
4640558: 575,
4640560: 735,
4640562: 863,
4640592: 575,
4640594: 735,
4640626: 575
}
static_tilesets = [
[4219100, 448],
[4223388, 448],
[4224028, 448],
[4225244, 448],
[4226268, 448],
[4226716, 448],
[4632980, 448],
[4640084, 448],
[4640788, 448],
[4641236, 448],
[4641684, 448],
[4642132, 448],
[4643124, 448],
[4643572, 448],
[4644020, 448],
[4644468, 448],
[4645172, 192],
[4645620, 448],
[4646068, 448],
[4646644, 448],
[4648820, 448],
[4649268, 448],
[4818056, 448],
[4818504, 448],
[4818952, 448],
[4819656, 448],
[4820104, 128],
[5031360, 448],
[5031808, 448],
[5032256, 448],
[5032704, 448],
[5033152, 448],
[5033600, 448],
[5034048, 448],
[5186040, 448],
[5186488, 448],
[5186936, 448],
[5187512, 448],
[5188184, 448],
[5310568, 448],
[5311016, 448],
[5311464, 352],
[5460880, 288],
[5461456, 448],
[5461904, 448],
[5462800, 448],
[5558492, 448],
[5559164, 448],
[5559612, 448]
]
tileset_single_pass = {
4641812: 32,
4647188: 32,
4819000: 8,
4819016: 8,
4819048: 8,
4819704: 8,
4819720: 8,
4819752: 8,
5186568: 5,
5186584: 7,
5186604: 6,
5186640: 4,
5186704: 4,
5186732: 6,
5186860: 6,
5311144: 32,
5460752: 32,
5460784: 32,
5460816: 32,
5460848: 32,
5462576: 32,
5462864: 32,
5462960: 16,
5463088: 16
}
animated_tilesets = [
[4223836, 192],
[4224476, 192],
[4633428, 320],
[4636308, 256],
[4640532, 256],
[4645364, 64],
[5187960, 224],
[5188632, 256],
[4819400, 256],
[4820232, 64],
[5558940, 224],
[5461168, 288],
[4644916, 256],
[5187384, 128],
[5185272, 160],
[5185880, 160],
[4646516, 128],
[4635092, 320],
[4642580, 256],
[4642836, 288],
[5311816, 64]
]
paired_tilesets = [
[
[3930000, 192], [4633748, 448]
],
[
[3280920, 96], [3561816, 32], [4218524, 448], [4218972, 128]
],
[
[3109872, 96], [4222236, 448], [4222684, 128]
],
[
[3297776, 96], [4222812, 448], [4223260, 128]
],
[
[3267440, 96], [4224668, 448], [4225116, 128]
],
[
[3084920, 96], [4225692, 448], [4226140, 128]
],
[
[3456412, 64], [4632340, 448], [4632788, 192], [4647540, 448], [4647988, 128], [4648116, 448], [4648564, 256]
],
[
[4647092, 448], [3451140, 32]
],
[
[4634644, 448], [4635412, 448]
],
[
[4219548, 448], [4635860, 448], [4636308, 256]
],
[
[4219996, 448], [4636564, 448], [4637012, 256]
],
[
[4220444, 448], [4637268, 448], [4637716, 256]
],
[
[4220892, 448], [4637972, 448], [4638420, 256]
],
[
[4221340, 448], [4638676, 448], [4639124, 256]
],
[
[4221788, 448], [4639380, 448], [4639828, 256]
],
[
[5184824, 448], [5185432, 448]
],
[
[3447972, 64], [5462352, 448]
]
]
sprite_fixes = {
3468542: 8266,
3468544: 7178,
3499380: 142,
3499406: 523,
3558744: 3264,
3558758: 14
}
sprites = [
[2835304, 128],
[3042180, 32],
[3058284, 96],
[3066148, 64],
[3070696, 32],
[3076896, 96],
[3103328, 64],
[3113676, 32],
[3117204, 32],
[3124184, 96],
[3130896, 64],
[3150104, 256],
[3169028, 160],
[3181768, 160],
[3192168, 160],
[3202568, 160],
[3212968, 160],
[3223368, 160],
[3231720, 128],
[3241064, 64],
[3245764, 64],
[3252504, 64],
[3254656, 32],
[3257752, 32],
[3260912, 32],
[3273680, 64],
[3288044, 64],
[3305456, 96],
[3310352, 32],
[3321092, 160],
[3332584, 160],
[3342984, 160],
[3353384, 160],
[3368040, 64],
[3373196, 64],
[3377084, 32],
[3384092, 64],
[3390996, 32],
[3391028, 32],
[3398460, 96],
[3403768, 32],
[3406232, 32],
[3411720, 64],
[3436688, 256],
[3443020, 32],
[3462012, 64],
[3468532, 64],
[3473740, 64],
[3479228, 64],
[3485468, 96],
[3493060, 96],
[3499376, 64],
[3503052, 32],
[3505876, 32],
[3508068, 32],
[3512272, 32],
[3519012, 96],
[3529712, 96],
[3534488, 64],
[3537920, 32],
[3540236, 32],
[3544716, 64],
[3547808, 32],
[3552044, 64],
[3554544, 32],
[3558732, 64],
[3578836, 256],
[3581056, 32],
[3581088, 32],
[3581120, 96],
[3611928, 256],
[3641296, 32],
[3643992, 32],
[3646200, 32],
[3652548, 64],
[3657176, 32],
[3659632, 32],
[3662052, 32],
[3664548, 32],
[3667884, 32],
[3672824, 64],
[3684520, 128],
[3690908, 32],
[3693436, 32],
[3695788, 32],
[3700504, 32],
[3755348, 224],
[3772744, 160],
[3798160, 32],
[3822584, 256],
[3829592, 64],
[3837700, 32],
[3887568, 256],
[3917260, 256]
]
paired_sprites = [
[
[5865648, 64], [5865776, 32], [6368840, 32], [6369096, 64], [6369224, 32]
],
[
[3098012, 192], [3794264, 224], [6515960, 96], [6516536, 32]
],
[
[3634936, 256], [3639120, 128]
],
[
[3803008, 64], [3858444, 256], [3868728, 64]
],
[
[2835432, 32], [3046752, 64], [3051992, 64], [3723188, 256]
],
[
[3363784, 160], [3835340, 32]
],
[
[4634196, 448], [6516792, 512]
]
]
beam_fixes = {
5813384: 8031,
5813388: 8472,
5813480: 24480
}
beams = [
[5813348, 32],
[5813380, 32],
[5813412, 32],
[5813444, 32],
[5813476, 32]
]
paired_beams = [
[
[5813508, 32], [4079900, 10], [4079996, 32]
]
]
suit_fixes = {
2678144: 32585,
2678150: 16643,
2678154: 799,
2678164: 501,
2678180: 6730,
2678182: 328,
2678186: 23070,
2678202: 10406,
2678208: 28311,
2678228: 648,
2678234: 10406,
2678246: 201
}
suit_misc = [
[2678268, 32],
[2678332, 32],
[2678364, 32],
[2678396, 32],
[2678428, 32],
[2678460, 32],
[2679036, 32],
[2679068, 32],
[2679868, 32],
[2679900, 32],
[2679932, 32],
[2679964, 32],
[2679996, 32],
[2680028, 32],
[2680060, 32],
[2680092, 32],
[2680124, 32],
[2680156, 32]
]
suits = [
[
[2678140, 14], [2678300, 14], [2678492, 14], [2679100, 14], [2679132, 14], [2679164, 14], [2679196, 14], [2679228, 14], [2679260, 14], [2679292, 14], [2679324, 14], [2679356, 14], [2679388, 14], [2679420, 14], [2679452, 14], [2679484, 14], [2679516, 14], [2679548, 14], [2679580, 14], [2679612, 14], [2679644, 14], [2679676, 14], [2679708, 14], [2679740, 14], [2679772, 14], [2679804, 14], [2679836, 14], [2680188, 14], [2680220, 14], [2680252, 14], [2680284, 14], [2680316, 14], [2681596, 14], [2681628, 14], [2681660, 14], [2681692, 14], [2682108, 14], [2682140, 14], [2682172, 14], [2682204, 14], [2682620, 14], [2682652, 14], [2682684, 14], [2682716, 14], [2683132, 14], [2683164, 14], [2683196, 14], [2683228, 14], [2683644, 14], [2683676, 14], [2683708, 14], [2683740, 14], [2684156, 14], [2684188, 14], [2684220, 14], [2684252, 14], [2684668, 14], [2684700, 14], [2684732, 14], [2684764, 14]
],
[
[2678172, 14], [2680348, 14], [2680380, 14], [2680412, 14], [2680444, 14], [2680476, 14], [2681724, 14], [2681756, 14], [2681788, 14], [2681820, 14], [2682236, 14], [2682268, 14], [2682300, 14], [2682332, 14], [2682748, 14], [2682780, 14], [2682812, 14], [2682844, 14], [2683260, 14], [2683292, 14], [2683324, 14], [2683356, 14], [2683772, 14], [2683804, 14], [2683836, 14], [2683868, 14], [2684284, 14], [2684316, 14], [2684348, 14], [2684380, 14], [2684796, 14], [2684828, 14], [2684860, 14], [2684892, 14]
],
[
[2678204, 14], [2680508, 14], [2680540, 14], [2680572, 14], [2680604, 14], [2680636, 14], [2681852, 14], [2681884, 14], [2681916, 14], [2681948, 14], [2682364, 14], [2682396, 14], [2682428, 14], [2682460, 14], [2682876, 14], [2682908, 14], [2682940, 14], [2682972, 14], [2683388, 14], [2683420, 14], [2683452, 14], [2683484, 14], [2683900, 14], [2683932, 14], [2683964, 14], [2683996, 14], [2684412, 14], [2684444, 14], [2684476, 14], [2684508, 14], [2684924, 14], [2684956, 14], [2684988, 14], [2685020, 14]
],
[
[2678236, 14], [2680988, 14], [2681020, 14], [2681052, 14], [2681084, 14], [2681116, 14], [2681980, 14], [2682012, 14], [2682044, 14], [2682076, 14], [2682492, 14], [2682524, 14], [2682556, 14], [2682588, 14], [2683004, 14], [2683036, 14], [2683068, 14], [2683100, 14], [2683516, 14], [2683548, 14], [2683580, 14], [2683612, 14], [2684028, 14], [2684060, 14], [2684092, 14], [2684124, 14], [2684540, 14], [2684572, 14], [2684604, 14], [2684636, 14], [2685052, 14], [2685084, 14], [2685116, 14], [2685148, 14]
]
]
skip_colors = {
4218620: 16,
4218716: 16,
4640148: 8,
4647764: 16,
4649428: 8,
5031520: 16,
5186680: 12,
5187704: 11,
5310686: 5,
5310696: 8,
5310760: 16,
5311112: 11,
5311176: 16,
5311528: 16,
5461634: 1
}
base_color_list = [
['blue', 'blue', 'green'],
['blue', 'blue', 'red'],
['blue', 'blue', 'None'],
['blue', 'green', 'blue'],
['blue', 'green', 'green'],
['blue', 'green', 'None'],
['blue', 'red', 'blue'],
['blue', 'red', 'green'],
['blue', 'red', 'red'],
['blue', 'red', 'None'],
['blue', 'None', 'blue'],
['blue', 'None', 'green'],
['blue', 'None', 'red'],
['green', 'blue', 'blue'],
['green', 'blue', 'green'],
['green', 'blue', 'red'],
['green', 'blue', 'None'],
['green', 'green', 'blue'],
['green', 'green', 'red'],
['green', 'green', 'None'],
['green', 'red', 'blue'],
['green', 'red', 'green'],
['green', 'red', 'red'],
['green', 'red', 'None'],
['green', 'None', 'blue'],
['green', 'None', 'green'],
['green', 'None', 'red'],
['red', 'blue', 'blue'],
['red', 'blue', 'green'],
['red', 'blue', 'red'],
['red', 'blue', 'None'],
['red', 'green', 'blue'],
['red', 'green', 'green'],
['red', 'green', 'red'],
['red', 'green', 'None'],
['red', 'red', 'blue'],
['red', 'red', 'green'],
['red', 'red', 'None'],
['red', 'None', 'blue'],
['red', 'None', 'green'],
['red', 'None', 'red'],
['None', 'blue', 'blue'],
['None', 'blue', 'green'],
['None', 'blue', 'red'],
['None', 'green', 'blue'],
['None', 'green', 'green'],
['None', 'green', 'red'],
['None', 'red', 'blue'],
['None', 'red', 'green'],
['None', 'red', 'red'],
['green', 'green', 'green']
]
def modify_color(color, arrangement, tileset=False):
if color == 0 or color == 32767:
return color
blue = (color & 31744) >> 10
green = (color & 992) >> 5
red = color & 31
if arrangement[0] == "blue":
high = blue << 10
elif arrangement[0] == "green":
high = green << 10
elif arrangement[0] == "red":
high = red << 10
else:
high = 0
if arrangement[1] == "blue":
mid = blue << 5
elif arrangement[1] == "green":
mid = green << 5
elif arrangement[1] == "red":
mid = red << 5
else:
mid = 0
if arrangement[2] == "blue":
low = blue
elif arrangement[2] == "green":
low = green
elif arrangement[2] == "red":
low = red
else:
low = 0
return high | mid | low
def get_color_slot():
color_list = base_color_list.copy()
old_color = None
while True:
if len(color_list) < 1:
color_list = base_color_list.copy()
new_color = color_list.pop(random.randrange(len(color_list)))
if new_color == old_color:
print("Repeat color")
new_color = color_list.pop(random.randrange(len(color_list)))
old_color = new_color
yield new_color
def randomize_palettes(data, seed=None, shuffle_tilesets=True, shuffle_sprites=True, shuffle_suits=True, shuffle_beams=True):
if seed is None:
random.seed()
else:
random.seed(seed)
if shuffle_tilesets:
for (offset, length) in static_tilesets:
skip = 0
color_slot = next(get_color_slot())
fixed_color_count = 0
fixed_color_slot = next(get_color_slot())
for x in range(0, length, 2):
current_offset = offset + x
if x % 32 == 0:
color_slot = next(get_color_slot())
if current_offset in skip_colors.keys():
skip = skip_colors.get(current_offset)
if skip > 0:
skip = skip - 1
else:
if current_offset in tileset_fixes.keys():
half_word = tileset_fixes.get(current_offset)
else:
half_word = struct.unpack_from("<H", data, current_offset)[0]
if current_offset in tileset_single_pass.keys():
fixed_color_count = tileset_single_pass.get(current_offset)
if fixed_color_count > 0:
half_word = modify_color(half_word, fixed_color_slot)
fixed_color_count = fixed_color_count - 1
else:
half_word = modify_color(half_word, color_slot, True)
struct.pack_into("<H", data, current_offset, half_word)
for (offset, length) in animated_tilesets:
skip = 0
color_slot = next(get_color_slot())
for x in range(0, length, 2):
current_offset = offset + x
if current_offset in skip_colors.keys():
skip = skip_colors.get(current_offset)
if skip > 0:
skip = skip - 1
else:
if current_offset in tileset_fixes.keys():
half_word = tileset_fixes.get(current_offset)
else:
half_word = struct.unpack_from("<H", data, current_offset)[0]
half_word = modify_color(half_word, color_slot)
struct.pack_into("<H", data, current_offset, half_word)
for group in paired_tilesets:
color_slot = next(get_color_slot())
for (offset, length) in group:
skip = 0
for x in range(0, length, 2):
current_offset = offset + x
if current_offset in skip_colors.keys():
skip = skip_colors.get(current_offset)
if skip > 0:
skip = skip - 1
else:
if current_offset in tileset_fixes.keys():
half_word = tileset_fixes.get(current_offset)
else:
half_word = struct.unpack_from("<H", data, current_offset)[0]
half_word = modify_color(half_word, color_slot, True)
struct.pack_into("<H", data, current_offset, half_word)
if shuffle_sprites:
for (offset, length) in sprites:
skip = 0
color_slot = next(get_color_slot())
for x in range(0, length, 2):
current_offset = offset + x
if current_offset in skip_colors.keys():
skip = skip_colors.get(current_offset)
if skip > 0:
skip = skip - 1
else:
if current_offset in sprite_fixes.keys():
half_word = sprite_fixes.get(current_offset)
else:
half_word = struct.unpack_from("<H", data, current_offset)[0]
half_word = modify_color(half_word, color_slot)
struct.pack_into("<H", data, current_offset, half_word)
for group in paired_sprites:
skip = 0
color_slot = next(get_color_slot())
for (offset, length) in group:
for x in range(0, length, 2):
current_offset = offset + x
if current_offset in skip_colors.keys():
skip = skip_colors.get(current_offset)
if skip > 0:
skip = skip - 1
else:
if current_offset in sprite_fixes.keys():
half_word = sprite_fixes.get(current_offset)
else:
half_word = struct.unpack_from("<H", data, current_offset)[0]
half_word = modify_color(half_word, color_slot)
struct.pack_into("<H", data, current_offset, half_word)
if shuffle_suits:
for (offset, length) in suit_misc:
color_slot = next(get_color_slot())
for x in range(0, length, 2):
current_offset = offset + x
if current_offset in suit_fixes.keys():
half_word = suit_fixes.get(current_offset)
else:
half_word = struct.unpack_from("<H", data, current_offset)[0]
half_word = modify_color(half_word, color_slot)
struct.pack_into("<H", data, current_offset, half_word)
for group in suits:
color_slot = next(get_color_slot())
for (offset, length) in group:
for x in range(0, length, 2):
current_offset = offset + x
if current_offset in suit_fixes.keys():
half_word = suit_fixes.get(current_offset)
else:
half_word = struct.unpack_from("<H", data, current_offset)[0]
half_word = modify_color(half_word, color_slot)
struct.pack_into("<H", data, current_offset, half_word)
if shuffle_beams:
for (offset, length) in beams:
color_slot = next(get_color_slot())
for x in range(0, length, 2):
current_offset = offset + x
if current_offset in beam_fixes.keys():
half_word = beam_fixes.get(current_offset)
else:
half_word = struct.unpack_from("<H", data, current_offset)[0]
half_word = modify_color(half_word, color_slot)
struct.pack_into("<H", data, current_offset, half_word)
for group in paired_beams:
color_slot = next(get_color_slot())
for (offset, length) in group:
for x in range(0, length, 2):
current_offset = offset + x
if current_offset in beam_fixes.keys():
half_word = beam_fixes.get(current_offset)
else:
half_word = struct.unpack_from("<H", data, current_offset)[0]
half_word = modify_color(half_word, color_slot)
struct.pack_into("<H", data, current_offset, half_word)
if __name__ == "__main__":
if len(sys.argv) > 1:
filename = sys.argv[1]
if len(sys.argv) > 2:
seed_arg = sys.argv[2]
else:
seed_arg = None
try:
checksum = file_hash(filename)
if checksum != 1819625372:
sys.exit("Only Metroid Fusion (U) is supported. Check the CRC32 value: it should be 6C75479C")
game = bytearray(Path(filename).read_bytes())
randomize_palettes(game, seed_arg)
filename = filename.replace(".gba", " Colorized.gba")
Path(filename).write_bytes(game)
except FileNotFoundError:
print(f"Could not open file {filename}")
except PermissionError:
print(f"Could not write file {filename}, it may be write protected.")
else:
exit("Usage: 'Metroid Fusion(U).gba' <optional seed>")