base rom changes
* V32 MSU * All items from chests/received in dark rooms now visible. * Regular bunny can read signs * Players up to Player 255 supported on send/received.
This commit is contained in:
		
							parent
							
								
									68f453f802
								
							
						
					
					
						commit
						73d1f56ffb
					
				| 
						 | 
					@ -226,7 +226,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')
 | 
				
			||||||
| 
						 | 
					@ -330,7 +329,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",
 | 
					                         'heartbeep', "skip_progression_balancing",
 | 
				
			||||||
                         '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.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()}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,15 +162,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)
 | 
				
			||||||
| 
						 | 
					@ -326,7 +325,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':
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -376,7 +376,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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										23
									
								
								Rom.py
								
								
								
								
							
							
						
						
									
										23
									
								
								Rom.py
								
								
								
								
							| 
						 | 
					@ -22,8 +22,7 @@ from EntranceShuffle import door_addresses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
JAP10HASH = '03a63945398191337e896e5771f77173'
 | 
					JAP10HASH = '03a63945398191337e896e5771f77173'
 | 
				
			||||||
RANDOMIZERBASEHASH = '1347ce535618fa1a844d2d45cf0ca661'
 | 
					RANDOMIZERBASEHASH = '680f844ec899a8349a11d95de17547f9'
 | 
				
			||||||
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'))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
		Loading…
	
		Reference in New Issue