palette fixes
This commit is contained in:
parent
0c6943fc6a
commit
2d43cae88e
|
@ -6,7 +6,7 @@ import textwrap
|
|||
import sys
|
||||
|
||||
from AdjusterMain import adjust
|
||||
from Rom import get_sprite_from_name
|
||||
from Rom import Sprite
|
||||
|
||||
class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter):
|
||||
|
||||
|
@ -55,7 +55,7 @@ def main():
|
|||
input(
|
||||
'Could not find valid rom for patching at expected path %s. Please run with -h to see help for further information. \nPress Enter to exit.' % args.rom)
|
||||
sys.exit(1)
|
||||
if args.sprite is not None and not os.path.isfile(args.sprite) and not get_sprite_from_name(args.sprite):
|
||||
if args.sprite is not None and not os.path.isfile(args.sprite) and not Sprite.get_sprite_from_name(args.sprite):
|
||||
input('Could not find link sprite sheet at given location. \nPress Enter to exit.')
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import shlex
|
|||
import sys
|
||||
|
||||
from Main import main, get_seed
|
||||
from Rom import get_sprite_from_name
|
||||
from Rom import Sprite
|
||||
from Utils import is_bundled, close_console
|
||||
|
||||
|
||||
|
@ -401,7 +401,7 @@ def start():
|
|||
input(
|
||||
'Could not find valid base rom for patching at expected path %s. Please run with -h to see help for further information. \nPress Enter to exit.' % args.rom)
|
||||
sys.exit(1)
|
||||
if any([sprite is not None and not os.path.isfile(sprite) and not get_sprite_from_name(sprite) for sprite in
|
||||
if any([sprite is not None and not os.path.isfile(sprite) and not Sprite.get_sprite_from_name(sprite) for sprite in
|
||||
args.sprite.values()]):
|
||||
input('Could not find link sprite sheet at given location. \nPress Enter to exit.')
|
||||
sys.exit(1)
|
||||
|
|
|
@ -11,7 +11,7 @@ import ModuleUpdate
|
|||
ModuleUpdate.update()
|
||||
|
||||
from Utils import parse_yaml
|
||||
from Rom import get_sprite_from_name
|
||||
from Rom import Sprite
|
||||
from EntranceRandomizer import parse_arguments
|
||||
from Main import main as ERmain
|
||||
from Main import get_seed, seeddigits
|
||||
|
@ -167,7 +167,7 @@ def main(args=None, callback=ERmain):
|
|||
if path:
|
||||
try:
|
||||
settings = settings_cache[path] if settings_cache[path] else roll_settings(weights_cache[path])
|
||||
if settings.sprite and not os.path.isfile(settings.sprite) and not get_sprite_from_name(
|
||||
if settings.sprite and not os.path.isfile(settings.sprite) and not Sprite.get_sprite_from_name(
|
||||
settings.sprite):
|
||||
logging.warning(
|
||||
f"Warning: The chosen sprite, \"{settings.sprite}\", for yaml \"{path}\", does not exist.")
|
||||
|
|
329
Rom.py
329
Rom.py
|
@ -1,3 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||
RANDOMIZERBASEHASH = '0fc63d72970ab96ffb18699f4d12a594'
|
||||
|
||||
|
@ -19,7 +21,8 @@ from BaseClasses import CollectionState, ShopType, Region, Location
|
|||
from Dungeons import dungeon_music_addresses
|
||||
from Regions import location_table
|
||||
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
|
||||
from Text import Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_texts
|
||||
from Text import Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, \
|
||||
BombShop2_texts, junk_texts
|
||||
|
||||
from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, \
|
||||
LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, \
|
||||
|
@ -35,6 +38,7 @@ try:
|
|||
except:
|
||||
z3pr = None
|
||||
|
||||
|
||||
class LocalRom(object):
|
||||
|
||||
def __init__(self, file, patch=True, vanillaRom=None, name=None, hash=None):
|
||||
|
@ -92,7 +96,6 @@ class LocalRom(object):
|
|||
self.encrypt_range(0x180000, 32, key)
|
||||
self.encrypt_range(0x180140, 32, key)
|
||||
|
||||
|
||||
def write_to_file(self, file, hide_enemizer=False):
|
||||
with open(file, 'wb') as outfile:
|
||||
outfile.write(self.buffer)
|
||||
|
@ -225,7 +228,7 @@ def apply_random_sprite_on_event(rom: LocalRom, sprite, local_random, allow_rand
|
|||
|
||||
rom.write_int16(0x18637F, onevent)
|
||||
|
||||
sprite = Sprite(sprite) if os.path.isfile(sprite) else get_sprite_from_name(sprite, local_random)
|
||||
sprite = Sprite(sprite) if os.path.isfile(sprite) else Sprite.get_sprite_from_name(sprite, local_random)
|
||||
|
||||
# write link sprite if required
|
||||
if sprite:
|
||||
|
@ -238,7 +241,8 @@ def apply_random_sprite_on_event(rom: LocalRom, sprite, local_random, allow_rand
|
|||
if isinstance(sprite_pool, str):
|
||||
sprite_pool = sprite_pool.split(':')
|
||||
for spritename in sprite_pool:
|
||||
sprite = Sprite(spritename) if os.path.isfile(spritename) else get_sprite_from_name(spritename, local_random)
|
||||
sprite = Sprite(spritename) if os.path.isfile(spritename) else Sprite.get_sprite_from_name(
|
||||
spritename, local_random)
|
||||
if sprite:
|
||||
sprites.append(sprite)
|
||||
else:
|
||||
|
@ -344,9 +348,15 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli):
|
|||
'IcePalace': world.get_dungeon("Ice Palace", player).boss.enemizer_name,
|
||||
'MiseryMire': world.get_dungeon("Misery Mire", player).boss.enemizer_name,
|
||||
'TurtleRock': world.get_dungeon("Turtle Rock", player).boss.enemizer_name,
|
||||
'GanonsTower1': world.get_dungeon('Ganons Tower' if world.mode[player] != 'inverted' else 'Inverted Ganons Tower', player).bosses['bottom'].enemizer_name,
|
||||
'GanonsTower2': world.get_dungeon('Ganons Tower' if world.mode[player] != 'inverted' else 'Inverted Ganons Tower', player).bosses['middle'].enemizer_name,
|
||||
'GanonsTower3': world.get_dungeon('Ganons Tower' if world.mode[player] != 'inverted' else 'Inverted Ganons Tower', player).bosses['top'].enemizer_name,
|
||||
'GanonsTower1':
|
||||
world.get_dungeon('Ganons Tower' if world.mode[player] != 'inverted' else 'Inverted Ganons Tower',
|
||||
player).bosses['bottom'].enemizer_name,
|
||||
'GanonsTower2':
|
||||
world.get_dungeon('Ganons Tower' if world.mode[player] != 'inverted' else 'Inverted Ganons Tower',
|
||||
player).bosses['middle'].enemizer_name,
|
||||
'GanonsTower3':
|
||||
world.get_dungeon('Ganons Tower' if world.mode[player] != 'inverted' else 'Inverted Ganons Tower',
|
||||
player).bosses['top'].enemizer_name,
|
||||
'GanonsTower4': 'Agahnim2',
|
||||
'Ganon': 'Ganon',
|
||||
}
|
||||
|
@ -373,7 +383,8 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli):
|
|||
stderr=subprocess.STDOUT,
|
||||
universal_newlines=True)
|
||||
|
||||
logging.debug(f"Enemizer attempt {i + 1} of {max_enemizer_tries} for player {player} using enemizer seed {enemizer_seed}")
|
||||
logging.debug(
|
||||
f"Enemizer attempt {i + 1} of {max_enemizer_tries} for player {player} using enemizer seed {enemizer_seed}")
|
||||
for stdout_line in iter(p_open.stdout.readline, ""):
|
||||
logging.debug(stdout_line.rstrip())
|
||||
p_open.stdout.close()
|
||||
|
@ -403,6 +414,7 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli):
|
|||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
sprite_list_lock = threading.Lock()
|
||||
_sprite_table = {}
|
||||
|
||||
|
@ -423,15 +435,6 @@ def _populate_sprite_table():
|
|||
for file in os.listdir(dir):
|
||||
pool.submit(load_sprite_from_file, os.path.join(dir, file))
|
||||
|
||||
def get_sprite_from_name(name, local_random=random):
|
||||
_populate_sprite_table()
|
||||
name = name.lower()
|
||||
if name.startswith('random'):
|
||||
sprites = list(set(_sprite_table.values()))
|
||||
sprites.sort(key=lambda x: x.name)
|
||||
return local_random.choice(sprites)
|
||||
return _sprite_table.get(name, None)
|
||||
|
||||
class Sprite(object):
|
||||
palette = (255, 127, 126, 35, 183, 17, 158, 54, 165, 20, 255, 1, 120, 16, 157,
|
||||
89, 71, 54, 104, 59, 74, 10, 239, 18, 92, 42, 113, 21, 24, 122,
|
||||
|
@ -490,6 +493,16 @@ class Sprite(object):
|
|||
else:
|
||||
self.valid = False
|
||||
|
||||
@staticmethod
|
||||
def get_sprite_from_name(name: str, local_random=random) -> Optional[Sprite]:
|
||||
_populate_sprite_table()
|
||||
name = name.lower()
|
||||
if name.startswith('random'):
|
||||
sprites = list(set(_sprite_table.values()))
|
||||
sprites.sort(key=lambda x: x.name)
|
||||
return local_random.choice(sprites)
|
||||
return _sprite_table.get(name, None)
|
||||
|
||||
@staticmethod
|
||||
def default_link_sprite():
|
||||
return Sprite(local_path('data', 'default.zspr'))
|
||||
|
@ -531,7 +544,8 @@ class Sprite(object):
|
|||
headersize = struct.calcsize(headerstr)
|
||||
if len(filedata) < headersize:
|
||||
return None
|
||||
(version, csum, icsum, sprite_offset, sprite_size, palette_offset, palette_size, kind) = struct.unpack_from(headerstr, filedata)
|
||||
(version, csum, icsum, sprite_offset, sprite_size, palette_offset, palette_size, kind) = struct.unpack_from(
|
||||
headerstr, filedata)
|
||||
if version not in [1]:
|
||||
logger.error('Error parsing ZSPR file: Version %g not supported', version)
|
||||
return None
|
||||
|
@ -571,8 +585,10 @@ class Sprite(object):
|
|||
|
||||
def decode_palette(self):
|
||||
"Returns the palettes as an array of arrays of 15 colors"
|
||||
|
||||
def array_chunk(arr, size):
|
||||
return list(zip(*[iter(arr)] * size))
|
||||
|
||||
def make_int16(pair):
|
||||
return pair[1] << 8 | pair[0]
|
||||
|
||||
|
@ -602,6 +618,7 @@ class Sprite(object):
|
|||
rom.write_bytes(0x307000, self.palette)
|
||||
rom.write_bytes(0x307078, self.glove_palette)
|
||||
|
||||
|
||||
def patch_rom(world, rom, player, team, enemized):
|
||||
local_random = world.rom_seeds[player]
|
||||
|
||||
|
@ -749,7 +766,9 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
rom.write_byte(0x180032, 0x00) # standard mode
|
||||
|
||||
uncle_location = world.get_location('Link\'s Uncle', player)
|
||||
if uncle_location.item is None or uncle_location.item.name not in ['Master Sword', 'Tempered Sword', 'Fighter Sword', 'Golden Sword', 'Progressive Sword']:
|
||||
if uncle_location.item is None or uncle_location.item.name not in ['Master Sword', 'Tempered Sword',
|
||||
'Fighter Sword', 'Golden Sword',
|
||||
'Progressive Sword']:
|
||||
# disable sword sprite from uncle
|
||||
rom.write_bytes(0x6D263, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
||||
rom.write_bytes(0x6D26B, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
|
||||
|
@ -845,7 +864,8 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
|
||||
# Set overflow items for progressive equipment
|
||||
rom.write_bytes(0x180090,
|
||||
[difficulty.progressive_sword_limit if world.swords[player] != 'swordless' else 0, overflow_replacement,
|
||||
[difficulty.progressive_sword_limit if world.swords[player] != 'swordless' else 0,
|
||||
overflow_replacement,
|
||||
difficulty.progressive_shield_limit, overflow_replacement,
|
||||
difficulty.progressive_armor_limit, overflow_replacement,
|
||||
difficulty.progressive_bottle_limit, overflow_replacement])
|
||||
|
@ -853,7 +873,8 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
# Work around for json patch ordering issues - write bow limit separately so that it is replaced in the patch
|
||||
rom.write_bytes(0x180098, [difficulty.progressive_bow_limit, overflow_replacement])
|
||||
|
||||
if difficulty.progressive_bow_limit < 2 and (world.swords[player] == 'swordless' or world.logic[player] == 'noglitches'):
|
||||
if difficulty.progressive_bow_limit < 2 and (
|
||||
world.swords[player] == 'swordless' or world.logic[player] == 'noglitches'):
|
||||
rom.write_bytes(0x180098, [2, overflow_replacement])
|
||||
rom.write_byte(0x180181, 0x01) # Make silver arrows work only on ganon
|
||||
rom.write_byte(0x180182, 0x00) # Don't auto equip silvers on pickup
|
||||
|
@ -862,8 +883,10 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
rom.write_bytes(0x178000, local_random.getrandbits(8 * 1024).to_bytes(1024, 'big'))
|
||||
if "g" in world.shuffle_prizes[player]:
|
||||
# shuffle prize packs
|
||||
prizes = [0xD8, 0xD8, 0xD8, 0xD8, 0xD9, 0xD8, 0xD8, 0xD9, 0xDA, 0xD9, 0xDA, 0xDB, 0xDA, 0xD9, 0xDA, 0xDA, 0xE0, 0xDF, 0xDF, 0xDA, 0xE0, 0xDF, 0xD8, 0xDF,
|
||||
0xDC, 0xDC, 0xDC, 0xDD, 0xDC, 0xDC, 0xDE, 0xDC, 0xE1, 0xD8, 0xE1, 0xE2, 0xE1, 0xD8, 0xE1, 0xE2, 0xDF, 0xD9, 0xD8, 0xE1, 0xDF, 0xDC, 0xD9, 0xD8,
|
||||
prizes = [0xD8, 0xD8, 0xD8, 0xD8, 0xD9, 0xD8, 0xD8, 0xD9, 0xDA, 0xD9, 0xDA, 0xDB, 0xDA, 0xD9, 0xDA, 0xDA, 0xE0,
|
||||
0xDF, 0xDF, 0xDA, 0xE0, 0xDF, 0xD8, 0xDF,
|
||||
0xDC, 0xDC, 0xDC, 0xDD, 0xDC, 0xDC, 0xDE, 0xDC, 0xE1, 0xD8, 0xE1, 0xE2, 0xE1, 0xD8, 0xE1, 0xE2, 0xDF,
|
||||
0xD9, 0xD8, 0xE1, 0xDF, 0xDC, 0xD9, 0xD8,
|
||||
0xD8, 0xE3, 0xE0, 0xDB, 0xDE, 0xD8, 0xDB, 0xE2, 0xD9, 0xDA, 0xDB, 0xD9, 0xDB, 0xD9, 0xDB]
|
||||
dig_prizes = [0xB2, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8,
|
||||
0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA,
|
||||
|
@ -962,12 +985,19 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
# enable Waterfall fairy chests
|
||||
rom.write_bytes(0xE9AE, [0x14, 0x01])
|
||||
rom.write_bytes(0xE9CF, [0x14, 0x01])
|
||||
rom.write_bytes(0x1F714, [225, 0, 16, 172, 13, 41, 154, 1, 88, 152, 15, 17, 177, 97, 252, 77, 129, 32, 218, 2, 44, 225, 97, 252, 190, 129, 97, 177, 98, 84, 218, 2,
|
||||
253, 141, 131, 68, 225, 98, 253, 30, 131, 49, 165, 201, 49, 164, 105, 49, 192, 34, 77, 164, 105, 49, 198, 249, 73, 198, 249, 16, 153, 160, 92, 153,
|
||||
162, 11, 152, 96, 13, 232, 192, 85, 232, 192, 11, 146, 0, 115, 152, 96, 254, 105, 0, 152, 163, 97, 254, 107, 129, 254, 171, 133, 169, 200, 97, 254,
|
||||
174, 129, 255, 105, 2, 216, 163, 98, 255, 107, 131, 255, 43, 135, 201, 200, 98, 255, 46, 131, 254, 161, 0, 170, 33, 97, 254, 166, 129, 255, 33, 2,
|
||||
202, 33, 98, 255, 38, 131, 187, 35, 250, 195, 35, 250, 187, 43, 250, 195, 43, 250, 187, 83, 250, 195, 83, 250, 176, 160, 61, 152, 19, 192, 152, 82,
|
||||
192, 136, 0, 96, 144, 0, 96, 232, 0, 96, 240, 0, 96, 152, 202, 192, 216, 202, 192, 216, 19, 192, 216, 82, 192, 252, 189, 133, 253, 29, 135, 255,
|
||||
rom.write_bytes(0x1F714,
|
||||
[225, 0, 16, 172, 13, 41, 154, 1, 88, 152, 15, 17, 177, 97, 252, 77, 129, 32, 218, 2, 44, 225, 97,
|
||||
252, 190, 129, 97, 177, 98, 84, 218, 2,
|
||||
253, 141, 131, 68, 225, 98, 253, 30, 131, 49, 165, 201, 49, 164, 105, 49, 192, 34, 77, 164, 105,
|
||||
49, 198, 249, 73, 198, 249, 16, 153, 160, 92, 153,
|
||||
162, 11, 152, 96, 13, 232, 192, 85, 232, 192, 11, 146, 0, 115, 152, 96, 254, 105, 0, 152, 163, 97,
|
||||
254, 107, 129, 254, 171, 133, 169, 200, 97, 254,
|
||||
174, 129, 255, 105, 2, 216, 163, 98, 255, 107, 131, 255, 43, 135, 201, 200, 98, 255, 46, 131, 254,
|
||||
161, 0, 170, 33, 97, 254, 166, 129, 255, 33, 2,
|
||||
202, 33, 98, 255, 38, 131, 187, 35, 250, 195, 35, 250, 187, 43, 250, 195, 43, 250, 187, 83, 250,
|
||||
195, 83, 250, 176, 160, 61, 152, 19, 192, 152, 82,
|
||||
192, 136, 0, 96, 144, 0, 96, 232, 0, 96, 240, 0, 96, 152, 202, 192, 216, 202, 192, 216, 19, 192,
|
||||
216, 82, 192, 252, 189, 133, 253, 29, 135, 255,
|
||||
255, 255, 255, 240, 255, 128, 46, 97, 14, 129, 14, 255, 255])
|
||||
# set Waterfall fairy prizes to be disappointing
|
||||
rom.write_byte(0x348DB, 0x3A) # Red Boomerang becomes Red Boomerang
|
||||
|
@ -976,7 +1006,6 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
# Remove Statues for upgrade fairy
|
||||
rom.write_bytes(0x01F810, [0x1A, 0x1E, 0x01, 0x1A, 0x1E, 0x01])
|
||||
|
||||
|
||||
rom.write_byte(0x180029, 0x01) # Smithy quick item give
|
||||
|
||||
# set swordless mode settings
|
||||
|
@ -1049,11 +1078,14 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
rom.write_byte(0x180211, gametype) # Game type
|
||||
|
||||
# assorted fixes
|
||||
rom.write_byte(0x1800A2, 0x01 if world.fix_fake_world[player] else 0x00) # Toggle whether to be in real/fake dark world when dying in a DW dungeon before killing aga1
|
||||
rom.write_byte(0x180169, 0x01 if world.lock_aga_door_in_escape else 0x00) # Lock or unlock aga tower door during escape sequence.
|
||||
rom.write_byte(0x1800A2, 0x01 if world.fix_fake_world[
|
||||
player] else 0x00) # Toggle whether to be in real/fake dark world when dying in a DW dungeon before killing aga1
|
||||
rom.write_byte(0x180169,
|
||||
0x01 if world.lock_aga_door_in_escape else 0x00) # Lock or unlock aga tower door during escape sequence.
|
||||
if world.mode[player] == 'inverted':
|
||||
rom.write_byte(0x180169, 0x02) # lock aga/ganon tower door with crystals in inverted
|
||||
rom.write_byte(0x180171, 0x01 if world.ganon_at_pyramid[player] else 0x00) # Enable respawning on pyramid after ganon death
|
||||
rom.write_byte(0x180171,
|
||||
0x01 if world.ganon_at_pyramid[player] else 0x00) # Enable respawning on pyramid after ganon death
|
||||
rom.write_byte(0x180173, 0x01) # Bob is enabled
|
||||
rom.write_byte(0x180168, 0x08) # Spike Cave Damage
|
||||
rom.write_bytes(0x18016B, [0x04, 0x02, 0x01]) # Set spike cave and MM spike room Cape usage
|
||||
|
@ -1062,7 +1094,8 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
rom.write_byte(0x50599, 0x00) # disable below ganon chest
|
||||
rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest
|
||||
rom.write_byte(0x18008B, 0x01 if world.open_pyramid[player] else 0x00) # pre-open Pyramid Hole
|
||||
rom.write_byte(0x18008C, 0x01 if world.crystals_needed_for_gt[player] == 0 else 0x00) # GT pre-opened if crystal requirement is 0
|
||||
rom.write_byte(0x18008C, 0x01 if world.crystals_needed_for_gt[
|
||||
player] == 0 else 0x00) # GT pre-opened if crystal requirement is 0
|
||||
rom.write_byte(0xF5D73, 0xF0) # bees are catchable
|
||||
rom.write_byte(0xF5F10, 0xF0) # bees are catchable
|
||||
rom.write_byte(0x180086, 0x00 if world.aga_randomness else 0x01) # set blue ball and ganon warp randomness
|
||||
|
@ -1139,9 +1172,12 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
'Magic Upgrade (1/4)', 'Magic Upgrade (1/2)'}:
|
||||
continue
|
||||
|
||||
set_table = {'Book of Mudora': (0x34E, 1), 'Hammer': (0x34B, 1), 'Bug Catching Net': (0x34D, 1), 'Hookshot': (0x342, 1), 'Magic Mirror': (0x353, 2),
|
||||
'Cape': (0x352, 1), 'Lamp': (0x34A, 1), 'Moon Pearl': (0x357, 1), 'Cane of Somaria': (0x350, 1), 'Cane of Byrna': (0x351, 1),
|
||||
'Fire Rod': (0x345, 1), 'Ice Rod': (0x346, 1), 'Bombos': (0x347, 1), 'Ether': (0x348, 1), 'Quake': (0x349, 1)}
|
||||
set_table = {'Book of Mudora': (0x34E, 1), 'Hammer': (0x34B, 1), 'Bug Catching Net': (0x34D, 1),
|
||||
'Hookshot': (0x342, 1), 'Magic Mirror': (0x353, 2),
|
||||
'Cape': (0x352, 1), 'Lamp': (0x34A, 1), 'Moon Pearl': (0x357, 1), 'Cane of Somaria': (0x350, 1),
|
||||
'Cane of Byrna': (0x351, 1),
|
||||
'Fire Rod': (0x345, 1), 'Ice Rod': (0x346, 1), 'Bombos': (0x347, 1), 'Ether': (0x348, 1),
|
||||
'Quake': (0x349, 1)}
|
||||
or_table = {'Green Pendant': (0x374, 0x04), 'Red Pendant': (0x374, 0x01), 'Blue Pendant': (0x374, 0x02),
|
||||
'Crystal 1': (0x37A, 0x02), 'Crystal 2': (0x37A, 0x10), 'Crystal 3': (0x37A, 0x40),
|
||||
'Crystal 4': (0x37A, 0x20),
|
||||
|
@ -1172,7 +1208,8 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
'Map (Misery Mire)': (0x369, 0x01),
|
||||
'Big Key (Turtle Rock)': (0x366, 0x08), 'Compass (Turtle Rock)': (0x364, 0x08),
|
||||
'Map (Turtle Rock)': (0x368, 0x08),
|
||||
'Big Key (Ganons Tower)': (0x366, 0x04), 'Compass (Ganons Tower)': (0x364, 0x04), 'Map (Ganons Tower)': (0x368, 0x04)}
|
||||
'Big Key (Ganons Tower)': (0x366, 0x04), 'Compass (Ganons Tower)': (0x364, 0x04),
|
||||
'Map (Ganons Tower)': (0x368, 0x04)}
|
||||
set_or_table = {'Flippers': (0x356, 1, 0x379, 0x02), 'Pegasus Boots': (0x355, 1, 0x379, 0x04),
|
||||
'Shovel': (0x34C, 1, 0x38C, 0x04), 'Flute': (0x34C, 3, 0x38C, 0x01),
|
||||
'Mushroom': (0x344, 1, 0x38C, 0x20 | 0x08), 'Magic Powder': (0x344, 2, 0x38C, 0x10),
|
||||
|
@ -1188,7 +1225,8 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
'Small Key (Universal)': [0x38B], 'Small Key (Hyrule Castle)': [0x37C, 0x37D]}
|
||||
bottles = {'Bottle': 2, 'Bottle (Red Potion)': 3, 'Bottle (Green Potion)': 4, 'Bottle (Blue Potion)': 5,
|
||||
'Bottle (Fairy)': 6, 'Bottle (Bee)': 7, 'Bottle (Good Bee)': 8}
|
||||
rupees = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)': 50, 'Rupees (100)': 100, 'Rupees (300)': 300}
|
||||
rupees = {'Rupee (1)': 1, 'Rupees (5)': 5, 'Rupees (20)': 20, 'Rupees (50)': 50, 'Rupees (100)': 100,
|
||||
'Rupees (300)': 300}
|
||||
bomb_caps = {'Bomb Upgrade (+5)': 5, 'Bomb Upgrade (+10)': 10}
|
||||
arrow_caps = {'Arrow Upgrade (+5)': 5, 'Arrow Upgrade (+10)': 10}
|
||||
bombs = {'Single Bomb': 1, 'Bombs (3)': 3, 'Bombs (10)': 10}
|
||||
|
@ -1209,8 +1247,12 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
equip[0x35C + equip[0x34F]] = bottles[item.name]
|
||||
equip[0x34F] += 1
|
||||
elif item.name in rupees:
|
||||
equip[0x360:0x362] = list(min(equip[0x360] + (equip[0x361] << 8) + rupees[item.name], 9999).to_bytes(2, byteorder='little', signed=False))
|
||||
equip[0x362:0x364] = list(min(equip[0x362] + (equip[0x363] << 8) + rupees[item.name], 9999).to_bytes(2, byteorder='little', signed=False))
|
||||
equip[0x360:0x362] = list(
|
||||
min(equip[0x360] + (equip[0x361] << 8) + rupees[item.name], 9999).to_bytes(2, byteorder='little',
|
||||
signed=False))
|
||||
equip[0x362:0x364] = list(
|
||||
min(equip[0x362] + (equip[0x363] << 8) + rupees[item.name], 9999).to_bytes(2, byteorder='little',
|
||||
signed=False))
|
||||
elif item.name in bomb_caps:
|
||||
starting_max_bombs = min(starting_max_bombs + bomb_caps[item.name], 50)
|
||||
elif item.name in arrow_caps:
|
||||
|
@ -1394,7 +1436,8 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
rom.write_bytes(0x180185, [0, 50, 0]) # Uncle respawn refills (magic, bombs, arrows)
|
||||
rom.write_bytes(0x180188, [0, 3, 0]) # Zelda respawn refills (magic, bombs, arrows)
|
||||
rom.write_bytes(0x18018B, [0, 3, 0]) # Mantle respawn refills (magic, bombs, arrows)
|
||||
elif uncle_location.item is not None and uncle_location.item.name in ['Cane of Somaria', 'Cane of Byrna', 'Fire Rod']:
|
||||
elif uncle_location.item is not None and uncle_location.item.name in ['Cane of Somaria', 'Cane of Byrna',
|
||||
'Fire Rod']:
|
||||
rom.write_byte(0x18004E, 4) # Escape Fill (magic)
|
||||
rom.write_bytes(0x180185, [0x80, 0, 0]) # Uncle respawn refills (magic, bombs, arrows)
|
||||
rom.write_bytes(0x180188, [0x20, 0, 0]) # Zelda respawn refills (magic, bombs, arrows)
|
||||
|
@ -1405,10 +1448,13 @@ def patch_rom(world, rom, player, team, enemized):
|
|||
|
||||
# powder patch: remove the need to leave the screen after powder, since it causes problems for potion shop at race game
|
||||
# temporarally we are just nopping out this check we will conver this to a rom fix soon.
|
||||
rom.write_bytes(0x02F539, [0xEA, 0xEA, 0xEA, 0xEA, 0xEA] if world.powder_patch_required[player] else [0xAD, 0xBF, 0x0A, 0xF0, 0x4F])
|
||||
rom.write_bytes(0x02F539,
|
||||
[0xEA, 0xEA, 0xEA, 0xEA, 0xEA] if world.powder_patch_required[player] else [0xAD, 0xBF, 0x0A, 0xF0,
|
||||
0x4F])
|
||||
|
||||
# allow smith into multi-entrance caves in appropriate shuffles
|
||||
if world.shuffle[player] in ['restricted', 'full', 'crossed', 'insanity'] or (world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'):
|
||||
if world.shuffle[player] in ['restricted', 'full', 'crossed', 'insanity'] or (
|
||||
world.shuffle[player] == 'simple' and world.mode[player] == 'inverted'):
|
||||
rom.write_byte(0x18004C, 0x01)
|
||||
|
||||
# set correct flag for hera basement item
|
||||
|
@ -1462,6 +1508,7 @@ def patch_race_rom(rom, world, player):
|
|||
rom.write_bytes(0x180213, [0x01, 0x00]) # Tournament Seed
|
||||
rom.encrypt(world, player)
|
||||
|
||||
|
||||
def write_custom_shops(rom, world, player):
|
||||
shops = [shop for shop in world.shops if shop.custom and shop.region.player == player]
|
||||
|
||||
|
@ -1484,7 +1531,10 @@ def write_custom_shops(rom, world, player):
|
|||
for item in shop.inventory:
|
||||
if item is None:
|
||||
break
|
||||
item_data = [shop_id, ItemFactory(item['item'], player).code] + int16_as_bytes(item['price']) + [item['max'], ItemFactory(item['replacement'], player).code if item['replacement'] else 0xFF] + int16_as_bytes(item['replacement_price'])
|
||||
item_data = [shop_id, ItemFactory(item['item'], player).code] + int16_as_bytes(item['price']) + [
|
||||
item['max'],
|
||||
ItemFactory(item['replacement'], player).code if item['replacement'] else 0xFF] + int16_as_bytes(
|
||||
item['replacement_price'])
|
||||
items_data.extend(item_data)
|
||||
|
||||
rom.write_bytes(0x184800, shop_data)
|
||||
|
@ -1511,11 +1561,11 @@ def hud_format_text(text):
|
|||
return output[:32]
|
||||
|
||||
|
||||
|
||||
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, palettes_options, world=None, player=1, allow_random_on_event=False):
|
||||
|
||||
def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite: str, palettes_options,
|
||||
world=None, player=1, allow_random_on_event=False):
|
||||
local_random = random if not world else world.rom_seeds[player]
|
||||
apply_random_sprite_on_event(rom, sprite, local_random, allow_random_on_event, world.sprite_pool[player] if world else [])
|
||||
apply_random_sprite_on_event(rom, sprite, local_random, allow_random_on_event,
|
||||
world.sprite_pool[player] if world else [])
|
||||
|
||||
# enable instant item menu
|
||||
if fastmenu == 'instant':
|
||||
|
@ -1543,8 +1593,12 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
|
|||
|
||||
rom.write_byte(0x0CFE18, 0x00 if disable_music else rom.orig_buffer[0x0CFE18] if rom.orig_buffer else 0x70)
|
||||
rom.write_byte(0x0CFEC1, 0x00 if disable_music else rom.orig_buffer[0x0CFEC1] if rom.orig_buffer else 0xC0)
|
||||
rom.write_bytes(0x0D0000, [0x00, 0x00] if disable_music else rom.orig_buffer[0x0D0000:0x0D0002] if rom.orig_buffer else [0xDA, 0x58])
|
||||
rom.write_bytes(0x0D00E7, [0xC4, 0x58] if disable_music else rom.orig_buffer[0x0D00E7:0x0D00E9] if rom.orig_buffer else [0xDA, 0x58])
|
||||
rom.write_bytes(0x0D0000,
|
||||
[0x00, 0x00] if disable_music else rom.orig_buffer[0x0D0000:0x0D0002] if rom.orig_buffer else [0xDA,
|
||||
0x58])
|
||||
rom.write_bytes(0x0D00E7,
|
||||
[0xC4, 0x58] if disable_music else rom.orig_buffer[0x0D00E7:0x0D00E9] if rom.orig_buffer else [0xDA,
|
||||
0x58])
|
||||
|
||||
rom.write_byte(0x18021A, 1 if disable_music else 0x00)
|
||||
|
||||
|
@ -1566,14 +1620,11 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
|
|||
rom.write_byte(0x6FA30, {'red': 0x24, 'blue': 0x2C, 'green': 0x3C, 'yellow': 0x28}[color])
|
||||
rom.write_byte(0x65561, {'red': 0x05, 'blue': 0x0D, 'green': 0x19, 'yellow': 0x09}[color])
|
||||
|
||||
|
||||
# write link sprite if required
|
||||
if sprite:
|
||||
sprite = Sprite(sprite) if os.path.isfile(sprite) else Sprite.get_sprite_from_name(sprite, local_random)
|
||||
sprite.write_to_rom(rom)
|
||||
|
||||
|
||||
|
||||
|
||||
if z3pr:
|
||||
def buildAndRandomize(option_name, mode):
|
||||
options = {
|
||||
|
@ -1586,9 +1637,11 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
|
|||
if mode == 'default':
|
||||
return
|
||||
ColorF = z3pr.ColorF
|
||||
|
||||
def next_color_generator():
|
||||
while True:
|
||||
yield ColorF(local_random.random(), local_random.random(), local_random.random())
|
||||
|
||||
if mode == 'random':
|
||||
mode = 'maseya'
|
||||
z3pr.randomize(rom.buffer, mode, offset_collections=offsets_array, random_colors=next_color_generator())
|
||||
|
@ -1613,19 +1666,19 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
|
|||
default_uw_palettes(rom)
|
||||
logging.warning("Could not find z3pr palette shuffle. "
|
||||
"If you want improved palette shuffling please install the maseya-z3pr package.")
|
||||
if ow_palettes == 'random':
|
||||
if palettes_options['overworld'] == 'random':
|
||||
randomize_ow_palettes(rom, local_random)
|
||||
if uw_palettes == 'random':
|
||||
randomize_uw_palettes(rom, local_random)
|
||||
|
||||
if ow_palettes == 'blackout':
|
||||
elif palettes_options['overworld'] == 'blackout':
|
||||
blackout_ow_palettes(rom)
|
||||
if uw_palettes == 'blackout':
|
||||
blackout_uw_palettes(rom)
|
||||
|
||||
if palettes_options['dungeon'] == 'blackout':
|
||||
blackout_uw_palettes(rom)
|
||||
elif palettes_options['dungeon'] == 'random':
|
||||
randomize_uw_palettes(rom, local_random)
|
||||
if isinstance(rom, LocalRom):
|
||||
rom.write_crc()
|
||||
|
||||
|
||||
def restore_maseya_colors(rom, offsets_array):
|
||||
if not rom.orig_buffer:
|
||||
return
|
||||
|
@ -1633,6 +1686,7 @@ def restore_maseya_colors(rom,offsets_array):
|
|||
for address in offsetC:
|
||||
rom.write_bytes(address, rom.orig_buffer[address:address + 2])
|
||||
|
||||
|
||||
def set_color(rom, address, color, shade):
|
||||
r = round(min(color[0], 0xFF) * pow(0.8, shade) * 0x1F / 0xFF)
|
||||
g = round(min(color[1], 0xFF) * pow(0.8, shade) * 0x1F / 0xFF)
|
||||
|
@ -1640,6 +1694,7 @@ def set_color(rom, address, color, shade):
|
|||
|
||||
rom.write_bytes(address, ((b << 10) | (g << 5) | (r << 0)).to_bytes(2, byteorder='little', signed=False))
|
||||
|
||||
|
||||
def default_ow_palettes(rom):
|
||||
if not rom.orig_buffer:
|
||||
return
|
||||
|
@ -1648,49 +1703,83 @@ def default_ow_palettes(rom):
|
|||
for address in [0x067FB4, 0x067F94, 0x067FC6, 0x067FE6, 0x067FE1, 0x05FEA9, 0x05FEB3]:
|
||||
rom.write_bytes(address, rom.orig_buffer[address:address + 2])
|
||||
|
||||
|
||||
def randomize_ow_palettes(rom, local_random):
|
||||
grass, grass2, grass3, dirt, dirt2, water, clouds, dwdirt, \
|
||||
dwgrass, dwwater, dwdmdirt, dwdmgrass, dwdmclouds1, dwdmclouds2 = [[local_random.randint(60, 215) for _ in range(3)] for _ in range(14)]
|
||||
dwgrass, dwwater, dwdmdirt, dwdmgrass, dwdmclouds1, dwdmclouds2 = [[local_random.randint(60, 215) for _ in range(3)]
|
||||
for _ in range(14)]
|
||||
dwtree = [c + local_random.randint(-20, 10) for c in dwgrass]
|
||||
treeleaf = [c + local_random.randint(-20, 10) for c in grass]
|
||||
|
||||
patches = {0x067FB4: (grass, 0), 0x067F94: (grass, 0), 0x067FC6: (grass, 0), 0x067FE6: (grass, 0), 0x067FE1: (grass, 3), 0x05FEA9: (grass, 0), 0x05FEB3: (dwgrass, 1),
|
||||
0x0DD4AC: (grass, 2), 0x0DE6DE: (grass2, 2), 0x0DE6E0: (grass2, 1), 0x0DD4AE: (grass2, 1), 0x0DE9FA: (grass2, 1), 0x0DEA0E: (grass2, 1), 0x0DE9FE: (grass2, 0),
|
||||
0x0DD3D2: (grass2, 2), 0x0DE88C: (grass2, 2), 0x0DE8A8: (grass2, 2), 0x0DE9F8: (grass2, 2), 0x0DEA4E: (grass2, 2), 0x0DEAF6: (grass2, 2), 0x0DEB2E: (grass2, 2), 0x0DEB4A: (grass2, 2),
|
||||
0x0DE892: (grass, 1), 0x0DE886: (grass, 0), 0x0DE6D2: (grass, 0), 0x0DE6FA: (grass, 3), 0x0DE6FC: (grass, 0), 0x0DE6FE: (grass, 0), 0x0DE70A: (grass, 0), 0x0DE708: (grass, 2), 0x0DE70C: (grass, 1),
|
||||
0x0DE6D4: (dirt, 2), 0x0DE6CA: (dirt, 5), 0x0DE6CC: (dirt, 4), 0x0DE6CE: (dirt, 3), 0x0DE6E2: (dirt, 2), 0x0DE6D8: (dirt, 5), 0x0DE6DA: (dirt, 4), 0x0DE6DC: (dirt, 2),
|
||||
0x0DE6F0: (dirt, 2), 0x0DE6E6: (dirt, 5), 0x0DE6E8: (dirt, 4), 0x0DE6EA: (dirt, 2), 0x0DE6EC: (dirt, 4), 0x0DE6EE: (dirt, 2),
|
||||
patches = {0x067FB4: (grass, 0), 0x067F94: (grass, 0), 0x067FC6: (grass, 0), 0x067FE6: (grass, 0),
|
||||
0x067FE1: (grass, 3), 0x05FEA9: (grass, 0), 0x05FEB3: (dwgrass, 1),
|
||||
0x0DD4AC: (grass, 2), 0x0DE6DE: (grass2, 2), 0x0DE6E0: (grass2, 1), 0x0DD4AE: (grass2, 1),
|
||||
0x0DE9FA: (grass2, 1), 0x0DEA0E: (grass2, 1), 0x0DE9FE: (grass2, 0),
|
||||
0x0DD3D2: (grass2, 2), 0x0DE88C: (grass2, 2), 0x0DE8A8: (grass2, 2), 0x0DE9F8: (grass2, 2),
|
||||
0x0DEA4E: (grass2, 2), 0x0DEAF6: (grass2, 2), 0x0DEB2E: (grass2, 2), 0x0DEB4A: (grass2, 2),
|
||||
0x0DE892: (grass, 1), 0x0DE886: (grass, 0), 0x0DE6D2: (grass, 0), 0x0DE6FA: (grass, 3),
|
||||
0x0DE6FC: (grass, 0), 0x0DE6FE: (grass, 0), 0x0DE70A: (grass, 0), 0x0DE708: (grass, 2),
|
||||
0x0DE70C: (grass, 1),
|
||||
0x0DE6D4: (dirt, 2), 0x0DE6CA: (dirt, 5), 0x0DE6CC: (dirt, 4), 0x0DE6CE: (dirt, 3), 0x0DE6E2: (dirt, 2),
|
||||
0x0DE6D8: (dirt, 5), 0x0DE6DA: (dirt, 4), 0x0DE6DC: (dirt, 2),
|
||||
0x0DE6F0: (dirt, 2), 0x0DE6E6: (dirt, 5), 0x0DE6E8: (dirt, 4), 0x0DE6EA: (dirt, 2), 0x0DE6EC: (dirt, 4),
|
||||
0x0DE6EE: (dirt, 2),
|
||||
0x0DE91E: (grass, 0),
|
||||
0x0DE920: (dirt, 2), 0x0DE916: (dirt, 3), 0x0DE934: (dirt, 3),
|
||||
0x0DE92C: (grass, 0), 0x0DE93A: (grass, 0), 0x0DE91C: (grass, 1), 0x0DE92A: (grass, 1), 0x0DEA1C: (grass, 0), 0x0DEA2A: (grass, 0), 0x0DEA30: (grass, 0),
|
||||
0x0DE92C: (grass, 0), 0x0DE93A: (grass, 0), 0x0DE91C: (grass, 1), 0x0DE92A: (grass, 1),
|
||||
0x0DEA1C: (grass, 0), 0x0DEA2A: (grass, 0), 0x0DEA30: (grass, 0),
|
||||
0x0DEA2E: (dirt, 5),
|
||||
0x0DE884: (grass, 3), 0x0DE8AE: (grass, 3), 0x0DE8BE: (grass, 3), 0x0DE8E4: (grass, 3), 0x0DE938: (grass, 3), 0x0DE9C4: (grass, 3), 0x0DE6D0: (grass, 4),
|
||||
0x0DE884: (grass, 3), 0x0DE8AE: (grass, 3), 0x0DE8BE: (grass, 3), 0x0DE8E4: (grass, 3),
|
||||
0x0DE938: (grass, 3), 0x0DE9C4: (grass, 3), 0x0DE6D0: (grass, 4),
|
||||
0x0DE890: (treeleaf, 1), 0x0DE894: (treeleaf, 0),
|
||||
0x0DE924: (water, 3), 0x0DE668: (water, 3), 0x0DE66A: (water, 2), 0x0DE670: (water, 1), 0x0DE918: (water, 1), 0x0DE66C: (water, 0), 0x0DE91A: (water, 0), 0x0DE92E: (water, 1), 0x0DEA1A: (water, 1), 0x0DEA16: (water, 3), 0x0DEA10: (water, 4),
|
||||
0x0DE924: (water, 3), 0x0DE668: (water, 3), 0x0DE66A: (water, 2), 0x0DE670: (water, 1),
|
||||
0x0DE918: (water, 1), 0x0DE66C: (water, 0), 0x0DE91A: (water, 0), 0x0DE92E: (water, 1),
|
||||
0x0DEA1A: (water, 1), 0x0DEA16: (water, 3), 0x0DEA10: (water, 4),
|
||||
0x0DE66E: (dirt, 3), 0x0DE672: (dirt, 2), 0x0DE932: (dirt, 4), 0x0DE936: (dirt, 2), 0x0DE93C: (dirt, 1),
|
||||
0x0DE756: (dirt2, 4), 0x0DE764: (dirt2, 4), 0x0DE772: (dirt2, 4), 0x0DE994: (dirt2, 4), 0x0DE9A2: (dirt2, 4), 0x0DE758: (dirt2, 3), 0x0DE766: (dirt2, 3), 0x0DE774: (dirt2, 3),
|
||||
0x0DE996: (dirt2, 3), 0x0DE9A4: (dirt2, 3), 0x0DE75A: (dirt2, 2), 0x0DE768: (dirt2, 2), 0x0DE776: (dirt2, 2), 0x0DE778: (dirt2, 2), 0x0DE998: (dirt2, 2), 0x0DE9A6: (dirt2, 2),
|
||||
0x0DE9AC: (dirt2, 1), 0x0DE99E: (dirt2, 1), 0x0DE760: (dirt2, 1), 0x0DE77A: (dirt2, 1), 0x0DE77C: (dirt2, 1), 0x0DE798: (dirt2, 1), 0x0DE980: (dirt2, 1),
|
||||
0x0DE75C: (grass3, 2), 0x0DE786: (grass3, 2), 0x0DE794: (grass3, 2), 0x0DE99A: (grass3, 2), 0x0DE75E: (grass3, 1), 0x0DE788: (grass3, 1), 0x0DE796: (grass3, 1), 0x0DE99C: (grass3, 1),
|
||||
0x0DE76A: (clouds, 2), 0x0DE9A8: (clouds, 2), 0x0DE76E: (clouds, 0), 0x0DE9AA: (clouds, 0), 0x0DE8DA: (clouds, 0), 0x0DE8D8: (clouds, 0), 0x0DE8D0: (clouds, 0), 0x0DE98C: (clouds, 2), 0x0DE990: (clouds, 0),
|
||||
0x0DE756: (dirt2, 4), 0x0DE764: (dirt2, 4), 0x0DE772: (dirt2, 4), 0x0DE994: (dirt2, 4),
|
||||
0x0DE9A2: (dirt2, 4), 0x0DE758: (dirt2, 3), 0x0DE766: (dirt2, 3), 0x0DE774: (dirt2, 3),
|
||||
0x0DE996: (dirt2, 3), 0x0DE9A4: (dirt2, 3), 0x0DE75A: (dirt2, 2), 0x0DE768: (dirt2, 2),
|
||||
0x0DE776: (dirt2, 2), 0x0DE778: (dirt2, 2), 0x0DE998: (dirt2, 2), 0x0DE9A6: (dirt2, 2),
|
||||
0x0DE9AC: (dirt2, 1), 0x0DE99E: (dirt2, 1), 0x0DE760: (dirt2, 1), 0x0DE77A: (dirt2, 1),
|
||||
0x0DE77C: (dirt2, 1), 0x0DE798: (dirt2, 1), 0x0DE980: (dirt2, 1),
|
||||
0x0DE75C: (grass3, 2), 0x0DE786: (grass3, 2), 0x0DE794: (grass3, 2), 0x0DE99A: (grass3, 2),
|
||||
0x0DE75E: (grass3, 1), 0x0DE788: (grass3, 1), 0x0DE796: (grass3, 1), 0x0DE99C: (grass3, 1),
|
||||
0x0DE76A: (clouds, 2), 0x0DE9A8: (clouds, 2), 0x0DE76E: (clouds, 0), 0x0DE9AA: (clouds, 0),
|
||||
0x0DE8DA: (clouds, 0), 0x0DE8D8: (clouds, 0), 0x0DE8D0: (clouds, 0), 0x0DE98C: (clouds, 2),
|
||||
0x0DE990: (clouds, 0),
|
||||
0x0DEB34: (dwtree, 4), 0x0DEB30: (dwtree, 3), 0x0DEB32: (dwtree, 1),
|
||||
0x0DE710: (dwdirt, 5), 0x0DE71E: (dwdirt, 5), 0x0DE72C: (dwdirt, 5), 0x0DEAD6: (dwdirt, 5), 0x0DE712: (dwdirt, 4), 0x0DE720: (dwdirt, 4), 0x0DE72E: (dwdirt, 4), 0x0DE660: (dwdirt, 4),
|
||||
0x0DEAD8: (dwdirt, 4), 0x0DEADA: (dwdirt, 3), 0x0DE714: (dwdirt, 3), 0x0DE722: (dwdirt, 3), 0x0DE730: (dwdirt, 3), 0x0DE732: (dwdirt, 3), 0x0DE734: (dwdirt, 2), 0x0DE736: (dwdirt, 2),
|
||||
0x0DE710: (dwdirt, 5), 0x0DE71E: (dwdirt, 5), 0x0DE72C: (dwdirt, 5), 0x0DEAD6: (dwdirt, 5),
|
||||
0x0DE712: (dwdirt, 4), 0x0DE720: (dwdirt, 4), 0x0DE72E: (dwdirt, 4), 0x0DE660: (dwdirt, 4),
|
||||
0x0DEAD8: (dwdirt, 4), 0x0DEADA: (dwdirt, 3), 0x0DE714: (dwdirt, 3), 0x0DE722: (dwdirt, 3),
|
||||
0x0DE730: (dwdirt, 3), 0x0DE732: (dwdirt, 3), 0x0DE734: (dwdirt, 2), 0x0DE736: (dwdirt, 2),
|
||||
0x0DE728: (dwdirt, 2), 0x0DE71A: (dwdirt, 2), 0x0DE664: (dwdirt, 2), 0x0DEAE0: (dwdirt, 2),
|
||||
0x0DE716: (dwgrass, 3), 0x0DE740: (dwgrass, 3), 0x0DE74E: (dwgrass, 3), 0x0DEAC0: (dwgrass, 3), 0x0DEACE: (dwgrass, 3), 0x0DEADC: (dwgrass, 3), 0x0DEB24: (dwgrass, 3), 0x0DE752: (dwgrass, 2),
|
||||
0x0DE718: (dwgrass, 1), 0x0DE742: (dwgrass, 1), 0x0DE750: (dwgrass, 1), 0x0DEB26: (dwgrass, 1), 0x0DEAC2: (dwgrass, 1), 0x0DEAD0: (dwgrass, 1), 0x0DEADE: (dwgrass, 1),
|
||||
0x0DE65A: (dwwater, 5), 0x0DE65C: (dwwater, 3), 0x0DEAC8: (dwwater, 3), 0x0DEAD2: (dwwater, 2), 0x0DEABC: (dwwater, 2), 0x0DE662: (dwwater, 2), 0x0DE65E: (dwwater, 1), 0x0DEABE: (dwwater, 1), 0x0DEA98: (dwwater, 2),
|
||||
0x0DE79A: (dwdmdirt, 6), 0x0DE7A8: (dwdmdirt, 6), 0x0DE7B6: (dwdmdirt, 6), 0x0DEB60: (dwdmdirt, 6), 0x0DEB6E: (dwdmdirt, 6), 0x0DE93E: (dwdmdirt, 6), 0x0DE94C: (dwdmdirt, 6), 0x0DEBA6: (dwdmdirt, 6),
|
||||
0x0DE79C: (dwdmdirt, 4), 0x0DE7AA: (dwdmdirt, 4), 0x0DE7B8: (dwdmdirt, 4), 0x0DEB70: (dwdmdirt, 4), 0x0DEBA8: (dwdmdirt, 4), 0x0DEB72: (dwdmdirt, 3), 0x0DEB74: (dwdmdirt, 3), 0x0DE79E: (dwdmdirt, 3), 0x0DE7AC: (dwdmdirt, 3), 0x0DEBAA: (dwdmdirt, 3), 0x0DE7A0: (dwdmdirt, 3),
|
||||
0x0DE716: (dwgrass, 3), 0x0DE740: (dwgrass, 3), 0x0DE74E: (dwgrass, 3), 0x0DEAC0: (dwgrass, 3),
|
||||
0x0DEACE: (dwgrass, 3), 0x0DEADC: (dwgrass, 3), 0x0DEB24: (dwgrass, 3), 0x0DE752: (dwgrass, 2),
|
||||
0x0DE718: (dwgrass, 1), 0x0DE742: (dwgrass, 1), 0x0DE750: (dwgrass, 1), 0x0DEB26: (dwgrass, 1),
|
||||
0x0DEAC2: (dwgrass, 1), 0x0DEAD0: (dwgrass, 1), 0x0DEADE: (dwgrass, 1),
|
||||
0x0DE65A: (dwwater, 5), 0x0DE65C: (dwwater, 3), 0x0DEAC8: (dwwater, 3), 0x0DEAD2: (dwwater, 2),
|
||||
0x0DEABC: (dwwater, 2), 0x0DE662: (dwwater, 2), 0x0DE65E: (dwwater, 1), 0x0DEABE: (dwwater, 1),
|
||||
0x0DEA98: (dwwater, 2),
|
||||
0x0DE79A: (dwdmdirt, 6), 0x0DE7A8: (dwdmdirt, 6), 0x0DE7B6: (dwdmdirt, 6), 0x0DEB60: (dwdmdirt, 6),
|
||||
0x0DEB6E: (dwdmdirt, 6), 0x0DE93E: (dwdmdirt, 6), 0x0DE94C: (dwdmdirt, 6), 0x0DEBA6: (dwdmdirt, 6),
|
||||
0x0DE79C: (dwdmdirt, 4), 0x0DE7AA: (dwdmdirt, 4), 0x0DE7B8: (dwdmdirt, 4), 0x0DEB70: (dwdmdirt, 4),
|
||||
0x0DEBA8: (dwdmdirt, 4), 0x0DEB72: (dwdmdirt, 3), 0x0DEB74: (dwdmdirt, 3), 0x0DE79E: (dwdmdirt, 3),
|
||||
0x0DE7AC: (dwdmdirt, 3), 0x0DEBAA: (dwdmdirt, 3), 0x0DE7A0: (dwdmdirt, 3),
|
||||
0x0DE7BC: (dwdmgrass, 3),
|
||||
0x0DEBAC: (dwdmdirt, 2), 0x0DE7AE: (dwdmdirt, 2), 0x0DE7C2: (dwdmdirt, 2), 0x0DE7A6: (dwdmdirt, 2), 0x0DEB7A: (dwdmdirt, 2), 0x0DEB6C: (dwdmdirt, 2), 0x0DE7C0: (dwdmdirt, 2),
|
||||
0x0DE7A2: (dwdmgrass, 3), 0x0DE7BE: (dwdmgrass, 3), 0x0DE7CC: (dwdmgrass, 3), 0x0DE7DA: (dwdmgrass, 3), 0x0DEB6A: (dwdmgrass, 3), 0x0DE948: (dwdmgrass, 3), 0x0DE956: (dwdmgrass, 3), 0x0DE964: (dwdmgrass, 3), 0x0DE7CE: (dwdmgrass, 1), 0x0DE7A4: (dwdmgrass, 1), 0x0DEBA2: (dwdmgrass, 1), 0x0DEBB0: (dwdmgrass, 1),
|
||||
0x0DE644: (dwdmclouds1, 2), 0x0DEB84: (dwdmclouds1, 2), 0x0DE648: (dwdmclouds1, 1), 0x0DEB88: (dwdmclouds1, 1),
|
||||
0x0DEBAE: (dwdmclouds2, 2), 0x0DE7B0: (dwdmclouds2, 2), 0x0DE7B4: (dwdmclouds2, 0), 0x0DEB78: (dwdmclouds2, 0), 0x0DEBB2: (dwdmclouds2, 0)
|
||||
0x0DEBAC: (dwdmdirt, 2), 0x0DE7AE: (dwdmdirt, 2), 0x0DE7C2: (dwdmdirt, 2), 0x0DE7A6: (dwdmdirt, 2),
|
||||
0x0DEB7A: (dwdmdirt, 2), 0x0DEB6C: (dwdmdirt, 2), 0x0DE7C0: (dwdmdirt, 2),
|
||||
0x0DE7A2: (dwdmgrass, 3), 0x0DE7BE: (dwdmgrass, 3), 0x0DE7CC: (dwdmgrass, 3), 0x0DE7DA: (dwdmgrass, 3),
|
||||
0x0DEB6A: (dwdmgrass, 3), 0x0DE948: (dwdmgrass, 3), 0x0DE956: (dwdmgrass, 3), 0x0DE964: (dwdmgrass, 3),
|
||||
0x0DE7CE: (dwdmgrass, 1), 0x0DE7A4: (dwdmgrass, 1), 0x0DEBA2: (dwdmgrass, 1), 0x0DEBB0: (dwdmgrass, 1),
|
||||
0x0DE644: (dwdmclouds1, 2), 0x0DEB84: (dwdmclouds1, 2), 0x0DE648: (dwdmclouds1, 1),
|
||||
0x0DEB88: (dwdmclouds1, 1),
|
||||
0x0DEBAE: (dwdmclouds2, 2), 0x0DE7B0: (dwdmclouds2, 2), 0x0DE7B4: (dwdmclouds2, 0),
|
||||
0x0DEB78: (dwdmclouds2, 0), 0x0DEBB2: (dwdmclouds2, 0)
|
||||
}
|
||||
for address, (color, shade) in patches.items():
|
||||
set_color(rom, address, color, shade)
|
||||
|
||||
|
||||
def blackout_ow_palettes(rom):
|
||||
rom.write_bytes(0xDE604, [0] * 0xC4)
|
||||
for i in range(0xDE6C8, 0xDE86C, 70):
|
||||
|
@ -1701,11 +1790,13 @@ def blackout_ow_palettes(rom):
|
|||
for address in [0x067FB4, 0x067F94, 0x067FC6, 0x067FE6, 0x067FE1, 0x05FEA9, 0x05FEB3]:
|
||||
rom.write_bytes(address, [0, 0])
|
||||
|
||||
|
||||
def default_uw_palettes(rom):
|
||||
if not rom.orig_buffer:
|
||||
return
|
||||
rom.write_bytes(0xDD734, rom.orig_buffer[0xDD734:0xDE544])
|
||||
|
||||
|
||||
def randomize_uw_palettes(rom, local_random):
|
||||
for dungeon in range(20):
|
||||
wall, pot, chest, floor1, floor2, floor3 = [[local_random.randint(60, 240) for _ in range(3)] for _ in range(6)]
|
||||
|
@ -1752,15 +1843,18 @@ def randomize_uw_palettes(rom, local_random):
|
|||
set_color(rom, 0x0DD7E2 + (0xB4 * dungeon), floor3, 3)
|
||||
set_color(rom, 0x0DD796 + (0xB4 * dungeon), floor3, 4)
|
||||
|
||||
|
||||
def blackout_uw_palettes(rom):
|
||||
for i in range(0xDD734, 0xDE544, 180):
|
||||
rom.write_bytes(i, [0] * 38)
|
||||
rom.write_bytes(i + 44, [0] * 76)
|
||||
rom.write_bytes(i + 136, [0] * 44)
|
||||
|
||||
|
||||
def get_hash_string(hash):
|
||||
return ", ".join([hash_alphabet[code & 0x1F] for code in hash])
|
||||
|
||||
|
||||
def write_string_to_rom(rom, target, string):
|
||||
address, maxbytes = text_addresses[target]
|
||||
rom.write_bytes(address, MultiByteTextMapper.convert(string, maxbytes))
|
||||
|
@ -1812,7 +1906,8 @@ def write_strings(rom, world, player, team):
|
|||
if world.shuffle[player] in ['simple', 'restricted', 'restricted_legacy']:
|
||||
for entrance in all_entrances:
|
||||
if entrance.name in entrances_to_hint:
|
||||
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(entrance.connected_region) + '.'
|
||||
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(
|
||||
entrance.connected_region) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
entrances_to_hint = {}
|
||||
break
|
||||
|
@ -1827,7 +1922,8 @@ def write_strings(rom, world, player, team):
|
|||
for entrance in all_entrances:
|
||||
if entrance.name in entrances_to_hint:
|
||||
if hint_count > 0:
|
||||
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(entrance.connected_region) + '.'
|
||||
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(
|
||||
entrance.connected_region) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
entrances_to_hint.pop(entrance.name)
|
||||
hint_count -= 1
|
||||
|
@ -1863,7 +1959,8 @@ def write_strings(rom, world, player, team):
|
|||
for entrance in all_entrances:
|
||||
if entrance.name in entrances_to_hint:
|
||||
if hint_count > 0:
|
||||
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(entrance.connected_region) + '.'
|
||||
this_hint = entrances_to_hint[entrance.name] + ' leads to ' + hint_text(
|
||||
entrance.connected_region) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
entrances_to_hint.pop(entrance.name)
|
||||
hint_count -= 1
|
||||
|
@ -1897,25 +1994,32 @@ def write_strings(rom, world, player, team):
|
|||
this_hint = ('The westmost chests in Misery Mire contain ' + first_item + ' and ' + second_item + '.')
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
elif location == 'Tower of Hera - Big Key Chest':
|
||||
this_hint = 'Waiting in the Tower of Hera basement leads to ' + hint_text(world.get_location(location, player).item) + '.'
|
||||
this_hint = 'Waiting in the Tower of Hera basement leads to ' + hint_text(
|
||||
world.get_location(location, player).item) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
elif location == 'Ganons Tower - Big Chest':
|
||||
this_hint = 'The big chest in Ganon\'s Tower contains ' + hint_text(world.get_location(location, player).item) + '.'
|
||||
this_hint = 'The big chest in Ganon\'s Tower contains ' + hint_text(
|
||||
world.get_location(location, player).item) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
elif location == 'Thieves\' Town - Big Chest':
|
||||
this_hint = 'The big chest in Thieves\' Town contains ' + hint_text(world.get_location(location, player).item) + '.'
|
||||
this_hint = 'The big chest in Thieves\' Town contains ' + hint_text(
|
||||
world.get_location(location, player).item) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
elif location == 'Ice Palace - Big Chest':
|
||||
this_hint = 'The big chest in Ice Palace contains ' + hint_text(world.get_location(location, player).item) + '.'
|
||||
this_hint = 'The big chest in Ice Palace contains ' + hint_text(
|
||||
world.get_location(location, player).item) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
elif location == 'Eastern Palace - Big Key Chest':
|
||||
this_hint = 'The antifairy guarded chest in Eastern Palace contains ' + hint_text(world.get_location(location, player).item) + '.'
|
||||
this_hint = 'The antifairy guarded chest in Eastern Palace contains ' + hint_text(
|
||||
world.get_location(location, player).item) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
elif location == 'Sahasrahla':
|
||||
this_hint = 'Sahasrahla seeks a green pendant for ' + hint_text(world.get_location(location, player).item) + '.'
|
||||
this_hint = 'Sahasrahla seeks a green pendant for ' + hint_text(
|
||||
world.get_location(location, player).item) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
elif location == 'Graveyard Cave':
|
||||
this_hint = 'The cave north of the graveyard contains ' + hint_text(world.get_location(location, player).item) + '.'
|
||||
this_hint = 'The cave north of the graveyard contains ' + hint_text(
|
||||
world.get_location(location, player).item) + '.'
|
||||
tt[hint_locations.pop(0)] = this_hint
|
||||
else:
|
||||
this_hint = location + ' contains ' + hint_text(world.get_location(location, player).item) + '.'
|
||||
|
@ -1950,19 +2054,21 @@ def write_strings(rom, world, player, team):
|
|||
|
||||
# We still need the older hints of course. Those are done here.
|
||||
|
||||
|
||||
silverarrows = world.find_items('Silver Bow', player)
|
||||
local_random.shuffle(silverarrows)
|
||||
silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
|
||||
silverarrow_hint = (
|
||||
' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
|
||||
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||
|
||||
prog_bow_locs = world.find_items('Progressive Bow', player)
|
||||
distinguished_prog_bow_loc = next((location for location in prog_bow_locs if location.item.code == 0x65), None)
|
||||
progressive_silvers = world.difficulty_requirements[player].progressive_bow_limit >= 2 or (world.swords[player] == 'swordless' or world.logic[player] == 'noglitches')
|
||||
progressive_silvers = world.difficulty_requirements[player].progressive_bow_limit >= 2 or (
|
||||
world.swords[player] == 'swordless' or world.logic[player] == 'noglitches')
|
||||
if distinguished_prog_bow_loc:
|
||||
prog_bow_locs.remove(distinguished_prog_bow_loc)
|
||||
silverarrow_hint = (' %s?' % hint_text(distinguished_prog_bow_loc).replace('Ganon\'s', 'my')) if progressive_silvers else '?\nI think not!'
|
||||
silverarrow_hint = (' %s?' % hint_text(distinguished_prog_bow_loc).replace('Ganon\'s',
|
||||
'my')) if progressive_silvers else '?\nI think not!'
|
||||
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||
|
||||
if any(prog_bow_locs):
|
||||
|
@ -1970,10 +2076,10 @@ def write_strings(rom, world, player, team):
|
|||
'my')) if progressive_silvers else '?\nI think not!'
|
||||
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||
|
||||
|
||||
crystal5 = world.find_items('Crystal 5', player)[0]
|
||||
crystal6 = world.find_items('Crystal 6', player)[0]
|
||||
tt['bomb_shop'] = 'Big Bomb?\nMy supply is blocked until you clear %s and %s.' % (crystal5.hint_text, crystal6.hint_text)
|
||||
tt['bomb_shop'] = 'Big Bomb?\nMy supply is blocked until you clear %s and %s.' % (
|
||||
crystal5.hint_text, crystal6.hint_text)
|
||||
|
||||
greenpendant = world.find_items('Green Pendant', player)[0]
|
||||
tt['sahasrahla_bring_courage'] = 'I lost my family heirloom in %s' % greenpendant.hint_text
|
||||
|
@ -2049,15 +2155,18 @@ def write_strings(rom, world, player, team):
|
|||
tt['kakariko_tavern_fisherman'] = TavernMan_texts[local_random.randint(0, len(TavernMan_texts) - 1)]
|
||||
|
||||
pedestalitem = world.get_location('Master Sword Pedestal', player).item
|
||||
pedestal_text = 'Some Hot Air' if pedestalitem is None else hint_text(pedestalitem, True) if pedestalitem.pedestal_hint_text is not None else 'Unknown Item'
|
||||
pedestal_text = 'Some Hot Air' if pedestalitem is None else hint_text(pedestalitem,
|
||||
True) if pedestalitem.pedestal_hint_text is not None else 'Unknown Item'
|
||||
tt['mastersword_pedestal_translated'] = pedestal_text
|
||||
pedestal_credit_text = 'and the Hot Air' if pedestalitem is None else pedestalitem.pedestal_credit_text if pedestalitem.pedestal_credit_text is not None else 'and the Unknown Item'
|
||||
|
||||
etheritem = world.get_location('Ether Tablet', player).item
|
||||
ether_text = 'Some Hot Air' if etheritem is None else hint_text(etheritem, True) if etheritem.pedestal_hint_text is not None else 'Unknown Item'
|
||||
ether_text = 'Some Hot Air' if etheritem is None else hint_text(etheritem,
|
||||
True) if etheritem.pedestal_hint_text is not None else 'Unknown Item'
|
||||
tt['tablet_ether_book'] = ether_text
|
||||
bombositem = world.get_location('Bombos Tablet', player).item
|
||||
bombos_text = 'Some Hot Air' if bombositem is None else hint_text(bombositem, True) if bombositem.pedestal_hint_text is not None else 'Unknown Item'
|
||||
bombos_text = 'Some Hot Air' if bombositem is None else hint_text(bombositem,
|
||||
True) if bombositem.pedestal_hint_text is not None else 'Unknown Item'
|
||||
tt['tablet_bombos_book'] = bombos_text
|
||||
|
||||
# inverted spawn menu changes
|
||||
|
@ -2108,6 +2217,7 @@ def write_strings(rom, world, player, team):
|
|||
rom.write_bytes(0x181500, data)
|
||||
rom.write_bytes(0x76CC0, [byte for p in pointers for byte in [p & 0xFF, p >> 8 & 0xFF]])
|
||||
|
||||
|
||||
def set_inverted_mode(world, player, rom):
|
||||
rom.write_byte(snes_to_pc(0x0283E0), 0xF0) # residual portals
|
||||
rom.write_byte(snes_to_pc(0x02B34D), 0xF0)
|
||||
|
@ -2309,10 +2419,12 @@ def set_inverted_mode(world, player, rom):
|
|||
rom.write_byte(snes_to_pc(0x0280A6), 0xD0)
|
||||
rom.write_bytes(snes_to_pc(0x06B2AB), [0xF0, 0xE1, 0x05])
|
||||
|
||||
|
||||
def patch_shuffled_dark_sanc(world, rom, player):
|
||||
dark_sanc = world.get_region('Inverted Dark Sanctuary', player)
|
||||
dark_sanc_entrance = str([i for i in dark_sanc.entrances if i.parent_region.name != 'Menu'][0].name)
|
||||
room_id, ow_area, vram_loc, scroll_y, scroll_x, link_y, link_x, camera_y, camera_x, unknown_1, unknown_2, door_1, door_2 = door_addresses[dark_sanc_entrance][1]
|
||||
room_id, ow_area, vram_loc, scroll_y, scroll_x, link_y, link_x, camera_y, camera_x, unknown_1, unknown_2, door_1, door_2 = \
|
||||
door_addresses[dark_sanc_entrance][1]
|
||||
door_index = door_addresses[str(dark_sanc_entrance)][0]
|
||||
|
||||
rom.write_byte(0x180241, 0x01)
|
||||
|
@ -2322,6 +2434,7 @@ def patch_shuffled_dark_sanc(world, rom, player):
|
|||
rom.write_int16s(0x180253, [vram_loc, scroll_y, scroll_x, link_y, link_x, camera_y, camera_x])
|
||||
rom.write_bytes(0x180262, [unknown_1, unknown_2, 0x00])
|
||||
|
||||
|
||||
InconvenientDungeonEntrances = {'Turtle Rock': 'Turtle Rock Main',
|
||||
'Misery Mire': 'Misery Mire',
|
||||
'Ice Palace': 'Ice Palace',
|
||||
|
|
Loading…
Reference in New Issue