Merge branch 'msu_v32'
This commit is contained in:
commit
030fa9c10b
|
@ -231,7 +231,6 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
''')
|
''')
|
||||||
parser.add_argument('--quickswap', help='Enable quick item swapping with L and R.', action='store_true')
|
parser.add_argument('--quickswap', help='Enable quick item swapping with L and R.', action='store_true')
|
||||||
parser.add_argument('--disablemusic', help='Disables game music.', action='store_true')
|
parser.add_argument('--disablemusic', help='Disables game music.', action='store_true')
|
||||||
parser.add_argument('--extendedmsu', help='Use v31 Extended msu', action='store_true')
|
|
||||||
parser.add_argument('--mapshuffle', default=defval(False), help='Maps are no longer restricted to their dungeons, but can be anywhere', action='store_true')
|
parser.add_argument('--mapshuffle', default=defval(False), help='Maps are no longer restricted to their dungeons, but can be anywhere', action='store_true')
|
||||||
parser.add_argument('--compassshuffle', default=defval(False), help='Compasses are no longer restricted to their dungeons, but can be anywhere', action='store_true')
|
parser.add_argument('--compassshuffle', default=defval(False), help='Compasses are no longer restricted to their dungeons, but can be anywhere', action='store_true')
|
||||||
parser.add_argument('--keyshuffle', default=defval(False), help='Small Keys are no longer restricted to their dungeons, but can be anywhere', action='store_true')
|
parser.add_argument('--keyshuffle', default=defval(False), help='Small Keys are no longer restricted to their dungeons, but can be anywhere', action='store_true')
|
||||||
|
@ -335,7 +334,7 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
|
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
|
||||||
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
|
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
|
||||||
'heartbeep', "skip_progression_balancing", "triforce_pieces_required",
|
'heartbeep', "skip_progression_balancing", "triforce_pieces_required",
|
||||||
'remote_items', 'progressive', 'extendedmsu', 'dungeon_counters', 'glitch_boots']:
|
'remote_items', 'progressive', 'dungeon_counters', 'glitch_boots']:
|
||||||
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
|
||||||
if player == 1:
|
if player == 1:
|
||||||
setattr(ret, name, {1: value})
|
setattr(ret, name, {1: value})
|
||||||
|
|
5
Gui.py
5
Gui.py
|
@ -88,9 +88,6 @@ def guiMain(args=None):
|
||||||
balancingVar = IntVar()
|
balancingVar = IntVar()
|
||||||
balancingVar.set(1) #set default
|
balancingVar.set(1) #set default
|
||||||
balancingCheckbutton = Checkbutton(checkBoxFrame, text="Multiworld Progression Balancing", variable=balancingVar)
|
balancingCheckbutton = Checkbutton(checkBoxFrame, text="Multiworld Progression Balancing", variable=balancingVar)
|
||||||
extendedmsuVar = IntVar()
|
|
||||||
extendedmsuVar.set(0) #set default
|
|
||||||
extendedmsuCheckbutton = Checkbutton(checkBoxFrame, text="Extended MSU", variable=extendedmsuVar)
|
|
||||||
createSpoilerCheckbutton.pack(expand=True, anchor=W)
|
createSpoilerCheckbutton.pack(expand=True, anchor=W)
|
||||||
suppressRomCheckbutton.pack(expand=True, anchor=W)
|
suppressRomCheckbutton.pack(expand=True, anchor=W)
|
||||||
openpyramidCheckbutton.pack(expand=True, anchor=W)
|
openpyramidCheckbutton.pack(expand=True, anchor=W)
|
||||||
|
@ -105,7 +102,6 @@ def guiMain(args=None):
|
||||||
hintsCheckbutton.pack(expand=True, anchor=W)
|
hintsCheckbutton.pack(expand=True, anchor=W)
|
||||||
customCheckbutton.pack(expand=True, anchor=W)
|
customCheckbutton.pack(expand=True, anchor=W)
|
||||||
balancingCheckbutton.pack(expand=True, anchor=W)
|
balancingCheckbutton.pack(expand=True, anchor=W)
|
||||||
extendedmsuCheckbutton.pack(expand=True, anchor=W)
|
|
||||||
|
|
||||||
romOptionsFrame = LabelFrame(rightHalfFrame, text="Rom options")
|
romOptionsFrame = LabelFrame(rightHalfFrame, text="Rom options")
|
||||||
romOptionsFrame.columnconfigure(0, weight=1)
|
romOptionsFrame.columnconfigure(0, weight=1)
|
||||||
|
@ -443,7 +439,6 @@ def guiMain(args=None):
|
||||||
guiargs.item_functionality = itemfunctionVar.get()
|
guiargs.item_functionality = itemfunctionVar.get()
|
||||||
guiargs.timer = timerVar.get()
|
guiargs.timer = timerVar.get()
|
||||||
guiargs.skip_progression_balancing = not balancingVar.get()
|
guiargs.skip_progression_balancing = not balancingVar.get()
|
||||||
guiargs.extendedmsu = extendedmsuVar.get()
|
|
||||||
if guiargs.timer == "none":
|
if guiargs.timer == "none":
|
||||||
guiargs.timer = False
|
guiargs.timer = False
|
||||||
guiargs.dungeon_counters = dungeonCounterVar.get()
|
guiargs.dungeon_counters = dungeonCounterVar.get()
|
||||||
|
|
8
Main.py
8
Main.py
|
@ -57,7 +57,6 @@ def main(args, seed=None):
|
||||||
world.shufflepots = args.shufflepots.copy()
|
world.shufflepots = args.shufflepots.copy()
|
||||||
world.progressive = args.progressive.copy()
|
world.progressive = args.progressive.copy()
|
||||||
world.dungeon_counters = args.dungeon_counters.copy()
|
world.dungeon_counters = args.dungeon_counters.copy()
|
||||||
world.extendedmsu = args.extendedmsu.copy()
|
|
||||||
world.glitch_boots = args.glitch_boots.copy()
|
world.glitch_boots = args.glitch_boots.copy()
|
||||||
world.triforce_pieces_required = args.triforce_pieces_required.copy()
|
world.triforce_pieces_required = args.triforce_pieces_required.copy()
|
||||||
world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()}
|
world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()}
|
||||||
|
@ -164,15 +163,15 @@ def main(args, seed=None):
|
||||||
or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default'
|
or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default'
|
||||||
or args.shufflepots[player] or sprite_random_on_hit)
|
or args.shufflepots[player] or sprite_random_on_hit)
|
||||||
|
|
||||||
rom = JsonRom() if args.jsonout or use_enemizer else LocalRom(args.rom, extendedmsu=args.extendedmsu[player])
|
rom = JsonRom() if args.jsonout or use_enemizer else LocalRom(args.rom)
|
||||||
|
|
||||||
patch_rom(world, rom, player, team, use_enemizer)
|
patch_rom(world, rom, player, team, use_enemizer)
|
||||||
|
|
||||||
if use_enemizer and (args.enemizercli or not args.jsonout):
|
if use_enemizer and (args.enemizercli or not args.jsonout):
|
||||||
patch_enemizer(world, player, rom, args.rom, args.enemizercli, args.shufflepots[player],
|
patch_enemizer(world, player, rom, args.rom, args.enemizercli, args.shufflepots[player],
|
||||||
sprite_random_on_hit, extendedmsu=args.extendedmsu[player])
|
sprite_random_on_hit)
|
||||||
if not args.jsonout:
|
if not args.jsonout:
|
||||||
rom = LocalRom.fromJsonRom(rom, args.rom, 0x400000, args.extendedmsu[player])
|
rom = LocalRom.fromJsonRom(rom, args.rom, 0x400000)
|
||||||
|
|
||||||
if args.race:
|
if args.race:
|
||||||
patch_race_rom(rom)
|
patch_race_rom(rom)
|
||||||
|
@ -327,7 +326,6 @@ def copy_world(world):
|
||||||
ret.beemizer = world.beemizer.copy()
|
ret.beemizer = world.beemizer.copy()
|
||||||
ret.timer = world.timer.copy()
|
ret.timer = world.timer.copy()
|
||||||
ret.shufflepots = world.shufflepots.copy()
|
ret.shufflepots = world.shufflepots.copy()
|
||||||
ret.extendedmsu = world.extendedmsu.copy()
|
|
||||||
|
|
||||||
for player in range(1, world.players + 1):
|
for player in range(1, world.players + 1):
|
||||||
if world.mode[player] != 'inverted':
|
if world.mode[player] != 'inverted':
|
||||||
|
|
|
@ -380,7 +380,6 @@ def roll_settings(weights):
|
||||||
romweights = weights['rom']
|
romweights = weights['rom']
|
||||||
ret.sprite = get_choice('sprite', romweights)
|
ret.sprite = get_choice('sprite', romweights)
|
||||||
ret.disablemusic = get_choice('disablemusic', romweights)
|
ret.disablemusic = get_choice('disablemusic', romweights)
|
||||||
ret.extendedmsu = get_choice('extendedmsu', romweights)
|
|
||||||
ret.quickswap = get_choice('quickswap', romweights)
|
ret.quickswap = get_choice('quickswap', romweights)
|
||||||
ret.fastmenu = get_choice('menuspeed', romweights)
|
ret.fastmenu = get_choice('menuspeed', romweights)
|
||||||
ret.heartcolor = get_choice('heartcolor', romweights)
|
ret.heartcolor = get_choice('heartcolor', romweights)
|
||||||
|
|
29
Rom.py
29
Rom.py
|
@ -22,8 +22,7 @@ from EntranceShuffle import door_addresses
|
||||||
|
|
||||||
|
|
||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||||
RANDOMIZERBASEHASH = '1347ce535618fa1a844d2d45cf0ca661'
|
RANDOMIZERBASEHASH = 'aec17dd8b3c76c16d0b0311c36eb1c00'
|
||||||
EXTENDEDMSURANDOMIZERBASEHASH = 'f42949bde03ba5ea71c2d43a21f5d6bf'
|
|
||||||
|
|
||||||
|
|
||||||
class JsonRom(object):
|
class JsonRom(object):
|
||||||
|
@ -74,15 +73,14 @@ class JsonRom(object):
|
||||||
|
|
||||||
class LocalRom(object):
|
class LocalRom(object):
|
||||||
|
|
||||||
def __init__(self, file, extendedmsu=False, patch=True, name=None, hash=None):
|
def __init__(self, file, patch=True, name=None, hash=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.hash = hash
|
self.hash = hash
|
||||||
self.orig_buffer = None
|
self.orig_buffer = None
|
||||||
self.extendedmsu = extendedmsu
|
|
||||||
with open(file, 'rb') as stream:
|
with open(file, 'rb') as stream:
|
||||||
self.buffer = read_rom(stream)
|
self.buffer = read_rom(stream)
|
||||||
if patch:
|
if patch:
|
||||||
self.patch_base_rom(extendedmsu)
|
self.patch_base_rom()
|
||||||
self.orig_buffer = self.buffer.copy()
|
self.orig_buffer = self.buffer.copy()
|
||||||
|
|
||||||
def write_byte(self, address: int, value):
|
def write_byte(self, address: int, value):
|
||||||
|
@ -96,14 +94,14 @@ class LocalRom(object):
|
||||||
outfile.write(self.buffer)
|
outfile.write(self.buffer)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fromJsonRom(rom, file, rom_size=0x200000, extendedmsu=False):
|
def fromJsonRom(rom, file, rom_size=0x200000):
|
||||||
ret = LocalRom(file, extendedmsu, True, rom.name, rom.hash)
|
ret = LocalRom(file, True, rom.name, rom.hash)
|
||||||
ret.buffer.extend(bytearray([0x00]) * (rom_size - len(ret.buffer)))
|
ret.buffer.extend(bytearray([0x00]) * (rom_size - len(ret.buffer)))
|
||||||
for address, values in rom.patches.items():
|
for address, values in rom.patches.items():
|
||||||
ret.write_bytes(int(address), values)
|
ret.write_bytes(int(address), values)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def patch_base_rom(self, extendedmsu):
|
def patch_base_rom(self):
|
||||||
# verify correct checksum of baserom
|
# verify correct checksum of baserom
|
||||||
basemd5 = hashlib.md5()
|
basemd5 = hashlib.md5()
|
||||||
basemd5.update(self.buffer)
|
basemd5.update(self.buffer)
|
||||||
|
@ -114,7 +112,7 @@ class LocalRom(object):
|
||||||
self.buffer.extend(bytearray([0x00]) * (0x200000 - len(self.buffer)))
|
self.buffer.extend(bytearray([0x00]) * (0x200000 - len(self.buffer)))
|
||||||
|
|
||||||
# load randomizer patches
|
# load randomizer patches
|
||||||
with open(local_path('data/base2current.json') if not extendedmsu else local_path('data/base2current_extendedmsu.json'), 'r') as stream:
|
with open(local_path('data/base2current.json')) as stream:
|
||||||
patches = json.load(stream)
|
patches = json.load(stream)
|
||||||
for patch in patches:
|
for patch in patches:
|
||||||
if isinstance(patch, dict):
|
if isinstance(patch, dict):
|
||||||
|
@ -124,7 +122,7 @@ class LocalRom(object):
|
||||||
# verify md5
|
# verify md5
|
||||||
patchedmd5 = hashlib.md5()
|
patchedmd5 = hashlib.md5()
|
||||||
patchedmd5.update(self.buffer)
|
patchedmd5.update(self.buffer)
|
||||||
if patchedmd5.hexdigest() not in [RANDOMIZERBASEHASH, EXTENDEDMSURANDOMIZERBASEHASH]:
|
if patchedmd5.hexdigest() not in [RANDOMIZERBASEHASH]:
|
||||||
raise RuntimeError('Provided Base Rom unsuitable for patching. Please provide a JAP(1.0) "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc" rom to use as a base.')
|
raise RuntimeError('Provided Base Rom unsuitable for patching. Please provide a JAP(1.0) "Zelda no Densetsu - Kamigami no Triforce (Japan).sfc" rom to use as a base.')
|
||||||
|
|
||||||
def write_crc(self):
|
def write_crc(self):
|
||||||
|
@ -159,10 +157,9 @@ def read_rom(stream) -> bytearray:
|
||||||
buffer = buffer[0x200:]
|
buffer = buffer[0x200:]
|
||||||
return buffer
|
return buffer
|
||||||
|
|
||||||
def patch_enemizer(world, player, rom, baserom_path, enemizercli, shufflepots, random_sprite_on_hit, extendedmsu):
|
def patch_enemizer(world, player, rom, baserom_path, enemizercli, shufflepots, random_sprite_on_hit):
|
||||||
baserom_path = os.path.abspath(baserom_path)
|
baserom_path = os.path.abspath(baserom_path)
|
||||||
basepatch_path = os.path.abspath(
|
basepatch_path = os.path.abspath(local_path('data/base2current.json'))
|
||||||
local_path('data/base2current.json') if not extendedmsu else local_path('data/base2current_extendedmsu.json'))
|
|
||||||
enemizer_basepatch_path = os.path.join(os.path.dirname(enemizercli), "enemizerBasePatch.json")
|
enemizer_basepatch_path = os.path.join(os.path.dirname(enemizercli), "enemizerBasePatch.json")
|
||||||
randopatch_path = os.path.abspath(output_path(f'enemizer_randopatch_{player}.json'))
|
randopatch_path = os.path.abspath(output_path(f'enemizer_randopatch_{player}.json'))
|
||||||
options_path = os.path.abspath(output_path(f'enemizer_options_{player}.json'))
|
options_path = os.path.abspath(output_path(f'enemizer_options_{player}.json'))
|
||||||
|
@ -1262,8 +1259,8 @@ def patch_rom(world, rom, player, team, enemized):
|
||||||
rom.write_bytes(0x7FC0, rom.name)
|
rom.write_bytes(0x7FC0, rom.name)
|
||||||
|
|
||||||
# set player names
|
# set player names
|
||||||
for p in range(1, min(world.players, 64) + 1):
|
for p in range(1, min(world.players, 255) + 1):
|
||||||
rom.write_bytes(0x186380 + ((p - 1) * 32), hud_format_text(world.player_names[p][team]))
|
rom.write_bytes(0x195FFC + ((p - 1) * 32), hud_format_text(world.player_names[p][team]))
|
||||||
|
|
||||||
# Write title screen Code
|
# Write title screen Code
|
||||||
hashint = int(rom.get_hash(), 16)
|
hashint = int(rom.get_hash(), 16)
|
||||||
|
@ -1330,7 +1327,7 @@ def hud_format_text(text):
|
||||||
output += bytes([0x77 + ord(char) - ord('0'), 0x29])
|
output += bytes([0x77 + ord(char) - ord('0'), 0x29])
|
||||||
elif char == '9':
|
elif char == '9':
|
||||||
output += b'\x4b\x29'
|
output += b'\x4b\x29'
|
||||||
elif char == ' ':
|
elif char == ' ' or char == '_':
|
||||||
output += b'\x7f\x00'
|
output += b'\x7f\x00'
|
||||||
else:
|
else:
|
||||||
output += b'\x2a\x29'
|
output += b'\x2a\x29'
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -200,7 +200,6 @@ rom:
|
||||||
randomonhit: 0
|
randomonhit: 0
|
||||||
link: 1 # to add other sprites: open the gui/Creator, go to adjust, select a sprite and write down the name the gui calls it
|
link: 1 # to add other sprites: open the gui/Creator, go to adjust, select a sprite and write down the name the gui calls it
|
||||||
disablemusic: off # If "on", all in-game music will be disabled
|
disablemusic: off # If "on", all in-game music will be disabled
|
||||||
extendedmsu: on # If "on", V31 extended MSU support will be available
|
|
||||||
quickswap: # Enable switching items by pressing the L+R shoulder buttons
|
quickswap: # Enable switching items by pressing the L+R shoulder buttons
|
||||||
on: 0
|
on: 0
|
||||||
off: 1
|
off: 1
|
||||||
|
|
Loading…
Reference in New Issue