From d6b7f5161d6303f2bd2e085e38f4820b2b145856 Mon Sep 17 00:00:00 2001 From: KrisDavie Date: Tue, 22 Apr 2025 09:53:26 +0200 Subject: [PATCH 01/73] More glitched fixes --- Fill.py | 2 +- ItemList.py | 12 +++++++++++- Rom.py | 7 +++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Fill.py b/Fill.py index 79af1403..c6189460 100644 --- a/Fill.py +++ b/Fill.py @@ -83,7 +83,7 @@ def fill_dungeons_restrictive(world, shuffled_locations): shuffled_locations.pop(i) # place 2 HMG keys hybrid_state_base = all_state_base.copy() - for x in bigs + smalls + prizes + others: + for x in bigs + smalls + others: hybrid_state_base.collect(x, True) hybrid_smalls = [ItemFactory('Small Key (Swamp Palace)', player)] * 2 fill(hybrid_state_base, hybrid_smalls, hybrid_locations, unplaced_smalls) diff --git a/ItemList.py b/ItemList.py index 5889e4d0..3dce2da3 100644 --- a/ItemList.py +++ b/ItemList.py @@ -368,7 +368,17 @@ def generate_itempool(world, player): or (item.map and world.mapshuffle[player]) or (item.compass and world.compassshuffle[player]))]) - + if world.logic[player] == 'hybridglitches' and world.pottery[player] not in ['none', 'cave']: + keys_to_remove = 2 + to_remove = [] + for wix, wi in enumerate(world.itempool): + if wi.name == 'Small Key (Swamp Palace)' and wi.player == player: + to_remove.append(wix) + if keys_to_remove == len(to_remove): + break + for wix in reversed(to_remove): + del world.itempool[wix] + # logic has some branches where having 4 hearts is one possible requirement (of several alternatives) # rather than making all hearts/heart pieces progression items (which slows down generation considerably) # We mark one random heart container as an advancement item (or 4 heart pieces in expert mode) diff --git a/Rom.py b/Rom.py index 4fd43122..984ac066 100644 --- a/Rom.py +++ b/Rom.py @@ -463,6 +463,13 @@ def patch_rom(world, rom, player, team, is_mystery=False): rom.write_byte(location.player_address, location.item.player) else: itemid = 0x5A + + if not location.locked and ((location.item.smallkey and world.keyshuffle[player] == 'none') or ( + location.item.bigkey and world.bigkeyshuffle[player] == 'none') or ( + location.item.map and world.mapshuffle[player] == 'none') or ( + location.item.compass and world.compassshuffle[player] == 'none')): + itemid = handle_native_dungeon(location, itemid) + rom.write_byte(location.address, itemid) else: # crystals From e63f686308a6c4572312a4640185cfe751585871 Mon Sep 17 00:00:00 2001 From: theclearmouse <105736589+theclearmouse@users.noreply.github.com> Date: Mon, 2 Jun 2025 23:52:43 -0400 Subject: [PATCH 02/73] Update Text.py updated ladder to stepladder because ladder is no more --- Text.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Text.py b/Text.py index f698eae2..59c5e716 100644 --- a/Text.py +++ b/Text.py @@ -192,8 +192,8 @@ Blind_texts = [ "Gloves open\na handful\nof checks", "Red mail?\nReturn to\nsender.", "For sale:\nBaby boots,\nNever found", - "SRL or rtGG?\nI prefer the\nLadder", - "Ladders are\nalways up\nto something", + "SRL or rtGG?\nI prefer the\nStepladder", + "Stepladders are\nalways up\nto something", "Zelda's\nfashion is\nvery chic", "Zombie geese\nare waterfoul.\n", "I bought some\ncuccos for a\npoultry sum.", From 97199581192d0dddf9e22b1b0798b251d6e06dc1 Mon Sep 17 00:00:00 2001 From: theclearmouse <105736589+theclearmouse@users.noreply.github.com> Date: Mon, 2 Jun 2025 23:55:23 -0400 Subject: [PATCH 03/73] revert --- Text.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Text.py b/Text.py index 59c5e716..72ee9c28 100644 --- a/Text.py +++ b/Text.py @@ -193,7 +193,7 @@ Blind_texts = [ "Red mail?\nReturn to\nsender.", "For sale:\nBaby boots,\nNever found", "SRL or rtGG?\nI prefer the\nStepladder", - "Stepladders are\nalways up\nto something", + "Ladders are\nalways up\nto something", "Zelda's\nfashion is\nvery chic", "Zombie geese\nare waterfoul.\n", "I bought some\ncuccos for a\npoultry sum.", From cb11ddb1c6d54b586081238e4c5563373bd2b06e Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 3 Sep 2025 02:41:26 -0500 Subject: [PATCH 04/73] Fixed follower plando error --- ItemList.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ItemList.py b/ItemList.py index de36b74a..4b4b3ace 100644 --- a/ItemList.py +++ b/ItemList.py @@ -1715,10 +1715,11 @@ def get_item_and_event_flag(item, world, player, dungeon_pool, prize_set, prize_ item_player = player if len(item_parts) < 2 else int(item_parts[1]) item_name = item_parts[0] event_flag = False - if item_name in prize_set: - item_player = player # prizes must be for that player + if item_name in prize_set or item_name in follower_pickups: + item_player = player # must be for that player item_to_place = ItemFactory(item_name, item_player) - prize_pool.remove(item_name) + if item_name in prize_set: + prize_pool.remove(item_name) event_flag = True elif is_dungeon_item(item_name, world, item_player): item_to_place = next(x for x in dungeon_pool From 95ec5c79838505ca0e918f45fe7783cbe79e2340 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 3 Sep 2025 02:51:28 -0500 Subject: [PATCH 05/73] Fixed error with placing Old Man cave in ER --- source/overworld/EntranceShuffle2.py | 1 + 1 file changed, 1 insertion(+) diff --git a/source/overworld/EntranceShuffle2.py b/source/overworld/EntranceShuffle2.py index c190c428..d02e3362 100644 --- a/source/overworld/EntranceShuffle2.py +++ b/source/overworld/EntranceShuffle2.py @@ -403,6 +403,7 @@ def do_old_man_cave_exit(entrances, exits, avail, cross_world): else: region_name = 'West Dark Death Mountain (Top)' om_cave_options = list(get_accessible_entrances(region_name, avail, [], cross_world, True, True, True, True)) + om_cave_options = [e for e in om_cave_options if e in avail.entrances] if avail.swapped: om_cave_options = [e for e in om_cave_options if e not in Forbidden_Swap_Entrances] assert len(om_cave_options), 'No available entrances left to place Old Man Cave' From 808daf224d8b5f4ee276d2b8b34dc2b19eb2c664 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 3 Sep 2025 02:52:55 -0500 Subject: [PATCH 06/73] Fixed EG2 spawn starts to connect logic exits more consistently --- source/overworld/EntranceShuffle2.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/source/overworld/EntranceShuffle2.py b/source/overworld/EntranceShuffle2.py index d02e3362..777edaec 100644 --- a/source/overworld/EntranceShuffle2.py +++ b/source/overworld/EntranceShuffle2.py @@ -644,7 +644,6 @@ def do_dark_sanc(entrances, exits, avail): entrances.remove(choice) exits.remove('Dark Sanctuary Hint') connect_entrance(choice, 'Dark Sanctuary Hint', avail) - ext.connect(avail.world.get_entrance(choice, avail.player).parent_region) if not avail.coupled: avail.decoupled_entrances.remove(choice) if avail.swapped and choice != 'Dark Sanctuary Hint': @@ -652,8 +651,7 @@ def do_dark_sanc(entrances, exits, avail): entrances.remove(swap_ent) exits.remove(swap_ext) elif not ext.connected_region: - # default to output to vanilla area, assume vanilla connection - ext.connect(avail.world.get_region('Dark Chapel Area', avail.player)) + raise Exception('Dark Sanctuary Hint was placed earlier but its exit not properly connected') def do_links_house(entrances, exits, avail, cross_world): @@ -723,8 +721,6 @@ def do_links_house(entrances, exits, avail, cross_world): connect_two_way(links_house, lh_exit, avail) else: connect_entrance(links_house, lh_exit, avail) - ext = avail.world.get_entrance('Big Bomb Shop Exit', avail.player) - ext.connect(avail.world.get_entrance(links_house, avail.player).parent_region) entrances.remove(links_house) exits.remove(lh_exit) if not avail.coupled: @@ -1908,6 +1904,12 @@ def connect_entrance(entrancename, exit_name, avail): avail.entrances.remove(entrancename) if avail.coupled: avail.exits.remove(exit_name) + if exit_name == 'Big Bomb Shop' and avail.world.is_bombshop_start(avail.player): + ext = avail.world.get_entrance('Big Bomb Shop Exit', avail.player) + ext.connect(avail.world.get_entrance(entrancename, avail.player).parent_region) + if exit_name == 'Dark Sanctuary Hint' and avail.world.is_dark_chapel_start(avail.player): + ext = avail.world.get_entrance('Dark Sanctuary Hint Exit', avail.player) + ext.connect(avail.world.get_entrance(entrancename, avail.player).parent_region) world.spoiler.set_entrance(entrance.name, exit.name if exit is not None else region.name, 'entrance', player) logging.getLogger('').debug(f'Connected (entr) {entrance.name} to {exit.name if exit is not None else region.name}') From 5fc3924b8ab81c3aaf16bdc9ddb15605bca8cfe0 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 3 Sep 2025 02:50:20 -0500 Subject: [PATCH 07/73] Allow Zelda escape to use TT Maiden Cell as checkpoint --- BaseClasses.py | 2 ++ Doors.py | 8 ++++++-- DungeonGenerator.py | 12 ++++++------ ItemList.py | 15 +++++++++------ KeyDoorShuffle.py | 5 ++++- Rom.py | 14 +++++++++++++- Rules.py | 2 +- data/base2current.bps | Bin 136642 -> 136664 bytes source/dungeon/DungeonStitcher.py | 8 ++++---- source/enemizer/Enemizer.py | 15 +++++++++++++++ 10 files changed, 60 insertions(+), 21 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index a82f3093..1a230d6b 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -76,6 +76,7 @@ class World(object): self.can_take_damage = True self.hints = hints.copy() self.prizes = {} + self.default_zelda_region = {} self.dynamic_regions = [] self.dynamic_locations = [] self.spoiler_mode = spoiler_mode @@ -185,6 +186,7 @@ class World(object): set_player_attr('standardize_palettes', 'standardize') set_player_attr('force_fix', {'gt': False, 'sw': False, 'pod': False, 'tr': False}) set_player_attr('prizes', {'dig;': [], 'pull': [0, 0, 0], 'crab': [0, 0], 'stun': 0, 'fish': 0, 'enemies': []}) + set_player_attr('default_zelda_region', 'Hyrule Dungeon Cellblock') set_player_attr('exp_cache', defaultdict(dict)) set_player_attr('enabled_entrances', {}) diff --git a/Doors.py b/Doors.py index aa55cf0c..a8a53a26 100644 --- a/Doors.py +++ b/Doors.py @@ -1302,8 +1302,12 @@ def create_doors(world, player): world.get_door('Swamp Flooded Room Ladder', player).event('Swamp Drain') if world.mode[player] == 'standard' and 'Zelda Herself' not in [i.name for i in world.precollected_items if i.player == player]: - world.get_door('Hyrule Castle Throne Room Tapestry', player).event('Zelda Pickup') - world.get_door('Hyrule Castle Tapestry Backwards', player).event('Zelda Pickup') + if not world.shuffle_followers[player]: + zelda_location = 'Zelda Pickup' + else: + zelda_location = 'Suspicious Maiden' + world.get_door('Hyrule Castle Throne Room Tapestry', player).event(zelda_location) + world.get_door('Hyrule Castle Tapestry Backwards', player).event(zelda_location) # crystal switches and barriers world.get_door('Hera Lobby Crystal Exit', player).c_switch() diff --git a/DungeonGenerator.py b/DungeonGenerator.py index d3e33bb8..3306b71d 100644 --- a/DungeonGenerator.py +++ b/DungeonGenerator.py @@ -586,13 +586,13 @@ def determine_paths_for_dungeon(world, player, all_regions, name): paths.append(portal.door.entrance.parent_region.name) if world.mode[player] == 'standard': if name == 'Hyrule Castle': - paths.append('Hyrule Dungeon Cellblock') - paths.append(('Hyrule Dungeon Cellblock', 'Sanctuary')) + paths.append(world.default_zelda_region[player]) + paths.append((world.default_zelda_region[player], 'Sanctuary')) if name == 'Hyrule Castle Sewers': paths.append('Sanctuary') if name == 'Hyrule Castle Dungeon': - paths.append('Hyrule Dungeon Cellblock') - paths.append(('Hyrule Dungeon Cellblock', 'Hyrule Castle Throne Room')) + paths.append(world.default_zelda_region[player]) + paths.append((world.default_zelda_region[player], 'Hyrule Castle Throne Room')) if world.doorShuffle[player] in ['basic'] and name == 'Thieves Town': paths.append('Thieves Attic Window') elif 'Thieves Attic Window' in all_r_names: @@ -1322,7 +1322,7 @@ def create_dungeon_builders(all_sectors, connections_tuple, world, player, dunge for r_name in dungeon_boss_sectors[key]: assign_sector(find_sector(r_name, candidate_sectors), current_dungeon, candidate_sectors, global_pole) if key == 'Hyrule Castle' and world.mode[player] == 'standard': - for r_name in ['Hyrule Dungeon Cellblock', 'Sanctuary', 'Hyrule Castle Throne Room']: # need to deliver zelda + for r_name in [world.default_zelda_region[player], 'Sanctuary', 'Hyrule Castle Throne Room']: # need to deliver zelda assign_sector(find_sector(r_name, candidate_sectors), current_dungeon, candidate_sectors, global_pole) if key == 'Thieves Town' and (world.get_dungeon("Thieves Town", player).boss.enemizer_name == 'Blind' @@ -3091,7 +3091,7 @@ def split_dungeon_builder(builder, split_list, builder_info): if builder.name == 'Hyrule Castle': assign_sector(find_sector('Hyrule Castle Throne Room', candidate_sectors), dungeon_map['Hyrule Castle Dungeon'], candidate_sectors, global_pole) - assign_sector(find_sector('Hyrule Dungeon Cellblock', candidate_sectors), + assign_sector(find_sector(world.default_zelda_region[player], candidate_sectors), dungeon_map['Hyrule Castle Dungeon'], candidate_sectors, global_pole) dungeon_map['Hyrule Castle Dungeon'].throne_door = world.get_door('Hyrule Castle Throne Room N', player) dungeon_map['Hyrule Castle Sewers'].sewers_access = builder.throne_door diff --git a/ItemList.py b/ItemList.py index 4b4b3ace..65d67f57 100644 --- a/ItemList.py +++ b/ItemList.py @@ -1676,7 +1676,7 @@ def set_event_item(world, player, location_name, item_name=None): def shuffle_event_items(world, player): - if (world.shuffle_followers[player]): + if world.shuffle_followers[player]: available_quests = follower_quests.copy() available_pickups = [quests[0] for quests in available_quests.values()] @@ -1688,11 +1688,14 @@ def shuffle_event_items(world, player): available_pickups.remove(loc.item.name) - if world.mode[player] == 'standard': - if 'Zelda Herself' in available_pickups: - zelda_pickup = available_quests.pop('Zelda Pickup')[0] - available_pickups.remove(zelda_pickup) - set_event_item(world, player, 'Zelda Pickup', zelda_pickup) + if world.mode[player] == 'standard' and 'Zelda Herself' in available_pickups: + zelda_dropoff = 'Zelda Pickup' + if world.default_zelda_region[player] == 'Thieves Blind\'s Cell': + zelda_dropoff = 'Suspicious Maiden' + available_quests.pop(zelda_dropoff) + zelda_pickup = 'Zelda Herself' + available_pickups.remove(zelda_pickup) + set_event_item(world, player, zelda_dropoff, zelda_pickup) random.shuffle(available_pickups) diff --git a/KeyDoorShuffle.py b/KeyDoorShuffle.py index d9c837b9..65ad0faf 100644 --- a/KeyDoorShuffle.py +++ b/KeyDoorShuffle.py @@ -1805,7 +1805,10 @@ def imp_locations_factory(world, player): return imp_locations imp_locations = ['Agahnim 1', 'Agahnim 2', 'Attic Cracked Floor', 'Suspicious Maiden'] if world.mode[player] == 'standard': - imp_locations.append('Zelda Pickup') + if world.default_zelda_region[player] == 'Thieves Blinds\' Cell': + imp_locations.append('Suspicious Maiden') + else: + imp_locations.append('Zelda Pickup') imp_locations.append('Zelda Drop Off') return imp_locations diff --git a/Rom.py b/Rom.py index faf0b6c3..42cfe59d 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '93386b05ee4b5de6b9165941b9e14e97' +RANDOMIZERBASEHASH = '20e588b832011dcf15dbd31dff6955ce' class JsonRom(object): @@ -1581,6 +1581,18 @@ def patch_rom(world, rom, player, team, is_mystery=False): rom.write_bytes(snes_to_pc(0x09A045), [0xEA, 0xEA]) # allow super bomb to follow into UW holes rom.write_byte(snes_to_pc(0x09ACDF), 0x6B) # allow kiki/locksmith to follow after screen transition + if world.default_zelda_region[player] == 'Thieves Blind\'s Cell': + write_int16(rom, snes_to_pc(0x02D8D6), 0x45) # change zelda spawn point to maiden cell + rom.write_bytes(snes_to_pc(0x02D8F0), [0x08, 0x08, 0x08, 0x09, 0x0B, 0x0A, 0x0B, 0x0B]) + write_int16(rom, snes_to_pc(0x02D91C), 0x0B00) + write_int16(rom, snes_to_pc(0x02D92A), 0x0800) + write_int16(rom, snes_to_pc(0x02D938), 0x0860) + write_int16(rom, snes_to_pc(0x02D946), 0x0B90) + write_int16(rom, snes_to_pc(0x02D954), 0x0078) + write_int16(rom, snes_to_pc(0x02D962), 0x017F) + rom.write_byte(snes_to_pc(0x02D975), 0x00) + rom.write_byte(snes_to_pc(0x02D98A), 0x02) + if world.enemy_shuffle[player] != 'none': # informs zelda and maiden to draw over gfx slots that are guaranteed unused rom.write_bytes(0x1802C1, world.data_tables[player].room_headers[0x80].free_gfx[0:2]) diff --git a/Rules.py b/Rules.py index b062d917..d87eaa45 100644 --- a/Rules.py +++ b/Rules.py @@ -1669,7 +1669,7 @@ def standard_rules(world, player): def find_rules_for_zelda_delivery(world, player): # path rules for backtracking - start_region = world.get_region('Hyrule Dungeon Cellblock', player) + start_region = world.get_region(world.default_zelda_region[player], player) queue = deque([(start_region, [], [])]) visited = {start_region} blank_state = CollectionState(world) diff --git a/data/base2current.bps b/data/base2current.bps index 3ac6a7ce81674927ee8d2e3aaa19e8698204ca37..0fe2d932963a31af760b5381bf17b8627f8c443c 100644 GIT binary patch delta 1792 zcmW+#4Ny~87S0VxNHB>3L8Bmqhw`JM)YX;ZN>v1dbt=@3%d}AJ)I#LpR-JBLEW*9f z1cD7oxR6(Tggn3~Z>bAw?4}(iy9LKWB4}pW?kL+<{!P%*>@=O#u3PuTxik09J?A^; zeD^!|4EKre^@#^ILO>NmvT1>EHYzAf3J-w!3pbBvD!tZgMM3$K0&$;YUg|C zQzJ3xEL!(i2I`%=wl?es@y=T{6QZ~zKQqvEeV#E(h{JxydUE@B7UEre4d$jS_!+Z- zkOb^`Ia64gJ#`uB26~E1kQ!2lUVos_8i{r+N2}K51(+$M8%4S-*r%?(c@W}6El0dK zFu0=T2XmX=yn=We7or`jI1O9FK=0Lad+wu!o8s)Ldp6=fm_nK0E$1zCBTASw!w^Z% zx{teaKp9RRDd%=Hl2L>T>AmkgwCwQ+g1asi?4C7lcQ77PHJtxaJKzDnG#Ks4_a#pq zllT()zj|ScwXWScF+Mq?AijMHiFZEN4l8~h&LYJ#S@e-Ago7jd)7crfO73~tx6GX- z_r($!^UMGrO5KX(TtkJd)TUUjd8Bzn)Zp?_WfC#RaE0WWN9=i3?ksm`59ZE#1TQQX zsNL8)`l>8@-q7p0#3qt_u4Mh1nnO9Tafi^GMUT%g8{o&*qw z9iE!?9LQwd5o7F966r6hD7w`i7EXp)|Ll?Y#P;%PAKu|j%xIcpG`1{Swi%AIz-Er@ zgfiC5@ysR(&ZVRh%1$|xV%u%Q*b=ceoh^J=?#13@qnXH((+ib*dIQJbaSya=utGy^W{67WE61rE`cU zkI8gg$Bj7!KuHs#a zEOgsXZ5g%+_g(&C7n23siLCp&#Iw&(R!gCS0%!3EeT2&Dy*DZL?- z8lWyCfjy;lD8&us9uQ0jli;eq`jD=|1!Ji|k57yx)O)XLjbDG$@1+~NfKEgL-jnCg z>GC{38ohfu&)@ddbux7Gy8YveRggZT#WiM!IfCVpoE(}a{8}U3X|Fhsl=MNZF3)e@ zj?e^k#a8;{UwR&w$DaAhZM4)=y5}~o%z)H^Xn6Zuwx@31lz5?QXs+WazjOlI#@81`a84nX zHPENpT52l3!TILFT(*5Kz_le5pqtUS^Bi;?TJN`3d_aFIm-DzK=VmR)&6rI6;%n@N ztFP?ZWbesY_MnaU635(GpLgV~MHG)y8gUGwD&L=Dr9nX`#Z87%-K5oOAx&dH*4f`U zGiM?#29Gp|f!-nsvuxS94=%mG57(!|v-s?tM-nmviZ^&SwnjOBcej4CsGtO5Nxt*P z|CNftOH`2v#DguaY7zKL^cu3{qH!-A2(}zv4Gl0DY0Ym!WVg`{5?#Mhg27dS#93VG z`tKINX0EB0J!$zvY=cd=G&!8r{SRJWWGytXCtvGRQGYE18$g^ZPzFNDt4{yw*-&rO zWuk1F=@-DO8T_EM|1f>T6{-hZ6Ds#MQ?fHIej~U6gm2bDD#JBs0Ddue*>$-EL;$eK z)r-Ms1YatpPE#NQl({-6a0SHV*XnId@5ML!+%VFb_)!yeih83R{3K30YSSHyq*7eP zm%!hF@WX_A^a)pb2dIhwt0`;;zXk_fUOVs$MdEC@Y;>RNa|hs`6pwYE*H?)S^ZpNL C%|25A delta 1753 zcmW+!e^66b7S2sVeh>%{pahgOJdlc&$|4mCt6&j9MO$R1s}@AJ{)j%Q*4e6zNbgMz z5H%#>3a|Kx?+IebQkJZ-P1Q+PV5|fI(`q~F?o@<;30j(taRzr>-IxAz&%Nh<-+bqM z=iKd)4D?8Biv+@IRr5ppTY|&N-0M^9%*+b}H3(TUkbciJ+Y?21Bj`r3TmN*5T?~=# z?B7C>er9IIO?@gs?G$e%YVRWC_6PICLTUOm$2YYQAK>3!k4-<|Wlsl@^roYRmN%`S z%_L5Ny0b5hYoYncBM#~Rx@+DVz{S^yefUpmQmXWE*{}3OgS|_Q_=z1;RK^#EZN%^+ z{D#4pI!hP%v$V!tWw6~qm~mn9tHC6Ib=i(ZmM424%-_9-a;YuY7rIUf) z_XpG^XSRwM`jaDgZm2khW0liMC=ct9U>_FmkgJ?R;aQ*hChi6+1G+4B=|+H zOEx}~_2yoa7Eq5FfcsoE@f_FKnyoOH6@<#eIu53^Hf`u-sufQw?3}(F>F2{xC7DA8D~H0))IGkoV4hcyWUyMK)&169A0)WK6sgaIYsznU>~GjV72GN`ixN|6Im zE?s4QmT6^ml3*u?+=>CUwRc)4vhsL3Xd(oc#V@OTQXn~^7%qOkI$z|(g#okrNtlR;-r!2g{jye47}l^>h*zCA9WrH8NuoP zWG9rnfPa2am6OYRM6bmaBdMxd56iXjlaJ|ie5cDLn-?@75f!Cn6gs8}UBT=~%$EE@ zFB-bFvC!M{{Y5e`c#%1EaxbJ0YjL%y%OtS!xFri{PT+SN>9fqP&ykWY)#{ddnYR(T zOBEb$D4b_gy-Kxvz>olc@r0>L27LjytxI-N0Txy8|$FXymi6jz{gePGR${Gx>anr-E};S8FGlN+%DQN{Z`)-b;?knAJ_sZO%B z)l3?>b!D;+dyG|Py(`R*LA_ZTEU7tf6`b9_3g@T6kFja&vGmPFP?I)H;zjo3w?2DI zl(`AwPgmKcFDoR8MJWyU$lezMznEC}KTB!yZ10DHG~gC+H)@_kD+1p{CCE0PG`tIK z{^s&{sE2-WYtacrb{LrLiH?m*a5YX?H-T#%Q5nFRo=_S-*L)^>L;1USQt%a1-@q-?CC1AbdN;41uP~i9ugCPNbpNwjxKpI%?xJZEuK(V>D-okdD z+|uKO;#Sqs6I3O&w+%d#h($ diff --git a/source/dungeon/DungeonStitcher.py b/source/dungeon/DungeonStitcher.py index 29a2c32f..d7ce3c4f 100644 --- a/source/dungeon/DungeonStitcher.py +++ b/source/dungeon/DungeonStitcher.py @@ -333,13 +333,13 @@ def determine_paths_for_dungeon(world, player, all_regions, name): if portal.destination: paths.append(portal.door.entrance.parent_region.name) if world.mode[player] == 'standard' and name == 'Hyrule Castle Dungeon': - paths.append('Hyrule Dungeon Cellblock') - paths.append(('Hyrule Dungeon Cellblock', 'Hyrule Castle Throne Room')) + paths.append(world.default_zelda_region[player]) + paths.append((world.default_zelda_region[player], 'Hyrule Castle Throne Room')) entrance = next(x for x in world.dungeon_portals[player] if x.name == 'Hyrule Castle South') # todo: in non-er, we can use the other portals too - paths.append(('Hyrule Dungeon Cellblock', entrance.door.entrance.parent_region.name)) + paths.append((world.default_zelda_region[player], entrance.door.entrance.parent_region.name)) paths.append(('Hyrule Castle Throne Room', [entrance.door.entrance.parent_region.name, - 'Hyrule Dungeon Cellblock'])) + world.default_zelda_region[player]])) if world.doorShuffle[player] in ['basic'] and name == 'Thieves Town': paths.append('Thieves Attic Window') elif 'Thieves Attic Window' in all_r_names: diff --git a/source/enemizer/Enemizer.py b/source/enemizer/Enemizer.py index f4e89207..cc32ba8c 100644 --- a/source/enemizer/Enemizer.py +++ b/source/enemizer/Enemizer.py @@ -521,6 +521,21 @@ def randomize_enemies(world, player): green_mail, blue_mail, red_mail = original_table[idx] del original_table[idx] world.data_tables[player].enemy_damage[i] = [green_mail, blue_mail, red_mail] + # determine default zelda follower location + if world.mode[player] == 'standard' and world.doorShuffle[player] == 'crossed' and world.shuffle_followers[player]: + def random_zelda(): + world.default_zelda_region[player] = random.choice(['Hyrule Dungeon Cellblock', 'Thieves Blind\'s Cell']) + if world.customizer: + placements = world.customizer.get_placements() + if placements and player in placements and 'Zelda Herself' in placements[player].values(): + location = [l for (l, item) in placements[player].items() if item == 'Zelda Herself'][0] + if location == 'Suspicious Maiden': + world.default_zelda_region[player] = 'Thieves Blind\'s Cell' + else: + random_zelda() + else: + random_zelda() + def write_enemy_shuffle_settings(world, player, rom): From a5f14530cd5c70b1ff21054dd814ceb1d4bb35d8 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 3 Sep 2025 02:50:20 -0500 Subject: [PATCH 08/73] Allow Zelda escape to use TT Maiden Cell as checkpoint --- BaseClasses.py | 2 ++ Doors.py | 8 ++++++-- DungeonGenerator.py | 12 ++++++------ ItemList.py | 15 +++++++++------ KeyDoorShuffle.py | 5 ++++- Rom.py | 14 +++++++++++++- Rules.py | 2 +- data/base2current.bps | Bin 136642 -> 136664 bytes source/dungeon/DungeonStitcher.py | 8 ++++---- source/enemizer/Enemizer.py | 15 +++++++++++++++ 10 files changed, 60 insertions(+), 21 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index a82f3093..1a230d6b 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -76,6 +76,7 @@ class World(object): self.can_take_damage = True self.hints = hints.copy() self.prizes = {} + self.default_zelda_region = {} self.dynamic_regions = [] self.dynamic_locations = [] self.spoiler_mode = spoiler_mode @@ -185,6 +186,7 @@ class World(object): set_player_attr('standardize_palettes', 'standardize') set_player_attr('force_fix', {'gt': False, 'sw': False, 'pod': False, 'tr': False}) set_player_attr('prizes', {'dig;': [], 'pull': [0, 0, 0], 'crab': [0, 0], 'stun': 0, 'fish': 0, 'enemies': []}) + set_player_attr('default_zelda_region', 'Hyrule Dungeon Cellblock') set_player_attr('exp_cache', defaultdict(dict)) set_player_attr('enabled_entrances', {}) diff --git a/Doors.py b/Doors.py index aa55cf0c..909fe40b 100644 --- a/Doors.py +++ b/Doors.py @@ -1302,8 +1302,12 @@ def create_doors(world, player): world.get_door('Swamp Flooded Room Ladder', player).event('Swamp Drain') if world.mode[player] == 'standard' and 'Zelda Herself' not in [i.name for i in world.precollected_items if i.player == player]: - world.get_door('Hyrule Castle Throne Room Tapestry', player).event('Zelda Pickup') - world.get_door('Hyrule Castle Tapestry Backwards', player).event('Zelda Pickup') + if world.default_zelda_region[player] == 'Thieves Blind\'s Cell': + zelda_location = 'Suspicious Maiden' + else: + zelda_location = 'Zelda Pickup' + world.get_door('Hyrule Castle Throne Room Tapestry', player).event(zelda_location) + world.get_door('Hyrule Castle Tapestry Backwards', player).event(zelda_location) # crystal switches and barriers world.get_door('Hera Lobby Crystal Exit', player).c_switch() diff --git a/DungeonGenerator.py b/DungeonGenerator.py index d3e33bb8..3306b71d 100644 --- a/DungeonGenerator.py +++ b/DungeonGenerator.py @@ -586,13 +586,13 @@ def determine_paths_for_dungeon(world, player, all_regions, name): paths.append(portal.door.entrance.parent_region.name) if world.mode[player] == 'standard': if name == 'Hyrule Castle': - paths.append('Hyrule Dungeon Cellblock') - paths.append(('Hyrule Dungeon Cellblock', 'Sanctuary')) + paths.append(world.default_zelda_region[player]) + paths.append((world.default_zelda_region[player], 'Sanctuary')) if name == 'Hyrule Castle Sewers': paths.append('Sanctuary') if name == 'Hyrule Castle Dungeon': - paths.append('Hyrule Dungeon Cellblock') - paths.append(('Hyrule Dungeon Cellblock', 'Hyrule Castle Throne Room')) + paths.append(world.default_zelda_region[player]) + paths.append((world.default_zelda_region[player], 'Hyrule Castle Throne Room')) if world.doorShuffle[player] in ['basic'] and name == 'Thieves Town': paths.append('Thieves Attic Window') elif 'Thieves Attic Window' in all_r_names: @@ -1322,7 +1322,7 @@ def create_dungeon_builders(all_sectors, connections_tuple, world, player, dunge for r_name in dungeon_boss_sectors[key]: assign_sector(find_sector(r_name, candidate_sectors), current_dungeon, candidate_sectors, global_pole) if key == 'Hyrule Castle' and world.mode[player] == 'standard': - for r_name in ['Hyrule Dungeon Cellblock', 'Sanctuary', 'Hyrule Castle Throne Room']: # need to deliver zelda + for r_name in [world.default_zelda_region[player], 'Sanctuary', 'Hyrule Castle Throne Room']: # need to deliver zelda assign_sector(find_sector(r_name, candidate_sectors), current_dungeon, candidate_sectors, global_pole) if key == 'Thieves Town' and (world.get_dungeon("Thieves Town", player).boss.enemizer_name == 'Blind' @@ -3091,7 +3091,7 @@ def split_dungeon_builder(builder, split_list, builder_info): if builder.name == 'Hyrule Castle': assign_sector(find_sector('Hyrule Castle Throne Room', candidate_sectors), dungeon_map['Hyrule Castle Dungeon'], candidate_sectors, global_pole) - assign_sector(find_sector('Hyrule Dungeon Cellblock', candidate_sectors), + assign_sector(find_sector(world.default_zelda_region[player], candidate_sectors), dungeon_map['Hyrule Castle Dungeon'], candidate_sectors, global_pole) dungeon_map['Hyrule Castle Dungeon'].throne_door = world.get_door('Hyrule Castle Throne Room N', player) dungeon_map['Hyrule Castle Sewers'].sewers_access = builder.throne_door diff --git a/ItemList.py b/ItemList.py index 4b4b3ace..65d67f57 100644 --- a/ItemList.py +++ b/ItemList.py @@ -1676,7 +1676,7 @@ def set_event_item(world, player, location_name, item_name=None): def shuffle_event_items(world, player): - if (world.shuffle_followers[player]): + if world.shuffle_followers[player]: available_quests = follower_quests.copy() available_pickups = [quests[0] for quests in available_quests.values()] @@ -1688,11 +1688,14 @@ def shuffle_event_items(world, player): available_pickups.remove(loc.item.name) - if world.mode[player] == 'standard': - if 'Zelda Herself' in available_pickups: - zelda_pickup = available_quests.pop('Zelda Pickup')[0] - available_pickups.remove(zelda_pickup) - set_event_item(world, player, 'Zelda Pickup', zelda_pickup) + if world.mode[player] == 'standard' and 'Zelda Herself' in available_pickups: + zelda_dropoff = 'Zelda Pickup' + if world.default_zelda_region[player] == 'Thieves Blind\'s Cell': + zelda_dropoff = 'Suspicious Maiden' + available_quests.pop(zelda_dropoff) + zelda_pickup = 'Zelda Herself' + available_pickups.remove(zelda_pickup) + set_event_item(world, player, zelda_dropoff, zelda_pickup) random.shuffle(available_pickups) diff --git a/KeyDoorShuffle.py b/KeyDoorShuffle.py index d9c837b9..65ad0faf 100644 --- a/KeyDoorShuffle.py +++ b/KeyDoorShuffle.py @@ -1805,7 +1805,10 @@ def imp_locations_factory(world, player): return imp_locations imp_locations = ['Agahnim 1', 'Agahnim 2', 'Attic Cracked Floor', 'Suspicious Maiden'] if world.mode[player] == 'standard': - imp_locations.append('Zelda Pickup') + if world.default_zelda_region[player] == 'Thieves Blinds\' Cell': + imp_locations.append('Suspicious Maiden') + else: + imp_locations.append('Zelda Pickup') imp_locations.append('Zelda Drop Off') return imp_locations diff --git a/Rom.py b/Rom.py index faf0b6c3..42cfe59d 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '93386b05ee4b5de6b9165941b9e14e97' +RANDOMIZERBASEHASH = '20e588b832011dcf15dbd31dff6955ce' class JsonRom(object): @@ -1581,6 +1581,18 @@ def patch_rom(world, rom, player, team, is_mystery=False): rom.write_bytes(snes_to_pc(0x09A045), [0xEA, 0xEA]) # allow super bomb to follow into UW holes rom.write_byte(snes_to_pc(0x09ACDF), 0x6B) # allow kiki/locksmith to follow after screen transition + if world.default_zelda_region[player] == 'Thieves Blind\'s Cell': + write_int16(rom, snes_to_pc(0x02D8D6), 0x45) # change zelda spawn point to maiden cell + rom.write_bytes(snes_to_pc(0x02D8F0), [0x08, 0x08, 0x08, 0x09, 0x0B, 0x0A, 0x0B, 0x0B]) + write_int16(rom, snes_to_pc(0x02D91C), 0x0B00) + write_int16(rom, snes_to_pc(0x02D92A), 0x0800) + write_int16(rom, snes_to_pc(0x02D938), 0x0860) + write_int16(rom, snes_to_pc(0x02D946), 0x0B90) + write_int16(rom, snes_to_pc(0x02D954), 0x0078) + write_int16(rom, snes_to_pc(0x02D962), 0x017F) + rom.write_byte(snes_to_pc(0x02D975), 0x00) + rom.write_byte(snes_to_pc(0x02D98A), 0x02) + if world.enemy_shuffle[player] != 'none': # informs zelda and maiden to draw over gfx slots that are guaranteed unused rom.write_bytes(0x1802C1, world.data_tables[player].room_headers[0x80].free_gfx[0:2]) diff --git a/Rules.py b/Rules.py index b062d917..d87eaa45 100644 --- a/Rules.py +++ b/Rules.py @@ -1669,7 +1669,7 @@ def standard_rules(world, player): def find_rules_for_zelda_delivery(world, player): # path rules for backtracking - start_region = world.get_region('Hyrule Dungeon Cellblock', player) + start_region = world.get_region(world.default_zelda_region[player], player) queue = deque([(start_region, [], [])]) visited = {start_region} blank_state = CollectionState(world) diff --git a/data/base2current.bps b/data/base2current.bps index 3ac6a7ce81674927ee8d2e3aaa19e8698204ca37..0fe2d932963a31af760b5381bf17b8627f8c443c 100644 GIT binary patch delta 1792 zcmW+#4Ny~87S0VxNHB>3L8Bmqhw`JM)YX;ZN>v1dbt=@3%d}AJ)I#LpR-JBLEW*9f z1cD7oxR6(Tggn3~Z>bAw?4}(iy9LKWB4}pW?kL+<{!P%*>@=O#u3PuTxik09J?A^; zeD^!|4EKre^@#^ILO>NmvT1>EHYzAf3J-w!3pbBvD!tZgMM3$K0&$;YUg|C zQzJ3xEL!(i2I`%=wl?es@y=T{6QZ~zKQqvEeV#E(h{JxydUE@B7UEre4d$jS_!+Z- zkOb^`Ia64gJ#`uB26~E1kQ!2lUVos_8i{r+N2}K51(+$M8%4S-*r%?(c@W}6El0dK zFu0=T2XmX=yn=We7or`jI1O9FK=0Lad+wu!o8s)Ldp6=fm_nK0E$1zCBTASw!w^Z% zx{teaKp9RRDd%=Hl2L>T>AmkgwCwQ+g1asi?4C7lcQ77PHJtxaJKzDnG#Ks4_a#pq zllT()zj|ScwXWScF+Mq?AijMHiFZEN4l8~h&LYJ#S@e-Ago7jd)7crfO73~tx6GX- z_r($!^UMGrO5KX(TtkJd)TUUjd8Bzn)Zp?_WfC#RaE0WWN9=i3?ksm`59ZE#1TQQX zsNL8)`l>8@-q7p0#3qt_u4Mh1nnO9Tafi^GMUT%g8{o&*qw z9iE!?9LQwd5o7F966r6hD7w`i7EXp)|Ll?Y#P;%PAKu|j%xIcpG`1{Swi%AIz-Er@ zgfiC5@ysR(&ZVRh%1$|xV%u%Q*b=ceoh^J=?#13@qnXH((+ib*dIQJbaSya=utGy^W{67WE61rE`cU zkI8gg$Bj7!KuHs#a zEOgsXZ5g%+_g(&C7n23siLCp&#Iw&(R!gCS0%!3EeT2&Dy*DZL?- z8lWyCfjy;lD8&us9uQ0jli;eq`jD=|1!Ji|k57yx)O)XLjbDG$@1+~NfKEgL-jnCg z>GC{38ohfu&)@ddbux7Gy8YveRggZT#WiM!IfCVpoE(}a{8}U3X|Fhsl=MNZF3)e@ zj?e^k#a8;{UwR&w$DaAhZM4)=y5}~o%z)H^Xn6Zuwx@31lz5?QXs+WazjOlI#@81`a84nX zHPENpT52l3!TILFT(*5Kz_le5pqtUS^Bi;?TJN`3d_aFIm-DzK=VmR)&6rI6;%n@N ztFP?ZWbesY_MnaU635(GpLgV~MHG)y8gUGwD&L=Dr9nX`#Z87%-K5oOAx&dH*4f`U zGiM?#29Gp|f!-nsvuxS94=%mG57(!|v-s?tM-nmviZ^&SwnjOBcej4CsGtO5Nxt*P z|CNftOH`2v#DguaY7zKL^cu3{qH!-A2(}zv4Gl0DY0Ym!WVg`{5?#Mhg27dS#93VG z`tKINX0EB0J!$zvY=cd=G&!8r{SRJWWGytXCtvGRQGYE18$g^ZPzFNDt4{yw*-&rO zWuk1F=@-DO8T_EM|1f>T6{-hZ6Ds#MQ?fHIej~U6gm2bDD#JBs0Ddue*>$-EL;$eK z)r-Ms1YatpPE#NQl({-6a0SHV*XnId@5ML!+%VFb_)!yeih83R{3K30YSSHyq*7eP zm%!hF@WX_A^a)pb2dIhwt0`;;zXk_fUOVs$MdEC@Y;>RNa|hs`6pwYE*H?)S^ZpNL C%|25A delta 1753 zcmW+!e^66b7S2sVeh>%{pahgOJdlc&$|4mCt6&j9MO$R1s}@AJ{)j%Q*4e6zNbgMz z5H%#>3a|Kx?+IebQkJZ-P1Q+PV5|fI(`q~F?o@<;30j(taRzr>-IxAz&%Nh<-+bqM z=iKd)4D?8Biv+@IRr5ppTY|&N-0M^9%*+b}H3(TUkbciJ+Y?21Bj`r3TmN*5T?~=# z?B7C>er9IIO?@gs?G$e%YVRWC_6PICLTUOm$2YYQAK>3!k4-<|Wlsl@^roYRmN%`S z%_L5Ny0b5hYoYncBM#~Rx@+DVz{S^yefUpmQmXWE*{}3OgS|_Q_=z1;RK^#EZN%^+ z{D#4pI!hP%v$V!tWw6~qm~mn9tHC6Ib=i(ZmM424%-_9-a;YuY7rIUf) z_XpG^XSRwM`jaDgZm2khW0liMC=ct9U>_FmkgJ?R;aQ*hChi6+1G+4B=|+H zOEx}~_2yoa7Eq5FfcsoE@f_FKnyoOH6@<#eIu53^Hf`u-sufQw?3}(F>F2{xC7DA8D~H0))IGkoV4hcyWUyMK)&169A0)WK6sgaIYsznU>~GjV72GN`ixN|6Im zE?s4QmT6^ml3*u?+=>CUwRc)4vhsL3Xd(oc#V@OTQXn~^7%qOkI$z|(g#okrNtlR;-r!2g{jye47}l^>h*zCA9WrH8NuoP zWG9rnfPa2am6OYRM6bmaBdMxd56iXjlaJ|ie5cDLn-?@75f!Cn6gs8}UBT=~%$EE@ zFB-bFvC!M{{Y5e`c#%1EaxbJ0YjL%y%OtS!xFri{PT+SN>9fqP&ykWY)#{ddnYR(T zOBEb$D4b_gy-Kxvz>olc@r0>L27LjytxI-N0Txy8|$FXymi6jz{gePGR${Gx>anr-E};S8FGlN+%DQN{Z`)-b;?knAJ_sZO%B z)l3?>b!D;+dyG|Py(`R*LA_ZTEU7tf6`b9_3g@T6kFja&vGmPFP?I)H;zjo3w?2DI zl(`AwPgmKcFDoR8MJWyU$lezMznEC}KTB!yZ10DHG~gC+H)@_kD+1p{CCE0PG`tIK z{^s&{sE2-WYtacrb{LrLiH?m*a5YX?H-T#%Q5nFRo=_S-*L)^>L;1USQt%a1-@q-?CC1AbdN;41uP~i9ugCPNbpNwjxKpI%?xJZEuK(V>D-okdD z+|uKO;#Sqs6I3O&w+%d#h($ diff --git a/source/dungeon/DungeonStitcher.py b/source/dungeon/DungeonStitcher.py index 29a2c32f..d7ce3c4f 100644 --- a/source/dungeon/DungeonStitcher.py +++ b/source/dungeon/DungeonStitcher.py @@ -333,13 +333,13 @@ def determine_paths_for_dungeon(world, player, all_regions, name): if portal.destination: paths.append(portal.door.entrance.parent_region.name) if world.mode[player] == 'standard' and name == 'Hyrule Castle Dungeon': - paths.append('Hyrule Dungeon Cellblock') - paths.append(('Hyrule Dungeon Cellblock', 'Hyrule Castle Throne Room')) + paths.append(world.default_zelda_region[player]) + paths.append((world.default_zelda_region[player], 'Hyrule Castle Throne Room')) entrance = next(x for x in world.dungeon_portals[player] if x.name == 'Hyrule Castle South') # todo: in non-er, we can use the other portals too - paths.append(('Hyrule Dungeon Cellblock', entrance.door.entrance.parent_region.name)) + paths.append((world.default_zelda_region[player], entrance.door.entrance.parent_region.name)) paths.append(('Hyrule Castle Throne Room', [entrance.door.entrance.parent_region.name, - 'Hyrule Dungeon Cellblock'])) + world.default_zelda_region[player]])) if world.doorShuffle[player] in ['basic'] and name == 'Thieves Town': paths.append('Thieves Attic Window') elif 'Thieves Attic Window' in all_r_names: diff --git a/source/enemizer/Enemizer.py b/source/enemizer/Enemizer.py index f4e89207..cc32ba8c 100644 --- a/source/enemizer/Enemizer.py +++ b/source/enemizer/Enemizer.py @@ -521,6 +521,21 @@ def randomize_enemies(world, player): green_mail, blue_mail, red_mail = original_table[idx] del original_table[idx] world.data_tables[player].enemy_damage[i] = [green_mail, blue_mail, red_mail] + # determine default zelda follower location + if world.mode[player] == 'standard' and world.doorShuffle[player] == 'crossed' and world.shuffle_followers[player]: + def random_zelda(): + world.default_zelda_region[player] = random.choice(['Hyrule Dungeon Cellblock', 'Thieves Blind\'s Cell']) + if world.customizer: + placements = world.customizer.get_placements() + if placements and player in placements and 'Zelda Herself' in placements[player].values(): + location = [l for (l, item) in placements[player].items() if item == 'Zelda Herself'][0] + if location == 'Suspicious Maiden': + world.default_zelda_region[player] = 'Thieves Blind\'s Cell' + else: + random_zelda() + else: + random_zelda() + def write_enemy_shuffle_settings(world, player, rom): From 52ed4cf7ded9b7e738b0c734c7ef94787cb4f294 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 7 Sep 2025 10:52:23 -0500 Subject: [PATCH 09/73] Re-fixed old man spawn on pyramid issue --- Rom.py | 2 +- data/base2current.bps | Bin 136664 -> 136651 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 42cfe59d..b70e983b 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '20e588b832011dcf15dbd31dff6955ce' +RANDOMIZERBASEHASH = '65fae75651987228878051028da066ad' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 0fe2d932963a31af760b5381bf17b8627f8c443c..d28bca6d34028f9c2ea3977ae252f75564d57ef4 100644 GIT binary patch delta 9554 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 H^K}0YTlch| delta 9605 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 A9{>OV From b8a40cf6c1f178d222452132f5a5de2527f3a1da Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 7 Sep 2025 10:59:34 -0500 Subject: [PATCH 10/73] Version bump 0.6.0.8 --- CHANGELOG.md | 6 ++++++ OverworldShuffle.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28128e2b..8e83b3b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.6.0.8 +- Re-fixed issue with Old Man spawning on pyramid +- Allowing Zelda to be in TT Prison for follower shuffle escape +- Fixed error with placing Old Man Cave in ER +- Fixed error when plando'ing followers at locations + ## 0.6.0.7 - Emergency fix for GT cutscene GFX diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 3d28147b..bfe555cd 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.6.0.7' +version_number = '0.6.0.8' # branch indicator is intentionally different across branches version_branch = '-u' From 277fdff0e1ed39f7cc4da4dede7748687e3f7810 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Mon, 8 Sep 2025 12:55:57 -0500 Subject: [PATCH 11/73] Added new Snitch Lady text when Links House is placed there --- Rom.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Rom.py b/Rom.py index b70e983b..9bf71867 100644 --- a/Rom.py +++ b/Rom.py @@ -2103,6 +2103,14 @@ def write_strings(rom, world, player, team): " ~~~2020~~~\n Linlinlin\n\n" " ~~~2019~~~\n Kohrek\n" ) + if not world.is_bombshop_start(player): + links_house = 'Links House' + else: + links_house = 'Big Bomb Shop' + links_house = world.get_region(links_house, player) + links_house = next(e for e in links_house.entrances if e.name != 'Links House S&Q') + if 'Snitch Lady' in links_house.name: + tt['kakariko_alert_guards'] = CompressedTextMapper.convert("Hey @! I'm taking your house!\nk.thx.bye") # Let's keep this guy's text accurate to the shuffle setting. if world.shuffle[player] in ['vanilla', 'dungeonsfull', 'dungeonssimple', 'lite', 'lean']: From 4a82b2ad50377989411b77b30e5116a7957d642a Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 21 Sep 2025 13:37:07 -0500 Subject: [PATCH 12/73] Remove unused argument from MultiServer call --- MultiServer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MultiServer.py b/MultiServer.py index c92f9989..44559953 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -83,7 +83,7 @@ def notify_client(client : Client, text : str): logging.info("Notice (Player %s in team %d): %s" % (client.name, client.team+1, text)) asyncio.create_task(send_msgs(client.socket, [['Print', text]])) -async def server(websocket, path, ctx : Context): +async def server(websocket, ctx : Context): client = Client(websocket) ctx.clients.append(client) From cce6abc4685dc25504348444449641e9b98d3f88 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 21 Sep 2025 13:39:07 -0500 Subject: [PATCH 13/73] Fixed issue with Duck overwriting GT cutscene gfx --- Rom.py | 2 +- data/base2current.bps | Bin 136651 -> 136653 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 9bf71867..021f96e6 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '65fae75651987228878051028da066ad' +RANDOMIZERBASEHASH = 'ba0de478a4377673b8c842ac5d12dd16' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index d28bca6d34028f9c2ea3977ae252f75564d57ef4..b76633a917d8f654f915096acc050cba7d4b3eff 100644 GIT binary patch delta 6283 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 From 237ed4bdfd60682ce24c3efe277c406467ed36c3 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 21 Sep 2025 13:56:41 -0500 Subject: [PATCH 14/73] Fixed pogdor (frogdor at PoD entrance) with Kiki following while exiting at PoD --- Rom.py | 2 +- data/base2current.bps | Bin 136653 -> 136674 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 021f96e6..c90871fc 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'ba0de478a4377673b8c842ac5d12dd16' +RANDOMIZERBASEHASH = '1831c9d47b9614b3dac3a68499dcb273' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index b76633a917d8f654f915096acc050cba7d4b3eff..3acec013f0ee2dc9162b62b1be84d582eb130355 100644 GIT binary patch delta 289 zcmV++0p9-2s|ez&2(T&x1akq5{Rgfvk-p(z8$`=M4dtvp6ymPYBeFB7^CmuXM9bfox1jiEF|zs|!`) zfiR8)fZ1!MP4E-R0`Lv3djrr2t@r}a1E~RPsizE8;*}x?<)E+ylMRQPag~wx2=}}fdmF5 n9oU;27`HT>0cisQYYUg3p8+)i9Jke<0q}JQGmb1YNM%K55r%r6 delta 268 zcmV+n0rURis|d}j2(T&x1oH_D_OmVnb{zqmv!x(y0}2J|pv-}W*p(t&lN=-<6o%@c zoSR-qftZ1XoR>Rgfvk-pzq3#z=M4davp6ymPXq9ydb3i2Y)m-CYo$%_6UhSb4Xt|v z&=F+yFRIz=;?(9src!W2F{lSZzzCz zpOd1_>Iz#afDkImJCp*CvzE`ZNEu^Ti;Y5nu<(*o8Gwm^@CTMfih*mQjh_LxVi*B+ zaRpj@fR{11+=&6X4FL?7mX`r40$p&o!j}Po1O|Q_*qe11w@I7 Date: Wed, 15 Oct 2025 18:31:15 -0500 Subject: [PATCH 15/73] New fix for pot drops when at sprite limit --- Rom.py | 2 +- data/base2current.bps | Bin 136674 -> 136766 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index c90871fc..5fe5f3b5 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '1831c9d47b9614b3dac3a68499dcb273' +RANDOMIZERBASEHASH = '5616ec09bb20de9a3d483ea2ca27bc4c' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 3acec013f0ee2dc9162b62b1be84d582eb130355..a7677e525820cb5824e3850b9857af84385c7669 100644 GIT binary patch delta 703 zcmWlRYe-XJ9LD|cc-&!g*z!__x^=+(;M6087=|voFmEJ6eUg>KY9)Ayv@o&vb<{R2#_J&HZe9ke^cS3ORI?hLCVjo{*Hi8sxu=is{1LtJtbT z*xH1#TW!MD;WgG5;1R=K4f2=83TxM??og?9y~48UtW?S&i~4ToD?ygk8JoqSE_RSy zFEL{-im?rQ-r??zM{K!x9<;JGLB7!JX**>W_-s|#p%b@yERDi2(}__$!uRKK*XU4d zYLD=_WibWDg~47c1$*{v+ii(7B#hc#Ga~KHE)DDnUe}cbF^l!7_p@WZg1CL^pJoDV z+Ram|Feg+_KcU2z-5GBcBoIPFCL{zFXn2zf;{mG*ez%B|Ku13qAb$|*#}sQ!B!}o2 zOGvg&uXAZ=#~0&`D11>;m-xP~JQ=$pv`-t)P$aM77f}*OKW(ia7?AfB7ogc~xp7~< zZr#q!t$I?LBu5tA7DuWxygh!)uF>e>l+o!W&UmtyT>8 zL?{0lQN;-Ox23K>Qo99z7&%XoDJLXL=fXUSeZE3AoKOodNv;dhp|@nh1qCW&t+hWI6OoNQa90|< zIGW&^T^CMGI6U-bzWMZ_7D2nD6N~NN*u*3^H@0`|_ zliA6=`@l_FgB??B9%3JeiiMOJ?xLHzj1|>IO_DBzqIvc3CoPt47ovKv9eZG`YE6l7A;-$OpOM_EZ{xUO6 zs&hDThdC!Fq)5yyHcInOBZO?o{Q*sEPqP=ofgfQjdp#VeGr2WLd|k#gXXTMb^ME)< z8xg1A(1R5;{>DVmihCxd&Fv3T(`ZWljN<=a#$9l&TeJW6$k|f z?yOKNJK)Gt5rB!Gd+`Pg;_cu(nS4>b^ypv{ixd>WX6PdYJ2{{a2@L!iN+u!K40J+O z5PJP-Z|PXsqJfMR;wIYsB_%;^Rc3H|g2WR`6XLA?&upbk&?;yWH=dfo$1&vRUgLT# zJGya5NSC&LkM?%;u|NNE?30xMD_}nchUih^%_Pa3u4()Y!wDF`*$!Z#57#?DP4so( zs}874&W8@DAW9TC?11_jtzzy`d~yF4*W!bPgxt9+=gsJouYvITj%L|r7ZdUlr6gq@ z7Z&dcvNc0Az)9Ce@i8ZKz%aHrAwTtLluHkp-ft8LkMXh-stXNKPO~nv(T=+BGD(1= zBBN0*%`a=VQ4v#=BO?|pcR?+4rQJFcm&8*17T3j2530f${T`HO*DCBN!>#GZH(bz9 zFztBT1zMuC0UvThd1l)gyZ1=z7;5rrTF2~nRa5ENV=av#og2Q6&?l$LtDCyd-TV*4 CBKRZ# From 917d126023207d8d0f7a1a0498821981f6c5d8b3 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 18 Oct 2025 02:27:43 -0500 Subject: [PATCH 16/73] Fixed Ganon silvers hint for free-standing items --- Rom.py | 2 +- data/base2current.bps | Bin 136766 -> 136743 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 5fe5f3b5..e29406ae 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '5616ec09bb20de9a3d483ea2ca27bc4c' +RANDOMIZERBASEHASH = 'e20f407ef55da945f893d32ee6fc541d' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index a7677e525820cb5824e3850b9857af84385c7669..cb0632acee3e06141779ffe3ab48ecf6326f8f5b 100644 GIT binary patch delta 11963 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 k*S*u@%@B4(AK!AWT2_p;;LRJnT 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 From 048487fce0b53a4346c83c7b3a0f84c46dbec3de Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 19 Oct 2025 23:35:17 -0500 Subject: [PATCH 17/73] Moved random settings resolutions into helper function --- Main.py | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/Main.py b/Main.py index df672380..34a819e7 100644 --- a/Main.py +++ b/Main.py @@ -97,29 +97,7 @@ def main(args, seed=None, fish=None): if args.securerandom: world.seed = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(9)) - world.crystals_needed_for_ganon = {player: random.randint(0, 7) if args.crystals_ganon[player] == 'random' else int(args.crystals_ganon[player]) for player in range(1, world.players + 1)} - world.crystals_needed_for_gt = {player: random.randint(0, 7) if args.crystals_gt[player] == 'random' else int(args.crystals_gt[player]) for player in range(1, world.players + 1)} - world.intensity = {player: random.randint(1, 3) if args.intensity[player] == 'random' else int(args.intensity[player]) for player in range(1, world.players + 1)} - - world.treasure_hunt_count = {} - world.treasure_hunt_total = {} - for p in args.triforce_goal: - if int(args.triforce_goal[p]) != 0 or int(args.triforce_pool[p]) != 0 or int(args.triforce_goal_min[p]) != 0 or int(args.triforce_goal_max[p]) != 0 or int(args.triforce_pool_min[p]) != 0 or int(args.triforce_pool_max[p]) != 0: - if int(args.triforce_goal[p]) != 0: - world.treasure_hunt_count[p] = int(args.triforce_goal[p]) - elif int(args.triforce_goal_min[p]) != 0 and int(args.triforce_goal_max[p]) != 0: - world.treasure_hunt_count[p] = random.randint(int(args.triforce_goal_min[p]), int(args.triforce_goal_max[p])) - else: - world.treasure_hunt_count[p] = 8 if world.goal[p] == 'trinity' else 20 - if int(args.triforce_pool[p]) != 0: - world.treasure_hunt_total[p] = int(args.triforce_pool[p]) - elif int(args.triforce_pool_min[p]) != 0 and int(args.triforce_pool_max[p]) != 0: - world.treasure_hunt_total[p] = random.randint(max(int(args.triforce_pool_min[p]), world.treasure_hunt_count[p] + int(args.triforce_min_difference[p])), min(int(args.triforce_pool_max[p]), world.treasure_hunt_count[p] + int(args.triforce_max_difference[p]))) - else: - world.treasure_hunt_total[p] = 10 if world.goal[p] == 'trinity' else 30 - else: - # this will be handled in ItemList.py and custom item pool is used to determine the numbers - world.treasure_hunt_count[p], world.treasure_hunt_total[p] = 0, 0 + resolve_random_settings(world, args) world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)} world.finish_init() @@ -519,6 +497,33 @@ def init_world(args, fish): return world +def resolve_random_settings(world, args): + world.crystals_needed_for_ganon = {player: random.randint(0, 7) if args.crystals_ganon[player] == 'random' else int(args.crystals_ganon[player]) for player in range(1, world.players + 1)} + world.crystals_needed_for_gt = {player: random.randint(0, 7) if args.crystals_gt[player] == 'random' else int(args.crystals_gt[player]) for player in range(1, world.players + 1)} + world.intensity = {player: random.randint(1, 3) if args.intensity[player] == 'random' else int(args.intensity[player]) for player in range(1, world.players + 1)} + + world.treasure_hunt_count = {} + world.treasure_hunt_total = {} + for p in args.triforce_goal: + if int(args.triforce_goal[p]) != 0 or int(args.triforce_pool[p]) != 0 or int(args.triforce_goal_min[p]) != 0 or int(args.triforce_goal_max[p]) != 0 or int(args.triforce_pool_min[p]) != 0 or int(args.triforce_pool_max[p]) != 0: + if int(args.triforce_goal[p]) != 0: + world.treasure_hunt_count[p] = int(args.triforce_goal[p]) + elif int(args.triforce_goal_min[p]) != 0 and int(args.triforce_goal_max[p]) != 0: + world.treasure_hunt_count[p] = random.randint(int(args.triforce_goal_min[p]), int(args.triforce_goal_max[p])) + else: + world.treasure_hunt_count[p] = 8 if world.goal[p] == 'trinity' else 20 + if int(args.triforce_pool[p]) != 0: + world.treasure_hunt_total[p] = int(args.triforce_pool[p]) + elif int(args.triforce_pool_min[p]) != 0 and int(args.triforce_pool_max[p]) != 0: + world.treasure_hunt_total[p] = random.randint(max(int(args.triforce_pool_min[p]), world.treasure_hunt_count[p] + int(args.triforce_min_difference[p])), min(int(args.triforce_pool_max[p]), world.treasure_hunt_count[p] + int(args.triforce_max_difference[p]))) + else: + world.treasure_hunt_total[p] = 10 if world.goal[p] == 'trinity' else 30 + else: + # this will be handled in ItemList.py and custom item pool is used to determine the numbers + world.treasure_hunt_count[p], world.treasure_hunt_total[p] = 0, 0 + return + + def set_starting_inventory(world, args): for player in range(1, world.players + 1): if args.usestartinventory[player]: From ba444f4bbc5abf745891d65f5b678866c01b596a Mon Sep 17 00:00:00 2001 From: codemann8 Date: Mon, 27 Oct 2025 23:23:10 -0500 Subject: [PATCH 18/73] Remove duplicated hint possibility between location and item hinting --- Rom.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Rom.py b/Rom.py index e29406ae..55ddde86 100644 --- a/Rom.py +++ b/Rom.py @@ -2229,6 +2229,7 @@ def write_strings(rom, world, player, team): # Next we write a few hints for specific inconvenient locations. We don't make many because in entrance this is highly unpredictable. locations_to_hint = InconvenientLocations.copy() + hinted_locations = [] if world.doorShuffle[player] == 'vanilla': locations_to_hint.extend(InconvenientDungeonLocations) if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']: @@ -2246,7 +2247,6 @@ def write_strings(rom, world, player, team): second_item = hint_text(world.get_location('Swamp Palace - West Chest', player).item) first_item = hint_text(world.get_location('Swamp Palace - Big Key Chest', player).item) this_hint = f'The westmost chests in Swamp Palace contain {first_item} and {second_item}.' - tt[hint_locations.pop(0)] = this_hint elif location == 'Mire Left': if random.randint(0, 1) == 0: first_item = hint_text(world.get_location('Misery Mire - Compass Chest', player).item) @@ -2255,38 +2255,31 @@ def write_strings(rom, world, player, team): second_item = hint_text(world.get_location('Misery Mire - Compass Chest', player).item) first_item = hint_text(world.get_location('Misery Mire - Big Key Chest', player).item) this_hint = f'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': item = hint_text(world.get_location(location, player).item) this_hint = f'Waiting in the Tower of Hera basement leads to {item}.' - tt[hint_locations.pop(0)] = this_hint elif location == 'Ganons Tower - Big Chest': item = hint_text(world.get_location(location, player).item) this_hint = f'The big chest in Ganon\'s Tower contains {item}.' - tt[hint_locations.pop(0)] = this_hint elif location == 'Thieves\' Town - Big Chest': item = hint_text(world.get_location(location, player).item) this_hint = f'The big chest in Thieves\' Town contains {item}.' - tt[hint_locations.pop(0)] = this_hint elif location == 'Ice Palace - Big Chest': item = hint_text(world.get_location(location, player).item) this_hint = f'The big chest in Ice Palace contains {item}.' - tt[hint_locations.pop(0)] = this_hint elif location == 'Eastern Palace - Big Key Chest': item = hint_text(world.get_location(location, player).item) this_hint = f'The antifairy guarded chest in Eastern Palace contains {item}.' - tt[hint_locations.pop(0)] = this_hint elif location == 'Sahasrahla': item = hint_text(world.get_location(location, player).item) this_hint = f'Sahasrahla seeks a green pendant for {item}.' - tt[hint_locations.pop(0)] = this_hint elif location == 'Graveyard Cave': item = hint_text(world.get_location(location, player).item) this_hint = f'The cave north of the graveyard contains {item}.' - tt[hint_locations.pop(0)] = this_hint else: this_hint = f'{location} contains {hint_text(world.get_location(location, player).item)}.' - tt[hint_locations.pop(0)] = this_hint + hinted_locations.append(location) + tt[hint_locations.pop(0)] = this_hint # Lastly we write hints to show where certain interesting items are. # It is done the way it is to re-use the silver code and also to give one hint per each type of item regardless @@ -2299,9 +2292,10 @@ def write_strings(rom, world, player, team): if world.owShuffle[player] != 'vanilla' or world.owMixed[player]: # Adding a guaranteed hint for the Flute in overworld shuffle. this_location = world.find_items_not_key_only(flute_item, player) - if this_location: + if this_location and this_location not in hinted_locations: this_hint = this_location[0].item.hint_text + ' can be found ' + hint_text(this_location[0]) + '.' this_hint = this_hint[0].upper() + this_hint[1:] + hinted_locations.append(this_location) tt[hint_locations.pop(0)] = this_hint items_to_hint.remove(flute_item) if world.keyshuffle[player] not in ['none', 'nearby', 'universal']: @@ -2317,11 +2311,12 @@ def write_strings(rom, world, player, team): while hint_count > 0 and len(items_to_hint) > 0: this_item = items_to_hint.pop(0) this_location = world.find_items_not_key_only(this_item, player) - if this_location: + if this_location and this_location not in hinted_locations: random.shuffle(this_location) item_name = this_location[0].item.hint_text item_name = item_name[0].upper() + item_name[1:] this_hint = f'{item_name} can be found {hint_text(this_location[0])}.' + hinted_locations.append(this_location) tt[hint_locations.pop(0)] = this_hint hint_count -= 1 From fdbe9cf9fd8930398ea75eec33944465743a6ea6 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 29 Oct 2025 00:20:41 -0500 Subject: [PATCH 19/73] Implemented Custom Goal Framework --- BaseClasses.py | 44 ++++++-- ItemList.py | 41 +++++-- Main.py | 153 +++++++++++++++++++++++++- Rom.py | 152 +++++++++++++++++++------- Rules.py | 180 +++++++++++++++++++++++++++---- Text.py | 1 + data/base2current.bps | Bin 136743 -> 137030 bytes docs/Customizer.md | 152 +++++++++++++++++++++----- source/classes/CustomSettings.py | 6 +- 9 files changed, 629 insertions(+), 100 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 1a230d6b..fc4f6394 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -187,6 +187,7 @@ class World(object): set_player_attr('force_fix', {'gt': False, 'sw': False, 'pod': False, 'tr': False}) set_player_attr('prizes', {'dig;': [], 'pull': [0, 0, 0], 'crab': [0, 0], 'stun': 0, 'fish': 0, 'enemies': []}) set_player_attr('default_zelda_region', 'Hyrule Dungeon Cellblock') + set_player_attr('custom_goals', {'gtentry': None, 'ganongoal': None, 'pedgoal': None, 'murahgoal': None}) set_player_attr('exp_cache', defaultdict(dict)) set_player_attr('enabled_entrances', {}) @@ -1211,16 +1212,35 @@ class CollectionState(object): def item_count(self, item, player): return self.prog_items[item, player] - def everything(self, player): - all_locations = self.world.get_filled_locations(player) - all_locations.remove(self.world.get_location('Ganon', player)) - return (len([x for x in self.locations_checked if x.player == player]) + def everything(self, player, all_except=0): + all_locations = [x for x in self.world.get_filled_locations(player) if not x.locked] + return (len([x for x in self.locations_checked if x.player == player and not x.locked]) + all_except >= len(all_locations)) def has_crystals(self, count, player): crystals = ['Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7'] return len([crystal for crystal in crystals if self.has(crystal, player)]) >= count + def has_pendants(self, count, player): + pendants = ['Green Pendant', 'Red Pendant', 'Blue Pendant'] + return len([pendant for pendant in pendants if self.has(pendant, player)]) >= count + + def has_bosses(self, count, player, prize_type=None): + dungeons = 'Eastern Palace', 'Desert Palace', 'Tower of Hera', 'Palace of Darkness', 'Swamp Palace', "Thieves' Town", 'Skull Woods', 'Ice Palace', 'Misery Mire', 'Turtle Rock' + reachable_bosses = 0 + for d in dungeons: + region = self.world.get_region(f'{d} - Boss Kill', player) + if prize_type is None or prize_type in region.dungeon.prize.name: + if self.can_reach(region, None, player): + reachable_bosses += 1 + return reachable_bosses >= count + + def has_crystal_bosses(self, count, player): + return self.has_bosses(count, player, 'Crystal') + + def has_pendant_bosses(self, count, player): + return self.has_bosses(count, player, 'Pendant') + def can_lift_rocks(self, player): return self.has('Power Glove', player) or self.has('Titans Mitts', player) @@ -3015,6 +3035,7 @@ class Spoiler(object): 'flute_mode': self.world.flute_mode, 'bow_mode': self.world.bow_mode, 'goal': self.world.goal, + 'custom_goals': self.world.custom_goals, 'ow_shuffle': self.world.owShuffle, 'ow_terrain': self.world.owTerrain, 'ow_crossed': self.world.owCrossed, @@ -3250,8 +3271,19 @@ class Spoiler(object): if self.metadata['goal'][player] in ['triforcehunt', 'trinity', 'ganonhunt']: outfile.write('Triforce Pieces Required:'.ljust(line_width) + '%s\n' % self.metadata['triforcegoal'][player]) outfile.write('Triforce Pieces Total:'.ljust(line_width) + '%s\n' % self.metadata['triforcepool'][player]) - outfile.write('Crystals Required for GT:'.ljust(line_width) + '%s\n' % str(self.world.crystals_gt_orig[player])) - outfile.write('Crystals Required for Ganon:'.ljust(line_width) + '%s\n' % str(self.world.crystals_ganon_orig[player])) + custom = self.metadata['custom_goals'][player] + if 'requirements' in custom['gtentry']: + outfile.write('GT Entry Requirement:'.ljust(line_width) + 'custom\n') + else: + outfile.write('GT Entry Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_gt_orig[player])) + if 'requirements' in custom['ganongoal']: + outfile.write('Ganon Requirement:'.ljust(line_width) + 'custom\n') + else: + outfile.write('Ganon Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_ganon_orig[player])) + if 'requirements' in custom['pedgoal']: + outfile.write('Pedestal Requirement:'.ljust(line_width) + 'custom\n') + if 'requirements' in custom['murahgoal']: + outfile.write('Murahdahla Requirement:'.ljust(line_width) + 'custom\n') outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player]) outfile.write('\n') outfile.write('Accessibility:'.ljust(line_width) + '%s\n' % self.metadata['accessibility'][player]) diff --git a/ItemList.py b/ItemList.py index 65d67f57..b7dd5e18 100644 --- a/ItemList.py +++ b/ItemList.py @@ -228,12 +228,17 @@ def generate_itempool(world, player): if world.timer in ['ohko', 'timed-ohko']: world.can_take_damage = False - if world.goal[player] in ['pedestal', 'triforcehunt']: + goal_req = None + if world.custom_goals[player]['ganongoal'] and 'requirements' in world.custom_goals[player]['ganongoal']: + goal_req = world.custom_goals[player]['ganongoal']['requirements'][0] + if world.goal[player] in ['pedestal', 'triforcehunt'] or (goal_req and goal_req['condition'] == 0x00): set_event_item(world, player, 'Ganon', 'Nothing') else: set_event_item(world, player, 'Ganon', 'Triforce') - if world.goal[player] in ['triforcehunt', 'trinity']: + if world.custom_goals[player]['murahgoal'] and 'requirements' in world.custom_goals[player]['murahgoal']: + goal_req = world.custom_goals[player]['murahgoal']['requirements'][0] + if world.goal[player] in ['triforcehunt', 'trinity'] or (goal_req and goal_req['condition'] != 0x00): region = world.get_region('Hyrule Castle Courtyard', player) loc = Location(player, "Murahdahla", parent=region) region.locations.append(loc) @@ -1159,11 +1164,17 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt place_item('Link\'s Uncle', swords_to_use.pop()) place_item('Blacksmith', swords_to_use.pop()) place_item('Pyramid Fairy - Left', swords_to_use.pop()) - if goal not in ['pedestal', 'trinity']: - place_item('Master Sword Pedestal', swords_to_use.pop()) - else: - place_item('Master Sword Pedestal', 'Triforce') + if world.custom_goals[player]['pedgoal'] and 'requirements' in world.custom_goals[player]['pedgoal'] and world.custom_goals[player]['pedgoal']['requirements'][0]['condition'] == 0x00: + place_item('Master Sword Pedestal', 'Nothing') + world.get_location('Master Sword Pedestal', player).locked = True pool.append(swords_to_use.pop()) + else: + if goal not in ['pedestal', 'trinity']: + place_item('Master Sword Pedestal', swords_to_use.pop()) + else: + place_item('Master Sword Pedestal', 'Triforce') + world.get_location('Master Sword Pedestal', player).locked = True + pool.append(swords_to_use.pop()) else: pool.extend(diff.progressivesword if want_progressives() else diff.basicsword) if swords == 'assured': @@ -1189,8 +1200,12 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt # note: massage item pool now handles shrinking the pool appropriately - if goal in ['pedestal', 'trinity'] and swords != 'vanilla': + if world.custom_goals[player]['pedgoal'] and 'requirements' in world.custom_goals[player]['pedgoal'] and world.custom_goals[player]['pedgoal']['requirements'][0]['condition'] == 0x00: + place_item('Master Sword Pedestal', 'Nothing') + world.get_location('Master Sword Pedestal', player).locked = True + elif goal in ['pedestal', 'trinity'] and swords != 'vanilla': place_item('Master Sword Pedestal', 'Triforce') + world.get_location('Master Sword Pedestal', player).locked = True if world.bow_mode[player].startswith('retro'): pool = [item.replace('Single Arrow', 'Rupees (5)') for item in pool] pool = [item.replace('Arrows (10)', 'Rupees (5)') for item in pool] @@ -1352,8 +1367,12 @@ def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer elif timer == 'ohko': clock_mode = 'ohko' - if goal in ['pedestal', 'trinity']: + if world.custom_goals[player]['pedgoal'] and 'requirements' in world.custom_goals[player]['pedgoal'] and world.custom_goals[player]['pedgoal']['requirements'][0]['condition'] == 0x00: + place_item('Master Sword Pedestal', 'Nothing') + world.get_location('Master Sword Pedestal', player).locked = True + elif goal in ['pedestal', 'trinity']: place_item('Master Sword Pedestal', 'Triforce') + world.get_location('Master Sword Pedestal', player).locked = True if mode == 'standard': if world.keyshuffle[player] == 'universal': @@ -1466,8 +1485,12 @@ def make_customizer_pool(world, player): elif timer == 'ohko': clock_mode = 'ohko' - if world.goal[player] in ['pedestal', 'trinity']: + if world.custom_goals[player]['pedgoal'] and 'requirements' in world.custom_goals[player]['pedgoal'] and world.custom_goals[player]['pedgoal']['requirements'][0]['condition'] == 0x00: + place_item('Master Sword Pedestal', 'Nothing') + world.get_location('Master Sword Pedestal', player).locked = True + elif world.goal[player] in ['pedestal', 'trinity']: place_item('Master Sword Pedestal', 'Triforce') + world.get_location('Master Sword Pedestal', player).locked = True guaranteed_items = alwaysitems + ['Magic Mirror', 'Moon Pearl'] if world.is_tile_swapped(0x18, player) or world.flute_mode[player] == 'active': diff --git a/Main.py b/Main.py index 34a819e7..41a46b11 100644 --- a/Main.py +++ b/Main.py @@ -521,8 +521,159 @@ def resolve_random_settings(world, args): else: # this will be handled in ItemList.py and custom item pool is used to determine the numbers world.treasure_hunt_count[p], world.treasure_hunt_total[p] = 0, 0 + + if world.customizer: + def process_goal(goal_type): + goal_input = goals[player][goal_type] + world.custom_goals[player][goal_type] = goal = {} + if 'cutscene_gfx' in goal_input and goal_type in ['gtentry', 'pedgoal', 'murahgoal']: + gfx = goal_input['cutscene_gfx'] + if type(gfx) is str: + from Tables import item_gfx_table + if gfx.lower() == 'random': + gfx = random.choice(list(item_gfx_table.keys())) + if gfx in item_gfx_table: + goal['cutscene_gfx'] = (item_gfx_table[gfx][1] + (0x8000 if not item_gfx_table[gfx][0] else 0), item_gfx_table[gfx][2]) + else: + raise Exception(f'Invalid name "{gfx}" in customized {goal_type} cutscene gfx') + else: + goal['cutscene_gfx'] = gfx + if 'requirements' in goal_input: + if goal_type == 'ganongoal' and world.goal[player] == 'pedestal': + goal['requirements'] = [0x00] + goal['logic'] = False + return + goal['requirements'] = [] + goal['logic'] = {} + if 'goaltext' in goal_input: + goal['goaltext'] = goal_input['goaltext'] + else: + raise Exception(f'Missing goal text for {goal_type}') + + req_table = { + 'Invulnerable': 0x00, + 'Pendants': 0x01, + 'Crystals': 0x02, + 'PendantBosses': 0x03, + 'CrystalBosses': 0x04, + 'Bosses': 0x05, + 'Agahnim1Defeated': 0x06, + 'Agahnim1': 0x06, + 'Aga1': 0x06, + 'Agahnim2Defeated': 0x07, + 'Agahnim2': 0x07, + 'Aga2': 0x07, + 'GoalItemsCollected': 0x08, + 'GoalItems': 0x08, + 'TriforcePieces': 0x08, + 'TriforceHunt': 0x08, + 'MaxCollectionRate': 0x09, + 'CollectionRate': 0x09, + 'Collection': 0x09, + 'CustomGoal': 0x0A, + 'Custom': 0x0A, + } + if isinstance(goal_input['requirements'], list): + for r in list(goal_input['requirements']): + req = {} + try: + req['condition'] = req_table[list(r.keys())[0]] + if req['condition'] == req_table['Invulnerable']: + goal['requirements']= [req] + goal['logic'] = False + break + elif req['condition'] == req_table['CustomGoal']: + if isinstance(r['address'], int) and 0x7E0000 <= r['address'] <= 0x7FFFFF: + compare_table = { + 'minimum': 0x00, + 'at least': 0x00, + 'equal': 0x01, + 'equals': 0x01, + 'equal to': 0x01, + 'any flag': 0x02, + 'all flags': 0x03, + 'flags match': 0x03, + 'count bits': 0x04, + 'count flags': 0x04, + } + if r['comparison'] in compare_table: + options = compare_table[r['comparison']] + if r['address'] >= 0x7F0000: + options |= 0x10 + if isinstance(r['target'], int) and 0 <= r['target'] <= 0xFFFF: + if 'size' in r and r['size'] in ['word', '16-bit', '16bit', '16 bit', '16', '2-byte', '2byte', '2 byte', '2-bytes', '2 bytes']: + options |= 0x08 + req['target'] = r['target'] + elif 0 <= r['target'] <= 0xFF: + req['target'] = r['target'] + else: + raise Exception(f'Invalid custom goal target for {goal_type}, must be an 8-bit integer') + req.update({'address': r['address'] & 0xFFFF, 'options': options}) + goal['requirements'].append(req) + else: + raise Exception(f'Invalid custom goal target for {goal_type}, must be a 16-bit integer') + else: + raise KeyError(f'Invalid custom goal comparison for {goal_type}') + else: + raise Exception(f'Custom goal address for {goal_type} only allows 0x7Exxxx and 0x7Fxxxx addresses') + else: + if req['condition'] not in [req_table['Aga1'], req_table['Aga2']]: + if 'target' not in r: + req['condition'] |= 0x80 + else: + if isinstance(r['target'], int): + if req['condition'] < req_table['TriforcePieces']: + if 0 <= r['target'] <= 0xFF: + req['target'] = r['target'] + else: + raise Exception(f'Invalid {list(r.keys())[0]} requirement target for {goal_type}, must be an 8-bit integer') + else: + if 0 <= r['target'] <= 0xFFFF: + req['target'] = r['target'] + else: + raise Exception(f'Invalid {list(r.keys())[0]} requirement target for {goal_type}, must be a 16-bit integer') + elif isinstance(r['target'], str): + if r['target'].lower() == 'random': + req['target'] = 'random' + elif r['target'].endswith('%') and 1 <= int(r['target'][:-1]) <= 100: + req['target'] = req['target'] + else: + raise Exception(f'Invalid {list(r.keys())[0]} requirement target for {goal_type}') + if req['condition'] & 0x7F == req_table['Pendants']: + goal['logic']['pendants'] = req['target'] or 3 + elif req['condition'] & 0x7F == req_table['Crystals']: + goal['logic']['crystals'] = req['target'] or 7 + elif req['condition'] & 0x7F == req_table['PendantBosses']: + goal['logic']['pendant_bosses'] = req['target'] or 3 + elif req['condition'] & 0x7F == req_table['CrystalBosses']: + goal['logic']['crystal_bosses'] = req['target'] or 7 + elif req['condition'] & 0x7F == req_table['Bosses']: + goal['logic']['bosses'] = req['target'] or 10 + elif req['condition'] & 0x7F == req_table['Aga1']: + goal['logic']['aga1'] = True + elif req['condition'] & 0x7F == req_table['Aga2']: + goal['logic']['aga2'] = True + elif req['condition'] & 0x7F == req_table['TriforcePieces']: + goal['logic']['goal_items'] = req['target'] or None + elif req['condition'] & 0x7F == req_table['CollectionRate']: + goal['logic']['collection'] = req['target'] or None + goal['requirements'].append(req) + except KeyError: + raise KeyError(f'Invalid {goal_type} requirement: {r}') + else: + raise KeyError(f'Invalid {goal_type} requirement definition') + if 'logic' in goal_input and goal['logic'] is not None: + goal['logic'].update(goal_input['logic']) + return + + goals = world.customizer.get_goals() + for player in range(1, world.players + 1): + if goals and player in goals: + for g in ['gtentry', 'ganongoal', 'pedgoal', 'murahgoal']: + if g in goals[player]: + process_goal(g) return - + def set_starting_inventory(world, args): for player in range(1, world.players + 1): diff --git a/Rom.py b/Rom.py index 55ddde86..9a43f813 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'e20f407ef55da945f893d32ee6fc541d' +RANDOMIZERBASEHASH = 'b7817fb00fb0a918a7fa275ff8f4c3be' class JsonRom(object): @@ -1218,8 +1218,6 @@ def patch_rom(world, rom, player, team, is_mystery=False): rom.write_bytes(0xE9A5, [0x7E, 0x00, 0x24]) # disable below ganon chest if world.is_pyramid_open(player): rom.initial_sram.pre_open_pyramid_hole() - if world.crystals_needed_for_gt[player] == 0: - rom.initial_sram.pre_open_ganons_tower() rom.write_byte(0x18008F, 0x01 if world.is_atgt_swapped(player) else 0x00) # AT/GT swapped rom.write_byte(0xF5D73, 0xF0) # bees are catchable rom.write_byte(0xF5F10, 0xF0) # bees are catchable @@ -1247,22 +1245,105 @@ def patch_rom(world, rom, player, team, is_mystery=False): (0x02 if 'bombs' in world.escape_assist[player] else 0x00) | (0x04 if 'magic' in world.escape_assist[player] else 0x00))) # Escape assist - if world.goal[player] in ['pedestal', 'triforcehunt']: - rom.write_byte(0x1801A8, 0x01) # make ganon invincible - elif world.goal[player] in ['dungeons']: - rom.write_byte(0x1801A8, 0x02) # make ganon invincible until all dungeons are beat - elif world.goal[player] in ['crystals', 'trinity']: - rom.write_byte(0x1801A8, 0x04) # make ganon invincible until all crystals - elif world.goal[player] in ['ganonhunt']: - rom.write_byte(0x1801A8, 0x05) # make ganon invincible until all triforce pieces collected - elif world.goal[player] in ['completionist']: - rom.write_byte(0x1801A8, 0x0B) # make ganon invincible until everything is collected - else: - rom.write_byte(0x1801A8, 0x03) # make ganon invincible until all crystals and aga 2 are collected + gt_entry, ped_pull, ganon_goal, murah_goal = [], [], [], [] + # 00: Invulnerable + # 01: All pendants + # 02: All crystals + # 03: Pendant bosses + # 04: Crystal bosses + # 05: Prize bosses + # 06: Agahnim 1 defeated + # 07: Agahnim 2 defeated + # 08: Goal items collected (ie. Triforce Pieces) + # 09: Max collection rate + # 0A: Custom goal - rom.write_byte(0x18019A, world.crystals_needed_for_gt[player]) - rom.write_byte(0x1801A6, world.crystals_needed_for_ganon[player]) - rom.write_byte(0x1801A2, 0x00) # ped requirement is vanilla, set to 0x1 for special requirements + def get_goal_bytes(type): + goal_bytes = [] + for req in world.custom_goals[player][type]['requirements']: + goal_bytes += [req['condition']] + if req['condition'] == 0x0A: + # custom goal + goal_bytes += [req['options']] + goal_bytes += int16_as_bytes(req['address']) + if 0x08 & req['options'] == 0: + goal_bytes += [req['target']] + else: + goal_bytes += int16_as_bytes(req['target']) + elif 'target' in req: + if req['condition'] & 0x7F < 0x08: + goal_bytes += [req['target']] + else: + goal_bytes += int16_as_bytes(req['target']) + return goal_bytes + + if world.custom_goals[player]['gtentry'] and 'requirements' in world.custom_goals[player]['gtentry']: + gt_entry += get_goal_bytes('gtentry') + else: + gt_entry += [0x02, world.crystals_needed_for_gt[player]] + if len(gt_entry) == 0 or gt_entry == [0x02, 0x00]: + rom.initial_sram.pre_open_ganons_tower() + + if world.custom_goals[player]['pedgoal'] and 'requirements' in world.custom_goals[player]['pedgoal']: + ped_pull += get_goal_bytes('pedgoal') + else: + ped_pull += [0x81] + + if world.custom_goals[player]['murahgoal'] and 'requirements' in world.custom_goals[player]['murahgoal']: + murah_goal += get_goal_bytes('murahgoal') + else: + if world.goal[player] in ['triforcehunt', 'trinity']: + murah_goal += [0x88] + else: + murah_goal += [0x00] + + if world.custom_goals[player]['ganongoal'] and 'requirements' in world.custom_goals[player]['ganongoal']: + ganon_goal += get_goal_bytes('ganongoal') + else: + if world.goal[player] in ['pedestal', 'triforcehunt']: + ganon_goal = [0x00] + elif world.goal[player] in ['dungeons']: + ganon_goal += [0x81, 0x82, 0x06, 0x07] # pendants, crystals, and agas + elif world.goal[player] in ['crystals', 'trinity']: + ganon_goal += [0x02, world.crystals_needed_for_ganon[player]] + elif world.goal[player] in ['ganonhunt']: + ganon_goal += [0x88] # triforce pieces + elif world.goal[player] in ['completionist']: + ganon_goal += [0x81, 0x82, 0x06, 0x07, 0x89] # AD and max collection rate + else: + ganon_goal += [0x02, world.crystals_needed_for_ganon[player], 0x07] # crystals and aga2 + + gt_entry += [0xFF] + ped_pull += [0xFF] + ganon_goal += [0xFF] + murah_goal += [0xFF] + start_address = 0x8198 + 8 + + write_int16(rom, 0x180198, start_address) + rom.write_bytes(snes_to_pc(0xB00000 + start_address), gt_entry) + start_address += len(gt_entry) + + write_int16(rom, 0x18019A, start_address) + rom.write_bytes(snes_to_pc(0xB00000 + start_address), ganon_goal) + start_address += len(ganon_goal) + + write_int16(rom, 0x18019C, start_address) + rom.write_bytes(snes_to_pc(0xB00000 + start_address), ped_pull) + start_address += len(ped_pull) + + write_int16(rom, 0x18019E, start_address) + rom.write_bytes(snes_to_pc(0xB00000 + start_address), murah_goal) + start_address += len(murah_goal) + + if start_address > 0x81D8: + raise Exception("Custom Goal data too long to fit in allocated space, try reducing the amount of requirements.") + + # gt entry + gtentry = world.custom_goals[player]['gtentry'] + if gtentry and 'cutscene_gfx' in gtentry: + gfx = gtentry['cutscene_gfx'] + write_int16(rom, snes_to_pc(0x3081D8), gfx[0]) + rom.write_byte(snes_to_pc(0x3081E6), gfx[1]) # block HC upstairs doors in rain state in standard mode prevent_rain = world.mode[player] == 'standard' and world.shuffle[player] != 'vanilla' and world.logic[player] != 'nologic' @@ -1654,26 +1735,6 @@ def patch_rom(world, rom, player, team, is_mystery=False): write_enemizer_tweaks(rom, world, player) write_strings(rom, world, player, team) - # gt entry - if world.customizer: - gtentry = world.customizer.get_gtentry() - if gtentry and player in gtentry: - gtentry = gtentry[player] - if 'cutscene_gfx' in gtentry: - gfx = gtentry['cutscene_gfx'] - if type(gfx) is str: - from Tables import item_gfx_table - if gfx.lower() == 'random': - gfx = random.choice(list(item_gfx_table.keys())) - if gfx in item_gfx_table: - write_int16(rom, snes_to_pc(0x3081AA), item_gfx_table[gfx][1] + (0x8000 if not item_gfx_table[gfx][0] else 0)) - rom.write_byte(snes_to_pc(0x3081AC), item_gfx_table[gfx][2]) - else: - logging.getLogger('').warning('Invalid name "%s" in customized GT entry cutscene gfx', gfx) - else: - write_int16(rom, snes_to_pc(0x3081AA), gfx[0]) - rom.write_byte(snes_to_pc(0x3081AC), gfx[1]) - # write initial sram rom.write_initial_sram() @@ -2502,6 +2563,21 @@ def write_strings(rom, world, player, team): tt['ganon_fall_in'] = Ganon1_texts[random.randint(0, len(Ganon1_texts) - 1)] tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!' tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!' + + def get_custom_goal_text(type): + goal_text = world.custom_goals[player][type]['goaltext'] + if '%d' in goal_text: + return goal_text % world.custom_goals[player][type]['requirements'][0]['target'] + return goal_text + + if world.custom_goals[player]['gtentry'] and 'goaltext' in world.custom_goals[player]['gtentry']: + tt['sign_ganons_tower'] = get_custom_goal_text('gtentry') + if world.custom_goals[player]['ganongoal'] and 'goaltext' in world.custom_goals[player]['ganongoal']: + tt['sign_ganon'] = get_custom_goal_text('ganongoal') + if world.custom_goals[player]['pedgoal'] and 'goaltext' in world.custom_goals[player]['pedgoal']: + tt['mastersword_pedestal_goal'] = get_custom_goal_text('pedgoal') + if world.custom_goals[player]['murahgoal'] and 'goaltext' in world.custom_goals[player]['murahgoal']: + tt['murahdahla'] = get_custom_goal_text('murahgoal') tt['kakariko_tavern_fisherman'] = TavernMan_texts[random.randint(0, len(TavernMan_texts) - 1)] diff --git a/Rules.py b/Rules.py index d87eaa45..5368b2f5 100644 --- a/Rules.py +++ b/Rules.py @@ -61,25 +61,33 @@ def set_rules(world, player): drop_rules(world, player) challenge_room_rules(world, player) - if world.goal[player] == 'dungeons': - # require all dungeons to beat ganon - add_rule(world.get_location('Ganon', player), lambda state: state.has_beaten_aga(player) and state.has('Beat Agahnim 2', player) and state.has('Beat Boss', player, 10)) - elif world.goal[player] in ['crystals', 'ganon']: - add_rule(world.get_location('Ganon', player), lambda state: state.has_crystals(world.crystals_needed_for_ganon[player], player)) - if world.goal[player] == 'ganon': - # require aga2 to beat ganon - add_rule(world.get_location('Ganon', player), lambda state: state.has('Beat Agahnim 2', player)) - elif world.goal[player] in ['triforcehunt', 'trinity']: - if world.goal[player] == 'trinity': + if world.custom_goals[player]['ganongoal'] and 'requirements' in world.custom_goals[player]['ganongoal']: + rule = get_goal_rule('ganongoal', world, player) + add_rule(world.get_location('Ganon', player), rule) + else: + if world.goal[player] == 'dungeons': + # require all dungeons to beat ganon + add_rule(world.get_location('Ganon', player), lambda state: state.has_beaten_aga(player) and state.has('Beat Agahnim 2', player) and state.has('Beat Boss', player, 10)) + elif world.goal[player] in ['crystals', 'ganon']: add_rule(world.get_location('Ganon', player), lambda state: state.has_crystals(world.crystals_needed_for_ganon[player], player)) - for location in world.get_region('Hyrule Castle Courtyard', player).locations: - if location.name == 'Murahdahla': - add_rule(location, lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) - elif world.goal[player] == 'ganonhunt': - add_rule(world.get_location('Ganon', player), lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) - elif world.goal[player] == 'completionist': - add_rule(world.get_location('Ganon', player), lambda state: state.everything(player)) + if world.goal[player] == 'ganon': + # require aga2 to beat ganon + add_rule(world.get_location('Ganon', player), lambda state: state.has('Beat Agahnim 2', player)) + elif world.goal[player] in ['triforcehunt', 'trinity']: + if world.goal[player] == 'trinity': + add_rule(world.get_location('Ganon', player), lambda state: state.has_crystals(world.crystals_needed_for_ganon[player], player)) + elif world.goal[player] == 'ganonhunt': + add_rule(world.get_location('Ganon', player), lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) + elif world.goal[player] == 'completionist': + add_rule(world.get_location('Ganon', player), lambda state: state.everything(player)) + for location in world.get_region('Hyrule Castle Courtyard', player).locations: + if location.name == 'Murahdahla': + if world.custom_goals[player]['murahgoal'] and 'requirements' in world.custom_goals[player]['murahgoal']: + rule = get_goal_rule('murahgoal', world, player) + add_rule(location, rule) + else: + add_rule(location, lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) if (world.flute_mode[player] != 'active' and not world.is_tile_swapped(0x18, player) and 'Ocarina (Activated)' not in list(map(str, [i for i in world.precollected_items if i.player == player]))): @@ -175,6 +183,132 @@ def add_rule(spot, rule, combine='and'): else: spot.access_rule = lambda state: rule(state) and old_rule(state) + +def get_goal_rule(goal_type, world, player): + goal_data = world.custom_goals[player][goal_type] + if goal_data['requirements'][0]['condition'] == 0x00: + return lambda state: False + rule = None + def add_to_rule(new_rule): + nonlocal rule + if rule is None: + rule = new_rule + else: + rule = and_rule(rule, new_rule) + if 'logic' in goal_data: + for logic, data in goal_data['logic'].items(): + if logic == 'pendants': + pendants = int(data) + add_to_rule(lambda state: state.has_pendants(pendants, player)) + elif logic == 'crystals': + crystals = int(data) + add_to_rule(lambda state: state.has_crystals(crystals, player)) + elif logic == 'pendant_bosses': + pendant_bosses = int(data) + add_to_rule(lambda state: state.has_pendant_bosses(pendant_bosses, player)) + elif logic == 'crystal_bosses': + crystal_bosses = int(data) + add_to_rule(lambda state: state.has_crystal_bosses(crystal_bosses, player)) + elif logic == 'bosses': + bosses = int(data) + add_to_rule(lambda state: state.has('Beat Boss', player, bosses)) + elif logic == 'aga1': + add_to_rule(lambda state: state.has('Beat Agahnim 1', player)) + elif logic == 'aga2': + add_to_rule(lambda state: state.has('Beat Agahnim 2', player)) + elif logic == 'goal_items': + if data is not None: + goal_items = int(data) + add_to_rule(lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= goal_items) + else: + add_to_rule(lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) >= int(state.world.treasure_hunt_count[player])) + elif logic == 'collection': + if data is not None: + all_locations = [x for x in world.get_filled_locations(player) if not x.locked] + collection = int(data) - len(all_locations) + add_to_rule(lambda state: state.everything(player, collection)) + else: + add_to_rule(lambda state: state.everything(player)) + elif logic == 'item': + for item in data: + item_name = item + if '(' in item_name: + item_name, region_name = item_name.rsplit(' (', 1) + region_name = region_name.rstrip(')') + region = world.get_region(region_name, player) + if region and region.dungeon: + region_name = region.dungeon.name + else: + try: + if world.get_dungeon(region_name, player): + pass + except: + raise Exception(f'Invalid dungeon/region name in custom goal logic for item {item}') + item_name = f'{item_name} ({region_name})' + if '=' in item_name: + item_name, count = item_name.rsplit('=', 1) + count = int(count) + add_to_rule(lambda state: state.has(item_name, player, count)) + else: + add_to_rule(lambda state: state.has(item_name, player)) + elif logic == 'access': + for region_name in data: + region = world.get_region(region_name, player) + if not region: + raise Exception(f'Invalid region name in custom goal logic for region: {region_name}') + add_to_rule(lambda state: state.can_reach(region, None, player)) + elif logic == 'ability': + for ability in data: + param = None + if '(' in ability: + ability, param = ability.split('(', 1) + param = param.rstrip(')') + if ability == 'FarmBombs': + add_to_rule(lambda state: state.can_farm_bombs(player)) + elif ability == 'FarmRupees': + add_to_rule(lambda state: state.can_farm_rupees(player)) + elif ability == 'NoBunny': + if not param: + raise Exception(f'NoBunny ability requires a region argument in custom goal logic') + bunny_region = param + region = world.get_region(bunny_region, player) + if region: + add_to_rule(lambda state: state.is_not_bunny(bunny_region, player)) + else: + raise Exception(f'Invalid region name in custom goal logic for NoBunny ability: {param}') + elif ability == 'CanUseBombs': + add_to_rule(lambda state: state.can_use_bombs(player)) + elif ability == 'CanBonkDrop': + add_to_rule(lambda state: state.can_collect_bonkdrops(player)) + elif ability == 'CanLift': + add_to_rule(lambda state: state.can_lift_rocks(player)) + elif ability == 'MagicExtension': + magic_count = 16 + if param: + magic_count = int(param) + add_to_rule(lambda state: state.can_extend_magic(player, magic_count)) + elif ability == 'CanStun': + add_to_rule(lambda state: state.can_stun_enemies(player)) + elif ability == 'CanKill': + if param: + enemy_count = int(param) + add_to_rule(lambda state: state.can_kill_most_things(player, enemy_count)) + else: + add_to_rule(lambda state: state.can_kill_most_things(player)) + elif ability == 'CanShootArrows': + add_to_rule(lambda state: state.can_shoot_arrows(player)) + elif ability == 'CanFlute': + add_to_rule(lambda state: state.can_flute(player)) + elif ability == 'HasFire': + add_to_rule(lambda state: state.has_fire_source(player)) + elif ability == 'CanMelt': + add_to_rule(lambda state: state.can_melt_things(player)) + elif ability == 'HasMMMedallion': + add_to_rule(lambda state: state.has_misery_mire_medallion(player)) + elif ability == 'HasTRMedallion': + add_to_rule(lambda state: state.has_turtle_rock_medallion(player)) + return rule if rule is not None else lambda state: True + def add_bunny_rule(spot, player): if spot.can_cause_bunny(player): add_rule(spot, lambda state: state.has_Pearl(player)) @@ -244,7 +378,11 @@ def global_rules(world, player): set_rule(world.get_entrance('Flute Spot 8', player), lambda state: state.can_flute(player)) # overworld location rules - set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) + if world.custom_goals[player]['pedgoal'] and 'requirements' in world.custom_goals[player]['pedgoal']: + rule = get_goal_rule('pedgoal', world, player) + set_rule(world.get_location('Master Sword Pedestal', player), rule) + else: + set_rule(world.get_location('Master Sword Pedestal', player), lambda state: state.has('Red Pendant', player) and state.has('Blue Pendant', player) and state.has('Green Pendant', player)) set_rule(world.get_location('Ether Tablet', player), lambda state: state.has('Book of Mudora', player) and state.has_beam_sword(player)) set_rule(world.get_location('Old Man', player), lambda state: state.has('Return Old Man', player)) set_rule(world.get_location('Old Man Drop Off', player), lambda state: state.has('Escort Old Man', player)) @@ -412,9 +550,13 @@ def global_rules(world, player): set_rule(world.get_entrance('Misery Mire', player), lambda state: state.has_sword(player) and state.has_misery_mire_medallion(player)) # sword required to cast magic (!) set_rule(world.get_entrance('Turtle Rock', player), lambda state: state.has('Turtle Opened', player)) + if world.custom_goals[player]['gtentry'] and 'requirements' in world.custom_goals[player]['gtentry']: + rule = get_goal_rule('gtentry', world, player) + set_rule(world.get_entrance('Ganons Tower' if not world.is_atgt_swapped(player) else 'Agahnims Tower', player), rule) + else: + set_rule(world.get_entrance('Ganons Tower' if not world.is_atgt_swapped(player) else 'Agahnims Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player)) if not world.is_atgt_swapped(player): set_rule(world.get_entrance('Agahnims Tower', player), lambda state: state.has('Cape', player) or state.has_beam_sword(player)) - set_rule(world.get_entrance('Ganons Tower' if not world.is_atgt_swapped(player) else 'Agahnims Tower', player), lambda state: state.has_crystals(world.crystals_needed_for_gt[player], player)) # Start of door rando rules # TODO: Do these need to flag off when door rando is off? - some of them, yes diff --git a/Text.py b/Text.py index 1a66b22f..07fb2e4d 100644 --- a/Text.py +++ b/Text.py @@ -2043,5 +2043,6 @@ class TextTable(object): text['ganon_phase_3_no_silvers'] = CompressedTextMapper.convert("You can't best me without silver arrows!") text['ganon_phase_3_silvers'] = CompressedTextMapper.convert("Oh no! Silver! My one true weakness!") text['murahdahla'] = CompressedTextMapper.convert("Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\ninvisibility.\n{PAUSE3}\n… … …\nWait! You can see me? I knew I should have\nhidden in a hollow tree.") + text['mastersword_pedestal_goal'] = CompressedTextMapper.convert("To claim thy reward, you must present all 3 Pendants of Virtue.") text['end_pad_data'] = bytearray([0xfb]) text['terminator'] = bytearray([0xFF, 0xFF]) diff --git a/data/base2current.bps b/data/base2current.bps index cb0632acee3e06141779ffe3ab48ecf6326f8f5b..f3da2d969e97766c7199198fc76924a7582f94c6 100644 GIT binary patch delta 12309 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 delta 12042 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%0DwMuGscL}* zx>^8+kWoJ9p8{Y8KF0SD;42De^x+`b0Jfl{LNF9K8V?rYTw%O0C%1$VD)Z%>)3w?) zPN=2`)Z)#Yh(IsN+k<8m1NXoi_O|>ukzf(@~_Fs>Trh_M_a=CZVXMfX2DhA zSFPV<1dG91;E4Vy#$F$13kog)X5W6U`I-i^Ww1RVs6#%1J$hcV@k}kg8f`sOt6n|1 zvuf~iG`1A`z~chY#!?U;bRCDv?qVZ1ZBK?kmzuk{UT0_Is|W4R)aYt)>O5^(e$M84>e8oUw=iO5#my!tT}u0q$! zfEzi<0(F&vOBTaC?x{o35eGO_Yju%02 zJ9$&M3oSQrm#txhk@zayxBm8xYuqD;c{i?EzHhU7*DYwdX!E|!cE+s@@ytvnh*EwT z6DE~c514JU`4IMyVtu{%Q3#|0Cxay@w!?xdWEsA6O0DJ1wLmgp7(z2 zeT_dit0IDt!waz0cH!hFg}uFZdtooK1IGLpU@4zBjdSWt{50docOa-gZ*;#iaI&w_ zhf5A2MaL#tGMiMfE?J6u&+iep2J{c5H5s-Bf*E0QEDak_gSPU>2oE(s0=C;21l-j2 zs79{q+WgwnBBp-NH{_KdMHhLbpOa%`YeP_SuAU&4h;P$$?8l`e(H9>6hJhnch$Xp# z6R{=BsI(*(lAbf{=ytJ8rxEAtGzKeXgc(T0pIYP>7A9Y6_B3(@)`: Link is required to not be a bunny in the specified region +* `MagicExtension()`: Link has a magic meter with a higher capacity (parameter is optional, a value of 8 represents one normal full magic bar, default value if left blank is 16, which is equivalent to half magic or one bottle with access to a green potion) +* `CanStun`: Link has the ability to stun enemies +* `CanKill()`: Link has the ability to kill most enemy types (parameter is optional, higher number tends to favor weapons that don't consume ammo, default value is 6 enemies) +* `CanShootArrows`: Link has ability to fire arrows at enemies +* `CanBonkDrop`: Link is able to retrieve Bonk Drops from trees and rocks +* `CanLift`: Link is able to lift basic rocks +* `CanFlute`: Link has ability to use flute (includes access to flute activation) +* `HasFire`: Link has a fire source +* `CanMelt`: Link can melt ice with Firerod or Bombos +* `HasMMMedallion`: Link has the medallion required for unlocking Misery Mire entrance +* `HasTRMedallion`: Link has the medallion required for unlocking Turtle Rock entrance + +#### (example) + +This entire section is very advanced and can be used to make very powerful customizations to the game. To make the overall definition more clear, we provide an example that makes use of a lot of the controls in place: Ganon requiring both 5 crystals AND requiring opening the GT Big Chest + +```yaml +goals: + 1: + ganongoal: + goaltext: You’ll need %d crystals and to open the Big Chest in Ganon’s Tower + requirements: + - Crystals: + target: 5 + - Custom: + address: 0x7ef118 + target: 0x80 + comparison: flags match + logic: + item: + - Big Key (GT Big Chest) + access: + - GT Big Chest + ability: + - NoBunny(GT Big Chest) +``` + ### placements This must be defined by player. Each player number should be listed with the appropriate placement list. @@ -348,27 +476,3 @@ prices: Dark Death Mountain Shop - Right: 300 Dark Lake Hylia Shop - Left: 200 ``` - -### gt_entry - -This must be defined by player. This is where you are able to customize aspects of GT entry - -#### cutscene_gfx - -This is where you can define custom GFX to be used in the GT entry cutscene. For convenience, there are a number of pre-defined names that can be used to indicate already known GFX values built into the ROM. There are too many to list, but a full list can be found in `item_gfx_table` in `Tables.py`. You can also use `Random` and it will take a random one from the aforementioned table. - -``` -gt_entry: - 1: - cutscene_gfx: Mirror Shield -``` - -Alternatively, you may also supply a custom address and palette ID, respectively, if you are injecting your own personal custom GFX into the ROM. - -``` -gt_entry: - 1: - cutscene_gfx: - - 0x8140 - - 0x04 -``` diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index 0b421fca..80b23e0d 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -299,9 +299,9 @@ class CustomSettings(object): return self.file_source['enemies'] return None - def get_gtentry(self): - if 'gt_entry' in self.file_source: - return self.file_source['gt_entry'] + def get_goals(self): + if 'goals' in self.file_source: + return self.file_source['goals'] return None From 6cb05f18ca6917e97aa11c1210c90581f9d6cc30 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 29 Oct 2025 14:07:21 -0500 Subject: [PATCH 20/73] Changed vital/useful hints to logic hints --- Rom.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rom.py b/Rom.py index 9a43f813..8b5f595c 100644 --- a/Rom.py +++ b/Rom.py @@ -2394,13 +2394,13 @@ def write_strings(rom, world, player, team): for name, district in world.districts[player].items(): hint_type = 'foolish' choices = [] - item_count, item_type = 0, 'useful' + item_count, item_type = 0, 'logic' for loc_name in district.locations: location_item = world.get_location(loc_name, player).item if location_item.advancement: if 'Heart Container' in location_item.name or location_item.compass or location_item.map: continue - itm_type = 'useful' if useful_item_for_hint(location_item, world) else 'vital' + itm_type = 'logic' hint_type = 'path' if item_type == itm_type: choices.append(location_item) From cf488fda36f724fdd36b921ebcb53f7ad2380ea1 Mon Sep 17 00:00:00 2001 From: hiimcody1 Date: Mon, 20 Oct 2025 17:53:34 -0400 Subject: [PATCH 21/73] Initial custom header implementation --- Main.py | 2 +- Plando.py | 2 +- Rom.py | 21 ++++++++++++++++++--- resources/app/cli/args.json | 5 +++-- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Main.py b/Main.py index 41a46b11..6324f3bc 100644 --- a/Main.py +++ b/Main.py @@ -290,7 +290,7 @@ def main(args, seed=None, fish=None): for player in range(1, world.players + 1): rom = JsonRom() if args.jsonout else LocalRom(args.rom) - patch_rom(world, rom, player, team, bool(args.mystery)) + patch_rom(world, rom, player, team, bool(args.mystery), str(args.rom_header) if args.rom_header else None) if args.race: patch_race_rom(rom) diff --git a/Plando.py b/Plando.py index cc97562f..2c948435 100755 --- a/Plando.py +++ b/Plando.py @@ -74,7 +74,7 @@ def main(args): logger.info('Patching ROM.') rom = LocalRom(args.rom) - patch_rom(world, rom, 1, 1, False) + patch_rom(world, rom, 1, 1, False, str(args.rom_header) if args.rom_header else None) apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, args.sprite, args.ow_palettes, args.uw_palettes) diff --git a/Rom.py b/Rom.py index 8b5f595c..68855318 100644 --- a/Rom.py +++ b/Rom.py @@ -418,7 +418,7 @@ def handle_native_dungeon(location, itemid): return itemid -def patch_rom(world, rom, player, team, is_mystery=False): +def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): random.seed(world.rom_seeds[player]) # progressive bow silver arrow hint hack @@ -1744,8 +1744,23 @@ def patch_rom(world, rom, player, team, is_mystery=False): # 21 bytes from Main import __version__ from OverworldShuffle import __version__ as ORVersion - seedstring = f'{world.seed:09}' if isinstance(world.seed, int) else world.seed - rom.name = bytearray(f'OR{__version__.split("-")[0].replace(".","")[0:3]}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21] + if rom_header: + if len(rom_header) > 21: + raise Exception('ROM header too long. Max 21 bytes, found %d bytes.' % len(rom_header)) + elif '|' in rom_header: + gen, seedstring = rom_header.split('|', 1) + gen = f'{gen:<3}' + seedstring = f'{int(seedstring):09}' if seedstring.isdigit() else seedstring[:9] + rom.name = bytearray(f'{gen}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21] + elif len(rom_header) <= 9: + seedstring = f'{int(rom_header):09}' if rom_header.isdigit() else rom_header + rom.name = bytearray(f'OR{__version__.split("-")[0].replace(".","")[0:3]}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21] + else: + rom.name = bytearray(rom_header, 'utf8')[:21] + else: + seedstring = f'{world.seed:09}' if isinstance(world.seed, int) else world.seed + rom.name = bytearray(f'OR{__version__.split("-")[0].replace(".","")[0:3]}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21] + rom.name.extend([0] * (21 - len(rom.name))) rom.write_bytes(0x7FC0, rom.name) diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index d042d93b..b0dbf825 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -641,5 +641,6 @@ }, "outputname": {}, "notes": {}, - "code": {} -} \ No newline at end of file + "code": {}, + "rom_header" : {} +} From fd28ef77d2f7c406e0b3be5ea94e1932ef701121 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 29 Oct 2025 15:01:56 -0500 Subject: [PATCH 22/73] Fixed issue with Locksmith despawning after purple chest turn-in when a follower is stored --- Rom.py | 2 +- data/base2current.bps | Bin 137030 -> 137030 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 68855318..6579220b 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'b7817fb00fb0a918a7fa275ff8f4c3be' +RANDOMIZERBASEHASH = 'ec0ac9063daaeb39faf1282faa3fdba8' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index f3da2d969e97766c7199198fc76924a7582f94c6..2f28105755a45943fc16a8d9725fba2536f5e5f0 100644 GIT binary patch delta 70 zcmV-M0J;Cht_a4i2(T&x1I$7*vn>Nz%ORs^cI2%v4$u*=%!07V4DbezM1YbzM1byZ cM3W0DfO>?3r_Q&h&H$Y)+>jNB{r; delta 70 zcmV-M0J;Cht_a4i2(T&x1J6P*vn>Nz%ORg=cI1z1k%`F+@RI?CkqIL0 Date: Wed, 29 Oct 2025 15:17:24 -0500 Subject: [PATCH 23/73] Implemented Custom Goal Framework --- BaseClasses.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index fc4f6394..f2305238 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -3272,17 +3272,17 @@ class Spoiler(object): outfile.write('Triforce Pieces Required:'.ljust(line_width) + '%s\n' % self.metadata['triforcegoal'][player]) outfile.write('Triforce Pieces Total:'.ljust(line_width) + '%s\n' % self.metadata['triforcepool'][player]) custom = self.metadata['custom_goals'][player] - if 'requirements' in custom['gtentry']: + if custom['gtentry'] and 'requirements' in custom['gtentry']: outfile.write('GT Entry Requirement:'.ljust(line_width) + 'custom\n') else: outfile.write('GT Entry Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_gt_orig[player])) - if 'requirements' in custom['ganongoal']: + if custom['ganongoal'] and 'requirements' in custom['ganongoal']: outfile.write('Ganon Requirement:'.ljust(line_width) + 'custom\n') else: outfile.write('Ganon Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_ganon_orig[player])) - if 'requirements' in custom['pedgoal']: + if custom['pedgoal'] and 'requirements' in custom['pedgoal']: outfile.write('Pedestal Requirement:'.ljust(line_width) + 'custom\n') - if 'requirements' in custom['murahgoal']: + if custom['murahgoal'] and 'requirements' in custom['murahgoal']: outfile.write('Murahdahla Requirement:'.ljust(line_width) + 'custom\n') outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player]) outfile.write('\n') From a5ce59c7e82ef84fc0b29c569b1a1554af3d6b54 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 29 Oct 2025 15:41:56 -0500 Subject: [PATCH 24/73] Version bump 0.6.1.0 --- CHANGELOG.md | 13 +++++++++++++ OverworldShuffle.py | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e83b3b2..ad540537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.6.1.0 +- New Custom Goal framework (see Customizer.md) +- New 'logic' hint terminology to replace vital/useful terminology +- Removed possibility of duplicated hints +- New fix for hammering pot drops when at sprite limit +- Fixed issue with incorrect Ganon silvers hint +- Fixed issue with Locksmith despawning after purple chest if a follower is stored +- Fixed pogdor glitch (frogdor but at PoD entrance and Kiki following) +- Fixed issue with Duck gfx overwriting GT Cutscene gfx +- New CLI argument to allow external generators to supply a custom ROM Header +- Fixed error with extra argument in MultiServer call +- Added new text if Link's House is placed at any Snitch Lady house + ## 0.6.0.8 - Re-fixed issue with Old Man spawning on pyramid - Allowing Zelda to be in TT Prison for follower shuffle escape diff --git a/OverworldShuffle.py b/OverworldShuffle.py index bfe555cd..80e781d0 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.6.0.8' +version_number = '0.6.1.0' # branch indicator is intentionally different across branches version_branch = '-u' From c5ea8e470339f616c2f360f7ad5fa4ed26500402 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 29 Oct 2025 20:17:45 -0500 Subject: [PATCH 25/73] Custom Goal framework fixes --- BaseClasses.py | 16 ++++++++++++++-- ItemList.py | 1 + Main.py | 9 +++++++-- Rom.py | 2 +- data/base2current.bps | Bin 137030 -> 137065 bytes docs/Customizer.md | 2 +- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index f2305238..a84a9ea5 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -3394,10 +3394,22 @@ class Spoiler(object): outfile.write(f'{dungeon}:'.ljust(line_width) + '%s Medallion\n' % medallion) for player in range(1, self.world.players + 1): player_name = '' if self.world.players == 1 else str(' (Player ' + str(player) + ')') - if self.world.crystals_gt_orig[player] == 'random': + goal = self.world.custom_goals[player]['gtentry'] + if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: + outfile.write('GT Entry Sign Text' + player_name + ':'.ljust(line_width) + '%s\n' % goal['goaltext']) + elif self.world.crystals_gt_orig[player] == 'random': outfile.write(str('Crystals Required for GT' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['gt_crystals'][player]))) - if self.world.crystals_ganon_orig[player] == 'random': + goal = self.world.custom_goals[player]['ganongoal'] + if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: + outfile.write('Ganon Sign Text' + player_name + ':'.ljust(line_width) + '%s\n' % goal['goaltext']) + elif self.world.crystals_ganon_orig[player] == 'random': outfile.write(str('Crystals Required for Ganon' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['ganon_crystals'][player]))) + goal = self.world.custom_goals[player]['pedgoal'] + if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: + outfile.write('Pedestal Sign Text' + player_name + ':'.ljust(line_width) + '%s\n' % goal['goaltext']) + goal = self.world.custom_goals[player]['murahgoal'] + if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: + outfile.write('Murahdahla Sign Text' + player_name + ':'.ljust(line_width) + '%s\n' % goal['goaltext']) outfile.write('\n\nPrizes:\n\n') for dungeon, prize in self.prizes.items(): outfile.write(str(dungeon + ':').ljust(line_width) + '%s\n' % prize) diff --git a/ItemList.py b/ItemList.py index b7dd5e18..5fd7cfaf 100644 --- a/ItemList.py +++ b/ItemList.py @@ -236,6 +236,7 @@ def generate_itempool(world, player): else: set_event_item(world, player, 'Ganon', 'Triforce') + goal_req = None if world.custom_goals[player]['murahgoal'] and 'requirements' in world.custom_goals[player]['murahgoal']: goal_req = world.custom_goals[player]['murahgoal']['requirements'][0] if world.goal[player] in ['triforcehunt', 'trinity'] or (goal_req and goal_req['condition'] != 0x00): diff --git a/Main.py b/Main.py index 6324f3bc..d03cd308 100644 --- a/Main.py +++ b/Main.py @@ -552,10 +552,12 @@ def resolve_random_settings(world, args): req_table = { 'Invulnerable': 0x00, + 'Disabled': 0x00, 'Pendants': 0x01, 'Crystals': 0x02, 'PendantBosses': 0x03, 'CrystalBosses': 0x04, + 'PrizeBosses': 0x05, 'Bosses': 0x05, 'Agahnim1Defeated': 0x06, 'Agahnim1': 0x06, @@ -577,7 +579,10 @@ def resolve_random_settings(world, args): for r in list(goal_input['requirements']): req = {} try: - req['condition'] = req_table[list(r.keys())[0]] + if isinstance(r, str): + req['condition'] = req_table[r] + else: + req['condition'] = req_table[list(r.keys())[0]] if req['condition'] == req_table['Invulnerable']: goal['requirements']= [req] goal['logic'] = False @@ -647,7 +652,7 @@ def resolve_random_settings(world, args): goal['logic']['pendant_bosses'] = req['target'] or 3 elif req['condition'] & 0x7F == req_table['CrystalBosses']: goal['logic']['crystal_bosses'] = req['target'] or 7 - elif req['condition'] & 0x7F == req_table['Bosses']: + elif req['condition'] & 0x7F == req_table['PrizeBosses']: goal['logic']['bosses'] = req['target'] or 10 elif req['condition'] & 0x7F == req_table['Aga1']: goal['logic']['aga1'] = True diff --git a/Rom.py b/Rom.py index 6579220b..43c3006e 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'ec0ac9063daaeb39faf1282faa3fdba8' +RANDOMIZERBASEHASH = '72c4b2d00057d1faced32871d8081f3a' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 2f28105755a45943fc16a8d9725fba2536f5e5f0..224e1fb6c7a305d7eaf1f730f18852f88bc3c6fd 100644 GIT binary patch delta 6496 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 delta 6471 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 i#0A|{;&UR6h#|ZQ Date: Wed, 29 Oct 2025 20:17:45 -0500 Subject: [PATCH 26/73] Custom Goal framework fixes --- BaseClasses.py | 18 +++++++++++++++--- ItemList.py | 1 + Main.py | 11 ++++++++--- Rom.py | 2 +- data/base2current.bps | Bin 137030 -> 137065 bytes docs/Customizer.md | 2 +- 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index f2305238..f41301eb 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -3394,10 +3394,22 @@ class Spoiler(object): outfile.write(f'{dungeon}:'.ljust(line_width) + '%s Medallion\n' % medallion) for player in range(1, self.world.players + 1): player_name = '' if self.world.players == 1 else str(' (Player ' + str(player) + ')') - if self.world.crystals_gt_orig[player] == 'random': + goal = self.world.custom_goals[player]['gtentry'] + if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: + outfile.write(str('GT Entry Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) + elif self.world.crystals_gt_orig[player] == 'random': outfile.write(str('Crystals Required for GT' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['gt_crystals'][player]))) - if self.world.crystals_ganon_orig[player] == 'random': - outfile.write(str('Crystals Required for Ganon' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['ganon_crystals'][player]))) + goal = self.world.custom_goals[player]['ganongoal'] + if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: + outfile.write(str('Ganon Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) + elif self.world.crystals_ganon_orig[player] == 'random': + outfile.write(str('Crystals Required for Ganon' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['ganon_crystals'][player]))) + goal = self.world.custom_goals[player]['pedgoal'] + if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: + outfile.write(str('Pedestal Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) + goal = self.world.custom_goals[player]['murahgoal'] + if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: + outfile.write(str('Murahdahla Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) outfile.write('\n\nPrizes:\n\n') for dungeon, prize in self.prizes.items(): outfile.write(str(dungeon + ':').ljust(line_width) + '%s\n' % prize) diff --git a/ItemList.py b/ItemList.py index b7dd5e18..5fd7cfaf 100644 --- a/ItemList.py +++ b/ItemList.py @@ -236,6 +236,7 @@ def generate_itempool(world, player): else: set_event_item(world, player, 'Ganon', 'Triforce') + goal_req = None if world.custom_goals[player]['murahgoal'] and 'requirements' in world.custom_goals[player]['murahgoal']: goal_req = world.custom_goals[player]['murahgoal']['requirements'][0] if world.goal[player] in ['triforcehunt', 'trinity'] or (goal_req and goal_req['condition'] != 0x00): diff --git a/Main.py b/Main.py index 6324f3bc..ee5a2d63 100644 --- a/Main.py +++ b/Main.py @@ -552,10 +552,12 @@ def resolve_random_settings(world, args): req_table = { 'Invulnerable': 0x00, + 'Disabled': 0x00, 'Pendants': 0x01, 'Crystals': 0x02, 'PendantBosses': 0x03, 'CrystalBosses': 0x04, + 'PrizeBosses': 0x05, 'Bosses': 0x05, 'Agahnim1Defeated': 0x06, 'Agahnim1': 0x06, @@ -577,7 +579,10 @@ def resolve_random_settings(world, args): for r in list(goal_input['requirements']): req = {} try: - req['condition'] = req_table[list(r.keys())[0]] + if isinstance(r, str): + req['condition'] = req_table[r] + else: + req['condition'] = req_table[list(r.keys())[0]] if req['condition'] == req_table['Invulnerable']: goal['requirements']= [req] goal['logic'] = False @@ -647,7 +652,7 @@ def resolve_random_settings(world, args): goal['logic']['pendant_bosses'] = req['target'] or 3 elif req['condition'] & 0x7F == req_table['CrystalBosses']: goal['logic']['crystal_bosses'] = req['target'] or 7 - elif req['condition'] & 0x7F == req_table['Bosses']: + elif req['condition'] & 0x7F == req_table['PrizeBosses']: goal['logic']['bosses'] = req['target'] or 10 elif req['condition'] & 0x7F == req_table['Aga1']: goal['logic']['aga1'] = True @@ -662,7 +667,7 @@ def resolve_random_settings(world, args): raise KeyError(f'Invalid {goal_type} requirement: {r}') else: raise KeyError(f'Invalid {goal_type} requirement definition') - if 'logic' in goal_input and goal['logic'] is not None: + if 'logic' in goal_input and goal['logic'] and goal['logic'] is not None: goal['logic'].update(goal_input['logic']) return diff --git a/Rom.py b/Rom.py index 6579220b..43c3006e 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'ec0ac9063daaeb39faf1282faa3fdba8' +RANDOMIZERBASEHASH = '72c4b2d00057d1faced32871d8081f3a' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 2f28105755a45943fc16a8d9725fba2536f5e5f0..224e1fb6c7a305d7eaf1f730f18852f88bc3c6fd 100644 GIT binary patch delta 6496 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 delta 6471 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 i#0A|{;&UR6h#|ZQ Date: Fri, 31 Oct 2025 01:24:22 -0500 Subject: [PATCH 27/73] Version bump 0.6.1.1 --- CHANGELOG.md | 5 +++++ OverworldShuffle.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad540537..61fc68fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.6.1.1 +- Fixed issue with Bosses goals in Custom Goal Framework +- Fixed error when using Custom Goals with no extra values +- Added more Custom Goal detail in Spoiler Log + ## 0.6.1.0 - New Custom Goal framework (see Customizer.md) - New 'logic' hint terminology to replace vital/useful terminology diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 80e781d0..ebd067bb 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.6.1.0' +version_number = '0.6.1.1' # branch indicator is intentionally different across branches version_branch = '-u' From 3f77398657459edfef0e478b808ab0ae46183860 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 31 Oct 2025 15:49:13 -0500 Subject: [PATCH 28/73] Documentation fix --- docs/Customizer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Customizer.md b/docs/Customizer.md index 6c7063e0..b1c85f19 100644 --- a/docs/Customizer.md +++ b/docs/Customizer.md @@ -76,7 +76,7 @@ This must be defined by player. Each player number should be listed with the app * `gtentry` (Ganon's Tower entrance) * `ganongoal` (Ganon vulnerability) -* `pedpull` (Master Sword Pedestal activation) +* `pedgoal` (Master Sword Pedestal activation) * `murahgoal` (Murahdahla requirement, if given requirements, Murahdahla appears always and acts as an alternative way to beat the game) These four custom goals use the following identical structure to define them. These goals have four primary subsections: `cutscene_gfx`, `goaltext`, `requirements`, and `logic` From e00c0ee88da6a5bbe4860c3903402e1d3d869db2 Mon Sep 17 00:00:00 2001 From: theclearmouse <105736589+theclearmouse@users.noreply.github.com> Date: Mon, 3 Nov 2025 10:55:14 -0500 Subject: [PATCH 29/73] update tournament winners in telepathy tiles --- Text.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Text.py b/Text.py index f698eae2..f328ae1f 100644 --- a/Text.py +++ b/Text.py @@ -1780,6 +1780,8 @@ class TextTable(object): text['hylian_text_2'] = CompressedTextMapper.convert("%%^= %==%\n ^ =%^=\n==%= ^^%^") text['desert_entry_translated'] = CompressedTextMapper.convert("Kneel before this stone, and magic will move around you.") text['telepathic_tile_under_ganon'] = CompressedTextMapper.convert("Doors Async League winners\n{HARP}\n" + " ~~~2025~~~\nSchulzer\n\n" + " ~~~2024~~~\nhumbugh\n\n" " ~~~2023~~~\nEriror\n\n" " ~~~2022~~~\nAndy\n\n" " ~~~2021~~~\nprdwong") @@ -1793,7 +1795,8 @@ class TextTable(object): text['telepathic_tile_ice_stalfos_knights_room'] = CompressedTextMapper.convert("{NOBORDER}\nKnock 'em down and then bomb them dead.") text['telepathic_tile_tower_of_hera_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nThis is a bad place, with a guy who will make you fall…\n\n\na lot.") text['houlihan_room'] = CompressedTextMapper.convert("Randomizer tournament winners\n{HARP}\n" - " ~~~2023~~~\nnGanonsGoneWild\n\n" + " ~~~2024~~~\nnGammachuu\n\n" + " ~~~2023~~~\nGanonsGoneWild\n\n" " ~~~2022~~~\nObscure\n\n" " ~~~2021~~~\nDaaanty\n\n" " ~~~2019~~~\nJet082\n\n" @@ -2027,6 +2030,7 @@ class TextTable(object): text['ganon_phase_3_alt'] = CompressedTextMapper.convert("Got wax in your ears? I cannot die!") # 190 text['sign_east_death_mountain_bridge'] = CompressedTextMapper.convert("Glitched\ntournament\nwinners\n{HARP}\n" + "~~~HMG 2025~~~\nSkelen\n" "~~~No Logic 2024~~~\ntam\n\n" "~~~HMG 2023~~~\ntam\n\n" "~~~No Logic 2022~~~\nChexhuman\n\n" From 61dd76e7ea88ca0f99629f6a620318b969738345 Mon Sep 17 00:00:00 2001 From: theclearmouse <105736589+theclearmouse@users.noreply.github.com> Date: Mon, 3 Nov 2025 10:56:55 -0500 Subject: [PATCH 30/73] typo --- Text.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Text.py b/Text.py index f328ae1f..2f27304c 100644 --- a/Text.py +++ b/Text.py @@ -1795,7 +1795,7 @@ class TextTable(object): text['telepathic_tile_ice_stalfos_knights_room'] = CompressedTextMapper.convert("{NOBORDER}\nKnock 'em down and then bomb them dead.") text['telepathic_tile_tower_of_hera_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nThis is a bad place, with a guy who will make you fall…\n\n\na lot.") text['houlihan_room'] = CompressedTextMapper.convert("Randomizer tournament winners\n{HARP}\n" - " ~~~2024~~~\nnGammachuu\n\n" + " ~~~2024~~~\nGammachuu\n\n" " ~~~2023~~~\nGanonsGoneWild\n\n" " ~~~2022~~~\nObscure\n\n" " ~~~2021~~~\nDaaanty\n\n" From 8b75aeb78f68c417b16e37285bbf3e05e528f454 Mon Sep 17 00:00:00 2001 From: theclearmouse <105736589+theclearmouse@users.noreply.github.com> Date: Mon, 3 Nov 2025 11:35:10 -0500 Subject: [PATCH 31/73] fix typo --- Text.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Text.py b/Text.py index 2f27304c..df662575 100644 --- a/Text.py +++ b/Text.py @@ -2030,7 +2030,7 @@ class TextTable(object): text['ganon_phase_3_alt'] = CompressedTextMapper.convert("Got wax in your ears? I cannot die!") # 190 text['sign_east_death_mountain_bridge'] = CompressedTextMapper.convert("Glitched\ntournament\nwinners\n{HARP}\n" - "~~~HMG 2025~~~\nSkelen\n" + "~~~HMG 2025~~~\nSkele\n" "~~~No Logic 2024~~~\ntam\n\n" "~~~HMG 2023~~~\ntam\n\n" "~~~No Logic 2022~~~\nChexhuman\n\n" From 2771040cb32ae9dbade05234e9c499e01f87e37d Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 7 Nov 2025 22:06:07 -0600 Subject: [PATCH 32/73] Added custom gfx for Ped and Murahdahla --- Rom.py | 21 ++++++++++++++------- data/base2current.bps | Bin 137065 -> 137148 bytes 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Rom.py b/Rom.py index 43c3006e..b471867c 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '72c4b2d00057d1faced32871d8081f3a' +RANDOMIZERBASEHASH = 'a1c8a1c9b4a626f25a240d5b35b17ffe' class JsonRom(object): @@ -1338,12 +1338,19 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): if start_address > 0x81D8: raise Exception("Custom Goal data too long to fit in allocated space, try reducing the amount of requirements.") - # gt entry - gtentry = world.custom_goals[player]['gtentry'] - if gtentry and 'cutscene_gfx' in gtentry: - gfx = gtentry['cutscene_gfx'] - write_int16(rom, snes_to_pc(0x3081D8), gfx[0]) - rom.write_byte(snes_to_pc(0x3081E6), gfx[1]) + # goal cutscene gfx + goals = { + #goal: gfx addr, palette addr + 'gtentry': (0x3081D8, 0x3081E6), + 'pedgoal': (0x3081ED, 0x3081F3), + 'murahgoal': (0x3081F6, 0x3081FC), + } + for goal_type, gfx_addr in goals.items(): + goal = world.custom_goals[player][goal_type] + if goal and 'cutscene_gfx' in goal: + gfx = goal['cutscene_gfx'] + write_int16(rom, snes_to_pc(gfx_addr[0]), gfx[0]) + rom.write_byte(snes_to_pc(gfx_addr[1]), gfx[1]) # block HC upstairs doors in rain state in standard mode prevent_rain = world.mode[player] == 'standard' and world.shuffle[player] != 'vanilla' and world.logic[player] != 'nologic' diff --git a/data/base2current.bps b/data/base2current.bps index 224e1fb6c7a305d7eaf1f730f18852f88bc3c6fd..9560fa8a184ce289aed573bdfbe895330229f819 100644 GIT binary patch delta 1993 zcmW+$3sh5A7JcU?At4|M)(?a*gb36qFrZYaU(_m}Q3ik2rBTBtm>QW{J}Oq=JtSbn zkk13I5R>uLYk-ax;t$&n!qg8sGcu3fb?;eg-?PuY>)dtD zd2(5B)gdsYp>>b0Y#Bh@j^HgGXEbL!f(B<9FMxy69?*>fH~ho-p?5xl7Uu(>mBP@g z!?quPY}Ltc(X#W^X8AT2t{|P44fBTN&BiOA=pWN-=Y&f=)2xFO)o_s7N(xU%Nvc7~ zA}-aTR69@1@!`Q`r!lBa0AJC|!j{7w=i#tGE=)L0^B?fwC|wY}8jN&T^a8l)9F86W z#Cb_yji~@N{a)+zdJMbiA_vWRX3?BG1YL|6(hIMLmRSTkY1A* z1;g}*iPFe(leSSuQ(yPkz|*_RGJ`UC(ss1;+}AZaKjn9mwyRWC^{+efltKAFnn|1o zqt5RW6A!Sd%=@%b3S+dRUkw?~*|%sBihSs7yO$XXce?yQ5i0I}Xfsw@Gk;^~66>T| zc{h_73Y|Q7#Y{%PzNk5tpKU4Z@;0>^x#XZin&Oni6n8x!C0FRF8V*14UCN9qpkZI3Fh1TyBe^0yP^c4Qbry0K~E0+z_e zI9^blZvKTkMEjatQg1($>Rh5W0g0FG1DSe`v3t-haE!4OM20(lp*n>UQesDEWg`0C zpwRJ>b#UzhlIQp@>pGhzQpyZEy5Fi$R#jea=+s~2wly8l;`Afs9d4mUqj|PLul($k z&Y88nwq}Q3={}{S6H9U9K3G+9dBo%;kw_G8rgVKCnO2rM(pnZHOJHrRcIZ^V2Qs3q ziIAm@yjC@N{mDc8An2`%AbOH|tHkILkxiI5c7l+xA~O|JQ(~XwsVRw2IBiuzp^B9W zPLAbbYt6=>M=ZH!ZuM$-HG#(B$;tmz$K@kp3 zhXCLF`oJhh7KK?QtT7oy-xBtf_t|!*kl`Ok-ezHCxv?C$ZJ!x54i?es(vJ41cu%l2w z)^2^HbBVv1b5uZHY;FuwU$FXBbSY~~OC5-88DA(rs&B!&Kf<>&AOr2p!Amni1KqeO z6Y70`7%^>g$s8qL;Gz(mlm(H<_Z@sV3*ykC$M};hI08dBOby%7mQnn%8l)^dqlSf1 zL7MRfMDjEqnH{k5z_@W9r61;ws?j747*SNX6mOb5=u<7x;&tNgKlHq3=F ztjLCD-@iSvwf4B5*mRtpems;7LE`JvH(%3&Qp)vhDZO+j=Iw`#kb}4EhX^Rdh5O;$ zTM655G0&fVsqc}0{OyrFe3DtA#0xc$;=fhZKj?}XO1d%1>5LY(^;mGZ2G&Z8A6tGO z-c6U+uu0BZOSE@Uy!KLxi%aq1bmoBuLc9Yc>&#z0ZITj>+s}#>Q^c|xQ$*)#ylyiN z$^{7u*o>FvLiFr{d^0s4$DE*351Xk#oL+2pWEA6LxzIa%@hh7i2zT)7dy5J_d#-f7 zsOov=72c8utDqm7^PnO$HudzrlY6CG@^CBSXTfsUSY?~-7^m|-38!6D1R?5ISO@>l)Q@boaQlYkGz*+TP3f;?5A=2 zCRt^`EG~p%j(k>z>B%*sQ%77wojT-+X(n_{S^Q>DK>S0y+uvHSiMf3o?s8BpiLa0# zlTMEVu2TA-JYFmNGkv_nl4>xspWybcn|%!bL_!oN{QcQX5CtJZ6!8&WQ3+AAl9!4| z{dQt^ZDew#rLd36uu9@_Q6*bHCAXRON(cf0k@bi|cy$KTe;RmR-jV_#Nr|xNugpI! zfO#SLB?8i*t*`g7tXe{Ljr*|euF=@blb+>zw0Nn6v7CW+n71U@)X*``SBMB<8(tIn z%mpAYZvEw#VwzLLOw_~oeBYf}MspGwtPo*I1T$cRxkx15Y;1Tvs(P)`@dPb@NMYVw zf{U0N>N zPAjO;z978B4jWKhFfO)3j_=zc)#emdXbt9ZnU{9x6Y}TA)Vxg{PhzhB5uU$=-c85X z`q+}o+lUAIV9Z|>SJ}Kdi{MWYY}8h3Rva^M0|YCPoQFMLC>({wG2VQ1k1ynGI%)BP tS~@h6neaoqdHx|Kz0J#sB0@zZ5K_XKtY-GiLR^mE-@LR7jlXMO_}(;!H9u| z5H9drLJ&0(0*lbi&^ueTbVIuZ?bLKv9ZN?y#K&USQMx{saksM9J#)^P`Of1zb7sz* zt3#qEmqjffqQ{Ru-Fg@C)xSO0>qy|`B1m_f5(M$kiw8`%$OXT19P~bdAlva!k|vJG zcUyn@sZXbEr^oq-c{|VY0G|k8zrunQ?y0J zAwE5*TI#4@AQ8Y8hcTpI1jS6sqEtBMIJ#&dAKDx((GLX>!c--!f#u9dLJS;qxDzG; zU3$%2O>6)Wld^Xs}Z{T&~b9*Bmm*qom?bMu)3{h>AJIw7v`oJ4xRc$amQ`V z`DW}cU6)Q96me759)lus%BtePn49_M`g`+kO zd#%M66TY*p)d39_-Lpw&;)Pqp!13dh-hOD)KtKiMPbI#=<@rEnAWDptJEjNGC!|zG z8gyKzt1~~08PsYtFNgIP`Tafnv{+H)9(0K{Txf${^;x6N5wpFceWzaKYSb~lG=7#3 zt50s3YVisV4pzRM(~WybE%~#%?^GiBfb+|=lZ`>;B+=hPkT2YC)IDB*@(_O)jWsVO zMzhA6W#}2=WPha2b*AZSga_oD$q# z0IB{noZq$5LR9ZetfE@qiz5!<$Ra32Vf%4I5ojO}&lEwIPu*0@b|*P>@(cWa7(QDJ zacJub{Fh=_iEcl}|1E}NP>YY0KrVXq4}7BpDA`kYdpu zd|U(B{tNTJ`@xwwnKd!Z8%_}Sk0#+e8dxXKc-*=<>I!qZom(NUDRS69d$8tW- zKa(e?b=1s*=zUaR!;v*-&b!1wxjE~>MPXQf1o~0RE}T>a-RM_Re7gz~z4ld`uH+nG zB}c)DP|99>vl=>s`Be?)dA4WTQN=c>P8gOr$;RydQQ}{{<60*<&iZPv zk$w|}E&;AZXDsrEr&npouPJ70V@KfEdcx)1xgrX$rXijuS?a@nL_@e3?LUZ(O%NX- zO_oynTw+g0+{UKXnsK_&tWL(RChn}(|CN2)1R)^WQ23ZeSWv)57(n3Vt*#VPv=ryw zV3#t01>q?tM3h0>)g@_NolK3)NVqSc(b!LCy{zzPacvO$=qwCCWVXD;GB_htN(pg4 z&W(L(_ZnqC@1yvmW1sh#OEWwd3rn!06B5zk82qRczLmz+Jhk}RdM1S6+F*{`%YJEw z8j#e+pE2CL{^A6)@i?1dfggoFVMRt$78R5k1t%bRKS8?{a#>W$7} zxAekASg}cax_vQ0014fj{7&_@cdXob`$Bk`9ajXm8G!o}#$}ZG7XF@A^wtlA2DdQ* zA$W-$)M#NS*4tqN`X~&4Z-)au1!S8knIfCojW)4ecW3PiK4QY5dNr<9QUJ|PkqWeN|+NLwD ue$c^`#jqJtv`65-i}=cxO4Jf+BAt*E4rwtv9Dw*d(WR7Ii%OTxd-6ZK(j7hk From a3dd82f4670db378da4f07c2c97ce26ee16632df Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 7 Nov 2025 22:08:18 -0600 Subject: [PATCH 33/73] Initial custom header implementation --- Rom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index b471867c..a04a4aab 100644 --- a/Rom.py +++ b/Rom.py @@ -1758,7 +1758,7 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): gen, seedstring = rom_header.split('|', 1) gen = f'{gen:<3}' seedstring = f'{int(seedstring):09}' if seedstring.isdigit() else seedstring[:9] - rom.name = bytearray(f'{gen}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21] + rom.name = bytearray(f'OR{gen}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21] elif len(rom_header) <= 9: seedstring = f'{int(rom_header):09}' if rom_header.isdigit() else rom_header rom.name = bytearray(f'OR{__version__.split("-")[0].replace(".","")[0:3]}_{team+1}_{player}_{seedstring}\0', 'utf8')[:21] From 7cfa8f4b4d31e6a09db2dd877be3b692124a6dcb Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 8 Nov 2025 02:36:28 -0600 Subject: [PATCH 34/73] Yaml errors no longer fail silently --- source/gui/bottom.py | 55 ++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/source/gui/bottom.py b/source/gui/bottom.py index 7faf3402..e25c2b2f 100644 --- a/source/gui/bottom.py +++ b/source/gui/bottom.py @@ -77,32 +77,37 @@ def bottom_frame(self, parent, args=None): argsDump['sprite'] = argsDump['sprite'].name save_settings(parent, argsDump, "last.json") - guiargs = create_guiargs(parent) - # get default values for missing parameters - cliargs = ['--multi', str(guiargs.multi)] - if hasattr(guiargs, 'customizer'): - cliargs.extend(['--customizer', str(guiargs.customizer)]) - for k,v in vars(parse_cli(cliargs)).items(): - if k not in vars(guiargs): - setattr(guiargs, k, v) - elif type(v) is dict: # use same settings for every player - players = guiargs.multi if len(v) == 0 else len(v) - setattr(guiargs, k, {player: getattr(guiargs, k) for player in range(1, players + 1)}) - argsDump = vars(guiargs) - - needEnemizer = False - falsey = ["none", "default", False, 0] - for enemizerOption in ["shuffleenemies", "enemy_damage", "shufflebosses", "enemy_health"]: - if enemizerOption in argsDump: - if isinstance(argsDump[enemizerOption], dict): - for playerID,playerSetting in argsDump[enemizerOption].items(): - if not playerSetting in falsey: - needEnemizer = True - elif not argsDump[enemizerOption] in falsey: - needEnemizer = True - seeds = [] - try: + guiargs = create_guiargs(parent) + # get default values for missing parameters + cliargs = ['--multi', str(guiargs.multi)] + if hasattr(guiargs, 'customizer'): + cliargs.extend(['--customizer', str(guiargs.customizer)]) + + for k,v in vars(parse_cli(cliargs)).items(): + if k not in vars(guiargs): + setattr(guiargs, k, v) + elif type(v) is dict: # use same settings for every player + players = guiargs.multi if len(v) == 0 else len(v) + setattr(guiargs, k, {player: getattr(guiargs, k) for player in range(1, players + 1)}) + if guiargs.multi == 1 and guiargs.names.endswith("=="): + # allow settings code thru player names entry + guiargs.code[1] = guiargs.names + guiargs.names = "" + argsDump = vars(guiargs) + + needEnemizer = False + falsey = ["none", "default", False, 0] + for enemizerOption in ["shuffleenemies", "enemy_damage", "shufflebosses", "enemy_health"]: + if enemizerOption in argsDump: + if isinstance(argsDump[enemizerOption], dict): + for playerID,playerSetting in argsDump[enemizerOption].items(): + if not playerSetting in falsey: + needEnemizer = True + elif not argsDump[enemizerOption] in falsey: + needEnemizer = True + seeds = [] + if guiargs.count is not None and guiargs.seed: seed = guiargs.seed for _ in range(guiargs.count): From 7016e5afbf0d72f3e13b5675a7cf8852ce984d72 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 8 Nov 2025 02:36:28 -0600 Subject: [PATCH 35/73] Yaml errors no longer fail silently --- source/classes/CustomSettings.py | 14 +++++--- source/gui/bottom.py | 55 +++++++++++++++++--------------- 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index 80b23e0d..af34f007 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -577,9 +577,13 @@ class CustomSettings(object): def load_yaml(path): - if os.path.exists(Path(path)): - with open(path, "r", encoding="utf-8") as f: - return yaml.load(f, Loader=yaml.SafeLoader) - elif urllib.parse.urlparse(path).scheme in ['http', 'https']: - return yaml.load(urllib.request.urlopen(path), Loader=yaml.FullLoader) + try: + if os.path.exists(Path(path)): + with open(path, "r", encoding="utf-8") as f: + return yaml.load(f, Loader=yaml.SafeLoader) + elif urllib.parse.urlparse(path).scheme in ['http', 'https']: + return yaml.load(urllib.request.urlopen(path), Loader=yaml.FullLoader) + except yaml.YAMLError as e: + error_msg = f"Error parsing YAML file '{path}':\n{str(e)}" + raise ValueError(error_msg) from e diff --git a/source/gui/bottom.py b/source/gui/bottom.py index 7faf3402..e25c2b2f 100644 --- a/source/gui/bottom.py +++ b/source/gui/bottom.py @@ -77,32 +77,37 @@ def bottom_frame(self, parent, args=None): argsDump['sprite'] = argsDump['sprite'].name save_settings(parent, argsDump, "last.json") - guiargs = create_guiargs(parent) - # get default values for missing parameters - cliargs = ['--multi', str(guiargs.multi)] - if hasattr(guiargs, 'customizer'): - cliargs.extend(['--customizer', str(guiargs.customizer)]) - for k,v in vars(parse_cli(cliargs)).items(): - if k not in vars(guiargs): - setattr(guiargs, k, v) - elif type(v) is dict: # use same settings for every player - players = guiargs.multi if len(v) == 0 else len(v) - setattr(guiargs, k, {player: getattr(guiargs, k) for player in range(1, players + 1)}) - argsDump = vars(guiargs) - - needEnemizer = False - falsey = ["none", "default", False, 0] - for enemizerOption in ["shuffleenemies", "enemy_damage", "shufflebosses", "enemy_health"]: - if enemizerOption in argsDump: - if isinstance(argsDump[enemizerOption], dict): - for playerID,playerSetting in argsDump[enemizerOption].items(): - if not playerSetting in falsey: - needEnemizer = True - elif not argsDump[enemizerOption] in falsey: - needEnemizer = True - seeds = [] - try: + guiargs = create_guiargs(parent) + # get default values for missing parameters + cliargs = ['--multi', str(guiargs.multi)] + if hasattr(guiargs, 'customizer'): + cliargs.extend(['--customizer', str(guiargs.customizer)]) + + for k,v in vars(parse_cli(cliargs)).items(): + if k not in vars(guiargs): + setattr(guiargs, k, v) + elif type(v) is dict: # use same settings for every player + players = guiargs.multi if len(v) == 0 else len(v) + setattr(guiargs, k, {player: getattr(guiargs, k) for player in range(1, players + 1)}) + if guiargs.multi == 1 and guiargs.names.endswith("=="): + # allow settings code thru player names entry + guiargs.code[1] = guiargs.names + guiargs.names = "" + argsDump = vars(guiargs) + + needEnemizer = False + falsey = ["none", "default", False, 0] + for enemizerOption in ["shuffleenemies", "enemy_damage", "shufflebosses", "enemy_health"]: + if enemizerOption in argsDump: + if isinstance(argsDump[enemizerOption], dict): + for playerID,playerSetting in argsDump[enemizerOption].items(): + if not playerSetting in falsey: + needEnemizer = True + elif not argsDump[enemizerOption] in falsey: + needEnemizer = True + seeds = [] + if guiargs.count is not None and guiargs.seed: seed = guiargs.seed for _ in range(guiargs.count): From 600865b6590b6c4214691619890ebf89ba520ade Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 8 Nov 2025 10:37:16 -0600 Subject: [PATCH 36/73] Some fixes for Custom Goals - Changed spoiler meta output to include goaltext - Fixed GT Cutscene crash - Allow multiple %d to resolve in goaltext --- BaseClasses.py | 22 ++++++++++++++-------- Main.py | 14 +++++++------- Rom.py | 15 ++++++++++----- data/base2current.bps | Bin 137148 -> 137199 bytes docs/Customizer.md | 2 +- 5 files changed, 32 insertions(+), 21 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index f41301eb..3abcbdd4 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -3274,16 +3274,20 @@ class Spoiler(object): custom = self.metadata['custom_goals'][player] if custom['gtentry'] and 'requirements' in custom['gtentry']: outfile.write('GT Entry Requirement:'.ljust(line_width) + 'custom\n') + outfile.write(' %s\n' % custom['gtentry']['goaltext']) else: outfile.write('GT Entry Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_gt_orig[player])) if custom['ganongoal'] and 'requirements' in custom['ganongoal']: outfile.write('Ganon Requirement:'.ljust(line_width) + 'custom\n') + outfile.write(' %s\n' % custom['ganongoal']['goaltext']) else: outfile.write('Ganon Requirement:'.ljust(line_width) + '%s crystals\n' % str(self.world.crystals_ganon_orig[player])) if custom['pedgoal'] and 'requirements' in custom['pedgoal']: outfile.write('Pedestal Requirement:'.ljust(line_width) + 'custom\n') + outfile.write(' %s\n' % custom['pedgoal']['goaltext']) if custom['murahgoal'] and 'requirements' in custom['murahgoal']: outfile.write('Murahdahla Requirement:'.ljust(line_width) + 'custom\n') + outfile.write(' %s\n' % custom['murahgoal']['goaltext']) outfile.write('Swords:'.ljust(line_width) + '%s\n' % self.metadata['weapons'][player]) outfile.write('\n') outfile.write('Accessibility:'.ljust(line_width) + '%s\n' % self.metadata['accessibility'][player]) @@ -3396,20 +3400,22 @@ class Spoiler(object): player_name = '' if self.world.players == 1 else str(' (Player ' + str(player) + ')') goal = self.world.custom_goals[player]['gtentry'] if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: - outfile.write(str('GT Entry Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) + pass + # outfile.write(str('GT Entry Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) elif self.world.crystals_gt_orig[player] == 'random': outfile.write(str('Crystals Required for GT' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['gt_crystals'][player]))) goal = self.world.custom_goals[player]['ganongoal'] if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: - outfile.write(str('Ganon Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) + pass + # outfile.write(str('Ganon Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) elif self.world.crystals_ganon_orig[player] == 'random': outfile.write(str('Crystals Required for Ganon' + player_name + ':').ljust(line_width) + '%s\n' % (str(self.metadata['ganon_crystals'][player]))) - goal = self.world.custom_goals[player]['pedgoal'] - if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: - outfile.write(str('Pedestal Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) - goal = self.world.custom_goals[player]['murahgoal'] - if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: - outfile.write(str('Murahdahla Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) + # goal = self.world.custom_goals[player]['pedgoal'] + # if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: + # outfile.write(str('Pedestal Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) + # goal = self.world.custom_goals[player]['murahgoal'] + # if goal and 'requirements' in goal and goal['requirements'][0]['condition'] != 0x00: + # outfile.write(str('Murahdahla Sign Text' + player_name + ':').ljust(line_width) + '%s\n' % goal['goaltext']) outfile.write('\n\nPrizes:\n\n') for dungeon, prize in self.prizes.items(): outfile.write(str(dungeon + ':').ljust(line_width) + '%s\n' % prize) diff --git a/Main.py b/Main.py index ee5a2d63..a8d2265f 100644 --- a/Main.py +++ b/Main.py @@ -645,23 +645,23 @@ def resolve_random_settings(world, args): else: raise Exception(f'Invalid {list(r.keys())[0]} requirement target for {goal_type}') if req['condition'] & 0x7F == req_table['Pendants']: - goal['logic']['pendants'] = req['target'] or 3 + goal['logic']['pendants'] = req['target'] = req.get('target', 3) elif req['condition'] & 0x7F == req_table['Crystals']: - goal['logic']['crystals'] = req['target'] or 7 + goal['logic']['crystals'] = req['target'] = req.get('target', 7) elif req['condition'] & 0x7F == req_table['PendantBosses']: - goal['logic']['pendant_bosses'] = req['target'] or 3 + goal['logic']['pendant_bosses'] = req['target'] = req.get('target', 3) elif req['condition'] & 0x7F == req_table['CrystalBosses']: - goal['logic']['crystal_bosses'] = req['target'] or 7 + goal['logic']['crystal_bosses'] = req['target'] = req.get('target', 7) elif req['condition'] & 0x7F == req_table['PrizeBosses']: - goal['logic']['bosses'] = req['target'] or 10 + goal['logic']['bosses'] = req['target'] = req.get('target', 10) elif req['condition'] & 0x7F == req_table['Aga1']: goal['logic']['aga1'] = True elif req['condition'] & 0x7F == req_table['Aga2']: goal['logic']['aga2'] = True elif req['condition'] & 0x7F == req_table['TriforcePieces']: - goal['logic']['goal_items'] = req['target'] or None + goal['logic']['goal_items'] = req['target'] = req.get('target', None) elif req['condition'] & 0x7F == req_table['CollectionRate']: - goal['logic']['collection'] = req['target'] or None + goal['logic']['collection'] = req['target'] = req.get('target', None) goal['requirements'].append(req) except KeyError: raise KeyError(f'Invalid {goal_type} requirement: {r}') diff --git a/Rom.py b/Rom.py index a04a4aab..8e69b142 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'a1c8a1c9b4a626f25a240d5b35b17ffe' +RANDOMIZERBASEHASH = '39c6d90d9aa4711fe3c95d85b1a9b16e' class JsonRom(object): @@ -1270,8 +1270,11 @@ def patch_rom(world, rom, player, team, is_mystery=False, rom_header=None): goal_bytes += [req['target']] else: goal_bytes += int16_as_bytes(req['target']) - elif 'target' in req: - if req['condition'] & 0x7F < 0x08: + elif req['condition'] & 0x80 == 0: + if req['condition'] & 0x7F == 0x06 or req['condition'] & 0x7F == 0x07: + # agahnims have no target value + pass + elif req['condition'] & 0x7F < 0x08: goal_bytes += [req['target']] else: goal_bytes += int16_as_bytes(req['target']) @@ -2588,8 +2591,10 @@ def write_strings(rom, world, player, team): def get_custom_goal_text(type): goal_text = world.custom_goals[player][type]['goaltext'] - if '%d' in goal_text: - return goal_text % world.custom_goals[player][type]['requirements'][0]['target'] + placeholder_count = goal_text.count('%d') + if placeholder_count > 0: + targets = [req['target'] for req in world.custom_goals[player][type]['requirements'] if 'target' in req][:placeholder_count] + return goal_text % tuple(targets) return goal_text if world.custom_goals[player]['gtentry'] and 'goaltext' in world.custom_goals[player]['gtentry']: diff --git a/data/base2current.bps b/data/base2current.bps index 9560fa8a184ce289aed573bdfbe895330229f819..2d325e9098601881c2aac9356f06c1ebc87e3f39 100644 GIT binary patch delta 6597 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 diff --git a/docs/Customizer.md b/docs/Customizer.md index 6c7063e0..b1c85f19 100644 --- a/docs/Customizer.md +++ b/docs/Customizer.md @@ -76,7 +76,7 @@ This must be defined by player. Each player number should be listed with the app * `gtentry` (Ganon's Tower entrance) * `ganongoal` (Ganon vulnerability) -* `pedpull` (Master Sword Pedestal activation) +* `pedgoal` (Master Sword Pedestal activation) * `murahgoal` (Murahdahla requirement, if given requirements, Murahdahla appears always and acts as an alternative way to beat the game) These four custom goals use the following identical structure to define them. These goals have four primary subsections: `cutscene_gfx`, `goaltext`, `requirements`, and `logic` From ace8f3144ee599e9f520c9d88d93477536806c94 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 8 Nov 2025 10:38:10 -0600 Subject: [PATCH 37/73] Adding missing rule for Hyrule Castle Tree Pull --- Rules.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Rules.py b/Rules.py index 5368b2f5..ee69a481 100644 --- a/Rules.py +++ b/Rules.py @@ -1805,6 +1805,9 @@ def standard_rules(world, player): add_rule(world.get_location('Hyrule Castle Tree', player), lambda state: state.has('Zelda Delivered', player)) add_rule(world.get_location('Central Bonk Rocks Tree', player), lambda state: state.has('Zelda Delivered', player)) + if not world.is_copied_world: + add_rule(world.get_location('Hyrule Castle Courtyard Tree Pull', player), lambda state: state.has('Zelda Delivered', player)) + # don't allow bombs to get past here before zelda is rescued set_rule(world.get_entrance('GT Hookshot South Entry to Ranged Crystal', player), lambda state: (state.can_use_bombs(player) and state.has('Zelda Delivered', player)) or state.has('Blue Boomerang', player) or state.has('Red Boomerang', player)) # or state.has('Cane of Somaria', player)) From d7af3a4a7d3d91283b1c94c1b335239ba3f81967 Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 4 Nov 2025 08:17:23 -0700 Subject: [PATCH 38/73] Merge pull request #170 from theclearmouse/patch-3 update tournament winners in telepathy tiles --- Text.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Text.py b/Text.py index 07fb2e4d..9eb6027f 100644 --- a/Text.py +++ b/Text.py @@ -1782,6 +1782,8 @@ class TextTable(object): text['hylian_text_2'] = CompressedTextMapper.convert("%%^= %==%\n ^ =%^=\n==%= ^^%^") text['desert_entry_translated'] = CompressedTextMapper.convert("Kneel before this stone, and magic will move around you.") text['telepathic_tile_under_ganon'] = CompressedTextMapper.convert("Doors Async League winners\n{HARP}\n" + " ~~~2025~~~\nSchulzer\n\n" + " ~~~2024~~~\nhumbugh\n\n" " ~~~2023~~~\nEriror\n\n" " ~~~2022~~~\nAndy\n\n" " ~~~2021~~~\nprdwong") @@ -1795,7 +1797,8 @@ class TextTable(object): text['telepathic_tile_ice_stalfos_knights_room'] = CompressedTextMapper.convert("{NOBORDER}\nKnock 'em down and then bomb them dead.") text['telepathic_tile_tower_of_hera_entrance'] = CompressedTextMapper.convert("{NOBORDER}\nThis is a bad place, with a guy who will make you fall…\n\n\na lot.") text['houlihan_room'] = CompressedTextMapper.convert("Randomizer tournament winners\n{HARP}\n" - " ~~~2023~~~\nnGanonsGoneWild\n\n" + " ~~~2024~~~\nGammachuu\n\n" + " ~~~2023~~~\nGanonsGoneWild\n\n" " ~~~2022~~~\nObscure\n\n" " ~~~2021~~~\nDaaanty\n\n" " ~~~2019~~~\nJet082\n\n" @@ -2029,6 +2032,7 @@ class TextTable(object): text['ganon_phase_3_alt'] = CompressedTextMapper.convert("Got wax in your ears? I cannot die!") # 190 text['sign_east_death_mountain_bridge'] = CompressedTextMapper.convert("Glitched\ntournament\nwinners\n{HARP}\n" + "~~~HMG 2025~~~\nSkele\n" "~~~No Logic 2024~~~\ntam\n\n" "~~~HMG 2023~~~\ntam\n\n" "~~~No Logic 2022~~~\nChexhuman\n\n" From 411f0bc7bc6752e209fd208f32f18b3235733f75 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 8 Nov 2025 11:12:27 -0600 Subject: [PATCH 39/73] Re-fixed purple chest follower dupe --- Rom.py | 2 +- data/base2current.bps | Bin 137199 -> 137207 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 8e69b142..c0335ec8 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '39c6d90d9aa4711fe3c95d85b1a9b16e' +RANDOMIZERBASEHASH = '2039c11b935d3b81f78810d9f4be19d6' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 2d325e9098601881c2aac9356f06c1ebc87e3f39..d052e425fa889e07974906a91a5ceaa7ae87a070 100644 GIT binary patch delta 116 zcmV-)0E_?cuL$?A2(T&x1o_?uA+s(6S<5M(IC|vSy)X{R4Db@k0MHSy%!07V4Dbdb z?c|`6J4Ar)Z$y)GDS!lnlc>(?312FJPASSalSH$e&kno=2z`K;Z?~_D0TLDgVwb|9 W0X6{yxA~y~?sW)?q8dZ9pzI7P1vB#i delta 108 zcmV-y0F(dsuL$q22(T&x1fStx9cWugrq5$qeuYk3@iyJ4Ar) zZ$y&|Du8-~ld#U~33n=hLMh50lTfpy&kno=e0+eHW4E`90TLDgR+q}50X6{;w*jI7 O?sW*Wos!Ymp2(|MA27NA From f66ec985a99600e2a16c09a0de35257214bb162f Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 8 Nov 2025 11:18:34 -0600 Subject: [PATCH 40/73] Version bump 0.6.1.2 --- CHANGELOG.md | 6 ++++++ OverworldShuffle.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61fc68fd..b7435482 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.6.1.2 +- Various fixes for Custom Goal Framework +- Added custom gfx for Pedestal and Murahdahla +- Re-fixed purple chest follower dupe +- Updated tournament winners texts + ## 0.6.1.1 - Fixed issue with Bosses goals in Custom Goal Framework - Fixed error when using Custom Goals with no extra values diff --git a/OverworldShuffle.py b/OverworldShuffle.py index ebd067bb..028f1659 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.6.1.1' +version_number = '0.6.1.2' # branch indicator is intentionally different across branches version_branch = '-u' From 96e48b2892984efc93c357e9e65fdf554235a929 Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 11 Nov 2025 15:32:00 -0700 Subject: [PATCH 41/73] fix: pot drops at sprite limit fix: music silence DR fix: kondongo AI in vanilla rooms --- Rom.py | 4 ++-- data/base2current.bps | Bin 117959 -> 118114 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Rom.py b/Rom.py index 71f65ef2..36c989fc 100644 --- a/Rom.py +++ b/Rom.py @@ -42,7 +42,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '54eaa40cc69c54b9d790b9c4ea107f4d' +RANDOMIZERBASEHASH = 'd55c23b3e6d92eeff28ca3724573f4ff' class JsonRom(object): @@ -469,7 +469,7 @@ def patch_rom(world, rom, player, team, is_mystery=False): location.item.map and world.mapshuffle[player] == 'none') or ( location.item.compass and world.compassshuffle[player] == 'none')): itemid = handle_native_dungeon(location, itemid) - + rom.write_byte(location.address, itemid) else: # crystals diff --git a/data/base2current.bps b/data/base2current.bps index d0cdd7d679a902d0d1b30607297ef54cbdf0ebed..ac39aaeff42839a87f46b102710c935e5b0ab167 100644 GIT binary patch delta 2051 zcmWkuc~nzp7XQ91CXf(<>^r=I3JL~P6tF@BE3~+Q3sSAxqC|qYzzirV-wTU8BpUM? zJ|Re=C=!r?`bL6A8VLmj<%kYCj?-GV9+g9f%uxrlY9_sZ-1EEJx%b@ddL8d+J+Jde z2$#`jI0rsp#-Rt~WSA}_)6>`rxQ3zF2cYA@at#sG-O}kY#c;WM*szQFD?b=cCo2$# zUSOc=M)hX|x=uQ?k=8oIvw(tr;4ld{Gb4`qfBGhfs+`4x#C~H7;uDVDEnCON#t8b3 ze-JTT)pda^6OyD-Ri{K80$ouSlT`cjGua9f@kz>wqFn2PF+1xsA{q($7UH&@@+KNS-VN6^Dj{l7=`x%c$%?&+)U>#6&Cd508r z(hFnIDU0OHCU3(Czt)+hxSp0w(l4(pi{6<3{*TQ3_oSl$DYS)(fBZ#J8YSp~8`$xxZ{X5Uje-ss_osFbG?oF344^a3>{lWFIaKKsEUk$H*a zJtIz5$06~Qu6V8H6+V#*{X%$~t4{-^igya}WDlF70(2+ZemP^2FmrpUb``HSzNDIB z@SR-f?Ys0_9aEa4A>ECNI!lnDx}#|IM12u7XJh$w@K*B{#_+c1D@D3YmO2N{{R(>x>GL?}`-m>1*^#k6=UG%^LEw(V+*9 z!WCy0dn!T^v7@TXD(=xc`JB=_4RTamne5G)UirDxBcgNqL2oO6aHf?rSY!qAwuo)L z!(1|EgiE|1Xq5K^i3TS+q5M^z&O5dqJDFiRJ8Gj9e`|(atT+PuT!a2G(l8d%B!I1$h>!KcC|1~d+}jIr_|}wn&EIj3XeKhpv&OSp zWt<~)Qs^)anLVsb1c|_MOal;*0!h;btgyfe7O?<3^uZM@X*ka8gT!>Vq+6DN6iUrK zSV=Bw`U+{k#x;E~Au>9pzHt@QSkj=zIR@?aNQ_p-}=z@#f5gAy&F#TnRpB+}% zY;>uv0-&blIQcqU=^3*<0`>UYifxZ#C%kR^Nq$jPQPu4NY`6|10);8=sQ2yLJ=UqI zh7WfmKS5w`{+KDS?BV`nO`%!%?R6OKSUBr8b)78bOrb5eBF zA@B#Y<7#VuijI!Y>84D;#H`2nZouF;m&LbrGyHDX`=mBDyQDVOJ4q`rtn4UAqm(v4 z0;4~LS8k%zqLhm!*LV>!yKNRBOA_}2y$VYPVFGJu2;MsggM5nZdUezGN8-Amxth?T(8LK$a2i&d-=Hde5;D~-Q4jjP@`-1+2bLV>Z+!7F)QprSbr1FhWqiYn{Z)DNM1KtO7BK(B@N9dn^tX{iMnjyr;FXu@emVEEhj(RlqXjk4}M-<0f2dnOoVXmb`fd}&MB+^#wyr@zq$nr O`NclpSC4=5arpn6A7;1! delta 1826 zcmWktdr*^i7X95X34~V&N&v$n5I_axr7kGo07YI?U!dZP6)ITKs6m#lQbd1WkVlX} z$k*_zAS5j-8d*jCMuMAS;6p(k7Pm!b>(;8B)w+%rI@V{^Z1$fs=iYPg%(-*s{@m&~ za@_I!6@Z0|6&8Y(eF|Q{Fa1NqXB>Dc;IV4n=Rk>TST{il58Bzo!XV(Qn00FAf>Q!j z-p2gu^a|YBN6!2HuWk_4xjSp*<>u4f{zVNM=9zyWoMA)(GU`bk6BQ5v43i%)EzqrM zQWr4UvNCGZa&|`RhKTJieCZ#9c<~ z{@cc%#qtxicyP+dO&POq8SmdRDsLN0ZW|RnDfs*-%z%Q6{yJ}t>87y7ol=d6#BZ2j zOWK@y``-RBci&su*#)cG%2eNfrfP{ze&~xG8QS70a5(tX>cq5KeBlDqYYDUCeM`6? zE`i>X#=3vw4v@jh`h5Tj*riv-J$+XuS}!I~>Gl`tPfCy+1)&vaHR8&O^h^>P@V%aL zmS)|(BAC@X8|Sk9w-!~xaq~)Jb36lBN&U8;NMNC##@CA$iFBq>h+gUO~aB`*~6X80$B zJcS8s?0D9$c^z`Z&lJQ%0e&H?&@W#hjn=UpI~L#RT#(e%+NLDmQ?G`fYC;-8s!8mQ3*cyVu|kP+BCpY3npL!LHdfh_(i=5iL8kce2HI$@ z?T0Dw>0ItpCBgkhH)*@kZIrJS6c_)VJ*em*S}RC+0_q2H+6pk2vu!jM(ewDbKXudNPs_Caz?9 z0DK^n2nS(@=uqyMuCAwEjXt1Ll|oW62oVmMZm!tiLe34s=MYQ6IEbMNH;_CINVqif zO;;hmRzJPz>6WKk&J^=&naYqGWLx+RO|sns*QiGrrJ(3e58^)r)l}XR^0y&aMOB26 z=R+W$wfdt8E+A8_6CA3cmv(-P+azS(RY;2T%4qFa1A1;H=q<43$6;;Dx;?t%Li<5N zgt)bPbX_ikLS*=O^!Q8w>s@ifUU5@J#j*wF2SE~stDM)rwLl2Si0Hf)vh zu_1t*9|4JU>t7|9mbJ#^JnqT0(`uWIIbx_rxD&{|5m@bAQWSyv{cQ(rKP{V{V-vm- z9;iD|HyJ@zT!#o*dWHlKzIahG^ZNCPci%;R0Avs2iA7d*r@XN2fuheghj^C#6l zD3MJGArsf33c|_SQSf&9?9)EA1zA`zDH(;J_>U7N4F$fFtX9Qlj5M7a)5+yA$fAk@2!9+R<-QKy zSe=h-JbKf5FU-vguh%Ur9i^W$;a1HMszL@gvVI&YSLZ~`!d#=p_i~f?)EO2B_UGsg`WJePtcCW9c$Vy1{p8UElnEDG%^fjTOUVBK D&VK2} From b64b7d9d6d3b979670f56bc91e164f6bc810e269 Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 11 Nov 2025 15:33:32 -0700 Subject: [PATCH 42/73] fix: ban swamola enemies --- source/enemizer/SpriteSheets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/enemizer/SpriteSheets.py b/source/enemizer/SpriteSheets.py index 001bc79e..abc2387c 100644 --- a/source/enemizer/SpriteSheets.py +++ b/source/enemizer/SpriteSheets.py @@ -363,7 +363,7 @@ def init_sprite_requirements(): SpriteRequirement(EnemySprite.TrinexxFireHead).exalt().sub_group(0, 0x40).sub_group(3, 0x3f), SpriteRequirement(EnemySprite.TrinexxIceHead).exalt().sub_group(0, 0x40).sub_group(3, 0x3f), SpriteRequirement(EnemySprite.Blind).exalt().sub_group(1, 0x2c).sub_group(2, 0x3b), - SpriteRequirement(EnemySprite.Swamola).no_drop().sub_group(3, 0x19), + SpriteRequirement(EnemySprite.Swamola).skip().no_drop().sub_group(3, 0x19), SpriteRequirement(EnemySprite.Lynel).sub_group(3, 0x14), SpriteRequirement(EnemySprite.BunnyBeam).no_drop().ow_skip(), SpriteRequirement(EnemySprite.FloppingFish).uw_skip().immune(), From 58daf424f346bc4367ccd43dbd744511c77d1eb8 Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 11 Nov 2025 16:38:49 -0700 Subject: [PATCH 43/73] fix: enemy bans doc: version information --- CHANGELOG.md | 420 -------------------------------- Main.py | 2 +- PastReleaseNotes.md | 6 +- RELEASENOTES.md | 15 +- source/enemizer/enemy_deny.yaml | 12 +- 5 files changed, 25 insertions(+), 430 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 6d9c32af..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,420 +0,0 @@ -(Note: these will be moving to PastReleaseNotes.md) - -# Feature Notes - -1.4.3: File Select/End Game screen: Mirror Scroll and Pseudoboots added (Thanks Hiimcody!) - - -# Patch Notes - -Changelog archive - -* 1.4.8.1 - - Fixed broken doors generation - - Fixed bomb/arrow upgrade ignoring custom pricing - - Extended `money_balance` to apply to price balancing for non-custom shops. -* 1.4.8 - - New option: Mirror Scroll - to add the item to the starting inventory in non-doors modes (Thanks Telethar!) - - Customizer: Ability to customize shop prices and control money balancing. `money_balance` is a percentage betwen 0 and 100 that attempts to ensure you have that much percentage of money available for purchases. (100 is default, 0 essentially ignores money considerations) - - Fixed a key logic bug with decoupled doors when a big key door leads to a small key door (the small key door was missing appropriate logic) - - Fixed an ER bug where Bonk Fairy could be used for a mandatory connector in standard mode (boots could allow escape to be skipped) - - Fixed an issue with flute activation in rain mode. (thanks Codemann!) - - Fixed an issue with enemies in TR Dark Ride room not requiring Somaria. (Refactored the room for decoupled logic better) - - More HMG fixes by Muffins - - Fixed an issue with multi-player HMG - - Fixed an issue limiting number of items specified in the item pool on the GUI - - Minor documentation fixes (thanks Codemann!) -* 1.4.7.2 - - Fixed an issue with shuffle_ganon/fix_gtower_exit causing a generation failure - - More HMG fixes by Muffins -* 1.4.7.1 - - Fixed an issue with the repaired "beemizer" setting not being backwards compatible -* 1.4.7 - - Fixed generation error with Big Key in starting inventory (thanks Cody!) - - HMG/NL logic fixes by Muffins - - Enemizer: Disabled Walking Zora in the UW due to crash with Swamola (they ignore a lot of collison anyway) - - Enemizer: Fixed an issue with enemizer bush sprites - - Enemizer: Banned new Mimics from being the randomized bush sprite due to crash - - "Beatable" or "accessibility: none" can now use randomized trap doors to seal off entire parts of dungeons (was intended, bug prevented the logic skip) - - Logic error with enemizer and standard should use new enemy logic rules - - Fixed a bug with the inconsistent treatment of the beemizer setting - - Fixed an issue with returning Blacksmith in Simple shuffle (when blacksmith is at Link's House) - - Fixed an issue with dark sanctuary spawn at tavern north door (thanks Codemann!) - - Various enemy bans for the last few months -* 1.4.6 - - Restores original Sanc & Quit behavior, if Aga1 is not dead, then no quick pyramid warp - - Fixed problem with Lite/Lean shuffling some fairy caves unnecessarily - - The 300 Rupees item is now marked as priority, so it will not be used as GT junk fill (this matches a change in the VT randomizer) - - Murahdahla is now logically accessible in inverted mode as a bunny. May affect some beatable-only TFH seeds by allowing Moon Pearl to be inaccessible. - - Fixed an issue around PreferredLocationGroups in customizer which would not work with pre-activated Ocraina or priority items. - - Minor fix on triforce text - - Enemy bans for poor placements -* 1.4.5 - - Logic: Added appropriate enemy logic to GT Mimics 1 and 2 rooms - - Logic: Added appropriate enemy logic to Mire 2 room. Note this does change the default logical strats, due to how enemy kill logic works. - - Ice Rod + 1 Bomb is now out of logic - - Fire Rod + 1 Bomb is now out of logic - - Fire Rod + 1 magic extension is still in logic - - Byrna + 1 magic extension is newly in logic - - (One magic extension is either half magic or a bottle with the ability to purchase a blue or green potion) In general, making up for a lack of magic extension with a few bombs is something that could be added to the logic. Using the ice rod to freeze an enemy and then using that enemy to deal blunt damage and then using bombs to clear the frozen enemy is another strategy that could be added to the logic someday. If these are important to you, let me know. - - Generation: Fixed an issue with dungeonsfull shuffle -* 1.4.4 - - Fixed a crash near the end of the credits when total collection rate was over 1000 -* 1.4.3 - * Key Logic Algorithm: Renamed "Default" to "Dangerous" to indicate the potential soft-lock issues - * Hera Basement Cage: Fix for small key counting multiple times (again) - * Generation: Fixed several generation problems with ER and intensity 3 - * Customizer: Generation bug when attempting to place small keys - * Hints: Updated pedestal/tablet text to be more clear - * Enemizer: Various enemy bans -* 1.4.2 - * New ER Options: - * [Skull Woods shuffle options](#skull-woods-shuffle) - * [New option](#linked-drops-override) to override linked drop down behavior - * Customizer: You can now start with a "RandomWeapon" in the start inventory section - * Customizer: You may now start with "Big Magic" or "Small Magic" items - * Customizer: Suppress warning for missing items if they are in start inventory - * MultiClient: change default port to 23074 for newer SNI versions - * Generation: Fixed typo causing ER gen failure with Bomb Shop at Graveyard Ledge -* 1.4.1.12u - * New Entrance Shuffle Algorithm no longer experimental - * Back of Tavern Shuffle now on by default - * Enemizer: Wallmasters banned from tiles where spiral staircases are. (Softlock issue) - * Packaged build of unstable now available - * Customizer: New PreferredLocationGroup for putting a set of items in a set of locations. See customizer docs. - * Customizer: Fixed an issue with starting with `Ocarina` and flute_mode is active - * Spoiler: Some reformatting. Crystal req. for GT/Ganon moved to requirements section so randomized requirements don't show up in the meta section - * Algorithm: Major_Only. Supports up to 16 extra locations (the visible heart pieces) for when major item count exceeds major location count. Examples: Triforce Hunt, Trinity (Triforce on Ped), Bombbag shuffle - * Fix: HC Big Key drop doesn't count on Basic Doors - * Fix: Small Key for this dungeon in Hera Basement doesn't count twice for the key counter - * Fix: All cross-dungeon modes with restrict boss items should require map/compass for the boss - * Fixed a small bug with traversal algorithm - * Enemizer: Enemy bans+ -* 1.4.1.11u - * New Feature: Several spoiler levels added: None, Settings-only, Semi, Full, Debug - * Semi includes only entrances, prizes, and medallions (potential new spoiler mode being worked on, definition may change) - * Entrance: Lite/Lean support enemy drop shuffle - * Standard: Re-added tutorial guard near large rock - * Enemizer - * Fixed the overwriting of bonk fairies - * Fixed broken graphics on hyrule castle - * Enemy bans - * Customizer: Fixed bug with customizing prize packs -* 1.4.1.10u - * Vanilla key logic: Fix for vanilla layout Misery Mire which allows more complex key logic. Locations blocked by crystal switch access are only locked by 2 keys thanks to that being the minimum in Mire to reach one of two crystal switches. - * Autotracking: Fix for chest turn counter with chest containing multiworld items (Thanks Hiimcody) - * Enemizer: Enemy bans - * Rom: Code prettification and fixing byte designations by Codemann - * Support added for BPS patches via jsonout setting (Thanks Veetorp!) -* 1.4.1.9u - * Enemy Drop Underworld: Changed enemy drop indicator to not require compass - * Experimental: Moved dark world bunny spawns out of experimental. (It is now always on) - * Fix: Red/Blue pendants were swapped for autotracking. (Thanks Muffins!) - * Fix: Red square sometimes wasn't blinking - * Updated tournament winners - * Enemizer: Enemy bans -* 1.4.1.8u - * HUD: New dungeon indicators based on common abbreviations - * OWG+HMG: EG is allowed to be armed - * Drop Shuffle: Fixed an issue with minor drops counting for the wrong dungeon - * Enemizer: Trinexx ice breath should be properly disabled if Trinexx is located outside of Turtle Rock - * Enemizer: Enemy bans -* 1.4.1.7u - * Some bugs around Triforce Pieces smoothed out - * Enemizer: No exception for mimics/eyegores in vanilla rooms if enemy logic is turned to off - * Enemizer: Various enemy bans -* 1.4.1.6u - * Difficulty: Fixed some issues around item caps not being respected - * Enemezier: Tutorial guards remove from South Kakariko - * Map: Pendant colors fixed - * Minor rom code cleanup - * Enemizer: Hovers added to problematic pool near pits. Some other bans -* 1.4.1.5u - * Major Fix: Problem with Ganon's Room sprites - * HMG: Remove extra Swamp Smalls in the pool due to pottery settings - * Enemizer: Couple enemy bans -* 1.4.1.4u - * Logic: Fixed logic bugs surrounding dynammic doors missing logic from big keys and other door types - * Inverted: Castle warp should not appear after defeating Aga 1 - * Enemzier: Fixed a crash with cached sprites Zora/Swamola -* 1.4.1.3v - * Enemizer: Raven/Murderdactyls using the correct damage table - * Enemzier: Boss drops only center when boss shuffle is on -* 1.4.1.2v - * Expert/Hard Item Pool: Capacity fairy no longer gives out free crystal - * Vanilla door + Universal Keys: Generation fixed - * Boss Shuffle: Generation fixed (thanks Codemann for easy solution) - * Vanilla ER: No need for ability to check prizes on keysanity menu - * Swapped ER: Possible generation issue fixed (thanks Codemann) - * Enemizer: Roller ban - * Performance: Faster text boxes. Thanks Kan! -* 1.4.1.1v - * Logic: Moon pearl logic respects blocked doors -* 1.4.1.0v - * World Model Refactor: The overworld has been split up by screen, brings OR and DR a bit closer together in the model sense. A few OWG clips have been rewritten to fit into this new logic better. - * Logic: New logic for some bosses on ice - * Helmasaur on Ice: Bombs for mask, sword or arrows for 2nd phase - * Blind on Ice: Beam sword, Somaria, or Byrna plus magic extension for damage. Red shield or Byrna for protection. - * Kholdstare on Ice: Three options (after cracking the shell) - * Beam sword - * Fire Rod with 1.5 magic extensions - * Fire Rod & Bombos & any Sword & 1 Magic Extension - * Vitreous on Ice: Arrows and Bombs or a Beam Sword - * Trinexx on Ice: Boots always required for dodging. Damage options: - * Gold sword - * Tempered sword with magic extension - * Hammer or Master sword with 3 magic extensions (Rod spam for elemental heads, non-ideal weapon for last phase) - * Trinexx on Ice forbidden in doors seeds until we can model some health requirements. Low health Trinexx still isn't realistically feasible (bascially playing OHKO) - * Logic: Added silver arrows as Arrghus damage option when item functionality is not set to hard or expert - * Logic: Byrna not in logic for laser bridge when item functionality is set to hard or expert - * Enemizer Damage Rework: - * Shuffled: Actually shuffles the damage groups in the table instead of picking random numbers and reducing for mails from there. Enemies will still be assigned to a damage group randomly. - * There will always be at least one group which does no damage. The thief will always be in that group. Ganon always has his own group. - * Glitched modes: Aga 1 should be vulnerable in rain state for glitched modes - * Generation: Trinexx and Lanmolas room allowed as lobbies in intensity 3 (works with enemizer now) - * Enemy AI: Terrorpin AI code removed. May help with unusual enemy behavior? -* 1.4.0.1v - * Key logic: Vanilla key logic fixes. Statically set some HC logic and PoD front door - * Generation: Fix a broken tile pattern - * Inverted: Castle warp should not appear after defeating Aga 1 - * Murahdahla: Should not disappear after Aga 1. May fix other subtle issues. - * Shopsanity: Buying multiple of an item in the potion shop should no longer increase item count. -* 1.4.0.0v - * Initial support for HMG (Thanks Muffins!) - * Generation: fix for bunny walk logic taking up too much memory - * Key Logic: Partial is now the new default - * Enemizer: enemy bans -* 1.3.0.9v - * ER: New Swapped ER mode borrowed from OWR - * ER: fixed a generation error where TR chooses all "must-exits" - * Ganonhunt: playthrough no longer collects crystals - * Vanilla Fill: Uncle weapon is always a sword, medallions for Mire/TR will be vanilla - * Customizer: support shufflebosses/shuffleenemies as well as boss_shuffle/enemy_shuffle - * Enemizer: enemy bans -* 1.3.0.8v - * Enemizer: Red Mimics correctly banned from challenge rooms in appropriate logic setting - * No Logic Standard ER: Rain doors aren't blocked if no logic is enabled. - * Trinexx: attempt to fix early start - * MW Progression Balancing: Change to be percentage based instead of raw count. (80% threshold) - * Take anys: Good Bee cave chosen as take any should no longer prevent generation - * Money balancing: Fixed generation issue - * Enemizer: various enemy bans -* 1.3.0.7v - * Fix for Mimic Cave enemy drops - * Fix for Spectacle Rock Cave enemy drops (the mini-moldorms) - * Fix for multiworld lamps with incorrect graphics - * No longer shuffles fairy bonks (from trees) as part of Enemizer -* 1.3.0.6v - * Flute can't be activated in rain state (except glitched modes) (Thanks codemann!) - * Enemizer - * Arrghus at Lanmo 2 no longer prevents pot pickups - * Trinexx at Lanmo 2 requires the Cape go backwards to face him - * Lift-able Blocks require a sprite slot (should help reduce problems) - * Fixed logic issues: - * Self-locking key not allowed in Sanctuary in standard (typo fixed) - * More advanced bunny-walking logic in dungeons (multiple paths considered) - * ER: Minor fix for Link's House on DM in Insanity (escape cave should not be re-used) - * MSU: GTBK song fix for DR (Thanks codemann!) - * District Algorithm: Fails if no available location outside chosen districts - * Various enemy bans - * More Gibos near kiki and Old Man - * Bumper/AntiFairy obstacles - * Damaging roller - * Statue + Pots don't mix - * Statues on Skull Big Key Chest tile - * Toppo in challenge rooms - * Misc others -* 1.3.0.5v - * Hud/Map Counter: Collecting a keys for this dungeon of a bonk torch no longer increments the counter twice and immediately updates the hud. - * Enemizer: Hera basement item counting twice fixed by banning wallmasters on the tile. - * Enemizer: Statues banned offscreen for pull switches - * Enemizer: Several sprite producing enemies have been limited on crowded tiles. Offenders: Hinox, Sluggula, Bomb Guard, Beamos, Gibo, Wall Cannons, Probe using Guards. Others do not spam as many projectiles. - * Enemizer: More enemy bans (mostly Wizzrobes near walls where they won't spawn, couple missed firebar spots) -* 1.3.0.4v - * Enemizer: The bunny beam near Lanmo 2 and the 4 fairies near Ice Armos are not shuffled anymore. This is due to how bosses shuffle works and since it cannot be guaranteed to work within the current system, they are vanilla. (Vitreous still overwrites the fairies and Arrghus only lets two spawn, etc.) - * Dropshuffle: Pokey 1 has been fixed to drop his item - * Mystery/Customizer: true/false and on/off in yaml files should behave the same. - * More enemy bans as have been reported -* 1.3.0.3v - * Faeries now part of the enemy shuffle pool. Take note, this will increase enemy drop locations to include fairy pools both in dungeons and in caves. - * Enemy drop indicator (blue square) now works in caves based on entrance used - * Fixes: - * Collection rate counter is properly hidden in mystery seeds - * Sprite limit lowered where possible to allow for lifting of pots - * Hovers in Swamp Waterway properly do not drop items anymore - * Lots more bans (thanks to jsd in particular but also thanks to all the reports) - * Minor issue with customizer/mystery files not allowing "true" for booleans -* 1.3.0.2v - * Fix for multiworld received keys not counting correctly - * Fix for multiworld lamps incorrect graphics - * Fix for collection rate decreasing on item "pickup" - * Fix for pendants as prizes counting as items - * Fix for castle barrier gfx in rain state - * Enemizer fixes and bans: - * Fixed a generation issue where ChainChomp placement would cause a failure. (Invincible enemies banned in Sprial Cave for early game traversal for now) - * Skull Pot Prison should not be blocked by "impassable" enemies - * Bumpers banned in Ice Hookshot room - * Fixed issue in GT Spike Crystal room - * Fixed blockage issues in TT Ambush and Compass rooms - * Forbid Bumper in Fairy Ascension cave; needed to clip into wall weirdly to pass. - * Enemy Drop bans - * Forbid Stals in many places where they cannot be woken up. Behind rails and on top of blocks, for example. - * A couple minor wizzrobes bans because of despawns. - * Enemies over pits and on conveyors near pits have been issued standard bans for falling enemies. Mimics join the ranks here as they don't work well on pits or on conveyors. - * Mimics banned where conveyors touch walls and could clip out unintentionally -* 1.3.0.1v - * Fixed bugs with item duping and disappearing drops - * Fixed multiworld crash - * Fixed assured sword missing when using start inventory (via GUI/CLI) - * Forbid extra statues in Swamp Push Statue room - * Forbid bumpers on OW water - * Forbid Stal on pits - * Text fix on sprite author (thanks Synack) -* 1.2.0.23u - * Generation: fix for bunny walk logic taking up too much memory - * Key Logic: Partial is now the new default -* 1.2.0.22u - * Flute can't be activated in rain state (except glitched modes) (Thanks codemann!) - * ER: Minor fix for Link's House on DM in Insanity (escape cave should not be re-used) - * Logic issues: - * Self-locking key not allowed in Sanctuary in standard (typo fixed) - * More advanced bunny-walking logic in dungeons (multiple paths considred) - * MSU: GTBK song fix for DR (Thanks codemann!) -* 1.2.0.21u - * Fix that should force items needed for leaving Zelda's cell to before the throne room, so S&Q isn't mandatory - * Small fix for Tavern Shuffle (thanks Catobat) - * Several small generation fixes -* 1.2.0.20u - * New generation feature that allows Spiral Stair to link to themselves (thank Catobat) - * Added logic for trap doors that could be opened using existing room triggers - * Fixed a problem with inverted generation and the experimental flag - * Added a notes field for user added notes either via CLI or Customizer (thanks Hiimcody and Codemann) - * Fixed a typo for a specific pot hint - * Fix for Hera Boss music (thanks Codemann) -* 1.1.6 (from Stable) - * Minor issue with dungeon counter hud interfering with timer -* 1.2.0.19u - * Added min/max for triforce pool, goal, and difference for CLI and Customizer. (Thanks Catobat) - * Fixed a bug with dungeon generation - * Multiworld: Fixed /missing command to not list all the pots - * Changed the "Ganonhunt" goal to use open pyramid on the Auto setting - * Customizer: Fixed the example yaml for shopsanity -* 1.2.0.18u - * Fixed an issue with pyramid hole being in logic when it is not opened. - * Crystal cutscene at GT use new symmetrical layouts (thanks Codemann) - * Fix for Hera Boss music (thanks Codemann) - * Fixed an issue where certain vanilla door types would not allow other types to be placed. - * Customizer: fixed an issue where last ditch placements would move customized items. Those are now locked and the generation will fail instead if no alternatives are found. - * Customizer: fixed an issue with assured sword and start_inventory - * Customizer: warns when trying to specifically place an item that's not in the item pool - * Fixed "accessibility: none" displaying a spoiling message - * Fixed warning message about custom item pool when it is fine -* 1.2.0.17u - * Fixed logic bug that allowed Pearl to be behind Graveyard Cave or King's Tomb entrances with only Mirror and West Dark World access (cross world shuffles only) - * Removed backup locations for Dungeon Only and Major Only algorithms. If item cannot be placed in the appropriate location, the seed will fail to generate instead - * Fix for Non-ER Inverted Experimental (Aga and GT weren't logically swapped) - * Fix for customizer setting crystals to 0 for either GT/Ganon -* 1.2.0.16u - * Fix for partial key logic on vanilla Mire - * Fix for Kholdstare Shell collision when at Lanmo 2 - * Fix for Mire Attic Hint door (direction was swapped) - * Dungeon at Chest Game displays correctly on OW map option -* 1.2.0.15u - * GUI reorganization - * Logic fix for pots in GT conveyor cross - * Auto option for pyramid open (trinity or ER + crystals goal) - * World model refactor (combining inverted and normal world models) - * Partitioned fix for lamp logic and links house - * Fix starting flute logic - * Reduced universal keys in pool slightly for non-vanilla dungeons - * Fake world fix finally - * Some extra restrictions on links house placement for lite/lean - * Collection_rate works in customizer files -* 1.2.0.14u - * Small fix for key logic validation (got rid of a false negative) - * Customized doors in ice cross work properly now -* 1.2.0.13u - * Allow green/blue potion refills to be customized - * OW Map showing dungeon entrance at Snitch Lady (West) fixed (instead of @ HC Courtyard) - * Standing item data is cleared on transition to overworld (enemy drops won't bleed to overworld sprites) - * Escape assist won't give you a free quiver in retro bow mode - * Fixed an issue where a door would be opened magically (due to original pairing) - * MultiServer can now disable forfeits if desired -* 1.2.0.12u - * Fix for mirror portal in inverted - * Yet another fix for blocked door in Standard ER -* 1.2.0.11u - * Fixed an issue with lower layer doors in Standard - * Fix for doors in cave state (will no longer be vanilla) - * Added a logic rule for th murderdactyl near bumper ledge for OHKO purposes - * Enemizer alteration for Hovers and normal enemies in shallow water - * Fix for beemizer including modes with an increased item pool - * Fix for district algorithm -* 1.2.0.10u - * Fixed overrun issues with edge transitions - * Better support for customized start_inventory with dungeon items - * Colorized pots now available with lottery. Default is on. - * Dungeon_only support pottery - * Fix AllowAccidentalGlitches flag in OWG - * Potential fix for mirror portal and entering cave on same frame - * A few other minor issues, generation and graphical -* 1.2.0.9-u - * Disallowed standard exits (due to ER) are now graphically half blocked instead of missing - * Graphical issues with Sanctuary and Swamp Hub lobbies are fixed - * Fixes an issue surrounding door state and decoupled doors leading to blocked doors - * Customizer improvements: - * Better logic around customized lobbies - * Better logic around customized door types - * Fix to key doors that was causing extra key doors - * Generation improvement around crystal switches - * Fix bug in dungeon_only that wasn't using pot key locations (known issue still exists in pottery modes) - * Fixes for multiworld: - * Fixes an issue when keys are found in own dungeon for another player when using the bizhawk plugin. - * Fixes an issue with absorbables for another player also being received by the player picking it up. -* 1.2.0.8-u - * New Features: trap_door_mode and key_logic_algorithm - * Change S&Q in door shuffle + standard during escape to spawn as Uncle - * Fix for vanilla doors + certain ER modes - * Fix for unintentional decoupled door in standard - * Fix a problem with BK doors being one-sided - * Change to how wilds keys are placed in standard, better randomization - * Removed a Triforce text - * Fix for Desert Tiles 1 key door -* 1.2.0.7-u - * Fix for some misery mire key logic - * Minor standard generation fix - * Fix for inactive flute start - * Settingsfile for multiworld generation support - * Fix for duped HC/AT Maps/Compasses -* 1.2.0.6-u - * Fix for light cone in Escape when entering from Dark World post-zelda - * Fix for light cone in Escape when lighting a torch with fire rod -* 1.2.0.5.u - * Logic fix for Sanctuary mirror (it wasn't resetting the crystal state) - * Minor bugfixes for customizer -* 1.2.0.4-u - * Starting inventory fixes if item not present in the item pool. - * Support for Assured sword setting and OWG Boots when using a custom item pool. (Customizer or GUI) - * Logic fix for the skull woods star tile that lets you into the X pot room. Now accounts for small key or big key door there blocking the way from the star tile. A trap door is not allowed there. - * Standard logic improvement that requires a path from Zelda to the start so that you cannot get softlocked by rescuing Zelda. Standard mirror scroll change may need to be reverted if impossible seed are still generated. -* 1.2.0.3-u - * Starting inventory taken into account with default item pool. (Custom pools must do this themselves) - * Fast ROM update - * Fix for restricted boss item counting maps & compasses as vital - * Bug fix for vanilla ER + inverted + experimental -* 1.2.0.2-u - * Fixed a bug with certain trap doors missing - * Added a hint reference for district hints -* 1.2.0.1-u - * Added new ganonhunt and completionist goals - * Fixed the issue when defeating Agahnim and standing in the doorway can cause door state to linger. - * Fix for Inverted Lean/Lite ER - * Fix for vanilla Doors + Standard + ER - * Added a limit per dungeon on small key doors to ensure reasonable generation - * Fixed many small bugs - -# Known Issues - -* Decoupled doors can lead to situations where you aren't logically supposed to go back through a door without a big key or small key, but you can if you press the correct direction back through the door first. There are some transitions where you may get stuck without a bomb. These problems are planned to be fixed. -* Logic getting to Skull X room may be wrong if a trap door, big key door, or bombable wall is shuffled there. A bomb jump to get to those pot may be required if you don't have boots to bonk across. \ No newline at end of file diff --git a/Main.py b/Main.py index 225a74d4..3c4d8c9b 100644 --- a/Main.py +++ b/Main.py @@ -38,7 +38,7 @@ from source.enemizer.DamageTables import DamageTable from source.enemizer.Enemizer import randomize_enemies from source.rom.DataTables import init_data_tables -version_number = '1.4.10' +version_number = '1.4.11' version_branch = '-u' __version__ = f'{version_number}{version_branch}' diff --git a/PastReleaseNotes.md b/PastReleaseNotes.md index 68b6b381..fa8d1286 100644 --- a/PastReleaseNotes.md +++ b/PastReleaseNotes.md @@ -5,7 +5,11 @@ # Patch Notes Changelog archive - +* 1.4.10 + * Logic: Changed the rule surrounding the Bumper Cave Ledge Drop (the murderdactyl) to only require Pearl AND (Cape OR Byrna OR a Sword) in OHKO mode for now. This is a temporary solution until a better way to prevent needing to use a framerule to get past the bird is invented. + * Helmacopter Fix. + * Fixed a bug in shopsanity that caused the generation to fail with certain prices. + * Enemizer: fairies were invalid on the overworld (unless a bonk occurred nearby), so they will no longer be randomized there. * 1.4.9 * Attempted fix for Moth conveyor room timing. Thanks for many people's input. Unsure if Helmacopter is still acceptable. * Mirror scroll will show up on file start screen if enabled (thanks Clearmouse!) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ec57a296..29af9f02 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,7 +1,12 @@ # Patch Notes -* 1.4.10 - * Logic: Changed the rule surrounding the Bumper Cave Ledge Drop (the murderdactyl) to only require Pearl AND (Cape OR Byrna OR a Sword) in OHKO mode for now. This is a temporary solution until a better way to prevent needing to use a framerule to get past the bird is invented. - * Helmacopter Fix. - * Fixed a bug in shopsanity that caused the generation to fail with certain prices. - * Enemizer: fairies were invalid on the overworld (unless a bonk occurred nearby), so they will no longer be randomized there. +* 1.4.11 + * Rom fixes (all thanks to Codemann, I believe) + * Pot bug when at sprite limit + * Kodongo AI vanilla in vanilla rooms + * Issue with music silencing across certain room transitions + * Gltiched: Some HMG logic fixed. Thanks Muffins! (Sorry it took me forever to get this PR in) + * Text: Updated tourney winners. Thanks clearmouse! + * Enemizer: Banned Swamola enemy everywhere as they may be causing crashes + * Enemizer: Enemy bans from Q2 and Q3. Thank you for all the reports. + diff --git a/source/enemizer/enemy_deny.yaml b/source/enemizer/enemy_deny.yaml index ea92264d..1e89ec3e 100644 --- a/source/enemizer/enemy_deny.yaml +++ b/source/enemizer/enemy_deny.yaml @@ -84,7 +84,7 @@ UwGeneralDeny: - [ 0x0039, 4, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "FirebarCW", "FirebarCCW" ] ] #"Skull Woods - Play Pen - Spike Trap 1" - [0x0039, 5, ["RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "Bumper", "AntiFairyCircle"]] #"Skull Woods - Play Pen - Hardhat Beetle" - [ 0x0039, 6, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "FirebarCW", "FirebarCCW" ] ] #"Skull Woods - Play Pen - Spike Trap 2" - - [0x003a, 1, ["RollerVerticalUp"]] + - [0x003a, 1, ["RollerVerticalUp", "RollerVerticalDown"]] - [ 0x003b, 1, [ "Bumper", "AntiFairyCircle" ]] - [ 0x003b, 4, ["RollerVerticalUp", "RollerVerticalDown"]] - [ 0x003c, 0, ["BigSpike"]] @@ -339,7 +339,11 @@ UwGeneralDeny: - [ 0x00c2, 5, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots - [ 0x00c5, 6, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Turtle Rock - Catwalk - Mini Helmasaur" - [ 0x00c5, 7, [ "Statue" ] ] #"Turtle Rock - Catwalk - Laser Eye (Left) 4" + - [0x00c6, 2, ["Bumper", "AntiFairyCircle"]] + - [0x00c6, 3, ["Bumper", "AntiFairyCircle"]] + - [0x00c6, 4, ["Bumper", "AntiFairyCircle"]] - [0x00c6, 5, ["Bumper", "AntiFairyCircle"]] + - [0x00c6, 6, ["Bumper", "AntiFairyCircle"]] - [ 0x00cb, 0, [ "Wizzrobe", "Statue" ] ] # Wizzrobes can't spawn on pots - [ 0x00cb, 3, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Thieves' Town - Grand Room NW - Zol 1" - [ 0x00cb, 5, [ "RollerVerticalUp", "RollerVerticalDown", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Thieves' Town - Grand Room NW - Zol 2" @@ -397,6 +401,7 @@ UwGeneralDeny: - [ 0x00e4, 2, [ "RollerHorizontalLeft", "RollerHorizontalRight", "Beamos", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Old Man Home - Keese 3" - [ 0x00e5, 4, [ "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Old Man Home Circle - Keese 5" - [ 0x00e5, 5, [ "RollerVerticalDown", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Old Man Home Circle - Keese 6" + - [0x00e6, 0, ["Statue"]] # Death Mountain Descent Cave Left - Keese 1 - Statue blocking pot access - [ 0x00e7, 0, [ "RollerVerticalUp", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Death Mountain Descent Cave Right - Keese 1" - [ 0x00e7, 1, [ "RollerVerticalUp", "AntiFairyCircle", "BigSpike", "SpikeBlock", "Bumper" ] ] #"Death Mountain Descent Cave Right - Keese 2" - [ 0x00e7, 2, [ "RollerVerticalUp", "RollerVerticalDown", "RollerHorizontalRight" ] ] #"Death Mountain Descent Cave Right - Keese 3" @@ -441,7 +446,7 @@ OwGeneralDeny: - [0x05, 10, ["Bumper", "AntiFairyCircle"]] # Blocks path - [0x05, 11, ["Bumper", "AntiFairyCircle"]] # Blocks path to portal - [0x07, 3, ["Bumper", "AntiFairyCircle", "RollerHorizontalRight", "RollerHorizontalLeft"]] # Blocks path to ladder - - [0x07, 4, ["RollerHorizontalLeft"]] # Blocks path to ladder + - [0x07, 4, ["Bumper", "AntiFairyCircle", "RollerHorizontalLeft"]] # Blocks path to ladder - [0x1e, 3, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle"]] # forbid a beamos here - [0x35, 8, ["RollerVerticalUp", "RollerVerticalDown"]] # blocks the dock - [0x37, 5, ["RollerVerticalUp"]] # combines with a roller above to make the way impassable @@ -450,7 +455,7 @@ OwGeneralDeny: - [0x40, 13, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]] - [0x40, 14, ["Beamos", "Bumper", "BigSpike", "AntiFairyCircle", "Thief"]] - [0x40, 16, ["RollerVerticalUp", "RollerVerticalDown"]] # Ropa near back hole is really large as a roller - - [0x55, 6, ["BigSpike"]] + - [0x55, 6, ["BigSpike", "Bumper", "AntiFairyCircle"]] - [0x57, 5, ["RollerVerticalUp", "RollerVerticalDown"]] - [0x5b, 0, ["AntiFairyCircle", "Bumper"]] # ropa on pyramid - [0x5e, 0, ["Gibo"]] # kiki eating Gibo @@ -480,6 +485,7 @@ OwGeneralDeny: - [0x77, 1, ["Bumper", "AntiFairyCircle"]] # soft-lock potential near ladder - [0x7f, 1, ["Bumper", "AntiFairyCircle"]] # soft-lock potential near ladder UwEnemyDrop: + - [0x0015, 8, ["Zoro"]] # layer issues - [0x0085, 9, ["Babasu"]] # ran off the edge and didn't return - [0x00cb, 3, ["Zoro"]] # layer issues - [0x00cb, 5, ["Zoro"]] # layer issues From 9847b71a0244133d57a2738437a2c5544b7cdad5 Mon Sep 17 00:00:00 2001 From: aerinon Date: Thu, 13 Nov 2025 08:57:15 -0700 Subject: [PATCH 44/73] fix: blind vram fight fix --- RELEASENOTES.md | 3 ++- Rom.py | 2 +- data/base2current.bps | Bin 118114 -> 118123 bytes 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 29af9f02..9e672645 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -5,7 +5,8 @@ * Pot bug when at sprite limit * Kodongo AI vanilla in vanilla rooms * Issue with music silencing across certain room transitions - * Gltiched: Some HMG logic fixed. Thanks Muffins! (Sorry it took me forever to get this PR in) + * Glitched: Some HMG logic fixed. Thanks Muffins! (Sorry it took me forever to get this PR in) + * Glitched: Blind fight VRAM fix. Thanks Mufffins! * Text: Updated tourney winners. Thanks clearmouse! * Enemizer: Banned Swamola enemy everywhere as they may be causing crashes * Enemizer: Enemy bans from Q2 and Q3. Thank you for all the reports. diff --git a/Rom.py b/Rom.py index 36c989fc..fc343d7e 100644 --- a/Rom.py +++ b/Rom.py @@ -42,7 +42,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'd55c23b3e6d92eeff28ca3724573f4ff' +RANDOMIZERBASEHASH = 'f0881c7ccde2f0d0cd5e9cfe481633ad' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index ac39aaeff42839a87f46b102710c935e5b0ab167..e919637df15e2adc47a00eb2383ceb334378988b 100644 GIT binary patch delta 51 zcmV-30L=g5ng{Ee2e1MI1ZcXKMY9G2NOujXji~{RDgm4TAL{DxgHn38QhEUhQwZeW JxTe&emx&s<7Eb^G delta 42 ycmaDoi~Z3o_6 Date: Thu, 13 Nov 2025 19:17:01 -0600 Subject: [PATCH 45/73] Fix to allow VRAM corruption in boss fights --- Rom.py | 2 +- data/base2current.bps | Bin 137207 -> 137216 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index c0335ec8..ea2930a2 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '2039c11b935d3b81f78810d9f4be19d6' +RANDOMIZERBASEHASH = '62eafe64b2673b686bc66abd42d68b71' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index d052e425fa889e07974906a91a5ceaa7ae87a070..aaaea0f03dff7dba31d8fe1f4ee3b2206fbe3673 100644 GIT binary patch delta 50 zcmV-20L}mRuLyv!2(T&x0}kHtvn>Oddkv|LsR4~D0h|CI>gw==$$q!VegP(#2o-c~ I1iIV{4Oddjx@v7=VM)ez($o0VbIUilQ1rv!Lt@arF_p From 923ba14d61d9992d0612d72fa3eec257f55406ad Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 14 Nov 2025 09:05:12 -0700 Subject: [PATCH 46/73] feat: force_enemy feature feat: rom-side enemy "spies" --- BaseClasses.py | 1 + Main.py | 9 ++++++++- Rom.py | 2 +- data/base2current.bps | Bin 118123 -> 118196 bytes source/classes/CustomSettings.py | 8 ++++++++ source/enemizer/Enemizer.py | 17 +++++++++++------ source/enemizer/SpriteSheets.py | 6 ++++-- 7 files changed, 33 insertions(+), 10 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 529eca39..6a12f32e 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -129,6 +129,7 @@ class World(object): set_player_attr('enemy_health', 'default') set_player_attr('enemy_damage', 'default') set_player_attr('any_enemy_logic', 'allow_all') + set_player_attr('force_enemy', None) set_player_attr('beemizer', '0') set_player_attr('escape_assist', []) set_player_attr('crystals_needed_for_ganon', 7) diff --git a/Main.py b/Main.py index 3c4d8c9b..197602e2 100644 --- a/Main.py +++ b/Main.py @@ -38,7 +38,7 @@ from source.enemizer.DamageTables import DamageTable from source.enemizer.Enemizer import randomize_enemies from source.rom.DataTables import init_data_tables -version_number = '1.4.11' +version_number = '1.5.0' version_branch = '-u' __version__ = f'{version_number}{version_branch}' @@ -170,6 +170,13 @@ def main(args, seed=None, fish=None): world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)} world.finish_init() + # custom settings - these haven't been promoted to full settings yet + in_progress_settings = ['force_enemy'] + for player in range(1, world.players + 1): + for setting in in_progress_settings: + if world.customizer and world.customizer.has_setting(player, setting): + getattr(world, setting)[player] = world.customizer.get_setting(player, setting) + logger.info( world.fish.translate("cli","cli","app.title") + "\n", __version__, diff --git a/Rom.py b/Rom.py index fc343d7e..04987530 100644 --- a/Rom.py +++ b/Rom.py @@ -42,7 +42,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'f0881c7ccde2f0d0cd5e9cfe481633ad' +RANDOMIZERBASEHASH = '1e87ad01a54f1c15e2ec16a79a9bcc20' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index e919637df15e2adc47a00eb2383ceb334378988b..a287a08d9090504aa003b5e346d481fe5fdad888 100644 GIT binary patch delta 1216 zcmWlXZA?>V7>3{X@YP`{trS{Xz*77eA1bm4eod*UYjH3~rYImVQQEN~0aS`Oc@MR< zr&@|VmUqz6ZmHs|vMzK=w@zAGRuM7y$7Da8)6Hd?nUu_I&WWDYU(bEt$@Sz(p8LL-DAqLZltqagIcQjG(WzpETA)R$V5ITn%ZQr+FfJr@DeQ z;7_QR=2BNRPW6~m4Zq$3o5uEBgKY%t#4|ovSgKN~TrucEHfyebXT|-I8ox&?O?#-T z33{|v{`+?>#=mwK7uM9=)zN3ED^8os-5cAAj5Xz>HhPju7`63xbo7~4pL&27_+dtL z>Q+9&d4AYO)MnvvKTIbMs*V+EgFapcPI z?~^cC+4j+6+Z)NJ=tZrW$Y2O^RPhMQn*JF+O_#SMAaa!>@wBzdZGJR)C#k4-@_p{T|KQ?MXj zm@`WW!3KBkQha9$YNY&4eB?aTe#xwq+o?~%3wPrW&VzD0U8nL;Uf^{ft;0ueK*{>m zZ_nCG(`N@o3fnMGVH-@4X))Bf1m%>G0VEhpr*PX|%FL0EdW$x2kZ(;b2L(!EF4OJR z_|6Tuk!W0klc%9XtZZ9=@IF2potXpwftRkqE+iWXND(cL#XF{9Ex)+>dm|fUfIy!G z#DU|$=#a^AU>YijatThj30Gvrump&z156aTc~=SwEXy&N*S6gtpVB!#V-RS7z2i+> zdlMe(-mr2Z3iNu#-V6vxkVK?+i99py!+P&!ZnhmOVS6sNTs%QkhQf+9l}KpH?`q5}r%b1hUZ zT8h1vGpSIQPB5@pwKFg}ty~x~UIN+nVc7@Widp#bCO?v$@$VQ z`Kw)Wg$W2W4B%#WP(XoV;U&vQfi&I7nxv;#bH0)7xW}60oTbF%Hb(Xak$LXrv9AV; zW#{6$3}&{;JzbF(9F%avl7doxWsQodAbfUBX24n2WV~9_ceRFG-bAAM@^6qs4B3I- zdx<8w?e)FBM=ru@rh{D*kB{XxUg*eez0lzbVKqKdnma3SH}@C@y*rNGz$3RvE3-z8 zl0mX)l{Sf?w)Kz>OF@v|=j9O%-HOeRTwB%y#mrDC?eIYjc;OD8~nnS+Ss<8_uYcB6 z5O~ryv*%&X!<-&N;7MMWIEe`zsNMyW05Glb2QH=9Hv0Yi zaYrLi=N1K~jf&DVMaYg41yfaoI7*hqN%i4$aCWxR_w?!c=ijBiBp}-U(-UX>skX(L zn1jELlC-&pmrij}knWZwV(hoXc)W6*g7zG)>a`Z@9o$j)*L~pYo^ri|Ut8SIdBEe& z%Ig=bZ6v9QpHIy%MM!~3YHEZlPK#LthMpGtg7hiJV&znObVg^_f{f1gdD=!KCRf$F zoVdY4-y#mT<#JY;{+cIjt&DmV@5`v5oAWupJx5JZHAd2zjR}}HMpQAn4?`)w6(*%; zeDDvvaJAP_?H7WY^3{QOZj9t9lsN-tDa3-%Y6A%z1G96{77QIH8BB5Mo>qTX2cu`G2qQE@i-R8 zi~sN#p23gs0K7@!ggIrQv@J2sV|xL0@b}ZUHBrCVGsMjPc9aNt2hM?nUqd^?3O}HF8cl*13=tS;67DL{c diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index a86e782b..a9ef34d9 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -189,6 +189,14 @@ class CustomSettings(object): args.shuffle_sfx[p] = get_setting(settings['shuffle_sfx'], args.shuffle_sfx[p]) args.msu_resume[p] = get_setting(settings['msu_resume'], args.msu_resume[p]) + def has_setting(self, player, setting): + if 'settings' in self.file_source and player in self.file_source['settings']: + return setting in self.file_source['settings'][player] + return False + + def get_setting(self, player, setting): + return self.file_source['settings'][player][setting] + def get_item_pool(self): if 'item_pool' in self.file_source: return self.file_source['item_pool'] diff --git a/source/enemizer/Enemizer.py b/source/enemizer/Enemizer.py index 90c7ef34..178e24b1 100644 --- a/source/enemizer/Enemizer.py +++ b/source/enemizer/Enemizer.py @@ -1,4 +1,5 @@ import RaceRandom as random +from collections import defaultdict from Utils import snes_to_pc from source.dungeon.EnemyList import SpriteType, EnemySprite, sprite_translation @@ -428,12 +429,16 @@ def randomize_enemies(world, player): if world.enemy_shuffle[player] != 'none': data_tables = world.data_tables[player] custom_uw, custom_ow = {}, {} - enemy_map = world.customizer.get_enemies() if world.customizer else None - if enemy_map and player in enemy_map: - if 'Underworld' in enemy_map[player]: - custom_uw = enemy_map[player]['Underworld'] - if 'Overworld' in enemy_map[player]: - custom_ow = enemy_map[player]['Overworld'] + if world.force_enemy[player]: + custom_ow = {area_id: {i: world.force_enemy[player] for i, s in enumerate(sprite_list)} for area_id, sprite_list in world.data_tables[player].ow_enemy_table.items()} + custom_uw = {room_id: {i: world.force_enemy[player] for i, s in enumerate(sprite_list)} for room_id, sprite_list in world.data_tables[player].uw_enemy_table.room_map.items()} + else: + enemy_map = world.customizer.get_enemies() if world.customizer else None + if enemy_map and player in enemy_map: + if 'Underworld' in enemy_map[player]: + custom_uw = enemy_map[player]['Underworld'] + if 'Overworld' in enemy_map[player]: + custom_ow = enemy_map[player]['Overworld'] randomize_underworld_sprite_sheets(data_tables.sprite_sheets, data_tables, custom_uw) randomize_underworld_rooms(data_tables, world, player, custom_uw) randomize_overworld_sprite_sheets(data_tables.sprite_sheets, data_tables, custom_ow) diff --git a/source/enemizer/SpriteSheets.py b/source/enemizer/SpriteSheets.py index abc2387c..7de739f3 100644 --- a/source/enemizer/SpriteSheets.py +++ b/source/enemizer/SpriteSheets.py @@ -655,9 +655,11 @@ def setup_custom_enemy_sheets(custom_enemies, sheets, data_tables, sheet_range, if key not in requirements: continue req = requirements[key] - if isinstance(req, dict): + if isinstance(req, dict) and room_id in req: req = req[room_id] - if req.static or not req.can_randomize: + else: + req = None + if req and (req.static or not req.can_randomize): try: combine_req(sub_groups_choices, req) except IncompatibleEnemyException: From f6d774b13f589c249b3e3158ee9cadffa542635f Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 14 Nov 2025 13:24:08 -0700 Subject: [PATCH 47/73] fix: potential fix for GT basement --- DoorShuffle.py | 7 ++++++- Rules.py | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/DoorShuffle.py b/DoorShuffle.py index e2e25390..32b15ec5 100644 --- a/DoorShuffle.py +++ b/DoorShuffle.py @@ -290,7 +290,12 @@ def vanilla_key_logic(world, player): create_alternative_door_rules('Mire Map Spike Side Blue Barrier', 2, 'Misery Mire', world, player) create_alternative_door_rules('Mire Crystal Dead End Left Barrier', 2, 'Misery Mire', world, player) create_alternative_door_rules('Mire Crystal Dead End Right Barrier', 2, 'Misery Mire', world, player) - # gt logic? I'm unsure it needs adjusting + # gt logic + conveyor_star_pits_door = world.key_logic[player]['Ganons Tower'].door_rules['GT Conveyor Star Pits EN'] + firesnake_door = world.key_logic[player]['Ganons Tower'].door_rules['GT Firesnake Room SW'] + firesnake_door.alternate_big_key_loc.update(conveyor_star_pits_door.alternate_big_key_loc) + tile_door = world.key_logic[player]['Ganons Tower'].door_rules['GT Tile Room EN'] + tile_door.alternate_big_key_loc.update(conveyor_star_pits_door.alternate_big_key_loc) def create_alternative_door_rules(door, amount, dungeon, world, player): diff --git a/Rules.py b/Rules.py index c0368efd..5d059a5c 100644 --- a/Rules.py +++ b/Rules.py @@ -2434,6 +2434,9 @@ def eval_small_key_door_partial_main(state, door_name, dungeon, player): number = min(number, door_rule.alternate_small_key) door_openable |= state.has_sm_key(key_logic.small_key_name, player, number) break + if state.placing_items and any(lock_item == item.name for item in state.placing_items): + number = min(number, door_rule.alternate_small_key) + door_openable |= state.has_sm_key(key_logic.small_key_name, player, number) return door_openable From 5ce9a3e297b94c2515470f0e47506a971ece7cdd Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 14 Nov 2025 13:43:32 -0700 Subject: [PATCH 48/73] refactor: remove old asm code --- asm/doorrando.asm | 44 -- asm/doortables.asm | 696 -------------------------------- asm/dr_lobby.asm | 10 - asm/drhooks.asm | 221 ---------- asm/edges.asm | 299 -------------- asm/gfx.asm | 95 ----- asm/hudadditions.asm | 291 ------------- asm/keydoors.asm | 42 -- asm/math.asm | 66 --- asm/normal.asm | 419 ------------------- asm/overrides.asm | 154 ------- asm/scroll.asm | 222 ---------- asm/spiral.asm | 332 --------------- asm/testdata/horizontaltest.txt | 227 ----------- asm/testdata/vanilla.txt | 227 ----------- asm/testdata/verticaltest.txt | 227 ----------- 16 files changed, 3572 deletions(-) delete mode 100644 asm/doorrando.asm delete mode 100644 asm/doortables.asm delete mode 100644 asm/dr_lobby.asm delete mode 100644 asm/drhooks.asm delete mode 100644 asm/edges.asm delete mode 100644 asm/gfx.asm delete mode 100644 asm/hudadditions.asm delete mode 100644 asm/keydoors.asm delete mode 100644 asm/math.asm delete mode 100644 asm/normal.asm delete mode 100644 asm/overrides.asm delete mode 100644 asm/scroll.asm delete mode 100644 asm/spiral.asm delete mode 100644 asm/testdata/horizontaltest.txt delete mode 100644 asm/testdata/vanilla.txt delete mode 100644 asm/testdata/verticaltest.txt diff --git a/asm/doorrando.asm b/asm/doorrando.asm deleted file mode 100644 index cc134be9..00000000 --- a/asm/doorrando.asm +++ /dev/null @@ -1,44 +0,0 @@ -!add = "clc : adc" -!addl = "clc : adc.l" -!sub = "sec : sbc" -!bge = "bcs" -!blt = "bcc" - -; Free RAM notes -; Normal doors use $AB-AC for scrolling indicator -; Normal doors use $FE to store the trap door indicator -; Normal doors use $045e to store Y coordinate when transitioning to in-room stairs -; Normal doors use $045f to determine the order in which supertile quadrants are drawn -; Straight stairs use $046d to store X coordinate on animation start -; Spiral doors use $045e to store stair type -; Gfx uses $b1 to for sub-sub-sub-module thing - -; Hooks into various routines -incsrc drhooks.asm - -;Main Code -org $278000 ;138000 -db $44, $52 ;DR -DRMode: -dw 0 -DRFlags: -dw 0 -DRScroll: -db 0 -OffsetTable: -dw -8, 8 - -incsrc normal.asm -incsrc scroll.asm -incsrc spiral.asm -incsrc gfx.asm -incsrc keydoors.asm -incsrc overrides.asm -incsrc edges.asm -incsrc math.asm -incsrc hudadditions.asm -incsrc dr_lobby.asm -warnpc $279C00 - -incsrc doortables.asm -warnpc $288000 diff --git a/asm/doortables.asm b/asm/doortables.asm deleted file mode 100644 index 90678ca3..00000000 --- a/asm/doortables.asm +++ /dev/null @@ -1,696 +0,0 @@ -org $279C00 -KeyDoorOffset: -; 0 1 2 3 4 5 6 7 8 9 a b c d e f --Offset Ruler -dw $0000,$0001,$0003,$0000,$0006,$0000,$000b,$0000,$0000,$0000,$000c,$000d,$0010,$0011,$0012,$0000 -dw $0000,$0015,$0018,$001c,$001e,$0025,$0027,$0000,$0000,$002b,$002d,$0033,$0035,$0038,$0039,$003d -dw $003f,$0040,$0043,$0045,$0047,$0000,$004f,$0000,$0053,$0000,$0055,$005b,$0000,$0000,$005f,$0000 -dw $0060,$0062,$0064,$0065,$0066,$0068,$006e,$0074,$007a,$007c,$007e,$0081,$0000,$0082,$0086,$0088 -dw $0089,$008a,$0000,$008b,$008e,$0092,$0096,$0000,$0000,$0099,$009d,$00a2,$00a5,$00a6,$00a8,$00aa -dw $00ab,$00ad,$00af,$00b2,$0000,$0000,$00b5,$00b9,$00bf,$00c5,$00c9,$00ca,$00cc,$00ce,$00d1,$00d5 -dw $00d6,$00dc,$00e3,$00e9,$00ec,$00ed,$00ee,$00f2,$00f5,$0000,$00f7,$00f8,$00fc,$00ff,$0102,$0000 -dw $0000,$0103,$0106,$0107,$010a,$010c,$010e,$0112,$0000,$0000,$0000,$0114,$0117,$011b,$011e,$0121 -dw $0000,$0123,$0000,$0124,$0127,$0128,$0000,$012c,$0000,$0000,$0000,$012e,$0133,$0139,$013e,$0000 -dw $013f,$0140,$0141,$0146,$0000,$0149,$014b,$014d,$014f,$0150,$0000,$0153,$0156,$015a,$015d,$0161 -dw $0163,$0164,$0166,$016a,$016c,$016d,$0000,$0000,$0170,$0176,$017c,$0182,$0184,$0000,$0185,$0186 -dw $0188,$018b,$018f,$0197,$019c,$019d,$019e,$01a3,$01a4,$01a6,$01aa,$01ad,$01b3,$0000,$01bb,$01be -dw $01bf,$01c2,$01ca,$01d2,$01d9,$01da,$01dd,$01e3,$01e6,$01e7,$0000,$01ec,$01ed,$0000,$01f0,$0000 -dw $01f1,$01f3,$01f7,$0000,$0000,$01f8,$01fa,$0000,$01fd,$0200,$0203,$0204,$0206,$0000,$0000,$0000 -dw $0207 - - -org $279E00 -SpiralOffset: -; 0 1 2 3 4 5 6 7 8 9 a b c d e f --Offset Ruler -db $00,$01,$02,$00,$03,$00,$00,$04,$00,$05,$07,$00,$08,$00,$0b,$00 -db $00,$0c,$00,$00,$00,$0d,$0e,$0f,$00,$00,$11,$00,$13,$14,$15,$00 -db $00,$00,$00,$00,$00,$00,$16,$19,$1b,$00,$00,$00,$00,$00,$00,$00 -db $00,$1c,$00,$00,$1f,$00,$00,$00,$20,$00,$21,$00,$00,$00,$00,$22 -db $23,$24,$25,$00,$00,$26,$00,$00,$00,$00,$27,$00,$29,$2a,$2b,$00 -db $00,$00,$00,$2c,$2d,$00,$00,$00,$00,$00,$00,$00,$2e,$2f,$00,$30 -db $00,$00,$00,$35,$36,$00,$37,$00,$00,$00,$38,$3a,$3b,$00,$3c,$00 -db $3d,$40,$41,$00,$00,$00,$42,$45,$00,$00,$00,$00,$00,$00,$00,$49 -db $4a,$00,$00,$00,$00,$00,$00,$4b,$00,$00,$00,$00,$4f,$00,$53,$00 -db $00,$54,$00,$55,$00,$00,$00,$56,$57,$58,$00,$00,$00,$00,$59,$00 -db $5a,$00,$5b,$00,$00,$5c,$5d,$00,$00,$00,$00,$5e,$00,$00,$5f,$00 -db $60,$00,$00,$00,$00,$63,$64,$00,$00,$00,$00,$00,$65,$00,$66,$00 -db $67,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -db $6a,$6d,$6e,$00,$00,$00,$00,$00,$00,$00,$6f,$00,$00,$00,$00,$00 -db $70 - -org $279F00 -DoorOffset: -db $00,$01,$02,$00,$03,$00,$04,$00,$00,$00,$00,$00,$9A,$05,$99,$00 -db $00,$06,$07,$08,$09,$0A,$0B,$00,$00,$0C,$0D,$0E,$00,$0F,$10,$11 -db $12,$13,$14,$15,$16,$00,$17,$00,$98,$00,$18,$19,$00,$00,$1A,$00 -db $1B,$00,$1C,$1D,$1E,$1F,$20,$21,$22,$23,$24,$25,$00,$26,$27,$00 -db $96,$28,$97,$29,$2A,$2B,$2C,$00,$00,$2D,$2E,$2F,$30,$31,$32,$00 -db $33,$34,$35,$36,$00,$00,$37,$38,$39,$3A,$3B,$3C,$3D,$3E,$3F,$40 -db $41,$42,$43,$A0,$00,$00,$44,$45,$46,$00,$47,$48,$49,$4A,$4B,$00 -; 0 1 2 3 4 5 6 7 8 9 a b c d e f --Offset Ruler -db $00,$4C,$00,$00,$00,$4D,$4E,$9E,$00,$00,$00,$4F,$50,$51,$52,$53 -db $00,$54,$00,$9C,$9D,$55,$00,$00,$00,$00,$00,$56,$57,$58,$59,$00 -db $5A,$5B,$5C,$5D,$00,$5E,$5F,$00,$9B,$60,$00,$61,$62,$63,$64,$65 -db $66,$67,$68,$69,$6A,$6B,$00,$00,$6C,$6D,$6E,$6F,$70,$00,$71,$72 -db $00,$73,$74,$75,$76,$77,$78,$79,$7A,$7B,$7C,$7D,$7E,$00,$7F,$80 -db $00,$81,$82,$83,$84,$85,$86,$87,$88,$89,$00,$8A,$8B,$00,$8C,$00 -db $00,$8D,$8E,$00,$00,$8F,$90,$00,$91,$92,$93,$94,$95,$00,$00,$00 -db $9f - -org $27A000 -DoorTable: -;; NW 00 N 01 NE 02 WN 00 W 01 WS 02 SW 00 S 01 SE 02 EN 00 E 01 ES 02 - Door ruler -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Default/Garbage row -dw $0003, $0003, $0003, $0450, $0003, $0003, $0003, $0003, $0003, $0452, $0003, $0003 ; HC Back Hall (x01) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Sewer Switches (x02) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Crystaroller -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Arghus -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Aga 2 -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Sewer Secret Room -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Sanc -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Pokey -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Lava Pipe -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Pipes n Ledge -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Swap Canal -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Pod dark Maze -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Pod Bridge -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Pod Eye Statue -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Pre Aga -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Cross -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice BK -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; x20 Aga1 -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Sewer Key Rat -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Sewer Waters -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Eye Entrance -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Chest Entrance -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Swamp Statue -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; PoD Arena (x2a) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; PoD Statue (x2b) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Compass -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; x30 Aga's Altar -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Dark Cross -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Lanmolas -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Swamp West Wing -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Flooded Key -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Swamp Main Hub (x36) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Swamp Hammer Time -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Swamp First Basement -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Drop to the Moth -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Pod 3 Catwalks -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Pod Conveyor -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Minihelma -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Conveyor -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Sewers -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Desert Torches -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TT Big Chest -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TT Cellblock -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Swamp Compass Loop -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Skull3 Torches -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Pod Entrance -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Pod Mimics 1 -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Conveyor Ice -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Moldorm -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; IPBJ -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0401, $0003, $0003 ; HC West Hall (x50) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; HC Throne Room (x51) -dw $0003, $0003, $0003, $0401, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; HC East Hall (x52) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Desert Tiles 1 -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Skull 2 Left Entrance -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Skull 2 Right Entrance -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Skull 1 Entrance -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Skull 3 Entrance -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Helmasaur -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Spike Switch -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Cannonball -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Gauntlet 1 -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Choice Cross -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Iced U -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; HC West Lobby (x60) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; HC Main Lobby (x61) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; HC East Lobby (x62) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; x66 Swamp Waterfall -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; x67 Skull 1 Left Drop -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; x68 Skull 1 Pinball -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; x6a Pod Rupees -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; x6b GT Mimics -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; x6c GT Lanmolas -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; x6d Gauntlet 2 -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; x6e Ice Gators -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; HC Armory -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Desert BK Chest -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Swamp Flooded Chests -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT DM's Tile -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Randoroom -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Warp Maze -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Freezors -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Hookpit -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; HC Catawalk -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Desert Right Entrance -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Left -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Hopeful Torch -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Right -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Lonely Freezor -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Vitreous (x90) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Rain -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Dark Crystals -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Blockswitch -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Fallbridge -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Torch Cross -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Eastern Darkness -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Warp Maze 2 -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Invis Bridge -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Compass Room -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Big Chests -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Icy Pots -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Pre-Vitreous (xa0) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Fishbone -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Bridges -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Corner -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Trinexx (xa4) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Wizzrobes -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Eastern Compass (xa8) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Eastern Courtyard (xa9) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Eastern Map (xaa) -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TT Switch -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Blind -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Iced T -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Slipway -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Warpzone -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire ???? -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Spikes -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Refill -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Dark Maze -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Chainchomp -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Rollers -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Eastern Big Key -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Easter Cannonball -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Eastern Dark Circle -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TT Hellway -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TT Bossway -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Blockswitch -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Backtracker -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Tiles -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Main Hub -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Big Chest -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Switch Maze -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Narrow -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Early Hub -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Floating Torches -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Armos -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Eastern Entrance -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TT NW Quad -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TT NE Quad -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Boss Drop -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire BK -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire 2 -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Laser Bridge -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TR Main Entrance -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Eastern Eyegores -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Eastern Attic Switches -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Eastern Attic Start -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TT Entrance Quad -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; TT SE Quad -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Aga 6F -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Sewers Rope -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Swamp Lobby -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Ice Lobby -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; GT Lobby -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Mire Lobby -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Desert West Lobby -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Desert Main Lobby -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Hera Lobby -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Tower Lobby -dw $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003, $0003 ; Desert Back Lobby -; this should end at 27AF18 about (160 * 24 bytes = 3840 or F18) -; some values you can hardcode for spirals -;dw $0070, $36a0 ; ->HC Stairwell -;dw $0072, $4ff8 ; ->HC Map Room -;dw $0080, $1f50 ; ->zelda's cellblock - -org $27B000 -SpiralTable: ;113 4 byte entries - should end at 27B1C4 -dw $0203, $8080 ;null row -dw $0203, $8080 ;HC Backhallway -dw $0203, $8080 ;Sewer Pull -dw $0203, $8080 ;Crystaroller -dw $0203, $8080 ;Moldorm -dw $0203, $8080, $0203, $8080 ;Pod Basement -dw $0203, $8080 ;Pod Stalfos -dw $0203, $8080, $0203, $8080, $0203, $8080 ;GT Entrance -dw $0203, $8080 ;Ice Entrance -dw $0203, $8080 ;Escape -dw $0203, $8080 ;TR Pipe Ledge -dw $0203, $8080 ;Swamp Way -dw $0203, $8080, $0203, $8080 ;Hera Fallplace -dw $0203, $8080, $0203, $8080 ;PoD Bridge -dw $0203, $8080 ;GT Ice -dw $0203, $8080 ;GT F8 -dw $0203, $8080 ;Ice Cross -dw $0203, $8080, $0203, $8080, $0203, $8080 ;Swamp Statue -dw $0203, $8080, $0203, $8080 ;Hera Big -dw $0203, $8080 ;Swamp Ent -dw $0203, $8080, $0203, $8080, $0203, $8080 ;Hera Startiles (middle value unused) -dw $0203, $8080 ;West Swamp -dw $0203, $8080 ;Swamp Basement -dw $0203, $8080 ;Pod Drops -dw $0203, $8080 ;Ice Hammer -dw $0203, $8080 ;Aga Guards -dw $0203, $8080 ;Sewer Begin -dw $0203, $8080 ;Sewer Rope -dw $0203, $8080 ;TT Cellblock -dw $0203, $8080, $0203, $8080 ;Pod Entrance -dw $0203, $8080 ;GT Icespike -dw $0203, $8080 ;GT Moldorm -dw $0203, $8080 ;IPBJ -dw $0203, $8080 ;Desert Prep -dw $0203, $8080 ;Swamp Attic -dw $0203, $8080 ;GT Cannonball -dw $0203, $8080 ;GT Gauntlet1 -dw $0203, $8080, $0203, $8080, $0203, $8080, $0203, $8080, $0203, $8080 ;Ice U (1st three values unused) -dw $0203, $8080 ;Desert Back -dw $0203, $8080 ;TT Attic L -dw $0203, $8080 ;Swamp Waterf -dw $0203, $8080 ;Pod Rupees -dw $0203, $8080 ;Pod Rupees -dw $0203, $8080 ;GT Mimics -dw $0203, $8080 ;GT Lanmo -dw $0203, $8080 ;Ice Gators -dw $0203, $8080, $0203, $8080, $0203, $8080 ;HC Tiny (first value placeholder) -dw $0203, $8080 ;HC Boomer -dw $0203, $8080 ;HC Pits1 -dw $0203, $8080, $0203, $8080, $0203, $8080 ;Swamp Sunken -dw $0203, $8080, $0203, $8080, $0203, $8080, $0203, $8080 ;Hera Entrance (first value unused) -dw $0203, $8080 ;Ice Hookshot -dw $0203, $8080 ;HC Cellblock -dw $0203, $8080, $0203, $8080, $0203, $8080, $0203, $8080 ;Hera Basement (first and third values unused) -dw $0203, $8080, $0203, $8080, $0203, $8080, $0203, $8080 ;GT Circle (third value unused) -dw $0203, $8080 ;Ice Last Freeze -dw $0203, $8080 ;Mire Drops -dw $0203, $8080 ;Mire Block -dw $0203, $8080 ;Mire Attic -dw $0203, $8080 ;Mire Entrance -dw $0203, $8080 ;East Dark -dw $0203, $8080 ;Ice Big -dw $0203, $8080 ;Mire Previtreous -dw $0203, $8080 ;Mire Bridges -dw $0203, $8080 ;GT Wizzrobes -dw $0203, $8080 ;GT Spikepit -dw $0203, $8080 ;TT Switch -dw $0203, $8080 ;Ice T -dw $0203, $8080, $0203, $8080, $0203, $8080 ;Tower Usains (2nd value unused) -dw $0203, $8080 ;TR PlatMaze -dw $0203, $8080 ;TR Chainchomp -dw $0203, $8080 ;TT Bossway -dw $0203, $8080 ;Ice FallZone -dw $0203, $8080, $0203, $8080, $0203, $8080 ;Tower Dark2 (2nd value unused) -dw $0203, $8080, $0203, $8080, $0203, $8080 ;Tower Dark1 (2nd value unused) -dw $0203, $8080 ;Mire BK Thang -dw $0203, $8080 ;Mire2 -dw $0203, $8080 ;East Attic Start -dw $0203, $8080 ;Tower Entrance - - -org $27C000 ;ends around 27C418 -PairedDoorTable: -dw $0000 ; the bad template -dw $0000,$0000 -dw $0000,$0000,$0000 -dw $0000,$0000,$0000,$0000,$0000 -dw $0000 -dw $0000 -dw $0000,$0000,$0000 -dw $0000 -dw $0000 -dw $0000,$0000,$0000 - -dw $0000,$0000,$8021 -dw $0000,$0000,$0000,$0000 -dw $4014,$0000 -dw $8024,$8013,$0000,$0000,$0000,$0000,$0000 -dw $0000,$0000 -dw $0000,$0000,$0000,$0000 -dw $201a,$401a -dw $0000,$4019,$8019,$402a,$0000,$0000 -dw $0000,$0000 -dw $0000,$0000,$0000 -dw $0000 -dw $0000,$0000,$0000,$0000 -dw $0000,$0000 - -dw $0000 -dw $2011,$0000,$0000 -dw $8032,$0000 -dw $0000,$0000 -dw $8014,$0000,$0000,$0000,$0000,$0000,$0000,$0000 -dw $4036,$0000,$0000,$0000 -dw $0000,$0000 -dw $0000,$101a,$402b,$0000,$0000,$0000 -dw $0000,$202a,$0000,$0000 -dw $0000 - -dw $0000,$0000 -dw $0000,$0000 -dw $8022 -dw $0000 -dw $0000,$0000 -dw $2036,$0000,$0000,$0000,$0000,$0000 -dw $8037,$8026,$8035,$0000,$0000,$0000 -dw $8036,$8038,$0000,$4038,$0000,$0000 -dw $4037,$1037 -dw $0000,$0000 -dw $204a,$0000,$0000 -dw $0000 -dw $0000,$0000,$804d,$0000 -dw $0000,$404e -dw $0000 - -dw $0000 -dw $0000 -dw $0000,$0000,$2053 -dw $0000,$0000,$0000,$0000 -dw $0000,$0000,$0000,$0000 -dw $0000,$0000,$0000 -dw $0000,$0000,$8059,$0000 -dw $0000,$0000,$803a,$0000,$0000 -dw $0000,$0000,$0000 -dw $0000 -dw $203d,$0000 -dw $0000,$403e -dw $0000 ; this is the odd extra room - shouldn't be used - -dw $0000,$0000 -dw $0000,$0000 -dw $0000,$0000,$0000 -dw $0000,$0000,$2043 -dw $0000,$0000,$0000,$0000 -dw $0000,$0000,$4058,$0000,$0000,$0000 -dw $0000,$2057,$4068,$0000,$0000,$0000 -dw $2049,$0000,$0000,$0000 -dw $0000 -dw $806b,$0000 -dw $0000,$0000 -dw $0000,$0000,$0000 -dw $805f,$0000,$0000,$0000 -dw $805e - -dw $0000,$0000,$0000,$0000,$0000,$0000 -dw $0000,$0000,$0000,$0000,$0000,$0000,$0000 -dw $0000,$0000,$0000,$0000,$0000,$0000 -dw $0000,$0000,$0000 -dw $0000 -dw $0000 -dw $0000,$0000,$0000,$0000 -dw $0000,$0000,$0000 -dw $0000,$2058 -dw $0000 -dw $805b,$0000,$0000,$0000 -dw $0000,$0000,$0000 -dw $0000,$0000,$0000 -dw $0000 - -dw $0000,$0000,$0000 -dw $0000 -dw $0000,$0000,$0000 -dw $0000,$0000 -dw $0000,$0000 -dw $0000,$0000,$0000,$0000 -dw $0000,$0000 -dw $0000,$207c,$0000 -dw $0000,$407d,$407b,$0000 -dw $0000,$407c,$0000 -dw $808e,$0000,$0000 -dw $0000,$0000 - -dw $0000 -dw $0000,$0000,$0000 -dw $0000 -dw $0000,$0000,$0000,$0000 -dw $0000,$0000 -dw $0000,$0000,$0000,$0000,$0000 -dw $0000,$0000,$0000,$0000,$0000,$0000 -dw $0000,$0000,$0000,$0000,$0000 -dw $807e - -dw $0000 -dw $0000 -dw $0000,$0000,$0000,$0000,$0000 -dw $0000,$0000,$0000 -dw $0000,$0000 -dw $0000,$0000 -dw $0000,$0000 -dw $0000 -dw $0000,$20a9,$0000 -dw $0000,$0000,$0000 -dw $0000,$0000,$0000,$0000 -dw $0000,$0000,$0000 -dw $0000,$0000,$0000,$0000 -dw $0000,$0000 - -dw $0000 -dw $40b1,$0000 -dw $80b2,$0000,$0000,$0000 -dw $0000,$0000 -dw $0000 -dw $0000,$0000,$0000 -dw $0000,$0000,$80b8,$0000,$0000,$0000 -dw $0000,$0000,$4099,$0000,$0000,$0000 -dw $0000,$0000,$0000,$0000,$0000,$0000 -dw $0000,$0000 -dw $0000 -dw $0000 -dw $0000,$0000 - -dw $0000,$0000,$0000 -dw $0000,$80a1,$0000,$0000 -dw $80a2,$0000,$0000,$0000,$0000,$0000,$0000,$0000 -dw $0000,$0000,$0000,$0000,$0000 -dw $0000 -dw $0000 -dw $0000,$0000,$80c6,$0000,$0000 -dw $0000 -dw $20a8,$0000 -dw $80ba,$0000,$0000,$0000 -dw $80b9,$0000,$0000 -dw $0000,$0000,$0000,$0000,$0000,$0000 -dw $0000,$80cc,$0000,$40cc,$0000,$0000,$0000,$0000 -dw $0000,$80bf,$0000 -dw $40be - -dw $0000,$0000,$0000 -dw $0000,$40c2,$0000,$0000,$0000,$0000,$0000,$0000 -dw $80c3,$40c1,$0000,$0000,$0000,$0000,$0000,$0000 -dw $80c2,$0000,$0000,$0000,$0000,$0000,$0000 -dw $80c5 -dw $80c4,$0000,$0000 -dw $20b6,$0000,$0000,$0000,$0000,$0000 -dw $0000,$0000,$0000 -dw $0000 -dw $0000,$0000,$0000,$0000,$0000 -dw $20cc -dw $40bc,$10bc,$80cb -dw $0000 - -dw $0000,$0000 -dw $0000,$0000,$0000,$0000 -dw $0000 -dw $0000,$0000 -dw $0000,$0000,$0000 -dw $0000,$0000,$0000 -dw $0000,$0000,$0000 -dw $0000 -dw $0000,$0000 -dw $0000 -dw $0000,$0000,$0000,$0000 -dw $ffff ; indicates the end - we can drop this - -; Edge Transition Table (Target Room, Flags, MultiDiv ratio for edges) -org $27C500 ;ends around 27C5F(9) 4 bytes would be 27C649 -;I kind of want to split the 3rd byte into two -NorthOpenEdge: -db $00,$80,$11, $00,$80,$11, $00,$80,$11, $00,$80,$11 -db $00,$80,$11, $00,$80,$11, $00,$80,$11, $00,$80,$11 -db $00,$80,$11, $00,$80,$11, $00,$80,$11 -SouthOpenEdge: -db $00,$80,$11, $00,$80,$11, $00,$80,$11, $00,$80,$11 -db $00,$80,$11, $00,$80,$11, $00,$80,$11, $00,$80,$11 -db $00,$80,$11, $00,$80,$11, $00,$80,$11 -WestOpenEdge: -db $00,$80,$11, $00,$80,$11, $00,$80,$11 -db $00,$80,$11, $00,$80,$11, $00,$80,$11 -db $00,$80,$11, $00,$80,$11, $00,$80,$11 -EastOpenEdge: -db $00,$80,$11, $00,$80,$11, $00,$80,$11 -db $00,$80,$11, $00,$80,$11, $00,$80,$11 -db $00,$80,$11, $00,$80,$11, $00,$80,$11 -; Edge Info Table (Midpoint, Width, Min Coord) -; I kind of want to add a fourth byte to help indicate quadrant info on min coord -NorthEdgeInfo: -db $a8,$10,$a0, $2c,$08,$28 ;HC -db $b8,$20,$a8 ; DP West Wing -db $38,$20,$28, $f8,$a0,$a8, $b8,$20,$a8 ; DP Main -db $78,$20,$68 ; DP East Wing -db $f8,$10,$f0, $7c,$18,$70 ; TT Lobby -db $74,$18,$68, $f8,$10,$f0 ; TT Compass -SouthEdgeInfo: -db $a8,$10,$a0, $2c,$08,$28 ; HC -db $b8,$20,$a8 ; DP Sandworm -db $38,$20,$28, $f8,$a0,$a8, $b8,$20,$a8 ; DP North Hall & Dead End -db $78,$20,$68 ; DP Arrow Pot -db $f8,$10,$f0, $7c,$18,$70 ; TT Ambush -db $74,$18,$68, $f8,$10,$f0 ; TT BK Corner -WestEdgeInfo: -db $78,$30,$60 ; TT Attic -db $40,$20,$30 ; DP North Hall -db $40,$20,$30 ; DP Arrow Pot -db $84,$18,$78, $68,$10,$60 ; HC South -db $a0,$a0,$50 ; DP East Wing -db $58,$50,$30, $98,$50,$70 ; TT BK Corner -db $58,$50,$30 ; TT Compass -EastEdgeInfo: -db $78,$30,$60 ; TT Attic -db $40,$20,$30 ; DP Sandworm -db $40,$20,$30 ; DP North Hall -db $68,$10,$60, $84,$18,$78 ; HC Guards -db $a0,$a0,$50 ; DP Main Lobby -db $58,$50,$30, $98,$50,$70 ; TT Ambush -db $58,$50,$30 ; TT Nook -MultDivInfo: ; (1, 2, 3, 4, 5, 6, 10, 20) -db $01, $02, $03, $04, $05, $06, $0a, $14 -; indices: 0-7 - -; In-room stairs in North/South pairs. From left to right: -; PoD, IP right side, IP Freezor chest and GT -org $27C700 -InroomStairsTable: -dw $0003,$0003, $0003,$0003, $0003,$0003, $0003,$0003 - -org $27C720 -InroomStairsRoom: -db $0B,$1B, $3F,$1F, $7E,$5E, $96,$3D -InroomStairsX: -dw $0190, $0160, $0040, $0178 -InroomStairsY: -dw $0058, $0148, $0198, $0190 - - -org $27E000 -CutoffRooms: -; TT Alcove, Mire Bridge Left & Right, Mire Bent Bridge, Mire Hub -; Pod Falling & Harmless, SW Star Pits, TR Lava Escape & TR Dual Pipes, Bob's Room & GT Big Chest -dw $00bc, $00a2, $00a3, $00c2, $001a, $0049, $0014, $008c -; Ice Many Pots, Swamp Waterfall, GT Gauntlet 3, Eastern Push Block, Eastern Courtyard, Eastern Map Valley -; Eastern Cannonball, HC East Hall -dw $009f, $0066, $005d, $00a8, $00a9, $00aa, $00b9, $0052 -; HC West Hall, TR Dash Bridge, TR Hub, Pod Arena, GT Petting Zoo, Ice Spike Cross -dw $0050, $00c5, $00c6, $0009, $0003, $002a, $007d, $005e -; Sewer Drop, Mire Cross, GT Crystal Circles -dw $0011, $00b2, $003d -dw $ffff - -; dungeon tables -; HC HC EP DP AT SP PD MM SW IP TH TT TR GT -org $27f000 -CompassBossIndicator: -dw $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000 -TotalKeys: ;27f020 -db $04, $04, $02, $04, $04, $06, $06, $06, $05, $06, $01, $03, $06, $08, $00, $00 -ChestKeys: ;27f030 -db $01, $01, $00, $01, $02, $01, $06, $03, $03, $02, $01, $01, $04, $04, $00, $00 -BigKeyStatus: ;27f040 (status 2 indicate BnC guard) -dw $0002, $0002, $0001, $0001, $0000, $0001, $0001, $0001, $0001, $0001, $0001, $0001, $0001, $0001, $0000, $0000 -DungeonReminderTable: ;27f060 -dw $2D50, $2D50, $2D51, $2D52, $2D54, $2D56, $2D55, $2D5A, $2D57, $2D59, $2D53, $2D58, $2D5B, $2D5C, $0000, $0000 -TotalLocationsLow: ;27f080 -db $08, $08, $06, $06, $02, $00, $04, $08, $08, $08, $06, $08, $02, $07, $00, $00 -TotalLocationsHigh: ;27f090 -db $00, $00, $00, $00, $00, $01, $01, $00, $00, $00, $00, $00, $01, $02, $00, $00 -org $27f0a0 -TotalLocations: -db $08, $08, $06, $06, $02, $0a, $0e, $08, $08, $08, $06, $08, $0c, $1b, $00, $00 -; no more room here - -; Vert 0,6,0 Horz 2,0,8 -org $27f0b0 -CoordIndex: ; Horizontal 1st -db 2, 0 ; Coordinate Index $20-$23 -OppCoordIndex: -db 0, 2 ; Swapped coordinate Index $20-$23 (minor optimization) -CameraIndex: ; Horizontal 1st -db 0, 6 ; Camera Index $e2-$ea -CamQuadIndex: ; Horizontal 1st -db 8, 0 ; Camera quadrants $600-$60f -ShiftQuadIndex: -db 2, 1 ; see ShiftQuad func (relates to $a9,$aa) -CamBoundIndex: ; Horizontal 1st -db 0, 4 ; Camera Bounds $0618-$61f -OppCamBoundIndex: ; Horizontal 1st -db 4, 0 ; Camera Bounds $0618-$61f -CamBoundBaseLine: ; X camera stuff is 1st column todo Y camera needs more testing -dw $007f, $0077 ; Left/Top camera bounds when at edge or layout frozen -dw $0007, $000b ; Left/Top camera bounds when not frozen + appropriate low byte $22/$20 (preadj. by #$78/#$6c) -dw $00ff, $010b ; Right/Bot camera bounds when not frozen + appropriate low byte $20/$22 -dw $017f, $0187 ; Right/Bot camera bound when at edge or layout frozen -;27f0ce next free byte - -org $27f0f0 -RemoveRainDoorsRoom: -dw $0060, $0062, $ffff ; ffff indicates end of list -RainDoorMatch: ; org $27f0f6 and f8 for now -dw $0081, $0061 ; not xba'd -BlockSanctuaryDoorInRain: ;27f0fa -dw $0000 - - -org $27f100 -TilesetTable: -; 0 1 2 3 4 5 6 7 8 9 a b c d e f --Offset Ruler -db $13,$04,$04,$06,$0d,$ff,$08,$05,$06,$07,$07,$07,$0e,$0e,$0b,$ff -db $13,$04,$04,$0d,$0d,$0d,$08,$05,$06,$07,$07,$07,$0e,$0e,$0b,$0b -db $04,$04,$04,$0d,$0d,$ff,$08,$05,$08,$09,$07,$07,$06,$ff,$0b,$06 -db $04,$05,$04,$12,$08,$08,$08,$08,$08,$09,$07,$07,$06,$0e,$0b,$0b -db $04,$04,$04,$12,$0a,$0a,$08,$ff,$ff,$09,$07,$07,$0e,$0e,$0b,$0b -db $04,$04,$04,$12,$08,$01,$09,$09,$09,$09,$07,$0e,$0e,$0e,$0b,$0b -db $04,$04,$04,$12,$0a,$0a,$08,$09,$09,$ff,$07,$0e,$0e,$0e,$0b,$ff -db $04,$04,$04,$12,$12,$12,$08,$05,$ff,$ff,$ff,$0e,$0e,$0e,$0b,$0b -db $04,$04,$04,$12,$12,$12,$ff,$05,$ff,$05,$ff,$0e,$0e,$0e,$0b,$ff -db $0c,$0c,$0c,$0c,$ff,$0e,$0e,$0c,$0c,$05,$ff,$0e,$0e,$0e,$0b,$0b -db $0c,$0c,$0c,$0c,$0d,$0e,$0e,$05,$05,$05,$05,$0a,$0a,$ff,$0b,$0b -db $04,$0c,$0c,$0c,$0d,$0d,$0d,$0d,$05,$05,$05,$0a,$0a,$ff,$0b,$0b -db $04,$0c,$0c,$0c,$0d,$0d,$0d,$0d,$05,$05,$ff,$0a,$0a,$ff,$0b,$ff -db $04,$0c,$0c,$ff,$ff,$0d,$0d,$ff,$05,$05,$05,$0a,$0a,$ff,$0b,$06 -db $04,$06,$06,$06,$06,$06,$06,$06,$06,$ff,$06,$06,$ff,$06,$06,$06 -db $06,$06,$03,$03,$03,$03,$ff,$ff,$06,$06,$06,$06,$ff,$06,$06,$06 - -;27f200 -PaletteTable: -db $21,$00,$00,$07,$00,$08,$00,$00,$07,$00,$00,$00,$00,$00,$00,$21 -db $21,$00,$00,$00,$00,$00,$00,$00,$07,$00,$00,$00,$00,$00,$00,$00 -db $00,$00,$00,$00,$00,$00,$00,$00,$00,$0e,$00,$00,$07,$00,$00,$07 -db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$07,$00,$00,$00 -db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$13 -db $00,$00,$00,$00,$00,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -; 0 1 2 3 4 5 6 7 8 9 a b c d e f --Offset Ruler -db $00,$00,$00,$00,$00,$00,$00,$06,$00,$00,$00,$00,$00,$00,$00,$00 -db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$14,$20 -db $00,$07,$20,$20,$07,$07,$07,$07,$07,$20,$20,$07,$20,$20,$20,$20 -db $07,$07,$02,$02,$02,$02,$07,$07,$07,$20,$20,$07,$20,$20,$20,$07 - -;27f300 -DungeonTilesets: -db $04,$04,$05,$12,$04,$08,$07,$0C,$09,$0B,$05,$0A,$0D,$0E,$06,$06 - -; -;org $27ff00 - -org $27fff0 -LinksHouseDarkWorld: -dw $ffff -SanctuaryDarkWorld: -dw $ffff -OldManDarkWorld: -dw $ffff \ No newline at end of file diff --git a/asm/dr_lobby.asm b/asm/dr_lobby.asm deleted file mode 100644 index 15ee435c..00000000 --- a/asm/dr_lobby.asm +++ /dev/null @@ -1,10 +0,0 @@ -CheckDarkWorldSpawn: - STA $A0 : STA $048E ; what we wrote over - LDA.l DRFlags : AND #$0200 : BEQ + ; skip if the flag isn't set - LDA.l $7EF357 : AND #$00FF : BNE + ; moon pearl? - LDA.l LinksHouseDarkWorld : CMP $A0 : BEQ ++ - LDA.l SanctuaryDarkWorld : CMP $A0 : BEQ ++ - LDA.l OldManDarkWorld : CMP $A0 : BNE + - ++ SEP #$30 : LDA #$17 : STA $5D - INC $02E0 : LDA.b #$40 : STA !DARK_WORLD : REP #$30 -+ RTL diff --git a/asm/drhooks.asm b/asm/drhooks.asm deleted file mode 100644 index e8c48b90..00000000 --- a/asm/drhooks.asm +++ /dev/null @@ -1,221 +0,0 @@ -org $02b5c4 ; -- moving right routine 135c4 -jsl WarpRight -org $02b665 ; -- moving left routine -jsl WarpLeft -org $02b713 ; -- moving down routine -jsl WarpDown -org $02b7b4 ; -- moving up routine -jsl WarpUp -org $02bd80 -jsl AdjustTransition -nop - -;turn off linking doors -- see .notRoomLinkDoor label in Bank02.asm -org $02b5a8 ; <- 135a8 - Bank02.asm : 8368 (LDA $7EC004 : STA $A0) -jsl CheckLinkDoorR -bcc NotLinkDoor1 -org $02b5b6 -NotLinkDoor1: -org $02b649 ; <- 135a8 - Bank02.asm : 8482 (LDA $7EC004 : STA $A0) -jsl CheckLinkDoorL -bcc NotLinkDoor2 -org $02b657 -NotLinkDoor2: - - -; Staircase routine -org $01c3d4 ; <- c3d4 - Bank01.asm : 9762-4 (Dungeon_DetectStaircase-> STA $A0 : LDA $063D, X) -jsl RecordStairType : nop -org $02a1e7 ;(PC: 121e7) -jsl SpiralWarp - -org $0291b3 ; <- Bank02.asm : 3303 (LDA $0462 : AND.b #$04) -jsl SpiralPriorityHack : nop -org $0290f9 ; <- Bank02.asm : 3188 (LDA $0462 : AND.b #$04) -jsl SpiralPriorityHack : nop - -org $029369 ; <- 11369 - Bank02.asm : 3610 (STX $0464 : STY $012E) -jsl StraightStairsAdj : nop #2 -org $029383 ; <- 11384 - Bank02.asm : 3629 (.walkingDownStaircase-> ADD $20 : STA $20) -jsl StraightStairsFix : nop -org $0293aa ; <- 113aa - Bank02.asm : 3653 (ADD $20 : STA $20) -jsl StraightStairsFix : nop -org $0293d1 ; <- 113d1 - Bank02.asm : 3683 (ADD $20 : STA $20 BRANCH_IOTA) -jsl StraightStairsFix : nop -org $029396 ; <- 11396 - Bank02.asm : 3641 (LDA $01C322, X) -jsl StraightStairLayerFix -org $02c06d ; <- Bank02.asm : 9874 (LDX $0418, CMP.b #$02) -jsl DoorToStraight : nop -org $02c092 ; STA $0020, Y : LDX #$00 -jsl DoorToInroom : nop -org $02c0f8 ; CMP $02C034, X -jsl DoorToInroomEnd -org $02941a ; <- Bank02.asm : 3748 module 7.12.11 (LDA $0464 : BNE BRANCH_$11513 : INC $B0 : RTS) -jsl StraightStairsTrapDoor : rts -org $028b54 ; <- Bank02.asm : 2200 (JSL UseImplicitRegIndexedLocalJumpTable) -jsl InroomStairsTrapDoor - -org $0289a0 ; JSL $0091C4 -jsl QuadrantLoadOrderBeforeScroll -org $02bd9c ; JSL $0091C4 -jsl QuadrantLoadOrderAfterScroll - - -; Graphics fix -org $02895d ; Bank 02 line 1812 (JSL Dungeon_LoadRoom : JSL Dungeon_InitStarTileChr : JSL $00D6F9 : INC $B0) -Splicer: -jsl GfxFixer -lda $b1 : beq .done -rts -nop #5 -.done - -org $01b618 ; Bank01.asm : 7963 Dungeon_LoadHeader (REP #$20 : INY : LDA [$0D], Y) -nop : jsl OverridePaletteHeader - -org $02817e ; Bank02.asm : 414 (LDA $02811E, X) -jsl FixAnimatedTiles - -org $0aef43 ; UnderworldMap_RecoverGFX -jsl FixCloseDungeonMap - -org $028a06 ; Bank02.asm : 1941 Dungeon_ResetTorchBackgroundAndPlayer -JSL FixWallmasterLamp - -org $00d377 ;Bank 00 line 3185 -DecompDungAnimatedTiles: -org $00fda4 ;Bank 00 line 8882 -Dungeon_InitStarTileCh: -org $00d6ae ;(PC: 56ae) -LoadTransAuxGfx: -org $00d739 ; -LoadTransAuxGfx_Alt: -org $00df5a ;(PC: 5f5a) -PrepTransAuxGfx: -org $0ffd65 ;(PC: 07fd65) -Dungeon_LoadCustomTileAttr: -org $01feb0 -Dungeon_ApproachFixedColor: -;org $01fec1 -;Dungeon_ApproachFixedColor_variable: -;org $a0f972 ; Rando version -;LoadRoomHook: -org $1bee74 ;(PC: 0dee74) -Palette_DungBgMain: -org $1bec77 -Palette_SpriteAux3: -org $1becc5 -Palette_SpriteAux2: -org $1bece4 -Palette_SpriteAux1: - - -org $0DFA53 -jsl.l LampCheckOverride -org $028046 ; <- 10046 - Bank02.asm : 217 (JSL EnableForceBlank) (Start of Module_LoadFile) -jsl.l OnFileLoadOverride -org $07A93F ; < 3A93F - Bank07.asm 6548 (LDA $8A : AND.b #$40 - Mirror checks) -jsl.l MirrorCheckOverride - -org $05ef47 -Sprite_HeartContainer_Override: ;sprite_heart_upgrades.asm : 96-100 (LDA $040C : CMP.b #$1A : BNE .not_in_ganons_tower) -jsl GtBossHeartCheckOverride : bcs .not_in_ganons_tower -nop : stz $0dd0, X : rts -.not_in_ganons_tower - - -org $07a955 ; <- Bank07.asm : around 6564 (JP is a bit different) (STZ $05FC : STZ $05FD) -jsl BlockEraseFix -nop #2 - -org $02A0A8 -Mirror_SaveRoomData: -org $07A95B ; < bank_07.asm ; #_07A95B: JSL Mirror_SaveRoomData -jsl EGFixOnMirror - -org $02b82a -jsl FixShopCode - -org $1ddeea ; <- Bank1D.asm : 286 (JSL Sprite_LoadProperties) -jsl VitreousKeyReset - -org $1ed024 ; f5024 sprite_guruguru_bar.asm : 27 (LDA $040C : CMP.b #$12 : INY #2 -jsl GuruguruFix : bra .next -nop #3 -.next - -org $028fc9 -nop #2 : jsl BlindAtticFix - -org $028409 -jsl SuctionOverworldFix - -org $0ded04 ; <- rando's hooks.asm line 2192 - 6ED04 - equipment.asm : 1963 (REP #$30) -jsl DrHudDungeonItemsAdditions -;org $098638 ; rando's hooks.asm line 2192 -;jsl CountChestKeys -org $06D192 ; rando's hooks.asm line 457 -jsl CountAbsorbedKeys -; rando's hooks.asm line 1020 -;org $05FC7E ; <- 2FC7E - sprite_dash_item.asm : 118 (LDA $7EF36F : INC A : STA $7EF36F) -;jsl CountBonkItem - -org $019dbd ; <- Bank01.asm : 4465 of Object_Draw8xN (LDA $9B52, Y : STA $7E2000, X) -jsl CutoffEntranceRug : bra .nextTile : nop -.nextTile - -;maybe set 02e2 to 0 - -org $0799de ; <- Bank07.asm : 4088 (LDA.b #$15 : STA $5D) -JSL StoreTempBunnyState -; -org $08c450 ; <- ancilla_receive_item.asm : 146-148 (STY $5D : STZ $02D8) -JSL RetrieveBunnyState : NOP - -org $02d9ce ; <- Bank02.asm : Dungeon_LoadEntrance 10829 (STA $A0 : STA $048E) -JSL CheckDarkWorldSpawn : NOP - -org $01891e ; <- Bank 01.asm : 991 Dungeon_LoadType2Object (LDA $00 : XBA : AND.w #$00FF) -JSL RainPrevention : BCC + : RTS : NOP : + - -org $1edabf ; <- sprite_energy_ball.asm : 86-7 Sprite_EnergyBall (LDA.b #$10 : LDX.b #$00) -JSL StandardAgaDmg - - -org $09a681 ; < - similar to talalong.asm : 1157 (JSL Main_ShowTextMessage) -JSL BlindsAtticHint : NOP #2 -org $1cfd69 -Main_ShowTextMessage: - -; Conditionally disable UW music changes in Door Rando -org $028ADB ; <- Bank02.asm:2088-2095 (LDX.b #$14 : LDA $A0 ...) -JSL.l Underworld_DoorDown_Entry : CPX #$FF -BEQ + : db $80, $1C ; BRA $028B04 -NOP #6 : + - -org $02C3F2 ; <- Bank02.asm:10521 Unused call -Underworld_DoorDown_Call: -org $02C3F3 -dw $8AD9 ; address of Bank02.asm:2085 - -; These two, if enabled together, have implications for vanilla BK doors in IP/Hera/Mire -; IPBJ is common enough to consider not doing this. Mire is not a concern for vanilla - maybe glitched modes -; Hera BK door back can be seen with Pot clipping - likely useful for no logic seeds - -;Kill big key (1e) check for south doors -;org $1aa90 -;DontCheck: -;bra .done -;nop #3 -;.done - -;Enable south facing bk graphic -;org $4e24 -;dw $2ac8 - -org $01b714 ; PC: b714 -OpenableDoors: -jsl CheckIfDoorsOpen -bcs .normal -rts -.normal diff --git a/asm/edges.asm b/asm/edges.asm deleted file mode 100644 index 58852b12..00000000 --- a/asm/edges.asm +++ /dev/null @@ -1,299 +0,0 @@ -HorzEdge: - cpy #$ff : beq + - jsr DetectWestEdge : ldy #$02 : bra ++ - + jsr DetectEastEdge - ++ cmp #$ff : beq + - sta $00 : asl : !add $00 : tax - cpy #$ff : beq ++ - jsr LoadWestData : bra .main - ++ jsr LoadEastData - .main - jsr LoadEdgeRoomHorz - sec : rts - + clc : rts - -VertEdge: - cpy #$ff : beq + - jsr DetectNorthEdge : bra ++ - + jsr DetectSouthEdge - ++ cmp #$ff : beq + - sta $00 : asl : !add $00 : tax - cpy #$ff : beq ++ - jsr LoadNorthData : bra .main - ++ jsr LoadSouthData - .main - jsr LoadEdgeRoomVert - sec : rts - + clc : rts - -LoadEdgeRoomHorz: - lda $03 : sta $a0 - sty $06 - and.b #$0f : asl a : !sub $23 : !add $06 : sta $02 - ldy #$00 : jsr ShiftVariablesMainDir - - lda $04 : and #$80 : bne .edge - lda $04 : sta $01 ; load up flags in $01 - jsr PrepScrollToNormal - bra .scroll - - .edge - lda $04 : and #$10 : beq + - lda #$01 - + sta $ee ; layer stuff - - jsr MathHorz - - .scroll - jsr ScrollY - rts - -LoadEdgeRoomVert: - lda $03 : sta $a0 - sty $06 - and.b #$f0 : lsr #3 : !sub $21 : !add $06 : sta $02 - - lda $04 : and #$80 : bne .edge - lda $04 : sta $01 ; load up flags in $01 - and #$03 : cmp #$03 : beq .inroom - ldy #$01 : jsr ShiftVariablesMainDir - jsr PrepScrollToNormal - bra .scroll - - .inroom - jsr ScrollToInroomStairs - rts - - .edge - ldy #$01 : jsr ShiftVariablesMainDir - lda $04 : and #$10 : beq + - lda #$01 - + sta $ee ; layer stuff - - jsr MathVert - lda $03 - - .scroll - jsr ScrollX - rts - - -MathHorz: - jsr MathStart : lda $20 - jsr MathMid : and #$0040 - jsr MathEnd - rts - -MathVert: - jsr MathStart : lda $22 - jsr MathMid : and #$0020 - jsr MathEnd - rts - -MathStart: - rep #$30 - lda $08 : and #$00ff : sta $00 - rts - -MathMid: - and #$01ff : !sub $00 : and #$00ff : sta $00 - ; nothing should be bigger than $a0 at this point - - lda $05 : and #$00f0 : lsr #4 : tax - lda MultDivInfo, x : and #$00ff : tay - lda $00 : jsr MultiplyByY : sta $02 - - lda $07 : and #$00ff : jsr MultiplyByY : tax - - lda $05 : and #$000f : tay - lda MultDivInfo, y : and #$00ff : tay - lda $02 : jsr DivideByY : sta $00 - lda $0c : and #$00ff : sta $02 - lda $04 - rts - -MathEnd: - beq + - lda #$0100 - + !add $02 : !add $00 - sta $04 - sep #$30 - rts - -; don't need midpoint of edge Link is leaving (formerly in $06 - used by dir indicator) -; don't need width of edge Link is going to (currently in $0b) -LoadNorthData: - lda NorthOpenEdge, x : sta $03 : inx ; target room - lda NorthEdgeInfo, x : sta $07 ; needed for maths - (divide by 2 anyway) - lda NorthOpenEdge, x : sta $04 : inx ; bit field - lda NorthEdgeInfo, x : sta $08 ; needed for maths - lda NorthOpenEdge, x : sta $05 ; ratio - lda $04 : jsr LoadSouthMidpoint : inx ; needed now, and for nrml transition - lda SouthEdgeInfo, x : sta $0b : inx ; probably not needed todo: remove - lda SouthEdgeInfo, x : sta $0c ; needed for maths - rts - -LoadSouthMidpoint: - and #$0f : sta $00 : asl : !add $00 : tax - lda SouthEdgeInfo, x : sta $0a ; needed now, and for nrml transition - rts - -LoadSouthData: - lda SouthOpenEdge, x : sta $03 : inx - lda SouthEdgeInfo, x : sta $07 - lda SouthOpenEdge, x : sta $04 : inx - lda SouthEdgeInfo, x : sta $08 - lda SouthOpenEdge, x : sta $05 - lda $04 : jsr LoadNorthMidpoint : inx - lda NorthEdgeInfo, x : sta $0b : inx - lda NorthEdgeInfo, x : sta $0c - rts - -LoadNorthMidpoint: - and #$0f : sta $00 : asl : !add $00 : tax - lda NorthEdgeInfo, x : sta $0a ; needed now, and for nrml transition - rts - -LoadWestData: - lda WestOpenEdge, x : sta $03 : inx - lda WestEdgeInfo, x : sta $07 - lda WestOpenEdge, x : sta $04 : inx - lda WestEdgeInfo, x : sta $08 - lda WestOpenEdge, x : sta $05 - lda $04 : jsr LoadEastMidpoint : inx - lda EastEdgeInfo, x : sta $0b : inx - lda EastEdgeInfo, x : sta $0c - rts - -LoadEastMidpoint: - and #$0f : sta $00 : asl : !add $00 : tax - lda EastEdgeInfo, x : sta $0a ; needed now, and for nrml transition - rts - -LoadEastData: - lda EastOpenEdge, x : sta $03 : inx - lda EastEdgeInfo, x : sta $07 - lda EastOpenEdge, x : sta $04 : inx - lda EastEdgeInfo, x : sta $08 - lda EastOpenEdge, x : sta $05 - lda $04 : jsr LoadWestMidpoint : inx - lda WestEdgeInfo, x : sta $0b : inx - lda WestEdgeInfo, x : sta $0c - - -LoadWestMidpoint: - and #$0f : sta $00 : asl : !add $00 : tax - lda WestEdgeInfo, x : sta $0a ; needed now, and for nrml transition - rts - - -DetectNorthEdge: - ldx #$ff - lda $a2 - cmp #$82 : bne + - lda $22 : cmp #$50 : bcs ++ - ldx #$01 : bra .end - ++ ldx #$00 : bra .end - + cmp #$83 : bne + - ldx #$02 : bra .end - + cmp #$84 : bne + - lda $a9 : beq ++ - lda $22 : cmp #$78 : bcs +++ - ldx #$04 : bra .end - +++ ldx #$05 : bra .end - ++ lda $22 : cmp #$78 : bcs ++ - ldx #$03 : bra .end - ++ ldx #$04 : bra .end - + cmp #$85 : bne + - ldx #$06 : bra .end - + cmp #$db : bne + - lda $a9 : beq ++ - lda $22 : beq ++ - ldx #$08 : bra .end - ++ ldx #$07 : bra .end - + cmp #$dc : bne .end - lda $a9 : bne ++ - lda $22 : cmp #$b0 : bcs ++ - ldx #$09 : bra .end - ++ ldx #$0a - .end txa : rts - -DetectSouthEdge: - ldx #$ff - lda $a2 - cmp #$72 : bne + - lda $22 : cmp #$50 : bcs ++ - ldx #$01 : bra .end - ++ ldx #$00 : bra .end - + cmp #$73 : bne + - ldx #$02 : bra .end - + cmp #$74 : bne + - lda $a9 : beq ++ - lda $22 : cmp #$78 : bcs +++ - ldx #$04 : bra .end - +++ ldx #$05 : bra .end - ++ lda $22 : cmp #$78 : bcs ++ - ldx #$03 : bra .end - ++ ldx #$04 : bra .end - + cmp #$75 : bne + - ldx #$06 : bra .end - + cmp #$cb : bne + - lda $a9 : beq ++ - lda $22 : beq ++ - ldx #$08 : bra .end - ++ ldx #$07 : bra .end - + cmp #$cc : bne .end - lda $a9 : bne ++ - lda $22 : cmp #$b0 : bcs ++ - ldx #$09 : bra .end - ++ ldx #$0a - .end txa : rts - -DetectWestEdge: - ldx #$ff - lda $a2 - cmp #$65 : bne + - ldx #$00 : bra .end - + cmp #$74 : bne + - ldx #$01 : bra .end - + cmp #$75 : bne + - ldx #$02 : bra .end - + cmp #$82 : bne + - lda $aa : beq ++ - ldx #$03 : bra .end - ++ ldx #$04 : bra .end - + cmp #$85 : bne + - ldx #$05 : bra .end - + cmp #$cc : bne + - lda $aa : beq ++ - ldx #$06 : bra .end - ++ ldx #$07 : bra .end - + cmp #$dc : bne .end - ldx #$08 - .end txa : rts - -DetectEastEdge: - ldx #$ff - lda $a2 - cmp #$64 : bne + - ldx #$00 : bra .end - + cmp #$73 : bne + - ldx #$01 : bra .end - + cmp #$74 : bne + - ldx #$02 : bra .end - + cmp #$81 : bne + - lda $aa : beq ++ - ldx #$04 : bra .end - ++ ldx #$03 : bra .end - + cmp #$84 : bne + - ldx #$05 : bra .end - + cmp #$cb : bne + - lda $aa : beq ++ - ldx #$06 : bra .end - ++ ldx #$07 : bra .end - + cmp #$db : bne .end - ldx #$08 - .end txa : rts - - - diff --git a/asm/gfx.asm b/asm/gfx.asm deleted file mode 100644 index 94cb8848..00000000 --- a/asm/gfx.asm +++ /dev/null @@ -1,95 +0,0 @@ -GfxFixer: -{ - lda.l DRMode : bne + - jsl LoadRoomHook ;this is the code we overwrote - jsl Dungeon_InitStarTileCh - jsl LoadTransAuxGfx_Alt - inc $b0 - rtl - + lda $b1 : bne .stage2 - jsl LoadRoomHook ; this is the rando version - let's only call this guy once - may fix star tiles and slower loads - jsl Dungeon_InitStarTileCh - jsl LoadTransAuxGfx - jsl Dungeon_LoadCustomTileAttr - jsl PrepTransAuxGfx - lda.l DRMode : cmp #$02 : bne + ; only do this in crossed mode - ldx $a0 : lda.l TilesetTable, x - cmp $0aa1 : beq + ; already eq no need to decomp - sta $0aa1 - tax : lda $02802e, x : tay - jsl DecompDungAnimatedTiles - + - lda #$09 : sta $17 : sta $0710 - jsl Palette_SpriteAux3 - jsl Palette_SpriteAux2 - jsl Palette_SpriteAux1 - jsl Palette_DungBgMain - jsr CgramAuxToMain - inc $b1 - rtl - .stage2 - lda #$0a : sta $17 : sta $0710 - stz $b1 : inc $b0 - rtl -} - -FixAnimatedTiles: - LDA.L DRMode : CMP #$02 : BNE + - LDA $040C : CMP.b #$FF : BEQ + - PHX - LDX $A0 : LDA.l TilesetTable, x - CMP $0AA1 : beq ++ - TAX : PLA : BRA + - ++ - PLX - + LDA $02802E, X ; what we wrote over - RTL - -FixCloseDungeonMap: - LDA.l DRMode : CMP #$02 : BNE .vanilla - LDA $040C : BMI .vanilla - LSR : TAX - LDA.l DungeonTilesets,x - RTL - .vanilla - LDA $7EC20E - RTL - -FixWallmasterLamp: -ORA $0458 -STY $1C : STA $1D : RTL ; what we wrote over - - -CgramAuxToMain: ; ripped this from bank02 because it ended with rts -{ - rep #$20 - ldx.b #$00 - - .loop - lda $7EC300, X : sta $7EC500, x - lda $7EC340, x : sta $7EC540, x - lda $7EC380, x : sta $7EC580, x - lda $7EC3C0, x : sta $7EC5C0, x - lda $7EC400, x : sta $7EC600, x - lda $7EC440, x : sta $7EC640, x - lda $7EC480, x : sta $7EC680, x - lda $7EC4C0, x : sta $7EC6C0, x - - inx #2 : cpx.b #$40 : bne .loop - sep #$20 - - ; tell NMI to upload new CGRAM data - inc $15 - rts -} - -OverridePaletteHeader: - lda.l DRMode : cmp #$02 : bne + - lda.l DRFlags : and #$20 : bne + - cpx #$01c2 : !bge + - rep #$20 - txa : lsr : tax - lda.l PaletteTable, x - iny : rtl - + rep #$20 : iny : lda [$0D], Y ; what we wrote over -rtl \ No newline at end of file diff --git a/asm/hudadditions.asm b/asm/hudadditions.asm deleted file mode 100644 index 575e189f..00000000 --- a/asm/hudadditions.asm +++ /dev/null @@ -1,291 +0,0 @@ -DrHudOverride: -{ - jsl.l NewDrawHud - jsr HudAdditions - rtl -} - -HudAdditions: -{ - LDA.l DRFlags : AND #$0008 : BNE + : JMP .end_item_count : + - LDA.l $7EF423 : PHA : CMP #1000 : !BLT + - JSL HexToDec4Digit_fast - LDX.b $04 : TXA : ORA.w #$2490 : STA !GOAL_DRAW_ADDRESS ; draw 1000's digit - BRA .skip - + JSL HexToDec_fast - .skip - LDA #$207F : STA !GOAL_DRAW_ADDRESS+2 : STA !GOAL_DRAW_ADDRESS+4 - PLA : PHA : CMP.w #100 : !BLT + - LDX.b $05 : TXA : ORA.w #$2490 : STA !GOAL_DRAW_ADDRESS+2 ; draw 100's digit - + PLA : CMP.w #10 : !BLT + - LDX.b $06 : TXA : ORA.w #$2490 : STA !GOAL_DRAW_ADDRESS+4 ; draw 10's digit - + LDX.b $07 : TXA : ORA.w #$2490 : STA !GOAL_DRAW_ADDRESS+6 ; draw 1's digit - LDA.w #$2830 : STA !GOAL_DRAW_ADDRESS+8 ; draw slash - LDA.l DRFlags : AND #$0100 : BNE + - LDA.l $7EF33E : CMP #1000 : !BLT .three_digit_goal - JSL HexToDec4Digit_fast - LDX.b $04 : TXA : ORA.w #$2490 : STA !GOAL_DRAW_ADDRESS+10 ; draw 1000's digit - LDX.b $05 : TXA : ORA.w #$2490 : STA !GOAL_DRAW_ADDRESS+12 ; draw 100's digit - LDX.b $06 : TXA : ORA.w #$2490 : STA !GOAL_DRAW_ADDRESS+14 ; draw 10's digit - LDX.b $07 : TXA : ORA.w #$2490 : STA !GOAL_DRAW_ADDRESS+16 ; draw 1's digit - BRA .end_item_count - .three_digit_goal - JSL HexToDec_fast - LDX.b $05 : TXA : ORA.w #$2490 : STA !GOAL_DRAW_ADDRESS+10 ; draw 100's digit - LDX.b $06 : TXA : ORA.w #$2490 : STA !GOAL_DRAW_ADDRESS+12 ; draw 10's digit - LDX.b $07 : TXA : ORA.w #$2490 : STA !GOAL_DRAW_ADDRESS+14 ; draw 1's digit - BRA .end_item_count - + LDA.w #$2405 : STA !GOAL_DRAW_ADDRESS+10 : STA !GOAL_DRAW_ADDRESS+12 - STA !GOAL_DRAW_ADDRESS+14 : STA !GOAL_DRAW_ADDRESS+16 - .end_item_count - - LDX $1B : BNE + : RTS : + ; Skip if outdoors - ldx $040c : cpx #$ff : bne + : rts : + ; Skip if not in dungeon - lda.l DRMode : bne + : rts : + ; Skip if not door rando - phb : phk : plb - lda $7ef364 : and.l $0098c0, x : beq + - lda.w CompassBossIndicator, x : and #$00ff : cmp $a0 : bne + - lda $1a : and #$0010 : beq + - lda #$345e : sta $7ec790 : bra .next - + lda #$207f : sta $7ec790 - .next lda.w DRMode : and #$0002 : bne + : plb : rts : + - lda $7ef36d : and #$00ff : beq + - lda.w DungeonReminderTable, x : bra .reminder - + lda #$207f - .reminder sta $7ec702 - + lda.w DRFlags : and #$0004 : beq .restore - lda $7ef368 : and.l $0098c0, x : beq .restore - txa : lsr : tax - - lda.l GenericKeys : and #$00ff : bne + - lda $7ef4e0, x : jsr ConvertToDisplay : sta $7ec7a2 - lda #$2830 : sta $7ec7a4 - + - lda.w ChestKeys, x : jsr ConvertToDisplay : sta $7ec7a6 - ; todo 4b0 no longer in use - - .restore - plb : rts -} - -;column distance for BK/Smalls -HudOffsets: -; none hc east desert aga swamp pod mire skull ice hera tt tr gt -dw $fffe, $0000, $0006, $0008, $0002, $0010, $000e, $0018, $0012, $0016, $000a, $0014, $001a, $001e - -; offset from 1644 -RowOffsets: -dw $0000, $0000, $0040, $0080, $0000, $0080, $0040, $0080, $00c0, $0040, $00c0, $0000, $00c0, $0000 - -ColumnOffsets: -dw $0000, $0000, $0000, $0000, $000a, $000a, $000a, $0014, $000a, $0014, $0000, $0014, $0014, $001e - - -DrHudDungeonItemsAdditions: -{ - jsl DrawHUDDungeonItems - lda.l HUDDungeonItems : and #$ff : bne + : rtl : + - lda.l DRMode : cmp #$02 : beq + : rtl : + - - phx : phy : php - rep #$30 - - lda.w #$24f5 : sta $1606 : sta $1610 : sta $161a : sta $1624 - sta $1644 : sta $164a : sta $1652 : sta $1662 : sta $1684 : sta $16c4 - ldx #$0000 - - sta $1704, x : sta $170e, x : sta $1718, x - inx #2 : cpx #$0008 : !blt - - - lda !HUD_FLAG : and.w #$0020 : beq + : JMP ++ : + - lda HUDDungeonItems : and.w #$0007 : bne + : JMP ++ : + - ; bk symbols - lda.w #$2811 : sta $1606 : sta $1610 : sta $161a : sta $1624 - ; sm symbols - lda.w #$2810 : sta $160a : sta $1614 : sta $161e : sta $16e4 - ; blank out stuff - lda.w #$24f5 : sta $1724 - - ldx #$0002 - - lda #$0000 : !addl RowOffsets,x : !addl ColumnOffsets, x : tay - lda.l DungeonReminderTable, x : sta $1644, y : iny #2 - lda.w #$24f5 : sta $1644, y - lda $7ef368 : and.l $0098c0, x : beq + ; must have map - jsr BkStatus : sta $1644, y : bra .smallKey ; big key status - + lda $7ef366 : and.l $0098c0, x : beq .smallKey - lda.w #$2826 : sta $1644, y - .smallKey - + iny #2 - cpx #$001a : bne + - tya : !add #$003c : tay - + stx $00 - txa : lsr : tax - lda.w #$24f5 : sta $1644, y - lda.l GenericKeys : and #$00FF : bne + - lda.l $7ef37c, x : and #$00FF : beq + - jsr ConvertToDisplay2 : sta $1644, y - + iny #2 : lda.w #$24f5 : sta $1644, y - phx : ldx $00 - lda $7ef368 : and.l $0098c0, x : beq + ; must have map - plx : sep #$30 : lda.l ChestKeys, x : sta $02 - lda.l GenericKeys : bne +++ - lda $02 : !sub $7ef4e0, x : sta $02 - +++ lda $02 - rep #$30 - jsr ConvertToDisplay2 : sta $1644, y ; small key totals - bra .skipStack - + plx - .skipStack iny #2 - cpx #$000d : beq + - lda.w #$24f5 : sta $1644, y - + - ldx $00 - + inx #2 : cpx #$001b : bcs ++ : JMP - - ++ - lda !HUD_FLAG : and.w #$0020 : bne + : JMP ++ : + - lda HUDDungeonItems : and.w #$000c : bne + : JMP ++ : + - ; map symbols (do I want these) ; note compass symbol is 2c20 - lda.w #$2821 : sta $1606 : sta $1610 : sta $161a : sta $1624 - ; blank out a couple thing from old hud - lda.w #$24f5 : sta $16e4 : sta $1724 - sta $160a : sta $1614 : sta $161e ; blank out sm key indicators - ldx #$0002 - - lda #$0000 ; start of hud area - !addl RowOffsets, x : !addl ColumnOffsets, x : tay - lda.l DungeonReminderTable, x : sta $1644, y - iny #2 - lda.w #$24f5 : sta $1644, y ; blank out map spot - lda $7ef368 : and.l $0098c0, x : beq + ; must have map - JSR MapIndicatorShort : STA $1644, Y - + iny #2 - cpx #$001a : bne + - tya : !add #$003c : tay - + lda $7ef364 : and.l $0098c0, x : beq + ; must have compass - phx ; total chest counts - txa : lsr : tax - sep #$30 - lda.l TotalLocations, x : !sub $7EF4BF, x : JSR HudHexToDec2DigitCopy - rep #$30 - lda $06 : jsr ConvertToDisplay2 : sta $1644, y : iny #2 - lda $07 : jsr ConvertToDisplay2 : sta $1644, y - plx - bra .skipBlanks - + lda.w #$24f5 : sta $1644, y : iny #2 : sta $1644, y - .skipBlanks iny #2 - cpx #$001a : beq + - lda.w #$24f5 : sta $1644, y ; blank out spot - + inx #2 : cpx #$001b : !bge ++ : JMP - - ++ - plp : ply : plx : rtl -} - -MapIndicatorLong: - PHX - LDA.l OldHudToNewHudTable, X : TAX - JSR MapIndicator - PLX -RTL - -MapIndicatorShort: - PHX - TXA : LSR : TAX - JSR MapIndicator - PLX -RTS - -OldHudToNewHudTable: - dw 1, 2, 3, 10, 4, 6, 5, 8, 11, 9, 7, 12, 13 - -IndicatorCharacters: - ; check 1 2 3 4 5 6 7 G B R - dw $2426, $2817, $2818, $2819, $281A, $281B, $281C, $281D, $2590, $258B, $259B - -MapIndicator: - LDA.l CrystalPendantFlags_3, X : AND #$00FF - PHX - ASL : TAX : LDA.l IndicatorCharacters, X - PLX -RTS - -BkStatus: - lda $7ef366 : and.l $0098c0, x : bne +++ ; has the bk already - lda.l BigKeyStatus, x : bne ++ - lda #$2827 : rts ; 0/O for no BK - ++ cmp #$0002 : bne + - lda #$2420 : rts ; symbol for BnC - + lda #$24f5 : rts ; black otherwise - +++ lda #$2826 : rts ; check mark - -ConvertToDisplay: - and.w #$00ff : cmp #$000a : !blt + - !add #$2553 : rts - + !add #$2490 : rts - -ConvertToDisplay2: - and.w #$00ff : beq ++ - cmp #$000a : !blt + - !add #$2553 : rts ; todo: use 2580 with 258A as "A" for non transparent digits - + !add #$2816 : rts - ++ lda #$2827 : rts ; 0/O for 0 or placeholder digit ;2483 - -CountAbsorbedKeys: - jsl IncrementSmallKeysNoPrimary : phx - lda $040c : cmp #$ff : beq + - lsr : tax - lda $7ef4b0, x : inc : sta $7ef4b0, x - + plx : rtl - -;================================================================================ -; 16-bit A, 8-bit X -; in: A(b) - Byte to Convert -; out: $04 - $07 (high - low) -;================================================================================ -HudHexToDec4DigitCopy: - LDY.b #$90 - - - CMP.w #1000 : !BLT + - INY - SBC.w #1000 : BRA - - + - STY $04 : LDY #$90 ; Store 1000s digit & reset Y - - - CMP.w #100 : !BLT + - INY - SBC.w #100 : BRA - - + - STY $05 : LDY #$90 ; Store 100s digit & reset Y - - - CMP.w #10 : !BLT + - INY - SBC.w #10 : BRA - - + - STY $06 : LDY #$90 ; Store 10s digit & reset Y - CMP.w #1 : !BLT + - - - INY - DEC : BNE - - + - STY $07 ; Store 1s digit -RTS - -;================================================================================ -; 8-bit registers -; in: A(b) - Byte to Convert -; out: $06 - $07 (high - low) -;================================================================================ -HudHexToDec2DigitCopy: ; modified - PHY - LDY.b #$00 - - - CMP.b #10 : !BLT + - INY - SBC.b #10 : BRA - - + - STY $06 : LDY #$00 ; Store 10s digit and reset Y - CMP.b #1 : !BLT + - - - INY - DEC : BNE - - + - STY $07 ; Store 1s digit - PLY -RTS \ No newline at end of file diff --git a/asm/keydoors.asm b/asm/keydoors.asm deleted file mode 100644 index 1ec10c39..00000000 --- a/asm/keydoors.asm +++ /dev/null @@ -1,42 +0,0 @@ -; code to un-pair or re-pair doors - -; doorlist is loaded into 19A0 but no terminator -; new room is in A0 -; for "each" door do the following: (each could mean the first four doors?) -; in lookup table, grab room and corresponding position -; find the info at 7ef000, x where x is twice the paired room -; check the corresponding bit (there are only 4) -; set the bit in 068C - -; Note the carry bit is used to indicate if we should aborted (set) or not -CheckIfDoorsOpen: { - jsr TrapDoorFixer ; see normal.asm - ; note we are 16bit mode right now - lda.l DRMode : beq + - lda $040c : cmp #$00ff : bne .gtg - + lda $a0 : dec : tax : and #$000f ; hijacked code - sec : rtl ; set carry to indicate normal behavior - - .gtg - phb : phk : plb - stx $00 : ldy #$0000 - .nextDoor - lda $a0 : asl : tax - lda.w KeyDoorOffset, x : beq .skipDoor - asl : sty $05 : !add $05 : tax - lda.w PairedDoorTable, x : beq .skipDoor - sta $02 : and #$00ff : asl a : tax - lda $02 : and #$ff00 : sta $03 - lda $7ef000, x : and #$f000 : and $03 : beq .skipDoor - tyx : lda $068c : ora $0098c0,x : sta $068c - .skipDoor - iny #2 : cpy $00 : bne .nextDoor - plb : clc : rtl -} - -; outstanding issues -; how to indicate opening for other (non-first four doors?) -; Bank01 Door Register stores the 4 bits in 068c to 400 (depending on type) -; Key collision and others depend on F0-F3 attribute not sure if extendable to other numbers -; Dungeon_ProcessTorchAndDoorInteractives.isOpenableDoor is the likely culprit for collision problems -; Saving open status to other unused rooms is tricky -- Bank 2 13947 (line 8888) \ No newline at end of file diff --git a/asm/math.asm b/asm/math.asm deleted file mode 100644 index 03cd46a3..00000000 --- a/asm/math.asm +++ /dev/null @@ -1,66 +0,0 @@ -;divide by 2 example -; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10--Offset Ruler -;v 00 01 01 02 02 03 03 04 04 04 05 05 06 06 07 07 08 - -;divide by 3 example -; 0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 -;00 00 01 01 01 02 02 02 03 03 03 04 04 04 05 05 05 06 06 06 07 07 07 08 08 - -MultiplyByY: -.loop cpy #$0001 : beq .done -cpy #$0003 : bne ++ - jsr MultiBy3 : bra .done -++ cpy #$0005 : bne ++ - jsr MultiBy5 : bra .done -++ asl : sta $00 : tya : lsr : tay : lda $00 : bra .loop -.done rts - -;Divisor in Y. Width of division is in X for rounding toward middle -DivideByY: -.loop -cpy #$0000 : beq .done -cpy #$0001 : beq .done -cpy #$0003 : bne ++ - jsr DivideBy3 : bra .done -++ cpy #$0005 : bne ++ - jsr DivideBy5 : bra .done -++ jsr DivideBy2 : sta $00 -tya : lsr : tay -txa : lsr : tax -lda $00 : bra .loop -.done rts - -MultiBy3: -sta $00 : asl : !add $00 -rts - -MultiBy5: -sta $00 : asl #2 : !add $00 -rts - -;width of divison in x: rounds toward X/2 -DivideBy2: -sta $00 -lsr : bcc .done -sta $02 : txa : lsr : cmp $00 : !blt + - lda $02 : inc : bra .done -+ lda $02 -.done rts - -DivideBy3: -sta $00 -ldx #$0000 -lda #$0002 -.loop cmp $00 : !bge .store - inx : !add #$0003 : bra .loop -.store txa -rts - -DivideBy5: -sta $00 -ldx #$0000 -lda #$0003 -.loop cmp $00 : !bge .store - inx : !add #$0005 : bra .loop -.store txa -rts \ No newline at end of file diff --git a/asm/normal.asm b/asm/normal.asm deleted file mode 100644 index 13323d88..00000000 --- a/asm/normal.asm +++ /dev/null @@ -1,419 +0,0 @@ -WarpLeft: - lda.l DRMode : beq .end - lda $040c : cmp.b #$ff : beq .end - lda $20 : ldx $aa - jsr CalcIndex - !add #$06 : ldy #$01 ; offsets in A, Y - jsr LoadRoomHorz -.end - jsr Cleanup - rtl - -WarpRight: - lda.l DRMode : beq .end - lda $040c : cmp.b #$ff : beq .end - lda $20 : ldx $aa - jsr CalcIndex - !add #$12 : ldy #$ff ; offsets in A, Y - jsr LoadRoomHorz -.end - jsr Cleanup - rtl - -WarpUp: - lda.l DRMode : beq .end - lda $040c : cmp.b #$ff : beq .end - lda $22 : ldx $a9 - jsr CalcIndex - ldy #$02 ; offsets in A, Y - jsr LoadRoomVert -.end - jsr Cleanup - rtl - -; Checks if $a0 is equal to . If it is, opens its stonewall if it's there -macro StonewallCheck(Room) - lda $a0 : cmp.b # : bne ?end - lda.l *2+$7ef000 : ora #$80 : sta.l *2+$7ef000 - ?end -endmacro - -WarpDown: - lda.l DRMode : beq .end - lda $040c : cmp.b #$ff : beq .end - lda $22 : ldx $a9 - jsr CalcIndex - !add #$0c : ldy #$ff ; offsets in A, Y - jsr LoadRoomVert - %StonewallCheck($43) -.end - jsr Cleanup - rtl - -; carry set = use link door like normal -; carry clear = we are in dr mode, never use linking doors -CheckLinkDoorR: - lda.l DRMode : bne + - lda $7ec004 : sta $a0 ; what we wrote over - sec : rtl - + clc : rtl - -CheckLinkDoorL: - lda.l DRMode : bne + - lda $7ec003 : sta $a0 ; what we wrote over - sec : rtl - + clc : rtl - -TrapDoorFixer: - lda $fe : and #$0038 : beq .end - xba : asl #2 : sta $00 - stz $0468 : lda $068c : ora $00 : sta $068c - .end - stz $fe ; clear our fe here because we don't need it anymore - rts - -Cleanup: - lda.l DRFlags : and #$10 : beq + - stz $047a - + inc $11 - lda $ef - rts - -;A needs be to the low coordinate, x needs to be either 0 for left,upper or non-zero for right,down -; This sets A (00,02,04) and stores half that at $04 for later use, (src door) -CalcIndex: ; A->low byte of Link's Coord, X-> Link's quadrant, DoorOffset x 2 -> A, DoorOffset -> $04 (vert/horz agnostic) - cpx.b #00 : bne .largeDoor - cmp.b #$d0 : bcc .smallDoor - lda #$01 : bra .done ; Middle Door - .smallDoor lda #$00 : bra .done - .largeDoor lda #$02 - .done - sta $04 - asl - rts - -; Y is an adjustment for main direction of travel -; A is a door table row offset -LoadRoomHorz: -{ - phb : phk : plb - sty $06 : sta $07 : lda $a0 : pha ; Store normal room on stack - lda $07 : jsr LookupNewRoom ; New room is in A, Room Data is in $00-$01 - lda $00 : cmp #$03 : bne .gtg - jsr HorzEdge : pla : bcs .end - sta $a0 : bra .end ; Restore normal room, abort (straight staircases and open edges can get in this routine) - - .gtg ;Good to Go! - pla ; Throw away normal room (don't fill up the stack) - lda $a0 : and.b #$0F : asl a : !sub $23 : !add $06 : sta $02 - ldy #$00 : jsr ShiftVariablesMainDir - - lda $01 : and #$80 : beq .normal - ldy $06 : cpy #$ff : beq + - lda $01 : jsr LoadEastMidpoint : bra ++ - + lda $01 : jsr LoadWestMidpoint - ++ jsr PrepScrollToEdge : bra .scroll - - .normal - jsr PrepScrollToNormal - .scroll - lda $01 : and #$40 : pha - jsr ScrollY - pla : beq .end - ldy #$06 : jsr ApplyScroll - .end - plb ; restore db register - rts -} - -; Y is an adjustment for main direction of travel (stored at $06) -; A is a door table row offset (stored a $07) -LoadRoomVert: -{ - phb : phk : plb - sty $06 : sta $07 : lda $a0 : pha ; Store normal room on stack - lda $07 : jsr LookupNewRoom ; New room is in A, Room Data is in $00-$01 - lda $00 : cmp #$03 : bne .gtg - jsr VertEdge : pla : bcs .end - sta $a0 : bra .end ; Restore normal room, abort (straight staircases and open edges can get in this routine) - .gtg ;Good to Go! - pla ; Throw away normal room (don't fill up the stack) - lda $a0 : and.b #$F0 : lsr #3 : !sub $21 : !add $06 : sta $02 - - lda $01 : and #$80 : beq .notEdge - ldy #$01 : jsr ShiftVariablesMainDir - ldy $06 : cpy #$ff : beq + - lda $01 : jsr LoadSouthMidpoint : bra ++ - + lda $01 : jsr LoadNorthMidpoint - ++ jsr PrepScrollToEdge : bra .scroll - - .notEdge - lda $01 : and #$03 : cmp #$03 : bne .normal - jsr ScrollToInroomStairs - stz $046d - bra .end - .normal - ldy #$01 : jsr ShiftVariablesMainDir - jsr PrepScrollToNormal - .scroll - lda $01 : and #$40 : sta $046d - jsr ScrollX - .end - plb ; restore db register - rts -} - -LookupNewRoom: ; expects data offset to be in A -{ - rep #$30 : and #$00FF ;sanitize A reg (who knows what is in the high byte) - sta $00 ; offset in 00 - lda $a2 : tax ; probably okay loading $a3 in the high byte - lda.w DoorOffset,x : and #$00FF ;we only want the low byte - asl #3 : sta $02 : !add $02 : !add $02 ;multiply by 24 (data size) - !add $00 ; should now have the offset of the address I want to load - tax : lda.w DoorTable,x : sta $00 - and #$00FF : sta $a0 ; assign new room - sep #$30 - rts -} - -; INPUTS-- Y: Direction Index , $02: Shift Value -; Sets high bytes of various registers -ShiftVariablesMainDir: -{ - lda.w CoordIndex,y : tax - lda $21,x : !add $02 : sta $21,x ; coordinate update - lda.w CameraIndex,y : tax - lda $e3,x : !add $02 : sta $e3,x ; scroll register high byte - lda.w CamQuadIndex,y : tax - lda $0605,x : !add $02 : sta $0605,x ; high bytes of these guys - lda $0607,x : !add $02 : sta $0607,x - lda $0601,x : !add $02 : sta $0601,x - lda $0603,x : !add $02 : sta $0603,x - rts -} - -; Normal Flags should be in $01 -ScrollToInroomStairs: -{ - jsr PrepScrollToInroomStairs - ldy #$01 : jsr ShiftVariablesMainDir - jsr ScrollX - ldy #$00 : jsr ApplyScroll - lda $a0 : and #$0f : cmp #$0f : bne + - stz $e0 : stz $e2 ; special case camera fix - lda #$1f : sta $e1 : sta $e3 - + - rts -} - -; Direction should be in $06, Shift Value (see above) in $02 and other info in $01 -; Sets $02, $04, $05, $ee, $045e, $045f and things related to Y coordinate -PrepScrollToInroomStairs: -{ - lda $01 : and #$30 : lsr #3 : tay - lda.w InroomStairsX,y : sta $04 - lda.w InroomStairsX+1,y : sta $05 - lda $06 : cmp #$ff : beq .south - lda.w InroomStairsY+1,y : bne + - inc $045f ; flag indicating special screen transition - dec $02 ; shift variables further - stz $aa - lda $a8 : and #%11111101 : sta $a8 - stz $0613 ; North scroll target - inc $0603 : inc $0607 - dec $0619 : dec $061b - + - lda.w InroomStairsY,y : !add #$20 : sta $20 - !sub #$38 : sta $045e - lda $01 : and #$40 : beq + - lda $20 : !add #$20 : sta $20 - stz $045f - + - dec $21 - %StonewallCheck($1b) - bra ++ - .south - lda.w InroomStairsY+1,y : beq + - inc $045f ; flag indicating special screen transition - inc $02 ; shift variables further - lda #$02 : sta $aa - lda $a8 : ora #%00000010 : sta $a8 - inc $0611 ; South scroll target - dec $0603 : dec $0607 - inc $0619 : inc $061b - + - lda.w InroomStairsY,y : !sub #$20 : sta $20 - !add #$38 : sta $045e - lda $01 : and #$40 : beq + - lda $20 : !sub #$20 : sta $20 - stz $045f - + - inc $21 - ++ - lda $01 : and #$04 : lsr #2 : sta $ee : bne + - stz $0476 - + rts -} - -; Target pixel should be in A, other info in $01 -; Sets $04 $05 and $ee -PrepScrollToEdge: -{ - sta $04 : lda $01 : and #$20 : beq + - lda #01 - + sta $05 - lda $01 : and #$10 : beq + - lda #01 - + sta $ee : bne + - stz $0476 - + rts -} - -; Normal Flags should be in $01 -; Sets $04 $05 and $ee, and $fe -PrepScrollToNormal: -{ - lda $01 : sta $fe : and #$04 : lsr #2 : sta $ee ; trap door and layer - bne + - stz $0476 - + stz $05 : lda #$78 : sta $04 - lda $01 : and #$03 : beq .end - cmp #$02 : !bge + - lda #$f8 : sta $04 : bra .end - + inc $05 - .end rts -} - -StraightStairsAdj: -{ - stx $0464 : sty $012e ; what we wrote over - lda.l DRMode : beq + - lda $045e : bne .toInroom - lda $046d : beq .noScroll - sta $22 - ldy #$00 : jsr ApplyScroll - stz $046d - .noScroll - jsr GetTileAttribute : tax - lda $11 : cmp #$12 : beq .goingNorth - lda $a2 : cmp #$51 : bne ++ - rep #$20 : lda #$0018 : !add $20 : sta $20 : sep #$20 ; special fix for throne room - jsr GetTileAttribute : tax - ++ lda.l StepAdjustmentDown, X : bra .end -; lda $ee : beq .end -; rep #$20 : lda #$ffe0 : !add $20 : sta $20 : sep #$20 - .goingNorth - cpx #$00 : bne ++ - lda $a0 : cmp #$51 : bne ++ - lda #$36 : bra .end ; special fix for throne room - ++ ldy $ee : cpy #$00 : beq ++ - inx - ++ lda.l StepAdjustmentUp, X - .end - pha : lda $0462 : and #$04 : bne ++ - pla : !add #$f6 : pha - ++ pla : !add $0464 : sta $0464 - + rtl - .toInroom - lda #$32 : sta $0464 : stz $045e - rtl -} - -GetTileAttribute: -{ - phk : pea.w .jslrtsreturn-1 - pea.w $02802c - jml $02c11d ; mucks with x/y sets a to Tile Attribute, I think - .jslrtsreturn - rts -} - -; 0 open edge -; 1 nrm door high -; 2 straight str -; 3 nrm door low -; 4 trap door high -; 5 trap door low (none of these exist on North direction) -StepAdjustmentUp: ; really North Stairs -db $00, $f6, $1a, $18, $16, $38 -StepAdjustmentDown: ; really South Stairs -db $d0, $f6, $10, $1a, $f0, $00 - -StraightStairsFix: -{ - pha - lda.l DRMode : bne + - pla : !add $20 : sta $20 : rtl ;what we wrote over - + pla : rtl -} - -StraightStairLayerFix: -{ - lda.l DRMode : beq + - lda $ee : rtl - + lda $01c322, x : rtl ; what we wrote over -} - -DoorToStraight: -{ - pha - lda.l DRMode : beq .skip - pla : bne .end - pha - lda $a0 : cmp #$51 : bne .skip - lda #$04 : sta $4e - .skip pla - .end ldx $0418 : cmp #$02 ;what we wrote over - rtl -} - -DoorToInroom: -{ - ldx $045e : bne .end - sta $0020, y ; what we wrote over - .end - ldx #$00 ; what we wrote over - rtl -} - -DoorToInroomEnd: -{ - ldy $045e : beq .vanilla - cmp $045e : bne .return - stz $045e ; clear - .return - rtl - .vanilla - cmp $02c034, x ; what we wrote over - rtl -} - -StraightStairsTrapDoor: -{ - lda $0464 : bne + - ; reset function - .reset phk : pea.w .jslrtsreturn-1 - pea.w $02802c - jml $028c73 ; $10D71 .reset label of Bank02 - .jslrtsreturn - lda $0468 : bne ++ - lda $a0 : cmp.b #$ac : bne .animateTraps - lda $0403 : and.b #$20 : bne .animateTraps - lda $0403 : and.b #$10 : beq ++ - .animateTraps - lda #$05 : sta $11 - inc $0468 : stz $068e : stz $0690 - ++ JSL Underworld_DoorDown_Call : rtl - + JML Dungeon_ApproachFixedColor ; what we wrote over -} - -InroomStairsTrapDoor: -{ - lda $0200 : cmp #$05 : beq .reset - lda $b0 : jml $008781 ; what we wrote over (essentially) - .reset - pla : pla : pla - jsl StraightStairsTrapDoor_reset - jml $028b15 ; just some RTS in bank 02 -} \ No newline at end of file diff --git a/asm/overrides.asm b/asm/overrides.asm deleted file mode 100644 index c822de5f..00000000 --- a/asm/overrides.asm +++ /dev/null @@ -1,154 +0,0 @@ -;================================================================================ -; Lamp Mantle & Light Cone Fix -;-------------------------------------------------------------------------------- -; Output: 0 for darkness, 1 for lamp cone -;-------------------------------------------------------------------------------- -LampCheckOverride: - LDA $7F50C4 : CMP.b #$01 : BNE + : RTL : + - CMP.b #$FF : BNE + : INC : RTL : + - - LDA $7EF34A : BNE .done ; skip if we already have lantern - - LDA $7EF3CA : BNE + - .lightWorld - LDA $040C : CMP.b #$04 : !BGE ++ ; check if we're in HC - LDA LampConeSewers : BRA .done - ++ - LDA LampConeLightWorld : BRA .done - + - .darkWorld - LDA LampConeDarkWorld - .done - ;BNE + : STZ $1D : + ; remember to turn cone off after a torch -RTL - -GtBossHeartCheckOverride: - lda $a0 : cmp #$1c : beq ++ - cmp #$6c : beq ++ - cmp #$4d : bne + - ++ lda.l DRFlags : and #$01 : bne ++ ;skip if flag on - lda $403 : ora #$80 : sta $403 - ++ clc -rtl - + sec -rtl - -OnFileLoadOverride: - jsl OnFileLoad ; what I wrote over - + lda.l DRFlags : and #$02 : beq + ; Mirror Scroll - lda $7ef353 : bne + - lda #$01 : sta $7ef353 -+ rtl - -MirrorCheckOverride: - lda.l DRFlags : and #$02 : beq ++ - lda $7ef353 : cmp #$01 : beq + - ++ lda $8A : and #$40 ; what I wrote over - rtl - + lda.l DRScroll : rtl - -EGFixOnMirror: - lda.l DRFlags : and #$10 : beq + - stz $047a - + jsl Mirror_SaveRoomData - rtl - -BlockEraseFix: - lda $7ef353 : and #$02 : beq + - stz $05fc : stz $05fd - + rtl - -FixShopCode: - cpx #$300 : !bge + - sta $7ef000, x - + rtl - -VitreousKeyReset: - lda.l DRMode : beq + - stz $0cba, x - + JML $0db818 ;restore old code - -GuruguruFix: - lda $a0 : cmp #$df : !bge + - and #$0f : cmp #$0e : !blt + - iny #2 - + rtl - -BlindAtticFix: - lda.l DRMode : beq + - lda #$01 : rtl - + lda $7EF3CC : cmp.b #$06 - rtl - -SuctionOverworldFix: - stz $50 : stz $5e - lda.l DRMode : beq + - stz $49 - + rtl - -!CutoffTable = "$27E000" - -CutoffEntranceRug: - PHA : PHX - LDA.l DRMode : BEQ .norm - LDA $04 : cmp #$000A : BEQ + ; only affect A & C objects - cmp #$000C : BNE .norm - + LDX #$0000 : LDA !CutoffTable, x - - CMP.W $A0 : BEQ .check - INX #2 : LDA !CutoffTable, x : CMP.w #$FFFF : BNE - - .norm PLX : PLA : LDA $9B52, y : STA $7E2000, x ; what we wrote over -RTL - .check - LDA $0c : CMP #$0004 : !BGE .skip - LDA $0e : CMP #$0008 : !BGE .skip - CMP.l #$0004 : !BLT .skip - BRA .norm -.skip PLX : PLA : RTL - -StoreTempBunnyState: - LDA $5D : CMP #$1C : BNE + - STA $5F - + LDA #$15 : STA $5D ; what we wrote over -RTL - -RetrieveBunnyState: - STY $5D : STZ $02D8 ; what we wrote over - LDA $5F : BEQ + - STA $5D -+ RTL - -RainPrevention: - LDA $00 : XBA : AND #$00FF : STA.b $0A ; what we wrote over - PHA - LDA $7EF3C5 : AND #$00FF : CMP #$0002 : !BGE .done ; only in rain states (0 or 1) - LDA.l $7EF3C6 : AND #$0004 : BNE .done ; zelda's been rescued - LDA.l BlockSanctuaryDoorInRain : BEQ .done ;flagged - LDA $A0 : CMP #$0012 : BNE + ;we're in the sanctuary - LDA.l $7EF3CC : AND #$00FF : CMP #$0001 : BEQ .done ; zelda is following - LDA $00 : AND #$00FF : CMP #$00A1 : BNE .done ; position is a1 - PLA : LDA #$0008 : RTL - + LDA.l BlockCastleDoorsInRain : AND #$00FF : BEQ .done ;flagged - LDX #$FFFE - - INX #2 : LDA.l RemoveRainDoorsRoom, X : CMP #$FFFF : BEQ .done - CMP $A0 : BNE - - SEP #$20 : LDA.l RainDoorMatch, X : CMP $00 : BNE .continue - REP #$20 : PLA : SEC : RTL - .continue - REP #$20 : BRA - - .done PLA : CLC : RTL - -; A should be how much dmg to do to Aga when leaving this function -StandardAgaDmg: - LDX.b #$00 ; part of what we wrote over - LDA.l $7EF3C6 : AND #$04 : BEQ + ; zelda's not been rescued - LDA.b #$10 ; hurt him! - + RTL ; A is zero if the AND results in zero and then Agahnim's invincible! - -; note: this skips both maiden dialog triggers if the hole is open -BlindsAtticHint: - REP #$20 - CMP.w #$0122 : BNE + - LDA $7EF0CA : AND.w #$0100 : BEQ + - SEP #$20 : RTL ; skip the dialog box if the hole is already open - + SEP #$20 : JML Main_ShowTextMessage - diff --git a/asm/scroll.asm b/asm/scroll.asm deleted file mode 100644 index 435b5c98..00000000 --- a/asm/scroll.asm +++ /dev/null @@ -1,222 +0,0 @@ -AdjustTransition: -{ - lda $ab : and #$01ff : beq .reset - phy : ldy #$06 ; operating on vertical registers during horizontal trans - cpx.b #$02 : bcs .horizontalScrolling - ldy #$00 ; operate on horizontal regs during vert trans - .horizontalScrolling - cmp #$0008 : bcs + - pha : lda $ab : and #$0200 : beq ++ - pla : bra .add - ++ pla : eor #$ffff : inc ; convert to negative - .add jsr AdjustCamAdd : ply : bra .reset - + lda $ab : and #$0200 : xba : tax - lda.l OffsetTable,x : jsr AdjustCamAdd - lda $ab : !sub #$0008 : sta $ab - ply : bra .done - .reset ; clear the $ab variable so to not disturb intra-tile doors - stz $ab - .done - lda $00 : and #$01fc - rtl -} - -AdjustCamAdd: - !add $00E2,y : pha - and #$01ff : cmp #$0111 : !blt + - cmp #$01f8 : !bge ++ - pla : and #$ff10 : pha : bra + - ++ pla : and #$ff00 : !add #$0100 : pha - + pla : sta $00E2,y : sta $00E0,y : rts - -; expects target quad in $05 (either 0 or 1) and target pixel in $04, target room should be in $a0 -; $06 is either $ff or $01/02 -; uses $00-$03 and $0e for calculation -; also set up $ac -ScrollY: ;change the Y offset variables - lda $a0 : and.b #$f0 : lsr #3 : sta $0603 : inc : sta $0607 - - lda $05 : bne + - lda $603 : sta $00 : stz $01 : bra ++ - + lda $607 : sta $00 : lda #$02 : sta $01 - ++ ; $01 now contains 0 or 2 and $00 contains the correct lat - - stz $0e - rep #$30 - lda $00 : pha - - lda $e8 : and #$01ff : sta $02 - lda $04 : jsr LimitYCamera : sta $00 - jsr CheckRoomLayoutY : bcc + - lda $00 : cmp #$0080 : !bge ++ - cmp #$0010 : !blt .cmpSrll - lda #$0010 : bra .cmpSrll - ++ cmp #$0100 : !bge .cmpSrll - lda #$0100 - .cmpSrll sta $00 - - ; figures out scroll amt - + lda $00 : cmp $02 : bne + - lda #$0000 : bra .next - + !blt + - !sub $02 : inc $0e : bra .next - + lda $02 : !sub $00 - - .next - sta $ab - jsr AdjustCameraBoundsY - - pla : sta $00 - sep #$30 - lda $04 : sta $20 - lda $00 : sta $21 : sta $0601 : sta $0605 - lda $01 : sta $aa - lda $0e : asl : ora $ac : sta $ac - lda $e9 : and #$01 : asl #2 : tax : lda $0603, x : sta $e9 - rts - -LimitYCamera: - cmp #$006c : !bge + - lda #$0000 : bra .end - + cmp #$017d : !blt + - lda #$0110 : bra .end - + !sub #$006c - .end rts - -CheckRoomLayoutY: - jsr LoadRoomLayout ;switches to 8-bit - cmp #$00 : beq .lock - cmp #$07 : beq .free - cmp #$01 : beq .free - cmp #$04 : !bge .lock - cmp #$02 : bne + - lda $06 : cmp #$ff : beq .lock - + cmp #$03 : bne .free - lda $06 : cmp #$ff : bne .lock - .free rep #$30 : clc : rts - .lock rep #$30 : sec : rts - -AdjustCameraBoundsY: - jsr CheckRoomLayoutY : bcc .free - - ; layouts that are camera locked (quads only) - lda $04 : and #$00ff : cmp #$007d : !blt + - lda #$0088 : bra ++ - + cmp #$006d : !bge + - lda #$0078 : bra ++ - + !add #$000b - - ; I think we no longer need the $02 variable - ++ sta $02 : lda $04 : and #$0100 : !add $02 : bra .setBounds - - ; layouts where the camera is free - .free lda $04 : cmp #$006c : !bge + - lda #$0077 : bra .setBounds - + cmp #$017c : !blt + - lda #$0187 : bra .setBounds - + !add #$000b - .setBounds sta $0618 : inc #2 : sta $061a - rts - -LoadRoomLayout: - lda $a0 : asl : !add $a0 : tax - lda $1f8001, x : sta $b8 - lda $1f8000, x : sta $b7 - sep #$30 - ldy #$01 : lda [$b7], y : and #$1c : lsr #2 - rts - -; expects target quad in $05 (either 0 or 1) and target pixel in $04, target room should be in $a0 -; uses $00-$03 and $0e for calculation -; also set up $ac -ScrollX: ;change the X offset variables - lda $a0 : and.b #$0f : asl : sta $060b : inc : sta $060f - - lda $05 : bne + - lda $60b : sta $00 : stz $01 : bra ++ - + lda $60f : sta $00 : lda #$01 : sta $01 - ++ ; $01 now contains 0 or 1 and $00 contains the correct long - - stz $0e ; pos/neg indicator - rep #$30 - lda $00 : pha - - lda $e2 : and #$01ff : sta $02 - lda $04 : jsr LimitXCamera : sta $00 - jsr CheckRoomLayoutX : bcc + - lda $00 : cmp #$0080 : !bge ++ - lda #$0000 : bra .cmpSrll - ++ lda #$0100 - .cmpSrll sta $00 - - ;figures out scroll amt - + lda $00 : cmp $02 : bne + - lda #$0000 : bra .next - + !blt + - !sub $02 : inc $0e : bra .next - + lda $02 : !sub $00 - - .next - sta $ab : lda $04 - - cmp #$0078 : !bge + - lda #$007f : bra ++ - + cmp #$0178 : !blt + - lda #$017f : bra ++ - + !add #$0007 - ++ sta $061c : inc #2 : sta $061e - - pla : sta $00 - sep #$30 - lda $04 : ldx $046d : bne .straight - sta $22 : bra + - .straight - sta $046d ; set X position later - + - lda $00 : sta $23 : sta $0609 : sta $060d - lda $01 : sta $a9 - lda $0e : asl : ora $ac : sta $ac - lda $e3 : and #$01 : asl #2 : tax : lda $060b, x : sta $e3 - - rts - -LimitXCamera: - cmp #$0079 : !bge + - lda #$0000 : bra .end - + cmp #$0178 : !blt + - lda #$0178 - + !sub #$0078 - .end rts - -CheckRoomLayoutX: - jsr LoadRoomLayout ;switches to 8-bit - cmp #$04 : !blt .lock - cmp #$05 : bne + - lda $06 : cmp #$ff : beq .lock - + cmp #$06 : bne .free - lda $06 : cmp #$ff : bne .lock - .free rep #$30 : clc : rts - .lock rep #$30 : sec : rts - -ApplyScroll: - rep #$30 - lda $ab : and #$01ff : sta $00 - lda $ab : and #$0200 : beq + - lda $00e2, y : !add $00 : bra .end - + lda $00e2, y : !sub $00 - .end - sta $00e2, y - sta $00e0, y - stz $ab : sep #$30 : rts - -QuadrantLoadOrderBeforeScroll: - lda $045f : beq .end - lda #$08 : sta $045c ; start with opposite quadrant row - .end - JML $0091c4 ; what we overwrote - -QuadrantLoadOrderAfterScroll: - lda $045f : beq .end - stz $045c : stz $045f ; draw other row and clear flag - .end - JML $0091c4 ; what we overwrote \ No newline at end of file diff --git a/asm/spiral.asm b/asm/spiral.asm deleted file mode 100644 index e73b5e16..00000000 --- a/asm/spiral.asm +++ /dev/null @@ -1,332 +0,0 @@ -RecordStairType: { - pha - lda.l DRMode : beq .norm - lda $040c : cmp #$ff : beq .norm - lda $0e - cmp #$25 : bcc ++ ; don't record straight staircases - sta $045e - ++ pla : bra + - .norm pla : sta $a0 - + lda $063d, x - rtl -} - -SpiralWarp: { - lda.l DRMode : beq .abort ; abort if not DR - lda $040c : cmp.b #$ff : beq .abort ; abort if not in dungeon - lda $045e : cmp #$5e : beq .gtg ; abort if not spiral - intended room is in A! - cmp #$5f : beq .gtg - cmp #$26 : beq .inroom - .abort - stz $045e : lda $a2 : and #$0f : rtl ; clear,run hijacked code and get out - .inroom - jsr InroomStairsWarp - lda $a2 : and #$0f ; this is the code we are hijacking - rtl - - .gtg - phb : phk : plb : phx : phy ; push stuff - jsr LookupSpiralOffset - rep #$30 : and #$00FF : asl #2 : tax - lda.w SpiralTable, x : sta $00 - lda.w SpiralTable+2, x : sta $02 - sep #$30 - lda $00 : sta $a0 - ; shift quadrant if necessary - stz $07 ; this is a x quad adjuster for those blasted staircase on the edges - lda $01 : and #$01 : !sub $a9 - bne .xQuad - lda $0462 : and #$04 : bne .xqCont - inc $07 - .xqCont lda $22 : bne .skipXQuad ; this is an edge case - dec $23 : bra .skipXQuad ; need to -1 if $22 is 0 - .xQuad sta $06 : !add $a9 : sta $a9 - lda $0462 : and #$04 : bne .xCont - inc $07 ; up stairs are going to -1 the quad anyway during transition, need to add this back - .xCont ldy #$00 : jsr ShiftQuadSimple - - .skipXQuad - lda $aa : lsr : sta $06 : lda $01 : and #$02 : lsr : !sub $06 - beq .skipYQuad - sta $06 : asl : !add $aa : sta $aa - ldy #$01 : jsr ShiftQuadSimple - - .skipYQuad - lda $01 : and #$04 : lsr : sta $048a ;fix layer calc 0->0 2->1 - lda $01 : and #$08 : lsr #2 : sta $0492 ;fix from layer calc 0->0 2->1 - ; shift lower coordinates - lda $02 : sta $22 : bne .adjY : lda $23 : !add $07 : sta $23 - .adjY lda $03 : sta $20 : bne .upDownAdj : inc $21 - .upDownAdj ldx #$08 - lda $0462 : and #$04 : beq .upStairs - ldx #$fd - lda $01 : and #$80 : bne .set53 - ; if target is also down adjust by (6,-15) - lda #$06 : !add $20 : sta $20 : lda #$eb : !add $22 : sta $22 : bra .set53 - .upStairs - lda $01 : and #$80 : beq .set53 - ; if target is also up adjust by (-6, 14) - lda #$fa : !add $20 : sta $20 : lda #$14 : !add $22 : sta $22 - bne .set53 : inc $23 - .set53 - txa : !add $22 : sta $53 - - lda $01 : and #$10 : sta $07 ; zeroHzCam check - ldy #$00 : jsr SetCamera - lda $01 : and #$20 : sta $07 ; zeroVtCam check - ldy #$01 : jsr SetCamera - - jsr StairCleanup - ply : plx : plb ; pull the stuff we pushed - lda $a2 : and #$0f ; this is the code we are hijacking - rtl -} - -StairCleanup: { - stz $045e ; clear the staircase flag - - ; animated tiles fix - lda.l DRMode : cmp #$02 : bne + ; only do this in crossed mode - ldx $a0 : lda.l TilesetTable, x - cmp $0aa1 : beq + ; already eq no need to decomp - sta $0aa1 - tax : lda $02802e, x : tay - jsl DecompDungAnimatedTiles - + - stz $047a - rts -} - -;Sets the offset in A -LookupSpiralOffset: { - ;where link currently is in $a2: quad in a8 & #$03 - ;count doors - stz $00 : ldx #$00 : stz $01 - - .loop - lda $047e, x : cmp $00 : bcc .continue - sta $00 - .continue inx #2 - cpx #$08 : bcc .loop - - lda $00 : lsr - cmp #$01 : beq .done - - ; look up the quad - lda $a9 : ora $aa : and #$03 : beq .quad0 - cmp #$01 : beq .quad1 - cmp #$02 : beq .quad2 - bra .quad3 - .quad0 - inc $01 : lda $a2 - cmp #$0c : beq .q0diff ;gt ent - cmp #$70 : bne .done ;hc stairwell - .q0diff lda $22 : cmp #$00 : beq .secondDoor - cmp #$98 : bcc .done ;gt ent and hc stairwell - .secondDoor inc $01 : bra .done - .quad1 - lda $a2 - cmp #$1a : beq .q1diff ;pod compass - cmp #$26 : beq .q1diff ;swamp elbows - cmp #$6a : beq .q1diff ;pod dark basement - cmp #$76 : bne .done ;swamp drain - .q1diff lda $22 : cmp #$98 : bcc .done - inc $01 : bra .done - .quad2 - lda #$03 : sta $01 : lda $a2 - cmp #$5f : beq .iceu ;ice u room - cmp #$3f : bne .done ;hammer ice exception - stz $01 : bra .done - .iceu lda $22 : cmp #$78 : bcc .done - inc $01 : bra .done - .quad3 - lda $a2 : cmp #$40 : beq .done ; top of aga exception - lda #$02 : sta $01 ; always 2 - - .done - lda $a2 : tax : lda.w SpiralOffset,x - !add $01 ;add a thing (0 in easy case) - rts -} - -InroomStairsWarp: { - phb : phk : plb : phx : phy ; push stuff - ; find stairs by room and store index in X - lda $a0 : ldx #$07 - .loop - cmp.w InroomStairsRoom,x - beq .found - dex - bne .loop - .found - rep #$30 - txa : and #$00ff : asl : tay - lda.w InroomStairsTable,y : sta $00 - sep #$30 - sta $a0 - - ; set position and everything else based on target door type - txa : and #$01 : eor #$01 : sta $07 - ; should be the same as lda $0462 : and #$04 : lsr #2 : eor #$01 : sta $07 - lda $01 : and #$80 : beq .notEdge - lda $07 : sta $03 : beq + - lda $01 : jsr LoadSouthMidpoint : sta $22 : lda #$f4 - bra ++ - + - lda $01 : jsr LoadNorthMidpoint : sta $22 : dec $21 : lda #$f7 - ++ - sta $20 - lda $01 : and #$20 : beq + - lda #$01 - + - sta $02 - stz $07 - lda $01 : and #$10 : lsr #4 - JMP .layer - .notEdge - lda $01 : and #$03 : cmp #$03 : bne .normal - txa : and #$06 : sta $07 - lda $01 : and #$30 : lsr #3 : tay - lda.w InroomStairsX+1,y : sta $02 - lda.w InroomStairsY+1,y : sta $03 - cpy $07 : beq .vanillaTransition - lda.w InroomStairsX,y : sta $22 - lda.w InroomStairsY,y - ldy $07 : beq + - !add #$07 - + - sta $20 - inc $07 - bra ++ - .vanillaTransition - lda #$c0 : sta $07 ; leave camera - ++ - %StonewallCheck($1b) - lda $01 : and #$04 : lsr #2 - bra .layer - .normal - lda $01 : sta $fe ; trap door - lda $07 : sta $03 : beq + - ldy $a0 : cpy #$51 : beq .specialFix ; throne room - cpy #$02 : beq .specialFix ; sewers pull switch - cpy #$71 : beq .specialFix ; castle armory - lda #$e0 - bra ++ - .specialFix - lda #$c8 - bra ++ - + - %StonewallCheck($43) - lda #$1b - ++ - sta $20 - inc $07 : stz $02 : lda #$78 : sta $22 - lda $01 : and #$03 : beq ++ - cmp #$02 : !bge + - lda #$f8 : sta $22 : stz $07 : bra ++ - + inc $02 - ++ - lda $01 : and #$04 : lsr #2 - - .layer - sta $ee - bne + - stz $0476 - + - - lda $02 : !sub $a9 - beq .skipXQuad - sta $06 : !add $a9 : sta $a9 - ldy #$00 : jsr ShiftQuadSimple - .skipXQuad - lda $aa : lsr : sta $06 : lda $03 : !sub $06 - beq .skipYQuad - sta $06 : asl : !add $aa : sta $aa - ldy #$01 : jsr ShiftQuadSimple - .skipYQuad - - lda $07 : bmi .skipCamera - ldy #$00 : jsr SetCamera ; horizontal camera - ldy #$01 : sty $07 : jsr SetCamera ; vertical camera - lda $20 : cmp #$e0 : bcc + - lda $e8 : bne + - lda #$10 : sta $e8 ; adjust vertical camera at bottom - + - .skipCamera - - jsr StairCleanup - ply : plx : plb ; pull the stuff we pushed - rts -} - -ShiftQuadSimple: { - lda.w CoordIndex,y : tax - lda $20,x : beq .skip - lda $21,x : !add $06 : sta $21,x ; coordinate update - .skip - lda.w CamQuadIndex,y : tax - lda $0601,x : !add $06 : sta $0601,x - lda $0605,x : !add $06 : sta $0605,x ; high bytes of these guys - rts -} - -SetCamera: { - stz $04 - tyx : lda $a9,x : bne .nonZeroHalf - lda.w CamQuadIndex,y : tax : lda $607,x : pha - lda.w CameraIndex,y : tax : pla : cmp $e3, x : bne .noQuadAdj - dec $e3,x - - .noQuadAdj - lda $07 : bne .adj0 - lda.w CoordIndex,y : tax - lda $20,x : beq .oddQuad - cmp #$79 : bcc .adj0 - !sub #$78 : sta $04 - tya : asl : !add #$04 : tax : jsr AdjCamBounds : bra .done - .oddQuad - lda #$80 : sta $04 : bra .adj1 ; this is such a weird case - quad cross boundary - .adj0 - tya : asl : tax : jsr AdjCamBounds : bra .done - - .nonZeroHalf ;meaning either right half or bottom half - lda $07 : bne .setQuad - lda.w CoordIndex,y : tax - lda $20,x : cmp #$78 : bcs .setQuad - !add #$78 : sta $04 - lda.w CamQuadIndex,y : tax : lda $0603, x : pha - lda.w CameraIndex,y : tax : pla : sta $e3, x - .adj1 - tya : asl : !add #$08 : tax : jsr AdjCamBounds : bra .done - - .setQuad - lda.w CamQuadIndex,y : tax : lda $0607, x : pha - lda.w CameraIndex,y : tax : pla : sta $e3, x - tya : asl : !add #$0c : tax : jsr AdjCamBounds : bra .done - - .done - lda.w CameraIndex,y : tax - lda $04 : sta $e2, x - rts -} - -; input, expects X to be an appropriate offset into the CamBoundBaseLine table -; when $04 is 0 no coordinate are added -AdjCamBounds: { - rep #$20 : lda.w CamBoundBaseLine, x : sta $05 - lda $04 : and #$00ff : beq .common - lda.w CoordIndex,y : tax - lda $20, x : and #$00ff : !add $05 : sta $05 - .common - lda.w OppCamBoundIndex,y : tax - lda $05 : sta $0618, x - inc #2 : sta $061A, x : sep #$20 - rts -} - -SpiralPriorityHack: { - lda.l DRMode : beq + - lda #$01 : rtl ; always skip the priority code - until I figure out how to fix it - + lda $0462 : and #$04 ; what we wrote over - rtl -} \ No newline at end of file diff --git a/asm/testdata/horizontaltest.txt b/asm/testdata/horizontaltest.txt deleted file mode 100644 index 8d9a7e54..00000000 --- a/asm/testdata/horizontaltest.txt +++ /dev/null @@ -1,227 +0,0 @@ -org $27A000 -DoorTable: -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Ganon -dw $8000, $8000, $8000, $0450, $8000, $8000, $8000, $8000, $8000, $0452, $8000, $8000 ; HC Back Hall (x01) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $0112, $8000, $8000, $8000, $8000 ; Sewer Switches (x02) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x10 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x20 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;PoD Arena (x2a) -dw $8000, $8000, $8000, $8000, $8000, $0161, $8000, $8000, $8000, $8000, $8000, $8000 ;PoD Statue (x2b) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x30 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $0061 ; Swamp Main (x36) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x40 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $0061, $8000, $8000 ;HC West Hall (x50) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;HC Throne Room (x51) -dw $8000, $8000, $8000, $0401, $8000, $8000, $0462, $0162, $8000, $8000, $8000, $8000 ;HC East Hall (x52) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $0550, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $0061, $0561, $8000 ;HC West Lobby (x60) -dw $8000, $8000, $8000, $0236, $00a9, $8000, $8000, $8000, $8000, $8000, $062b, $8000 ;HC Main Lobby (x61) -dw $0452, $0152, $8000, $8000, $0561, $8000, $8000, $8000, $8000, $0203, $0203, $0203 ;HC East Lobby (x62) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;Desert Back (x63) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;TT Attic L (x64) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;TT Attic R (x65) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x66 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x67 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x68 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x69 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6a -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6b -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6c -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6d -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6e -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6f -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x70 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; HC Cellblock (x80) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Vitreous (x90) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Mire Pre-Vitreous (xa0) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Trinexx (xa4) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Eastern Compass (xa8) -dw $8000, $8000, $8000, $04a8, $00a8, $8000, $8000, $8000, $8000, $0161, $00aa, $8000 ; Eastern Courtyard (xa9) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Eastern Map (xaa) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xb0 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xc0 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xd0 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xe0 diff --git a/asm/testdata/vanilla.txt b/asm/testdata/vanilla.txt deleted file mode 100644 index 8f3f4517..00000000 --- a/asm/testdata/vanilla.txt +++ /dev/null @@ -1,227 +0,0 @@ -org $27A000 -DoorTable: -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Ganon -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; HC Back Hall (x01) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Sewer Switches (x02) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x10 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x20 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;PoD Arena (x2a) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;PoD Statue (x2b) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x30 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Swamp Main (x36) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x40 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;HC West Hall (x50) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;HC Throne Room (x51) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;HC East Hall (x52) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;HC West Lobby (x60) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;HC Main Lobby (x61) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;HC East Lobby (x62) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;Desert Back (x63) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;TT Attic L (x64) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;TT Attic R (x65) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x66 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x67 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x68 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x69 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6a -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6b -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6c -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6d -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6e -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6f -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x70 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; HC Cellblock (x80) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Vitreous (x90) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Mire Pre-Vitreous (xa0) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Trinexx (xa4) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Eastern Compass (xa8) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Eastern Courtyard (xa9) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Eastern Map (xaa) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xb0 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xc0 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xd0 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xe0 diff --git a/asm/testdata/verticaltest.txt b/asm/testdata/verticaltest.txt deleted file mode 100644 index 89c79232..00000000 --- a/asm/testdata/verticaltest.txt +++ /dev/null @@ -1,227 +0,0 @@ -org $27A000 -DoorTable: -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Ganon -dw $8000, $8000, $8000, $0450, $8000, $8000, $8000, $8000, $8000, $0452, $8000, $8000 ; HC Back Hall (x01) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $0112, $8000, $8000, $8000, $8000 ; Sewer Switches (x02) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x10 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x20 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;PoD Arena (x2a) -dw $8000, $8000, $8000, $8000, $8000, $0161, $8000, $8000, $8000, $8000, $8000, $8000 ;PoD Statue (x2b) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x30 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $0061 ; Swamp Main (x36) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; x40 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $0462, $0061, $8000, $8000 ;HC West Hall (x50) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;HC Throne Room (x51) -dw $8000, $8000, $8000, $0401, $8000, $8000, $0162, $0660, $8000, $8000, $8000, $8000 ;HC East Hall (x52) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $0152, $8000, $8000, $8000, $8000, $8000, $8000, $0061, $0561, $8000 ;HC West Lobby (x60) -dw $8000, $8000, $8000, $0236, $0160, $8000, $8000, $8000, $8000, $8000, $0162, $8000 ;HC Main Lobby (x61) -dw $0650, $0452, $8000, $8000, $0561, $8000, $8000, $8000, $8000, $0203, $0203, $0203 ;HC East Lobby (x62) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;Desert Back (x63) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;TT Attic L (x64) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;TT Attic R (x65) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x66 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x67 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x68 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x69 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6a -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6b -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6c -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6d -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6e -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x6f -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ;x70 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; HC Cellblock (x80) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Vitreous (x90) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Mire Pre-Vitreous (xa0) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Trinexx (xa4) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Eastern Compass (xa8) -dw $8000, $8000, $8000, $04a8, $00a8, $8000, $8000, $8000, $8000, $0161, $00aa, $8000 ; Eastern Courtyard (xa9) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; Eastern Map (xaa) -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xb0 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xc0 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xd0 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 -dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000 ; xe0 From f4021afac0d3b19627fb35b3fe5eafe1d463f264 Mon Sep 17 00:00:00 2001 From: aerinon Date: Fri, 14 Nov 2025 14:37:46 -0700 Subject: [PATCH 49/73] feat: free_lamp_cone as experimental feature --- BaseClasses.py | 3 ++- ItemList.py | 18 ++++++------------ Main.py | 4 ++-- Rom.py | 5 +++-- Rules.py | 2 +- data/base2current.bps | Bin 118196 -> 118191 bytes 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 6a12f32e..3b06f10b 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -69,7 +69,6 @@ class World(object): self.dynamic_locations = [] self.spoiler_mode = spoiler_mode self.spoiler = Spoiler(self) - self.lamps_needed_for_dark_rooms = 1 self.doors = [] self._door_cache = {} self.paired_doors = {} @@ -123,6 +122,8 @@ class World(object): set_player_attr('bombbag', False) set_player_attr('flute_mode', False) set_player_attr('bow_mode', False) + set_player_attr('free_lamp_cone', False) + set_player_attr('difficulty_requirements', None) set_player_attr('boss_shuffle', 'none') set_player_attr('enemy_shuffle', 'none') diff --git a/ItemList.py b/ItemList.py index 3dce2da3..32da56cc 100644 --- a/ItemList.py +++ b/ItemList.py @@ -266,13 +266,13 @@ def generate_itempool(world, player): # set up item pool skip_pool_adjustments = False if world.customizer and world.customizer.get_item_pool() and player in world.customizer.get_item_pool(): - (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = make_customizer_pool(world, player) + (pool, placed_items, precollected_items, clock_mode) = make_customizer_pool(world, player) skip_pool_adjustments = True elif world.custom: - (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) = make_custom_item_pool(world, player, world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.bombbag[player], world.customitemarray) + (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon) = make_custom_item_pool(world, player, world.progressive, world.shuffle[player], world.difficulty[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.bombbag[player], world.customitemarray) world.rupoor_cost = min(world.customitemarray[player]["rupoorcost"], 9999) else: - (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) = get_pool_core(world, player, world.progressive, world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.bombbag[player], world.doorShuffle[player], world.logic[player], world.flute_mode[player] == 'active') + (pool, placed_items, precollected_items, clock_mode) = get_pool_core(world, player, world.progressive, world.shuffle[player], world.difficulty[player], world.treasure_hunt_total[player], world.timer, world.goal[player], world.mode[player], world.swords[player], world.bombbag[player], world.doorShuffle[player], world.logic[player], world.flute_mode[player] == 'active') if player in world.pool_adjustment.keys() and not skip_pool_adjustments: amt = world.pool_adjustment[player] @@ -351,8 +351,6 @@ def generate_itempool(world, player): if item.name == 'Bomb Upgrade (+10)' and item.player == player: item.advancement = True - world.lamps_needed_for_dark_rooms = lamps_needed_for_dark_rooms - if clock_mode is not None: world.clock_mode = clock_mode @@ -946,8 +944,6 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt else: pool.extend(basicgloves) - lamps_needed_for_dark_rooms = 1 - # old insanity shuffle didn't have fake LW/DW logic so this used to be conditional pool.extend(['Magic Mirror', 'Moon Pearl']) @@ -1048,7 +1044,7 @@ def get_pool_core(world, player, progressive, shuffle, difficulty, treasure_hunt pool.extend(['Small Key (Universal)']) else: pool.extend(['Small Key (Universal)']) - return (pool, placed_items, precollected_items, clock_mode, lamps_needed_for_dark_rooms) + return (pool, placed_items, precollected_items, clock_mode) item_alternates = { @@ -1152,8 +1148,6 @@ def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer diff = difficulties[difficulty] - lamps_needed_for_dark_rooms = 1 - # expert+ difficulties produce the same contents for # all bottles, since only one bottle is available if diff.same_bottle: @@ -1213,7 +1207,7 @@ def make_custom_item_pool(world, player, progressive, shuffle, difficulty, timer pool.remove('Fighter Sword') pool.append('Rupees (50)') - return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms) + return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon) def make_customizer_pool(world, player): @@ -1357,7 +1351,7 @@ def make_customizer_pool(world, player): pool.remove('Fighter Sword') pool.append('Rupees (50)') - return pool, placed_items, precollected_items, clock_mode, 1 + return pool, placed_items, precollected_items, clock_mode filler_items = { diff --git a/Main.py b/Main.py index 197602e2..5a67ca15 100644 --- a/Main.py +++ b/Main.py @@ -171,7 +171,7 @@ def main(args, seed=None, fish=None): world.finish_init() # custom settings - these haven't been promoted to full settings yet - in_progress_settings = ['force_enemy'] + in_progress_settings = ['force_enemy', 'free_lamp_cone'] for player in range(1, world.players + 1): for setting in in_progress_settings: if world.customizer and world.customizer.has_setting(player, setting): @@ -494,7 +494,6 @@ def copy_world(world): ret.can_take_damage = world.can_take_damage ret.difficulty_requirements = world.difficulty_requirements.copy() ret.fix_fake_world = world.fix_fake_world.copy() - ret.lamps_needed_for_dark_rooms = world.lamps_needed_for_dark_rooms ret.mapshuffle = world.mapshuffle.copy() ret.compassshuffle = world.compassshuffle.copy() ret.keyshuffle = world.keyshuffle.copy() @@ -502,6 +501,7 @@ def copy_world(world): ret.bombbag = world.bombbag.copy() ret.flute_mode = world.flute_mode.copy() ret.bow_mode = world.bow_mode.copy() + ret.free_lamp_cone = world.free_lamp_cone.copy() ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy() ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy() ret.crystals_ganon_orig = world.crystals_ganon_orig.copy() diff --git a/Rom.py b/Rom.py index 04987530..ec343ee7 100644 --- a/Rom.py +++ b/Rom.py @@ -42,7 +42,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '1e87ad01a54f1c15e2ec16a79a9bcc20' +RANDOMIZERBASEHASH = 'f327962e7f2872c80fd75b35c6f2c985' class JsonRom(object): @@ -811,7 +811,8 @@ def patch_rom(world, rom, player, team, is_mystery=False): rom.write_bytes(0x6D323, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E]) # set light cones - rom.write_byte(0x180038, 0x01 if world.sewer_light_cone[player] else 0x00) + lamp_cone_flags = (0x1 if world.sewer_light_cone[player] else 0) | (0x10 if world.free_lamp_cone[player] else 0) + rom.write_byte(0x180038, lamp_cone_flags) GREEN_TWENTY_RUPEES = 0x47 TRIFORCE_PIECE = ItemFactory('Triforce Piece', player).code diff --git a/Rules.py b/Rules.py index 5d059a5c..19dc9922 100644 --- a/Rules.py +++ b/Rules.py @@ -160,7 +160,7 @@ def and_rule(rule1, rule2): def add_lamp_requirement(spot, player): - add_rule(spot, lambda state: state.has('Lamp', player, state.world.lamps_needed_for_dark_rooms)) + add_rule(spot, lambda state: state.has('Lamp', player) or state.world.free_lamp_cone[player]) def forbid_item(location, item, player): diff --git a/data/base2current.bps b/data/base2current.bps index a287a08d9090504aa003b5e346d481fe5fdad888..f2b1f9252dcd8bf45d222cc667e40bebec06f83d 100644 GIT binary patch delta 7371 zcmX{*d0Z3M^O;4b6DxS5dup3xl!I*?+SRg=F zt`H~&2^w##)e5b)v|3xM^+2nX>QAiLDn0x?`p1{gXLsJbnVrvM-pst2p;K>T*4wn7 z2UvuDe4q`66Gn^MT|+qeLdq8hZsU;T9h_9T;t z@*gpN~Bnbs0}EpHq- zA($;yu4Mo_ED`RR*wU6Vk1T)~^q1#NV9YN}{2$qdk(AzTwc{an}% z>xpujBjWDY5ltxFJ7R&|7hHvoNY-$@e(b7(v!(aC8N78tys6&+^& zLIq>5!Y?Szcbi>=1}jrFiPRB`&{w{p2}?9w1Jh#U9;paHGbf`|#5fJdqo|s_g_J6Q zq6sg9RQV&NnnzKpldPwP$*HIJ7f>}CszyTA5J8qn=nx61pIPUN3RRO(Y&^^bE~S<0i-;acZ>iWFkmLZymOBicV32+JS-Dj1z;;T}Es*p=i7@S2jg7h#E{TO6~QHTtl zK2CLwBZb7cuepAT>eUg;3OS9yi&PPgYGbuZeh1wOJ~d&ynd_#QvyBYl@@pL_SolxP zD(rZd&D@}H;I)cSJ+7NaQcN?&V6Of6+uP{#kbF3U-U*EouRO`!sreA?4^6~IxfqIU zZ&|p3R8mVgp|xR$Bv-F;<0&1Ew4t!;qp>c8yob|NVs(gtuehm2RAE*@C1F7K!vmc2 zahxRM5GbY!Wu%EXjoijhaM^Z^W25$!&tq8onH866i0f$Ocp3bGJ{}+J>URl;$fx>H zUwpV9Ugr9-YolZ1-Q=i)YntbPH#6?nec|1pBHrGw`|*e6k(5_WC9&%m{z%i#eBRE@ zBir#x2J`>JN)w#3BG! zv@J3kryMTw-7y~(as%ymOe$Mf`GPAA14RF?tY~KG!5ZQ~jg84EI0eT<=GR>_oT!sDk#}W`^dRIipO716jpNUITdlJpur0}+y9|!vt+h3ah2WT+@Yb+@T~Dk4=TCVXwQxi z(y}u@wMaz-V__PKw8yz`_hD{eBsXHf9V1p@AlvbfD8g_CNv)4Qh_hokw|;7gPJRP@ zlpyn~#FVS}V01=%nkN3$N4(R~ts{P~A>P3h(21Nr7F+(5~KmOdHr&$syS2Qn9BCJ`yyPuJGR{gr6nyp44fae*4yXR7*=oQ zP#96f{A(%Q9tcipZCusDz@HfmPZTm~sB6b2zo}*1Kqp04u(PJ#t!8q{xMr=2_@IoF z*KKVP5;AC$i{3UZNU=QNO`XZXDp1@8)n)o9tS zx9}TUwmZ#sD;xYSH?M%%YH8cO7$C>;_nv3?MnVI7_u*f&@soe~A~V{UV}!-Xao=cI zfkO6$zzR#+J^?u5oX^^M)mKxs8k(p;8}|3YVH9&<8#to+14}?{d3iuD;1}pDTI!4# z9$6L@Zv{_3Qv54lo$xYOVZM}_*XwPbO16hO527y_YsTY3j_9~uM=bcEu9=f9Ty2 z^j(aGmX3U@F-DhCt1v1k8bKS3(jr@G^?$h5)zYU56^t|EdwMK+1lyUkCmggK>NRBK zQ;Loa{*{yhZ9-w%X-=dF+unk!)vP@&*MdyHP)yJZpQ-S6j%g%`8_l zFsdsTgD}^wG7L7mb~Rzp;@Wk3gy!1y^$5+at8awn*7e5-&8 zHxoW#JmNQWctsqdCq!BzW4jGUSZ!6GzLwQSkq4%9o1>?89}1$P$W3U1ZZ_;fJ9QBd zh>qyo?59_8B8N&IufJcv0O5KM*Km(?i+#uYcYjNg@qIEgO}6)t?J;JAJ>Jz!t6SJb zIVi1s>eNm8o=l!bkkYO1k&eLN>K+(@h1Ho-c7H&(11XvMYro*Jlzd6sUwGRq<;0DS zUY`V^&&mVw#r&jP>At9jGpD8I^}NOI@AryU)bSP$EkwEOuJGS#`(&)$n(HEE#W(9y z^RU?8YP+DP9kc$of-}LfL^Lv8ud$ZxA)V$&5 zi_!Ja(v@l8T4dRVoMF~w@1TB1!t2jcy3zBBV7K9V4tW()D_fP+UwS2#j^W=Ztg>)+ zo1tXTe&Nt>26crCIqwfzQM$0Tk?XPT70a$R$TI6%&ykM3b_<8>xuM`!a`c*3)VndJ z3kJ+aJQ=E$y@Os7kOU852HNPiBrx8?GM|rR$Tu=6dz(RFRPKqTayI>@%#LSD?Q}x#+i}(|TXX zMz{1cU>JE+Z-Eq4P`xK=Y}6x**Pgq_v9*3mFHygjnpel;c&uYwfeBkmBnxRIg*|+O zmr@740$B(OtqHadY0MdJU0*-y3X_tA+8_;3BHCV5k4Q+Cs?ru}Go?Ht^m9jFb4nW(WgNHoUiW0axZ+Od#^ z{;$>-H%$(PY}YYbPEnq?P>DWcWX5K7F(W&KG=}gol4g#yITy_*40r3Y6eFYxOJ9^or7c~rS~yjIYS*7A^2kKEhu%99?|!>k zeZ2I2l6n4fvw8!0?h7$?=L}>yGF~ihB?YoK=$9jYW45^dbS|$l+ewiuA(~n_4I%Su zHO4JdqAVn8 zO)IA`#n9dCjBAXYIhniI+ z2~FNujJzqt$9?VJ-*;X7u`X)IQ0}0xPv)iQ^HUtP7haSZd=b|))iE#RZY?i{RMAq> z(VT!DH*J9;wA?sRdce{n)WCFw>;TdjQ{g@Iz$o)w6+yBdHMGL4UPm6sNkBUo)>AeZ z)Pn{I)*%v&YYu`Sl+-+p4;n-@M|nqWEI3`;BO`J&oV=#9&^#NTf=v$$N(^%JRdWnn zMsJ(vxLrHWT@wg;XXpdN{?tw~Ns?RHY_!6pg0bkKX*|x-&Mp4#>rQYA^|qI}Kj||` zYMWYF+FVI^pyZZ!V5~*cG8Menok%wE)RR;5*sUb%DZN$WV2&Hg9ixt8W$0mR7_756 zei{vYxP%hgMhAM&=8;SX&G#q0=I}_JxjZ#*`gFBQXEM+{lQNFPQ;d`sD7S5l1d@2< zLZvtfaczDugf6zN7R6so!D3`b--Q>Jy+NM~6N}Eti4VI;o z>idj>bFcG??_;1FSAS@B`v&+5HMBF4A(uJQ?V`-Q-?G_xfSGogJN?m|GAfdl|!c5SdqWQggQg(n+59l^e#W8P?`P~9TbXTAGc zt9z&-irL^*udy?aRewMtCrg}jw@!ZUq@Ly(LcHEkp6pH}x9oD?(W7YO$&P-h=t}rJ zmuUT0Y4~7FGkRs2F-AWt^c9*J`bz%}hDo8X%JbG-u5rd;yaUB`Ho{T#pflRx;mUKP{}_XF4FVnp@QQn>9c0Os#<5OD`_{hn3eSNYpn%lC0aW3 zRsFJ=ua0)(jj95=Po~d~dqs~rUY6hLiu=j+jXWc-%d#MfqAx~QxsvqkudA9$Pq6L@ zuSS;p78S8!jxSNziCM4#Z9cKV!P?7dq`eYz_4(Xyj-y*AHi%kVmA{%$f_0p?sh3lG zlch6B)$>-o+(}Yr)u$;lz6{$?j@3tOX`QU3j-hJn`*6SPWG|jheS6Z?c4sujY-@>GN7R4Lmwbv|pCQCC)2XfS7Rk=;#C6Z%v+u(~^!jWph%8a(ya0SH z$>(o6z*Eb(t3zTR$M~*}gd1hsGj)ybJc8%Po5x$sySOV;hu}R+)b+!BseJy==S8DV zxRP#`Yu}HP!2h9VKL^7*$o+00grm5-vv8TR@2)o<`>}U3AQHX0yKZd6qN49LE-fR; zs@W;?Wv&`ODWaPu-UajCMQHoIFkGiq-}B=OTv6A(KGE*%B6b35y8qm9`<|kj`{n~L zai||?m7)3v3jTpT$hj{9)>>xv&E(_e>A<5X*llThv;w4~PH`qs{mLiWEcTD%!P)7P z;zsqh)V%ewlAje4EOPaeAlzt?PvXHFoqrM~TeP;Ab{<9(5PEmoFEu89GU+&M;v0gO z7ceG4vSBZB=nv-SuCv7UKL^M_K?5JS$0U+k&qhvkgbl;19)ZSxDjSHnf#VU&WW_2| zF71HaOQ~&$r94<$-><%v;&${L?*apZt7It;+n34CK5Spi`Xc3TX)qq$_-#9$F(f^G z41gk@g-qQ#tC$KjtUQh8PQ(jb_5`Yx>YRKwB%+uKVr|Y)L58q1$TJ3Gm>8s1GC@PR z?EZ;J^=twl*H0ON!b*B0i3xU;yY9(g+t+L-w2 zd92f0W*!cw=?Ns8IzSJ4d?!mZQVK)PMl^LWiOdWXuqSHa!^Sn9pn^-x=%3}*oy z)vnqpP?QTpbn0n+)OaLg=kp=bBmE?YyUAd~-sD3MOKP@K?R3hp{1aBihbPj}?-i-O zDW}?5KAS6mJCY3tZX$TB4`w$AAp-tpH9}Ycw(Mge zz3gop7%g&Nc!(9UZ)|{uQ*53D!m+Zg5*QzmMx(<_NR~oQTW5%E#ZsWySHC}j`$7wgOh+=Mu@L`&ny_zhpg7-vT(-4T(J z#;8Fdp|`%3!ZrXucAGsUf{*pMJzNF1`I`?Nv#V=F+-qmqkEP`7>GeA{vpPpObXvN0}$Yxn_QR zh!X0RfuuMs&&21^Lc*8b=?P2SriH8NvjbImsHS8Ak)>~-?b&$tmM8ebdiEbrNXA+v zdBG&e%UG$RdxJd4$qv`}#XcX`8a|vq(6l{;QStfw&>&i}h++5688AA?e`UJJ-}M3W zpHN|c#ieLa_$Lq1C@H>3>(Y{{^$v3>%7oSxQgiDgy(orHdj6CqD6e0&R#hW17yX{A zFv;}(YgKKDKS@S^8 zVS#x2#wvElht^xkKnq5Br2JV!WEU9a?xo6d@p_V#v)L(d-o`%a52~NtX`Q?XlKE11 zhbl%!GKO7ytwl>f53rK;PlFU#Zp}^uHNfc;%U}xlDE#%NLD7im6lO7LWcT{(*(IGQ zVqB$u4ZCbPj<{g9a5>C|*=+Z6hy}#HT@Hl%ntfHYMqD2J(d`<=MOhC4z4nF!*4P!W zh3`CNbX8+}yRgodtPy*}62BjZKH`c1{PXw1Z-qV@0bk+mR0QMtSn}TFjNl zq75Wv&+g#sS(`PG1zXwdH4x6sMx}~ZH6LnWve%X z83%BR0{h5BcAo+!I>l!f>mHXqE^Ey~F(qt<^{fJZ@D%MM&Y=&i75Nb3BnpUoz(!ho z%b-0(G$o_ZAhyzHV1bbDn8beD1OAF5V;9>g!MZs^jRVW!s?7Yw<(Amuu3huCjYLX~{-|ae`;=0&h ze55m0yObfc#Te$6jx}v88<~MnD130gk0|($M;7|rxMA?Ov*r7a36&yK6gu!diF-vZ@U;!anMc9_= z+N><+Yt9z1L&V>OU02m|VnP9%PEs}66s>ZdqKP)k*}GKXQL69@lJ1kU+EA50^{Ai? zr4glamWX*;N7O=!SJ(pHb+)pch*hy>UuI4I`I09+G@iPoT%qVxvPVin$Xm)8mF0RK zu?5&l+M;4%a~pW&Rl>&3bW*pLx~m{Yw6JXo!WO>u3U!~+$)2DJPt%sGtOsQx&QmM2 zGM4TH7w;gn8e+UBqMNYI`>4z3*VrVI()3WZ?3Z3MsfJd91EWU=%=x8*C31gIoSEt8Nmv9yU<7+-W=!vZgM1@S@0iYW!*u3|Y9Rr5swrSPZZ zgp*bzdq64TC`xgfaaYk<_3}gcRE>(N5t22;7~>?L9)ud<|HS_G<5g^(0}q?viAEv- z#`}uVH?YKajn~dj@QWuanUwY95jcFViZw)5w6!=er|DgA#dkgGH2M+^Q0%`_}Jc?~KCFCRX&asw(_=qVFav$gd(8cpU2QbP#(+A~yOWsz6NYi4GVs zZi4fs+bk1)up*9T>}FP8ts!p0ig9A}E9@N?lsoDwc8U|4kTLi;Ke@*CV`FY-Evibj zr2R&NB~C_r+^WMyTGGKDkF&=zsZZ;!do?JCk5B6!e79mem7rVuvbXF?w;;QoyLLehNtK-wqaLNPR!G?>DZ3E^A$vrydjpN$bL1U1UBue zX{?-2Hu4o5ZW@tO#ip?eqBOt30~^~5xH(H~uOO}h%lK>sg?XYF24{^+_`Zs5*{}v$=Cv~LiF7E=qlvR4Mlg2hPl%bx(>g@6}l;V*c}>5IS3=09#EP# zO4Cmh*P$rh*Z)Be-Xx_tN@*nIPm&EcSWEGO<~}j;?ptgDmh?sG2}B&+j;})=#vKXQ zf}^%wWz%$?b4%h#h|9b;2?v8pSn7Q(jid@sm;!y2^6$sG6yyx`1%~qefUj z*TB~8k5QI!;f}G$>Bp9OyWAS>+AS=MB?{?3jPjiU$Z>uvTfH#g5shhA0X-ki?Aq)b zQN~(2DS0I`YwF{p^sX|tNsaBbjFsS%vnx^%>tXKhK-bw=%5ro#D$#c}{Ln|26_3Wa~oNMzI^APxqjMaG2(dB_20 z3C7l={wP(ek`pSB95SQB5SG0i37{r>2`V(c&ergFHRDyrV(Od#{b)=m+J+nvDR{+I z#=gyw8m=bin&BpGN_||w5*8eTm_oEZuR9;XHCqvnO4uf{TSzQ@Qm0BtOfhhha|f)6`~o&944xEE zwiQ_QQ-5k?tpegK_>_!9PB5ip#fV2GH}WqxdSOYwLN@7j0dWnEmWZ)CUMQI_xKz~J zr`rg2hb8C|Y(5+s{-8v&E1w#9E{dd_p2!prN_wqyK{9Igvn<)U&+~_Iur66n&3Ps} zH(#!J0AC)CcEXb}I!Qhik0)1R8L(3<$+a!*jnqvqrk3JKYqbJHYn_9dTJ}GfG7Ohv zxL-BQ73gwQ)CvsIzrrCpp_*FxKX_souKFK*JPcQ37*aC)Ta_-Ngj$0kuW%SP=tPA! z)Y^Zs+Sd3?5yJD);gmj_Jcjj5+7VW27R=hzJWATJ!LN#v!deJbM?1bLW6jT{_-@De zZMvl4z;5+svt-g|y@6qCEF-%2VKUaGyBL!#F5R`5G`nSMs;bdl1k3l@Or!v>XY`2;aPAie0ooffyZ`cvL7T@Or83vrZ=6V;w4?u^ooY5&(U5q zOmmK=iZ^X<3laHNZg=UUS;Pt&9Xt+S#3A!ZNsAf4mrJT-y~xf;U#?s z-j#EZD|}M0h-Iq4GoS{dZ}dp$m}0%}!@jC!k) zQ7M=XLP%A?>_%YGa2`XTw1cQrIGEmF$=_38^n^jmJ6hV*>>R|pB)T( zCxQ2JX}v40Kdr@L#LK~2@hljq8awta+snnfn|iF5hsjsRdiiFQRX$xMP7l5CpI;RGhvoy z6gmZKHHjXP9{uHt@hIt4y_TEar(GPEuenV*Yd(cDnlUI19%!bc-@)x@CW?c+qx-_` z!=D>H_B}p@Rq`;USovvkZXJi^Fgerm^;jKNVsRtM@8xPeWaY@r6N@3ZCdf|Qm^IXr zRzKnfoir2H)qH~T;att)h|M}Z_hF&|FVUPK7V9AESv(m+nysJO4e-Q8$9wwmUt03< z6~`sVGmdXPz6YXf=iuV(P;C&J0u8l+RwHz-IuH1!b~Ks|uWQGkabTz2;W9$aN-N?Q z%HT3B);1}NXmJ53wV|GzCYH3m5Wyw1kLxm|!>meh6_D-X)5g2nXe9o*nZ3qW@%qVk z-M=)m6&YJfek&G+(2HqF2MG= z5;~5J6a3Rm^2EQv^JBiAsV)yMPVwTHb4fxc}K(&xs7lE9i zv~C$LyMC&hHJk|R1IC{>v8`A6-}sVk0~*^|^7dZq0Wacf6D!q6%6pjUw`p5LD3ffR zU!}K}5?{lfdIH@5rar;J$DgDIAl8@E>m7+3@N<0t@&f0EAntAsOl$DmS9jZSvB)?V_K1@mHG4sjWf~=wQ>+Pgs%y^eI z#EPX4S!6gAjElR7A0pR}{~pgoxv*R}QMA|C%U7XkQt@6;>XPvlQ(DTp)p^Y5qft*K6ArW6 zHlQz|p^Y9dzQ&TSSHy-x#uO(DJ>eRAcI%unDuvl@Z~1Ps%rw=>qIS*rIU|M1oiEpI zgLUoxqIox@y6JEe#K*sqcE^61L$v%O(|+#R1lxk& zY4!)dgMFChV)~PDx~L*|-L)Dg?8aLlsEE4i+{QBql7MYXg{mQi}BG<}A9Y=4`~qpQA_8gAiR zu9Gr^RN(aHz-ZvJ2#U^pn*&?n)#)E`gXsF1FsmuN_sl$ae(-!vn=>7p?|5)`rWr%;9N~(R=0Cb#VyR=9)E&nz|tq4 zT;XEKd@>eIhRP?t+}$JK+><^ltDS|6FVsDKzm2Nwb6m+;kbLJf4&llL}yq%QoQ04jYi>%8OX`!KvAP|dvb1?xcHG&h?iXX zG7u%fp_emoH{k5caB=GTBDvELOaPb{{ofirH<5H0(sQ*zEAnYQFHxHTHvK_dhcx5F z{x=9^0%7^w4Y!Zf?v1R~F~$>*dU-0psf-&OwVVq3OkAYU=g95Bt%TYR3^kHDF#6`V zB3!>-;9R27z#4JVv$o~p^UvBAGY*jR^HMY&%s=nMTbc9A3!D{0UI$OjnN>suXjh$u z5m}Rp*vEBQ5JlGS|K5k>tfu8niSVWopRXP%mn7$AXyQe0 zsYJ&0VE=37=NJ=N_%dQRjH`<$%HeOP0c$;18OP-QL&ssy8XHS8$rky*$o~k%@j6PX z6>Wk^0}0$+o8Ztu1oAVs4t(NZpDih_N-b~f@z~5^Qef1_5YhJ8#R{V0zocfqG3nzD zuJ`tcQnjtLhP5p#sTysl$9c>38=GF`28BVmm3e^BGOx`prLBEp97M{gHpOn9w1OX8 zt_oL~B^xMmyGCQllY>||&zdMOI|v{3O)1=YrkV6u4V zN8z&U`+#0(+?n-!6ov+w!+f+7jbi%vC=bnNHd>)}~pcOB3sZR+1%`x-ZKOJ}n6*xnZ$pr3tov51th^Xa>q;X4;@A!KkD^{!g-=IcS4? z&?-h_gCuAr^WFvppv}w}5sIGqyp;_el2*)ET619rO-hNd)2zhwElc1J?4Cfrw$i)G zou!RVy(7%;(w(LM^1N`%3nz6UWH99-6dCE^QFu&nl69<&v=G=Y)Yp?EaT)NY4vA=kBAO51Jg8i9T9Bz{mr z&Yo7!l`?7vbjEq9bqVFFt*^4JTM6vnPFVTt98t9(dXhpboMigoh{o~IZYJ0Td7}hV zybJn)hk_YjcNF8YXMZWh*T@1$!O~nkmm}vBBbn{)XqoH$P^J95r8*aCiWd+Wng+QY z6UN+gM}8=o`O6(8;$6-0K$B2z<|>8U95|AkY=4_u-Fb)dJf^ro5Shp(JtSvIOCy7`xlT_A3xTm*J~G;HhH0^HeLrlQ+&(g=qKSC zRX>8Oycm;{=14knJ3^U>rVRn;Yh)colv0D53{zAPYP1#ab}Lj^aRzL(>#YjE7xam1 z&Gu=1;znn)x4wc!M6T)YiD(GfOLr7hnFllUGsxMRIVRp@G#;UB6YhzwMM%gTjzS@5 zm8mNVIoqLwrk=TIBtl~5NgVprHQHKD1vAt0KwzV$Mlk`-YD1uDMLcrhardofHYXx4 zw1$xMaId6m@>CYNsN4`$tRwAnqq>;>4W@{3A5=f{nQ6iz zl*knY*jLkHlGgGMnDUk&4MGWw&r+0x(oI{JA|*l{roWe=DCB+6Pop2O8dkB?ARu*& z&|kwW>4X_RRhos&k`>rjqZru=G#lIJ)fH$8Dq%jXK!lt0V6|K&s0iBnLyh!`xR*d? zJ8hqNzjr^&Dy_2SgP99WB{qXkUYS~SMB{s=qV6bbog zMjHQ>f650Clgjk3MN?emrV2=rHCl6U5pAl_I|mzF4>1ubXs4}DcC~syAayK zU~E#c(@ka$q@qBymSIzo8yd-UrQ+D&Z@Qm~h6JJ{-k)6=-Y5OY(WZy#D3a&svr4O$ zbGw7vG=gHfsQg9Qi?Wssh%9CnnM_jjox7E--vz)yD-T6FTDivj#LP6^EJJO@>YMrF F{{uxx<%0kK From 3e9070f30d30844fdf80d03ef04bf517bd492a83 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 18 Nov 2025 05:47:14 -0600 Subject: [PATCH 50/73] Added missing entries to OWR vanilla preset --- presets/world/owr_vanilla.yaml | 143 ++++++++++++--------------------- 1 file changed, 53 insertions(+), 90 deletions(-) diff --git a/presets/world/owr_vanilla.yaml b/presets/world/owr_vanilla.yaml index d26bb8fa..9c86cc79 100644 --- a/presets/world/owr_vanilla.yaml +++ b/presets/world/owr_vanilla.yaml @@ -1,14 +1,36 @@ ow-edges: 1: two-way: + Lost Woods NW: Master Sword Meadow SC + Lost Woods SW*: Lost Woods Pass NW* + Lost Woods SC*: Lost Woods Pass NE* + Lost Woods SE*: Kakariko Fortune NE* + Lost Woods EN*: Lumberjack WN* + Skull Woods SW*: Skull Woods Pass NW* + Skull Woods SC*: Skull Woods Pass NE* + Skull Woods SE*: Dark Fortune NE* + Skull Woods EN*: Dark Lumberjack WN* Lumberjack SW*: Mountain Pass NW* Dark Lumberjack SW*: Bumper Cave NW* + West Death Mountain EN*: East Death Mountain WN* + West Death Mountain ES*: East Death Mountain WS* + West Dark Death Mountain EN*: East Dark Death Mountain WN* + West Dark Death Mountain ES*: East Dark Death Mountain WS* + East Death Mountain EN*: Death Mountain TR Pegs WN* + East Dark Death Mountain EN*: Turtle Rock WN* Mountain Pass SE*: Kakariko Pond NE* Bumper Cave SE*: Outcast Pond NE* + Zora Waterfall NE: Zoras Domain SW Zora Waterfall SE*: Zora Approach NE* Catfish SE*: Catfish Approach NE* + Lost Woods Pass SW*: Kakariko NW* + Lost Woods Pass SE*: Kakariko NC* + Skull Woods Pass SW*: Village of Outcasts NW* + Skull Woods Pass SE*: Village of Outcasts NC* + Kakariko Fortune SC*: Kakariko NE* Kakariko Fortune EN*: Kakariko Pond WN* Kakariko Fortune ES*: Kakariko Pond WS* + Dark Fortune SC*: Village of Outcasts NE* Dark Fortune EN*: Outcast Pond WN* Dark Fortune ES*: Outcast Pond WS* Kakariko Pond EN*: Sanctuary WN* @@ -39,8 +61,25 @@ ow-edges: Potion Shop EC*: Zora Approach WC* Dark Witch EN*: Catfish Approach WN* Dark Witch EC*: Catfish Approach WC* + Zora Approach NE*: Zora Waterfall SE* + Catfish Approach NE*: Catfish SE* + Kakariko SE*: Kakariko Suburb NE* + Kakariko ES*: Blacksmith WS* + Village of Outcasts SE*: Frog NE* + Village of Outcasts ES*: Hammer Pegs WS* + Forgotten Forest ES: Hyrule Castle WN + Hyrule Castle SW*: Central Bonk Rocks NW* + Hyrule Castle SE*: Links House NE* + Hyrule Castle ES*: Sand Dunes WN* + Pyramid SW*: Dark Bonk Rocks NW* + Pyramid SE*: Big Bomb Shop NE* + Pyramid ES*: Dark Dunes WN* Wooden Bridge SW*: Sand Dunes NW* Broken Bridge SW*: Dark Dunes NW* + Eastern Palace SW*: Tree Line NW* + Eastern Palace SE*: Eastern Nook NE* + Palace of Darkness SW*: Dark Tree Line NW* + Palace of Darkness SE*: Palace of Darkness Nook NE* Sand Dunes SC*: Stone Bridge NC* Dark Dunes SC*: Hammer Bridge NC* Maze Race ES*: Kakariko Suburb WS* @@ -65,10 +104,18 @@ ow-edges: Big Bomb Shop SC*: Hype Cave NC* Big Bomb Shop ES*: Hammer Bridge WS* Stone Bridge WC: Hobo EC + Stone Bridge SC*: Lake Hylia NW* Stone Bridge EN*: Tree Line WN* Stone Bridge EC*: Tree Line WC* + Hammer Bridge SC*: Ice Lake NW* Hammer Bridge EN*: Dark Tree Line WN* Hammer Bridge EC*: Dark Tree Line WC* + Tree Line SC*: Lake Hylia NC* + Tree Line SE*: Lake Hylia NE* + Dark Tree Line SC*: Ice Lake NC* + Dark Tree Line SE*: Ice Lake NE* + Desert EC: Desert Pass WC + Desert ES: Desert Pass WS Flute Boy Approach EC*: C Whirlpool WC* Stumpy Approach EC*: Dark C Whirlpool WC* C Whirlpool EN*: Statues WN* @@ -81,6 +128,10 @@ ow-edges: Dark C Whirlpool SC*: Swamp NC* Statues SC*: South Pass NC* Hype Cave SC*: Dark South Pass NC* + Lake Hylia EC*: Octoballoon WC* + Lake Hylia ES*: Octoballoon WS* + Ice Lake EC*: Bomber Corner WC* + Ice Lake ES*: Bomber Corner WS* Ice Cave SW*: Octoballoon NW* Ice Cave SE*: Octoballoon NE* Shopping Mall SW*: Bomber Corner NW* @@ -91,96 +142,8 @@ ow-edges: Swamp Nook ES*: Swamp WS* Dam EC*: South Pass WC* Swamp EC*: Dark South Pass WC* - Lumberjack SW*: Mountain Pass NW* - Dark Lumberjack SW*: Bumper Cave NW* - Mountain Pass SE*: Kakariko Pond NE* - Bumper Cave SE*: Outcast Pond NE* - Zora Waterfall SE*: Zora Approach NE* - Catfish SE*: Catfish Approach NE* - Kakariko Fortune EN*: Kakariko Pond WN* - Kakariko Fortune ES*: Kakariko Pond WS* - Dark Fortune EN*: Outcast Pond WN* - Dark Fortune ES*: Outcast Pond WS* - Kakariko Pond EN*: Sanctuary WN* - Kakariko Pond ES*: Sanctuary WS* - Kakariko Pond SW*: Forgotten Forest NW* - Kakariko Pond SE*: Forgotten Forest NE* - Outcast Pond EN*: Dark Chapel WN* - Outcast Pond ES*: Dark Chapel WS* - Outcast Pond SW*: Shield Shop NW* - Outcast Pond SE*: Shield Shop NE* - Sanctuary EC*: Graveyard WC* - Dark Chapel EC*: Dark Graveyard WC* - Graveyard EC*: River Bend WC* - Dark Graveyard EC*: Qirn Jump WC* - River Bend EN*: Potion Shop WN* - River Bend EC*: Potion Shop WC* - River Bend ES*: Potion Shop WS* - River Bend SW*: Wooden Bridge NW* - River Bend SC*: Wooden Bridge NC* - River Bend SE*: Wooden Bridge NE* - Qirn Jump EN*: Dark Witch WN* - Qirn Jump EC*: Dark Witch WC* - Qirn Jump ES*: Dark Witch WS* - Qirn Jump SW*: Broken Bridge NW* - Qirn Jump SC*: Broken Bridge NC* - Qirn Jump SE*: Broken Bridge NE* - Potion Shop EN*: Zora Approach WN* - Potion Shop EC*: Zora Approach WC* - Dark Witch EN*: Catfish Approach WN* - Dark Witch EC*: Catfish Approach WC* - Wooden Bridge SW*: Sand Dunes NW* - Broken Bridge SW*: Dark Dunes NW* - Sand Dunes SC*: Stone Bridge NC* - Dark Dunes SC*: Hammer Bridge NC* - Maze Race ES*: Kakariko Suburb WS* - Dig Game EC: Frog WC - Dig Game ES*: Frog WS* - Kakariko Suburb ES*: Flute Boy WS* - Frog ES*: Stumpy WS* - Flute Boy SW*: Flute Boy Approach NW* - Flute Boy SC*: Flute Boy Approach NC* - Stumpy SW*: Stumpy Approach NW* - Stumpy SC*: Stumpy Approach NC* - Central Bonk Rocks EN*: Links House WN* - Central Bonk Rocks EC*: Links House WC* - Central Bonk Rocks ES*: Links House WS* - Central Bonk Rocks SW*: C Whirlpool NW* - Dark Bonk Rocks EN*: Big Bomb Shop WN* - Dark Bonk Rocks EC*: Big Bomb Shop WC* - Dark Bonk Rocks ES*: Big Bomb Shop WS* - Dark Bonk Rocks SW*: Dark C Whirlpool NW* - Links House SC*: Statues NC* - Links House ES*: Stone Bridge WS* - Big Bomb Shop SC*: Hype Cave NC* - Big Bomb Shop ES*: Hammer Bridge WS* - Stone Bridge WC: Hobo EC - Stone Bridge EN*: Tree Line WN* - Stone Bridge EC*: Tree Line WC* - Hammer Bridge EN*: Dark Tree Line WN* - Hammer Bridge EC*: Dark Tree Line WC* - Flute Boy Approach EC*: C Whirlpool WC* - Stumpy Approach EC*: Dark C Whirlpool WC* - C Whirlpool EN*: Statues WN* - C Whirlpool EC*: Statues WC* - C Whirlpool ES*: Statues WS* - C Whirlpool SC*: Dam NC* - Dark C Whirlpool EN*: Hype Cave WN* - Dark C Whirlpool EC*: Hype Cave WC* - Dark C Whirlpool ES*: Hype Cave WS* - Dark C Whirlpool SC*: Swamp NC* - Statues SC*: South Pass NC* - Hype Cave SC*: Dark South Pass NC* - Ice Cave SW*: Octoballoon NW* - Ice Cave SE*: Octoballoon NE* - Shopping Mall SW*: Bomber Corner NW* - Shopping Mall SE*: Bomber Corner NE* - Desert Pass EC*: Dam WC* - Desert Pass ES*: Dam WS* - Swamp Nook EC*: Swamp WC* - Swamp Nook ES*: Swamp WS* - Dam EC*: South Pass WC* - Swamp EC*: Dark South Pass WC* + South Pass ES*: Lake Hylia WS* + Dark South Pass ES*: Ice Lake WS* ow-whirlpools: 1: two-way: From 2b7a9e3bf8696d6e9d60f9ee9f13bfef31a0ff10 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 18 Nov 2025 23:57:27 -0600 Subject: [PATCH 51/73] Added new gfx for 10/11 keys rather than A/B keys --- Rom.py | 2 +- data/base2current.bps | Bin 137216 -> 138220 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index ea2930a2..44381bb7 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '62eafe64b2673b686bc66abd42d68b71' +RANDOMIZERBASEHASH = '4397d4085a981cf416b0e8b4f57584a0' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index aaaea0f03dff7dba31d8fe1f4ee3b2206fbe3673..9dd44444d33227ac5abf8cdcf27c031194e8e0c8 100644 GIT binary patch delta 5184 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 delta 4153 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 From fb99d33007af96c08e5f8ad505e896f7a4e3baad Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 19 Nov 2025 09:54:31 -0600 Subject: [PATCH 52/73] Added new post-gen option to change TF Piece GFX --- Adjuster.py | 1 + AdjusterMain.py | 10 +- CLI.py | 3 +- Main.py | 2 +- Plando.py | 2 +- Rom.py | 18 +- Tables.py | 225 +++++++++++++---------- data/base2current.bps | Bin 138220 -> 138220 bytes data/itemgfx/Apples.gif | Bin 0 -> 268 bytes data/itemgfx/Arrow Upgrade (+10).gif | Bin 0 -> 260 bytes data/itemgfx/Arrow Upgrade (+5).gif | Bin 0 -> 260 bytes data/itemgfx/Arrow Upgrade (70).gif | Bin 0 -> 263 bytes data/itemgfx/Arrow.gif | Bin 0 -> 194 bytes data/itemgfx/Arrows (10).gif | Bin 0 -> 266 bytes data/itemgfx/Bee Trap.gif | Bin 0 -> 254 bytes data/itemgfx/Big Key.gif | Bin 0 -> 287 bytes data/itemgfx/Blacksmith.gif | Bin 0 -> 330 bytes data/itemgfx/Blue Clock.gif | Bin 0 -> 288 bytes data/itemgfx/Blue Maiden (Body).gif | Bin 0 -> 313 bytes data/itemgfx/Blue Mail.gif | Bin 0 -> 301 bytes data/itemgfx/Blue Pendant.gif | Bin 0 -> 310 bytes data/itemgfx/Blue Potion (B).gif | Bin 0 -> 320 bytes data/itemgfx/Blue Potion.gif | Bin 0 -> 301 bytes data/itemgfx/Blue Shield (Thin).gif | Bin 0 -> 190 bytes data/itemgfx/Blue Shield.gif | Bin 0 -> 212 bytes data/itemgfx/Bomb Upgrade (+10).gif | Bin 0 -> 292 bytes data/itemgfx/Bomb Upgrade (+5).gif | Bin 0 -> 296 bytes data/itemgfx/Bomb Upgrade (50).gif | Bin 0 -> 291 bytes data/itemgfx/Bomb.gif | Bin 0 -> 269 bytes data/itemgfx/Bombbag.gif | Bin 0 -> 305 bytes data/itemgfx/Bombos.gif | Bin 0 -> 271 bytes data/itemgfx/Bombs (10).gif | Bin 0 -> 296 bytes data/itemgfx/Bombs (3).gif | Bin 0 -> 326 bytes data/itemgfx/Book of Mudora.gif | Bin 0 -> 292 bytes data/itemgfx/Boomerang.gif | Bin 0 -> 167 bytes data/itemgfx/Bottle (Bee).gif | Bin 0 -> 277 bytes data/itemgfx/Bottle (Blue Potion).gif | Bin 0 -> 287 bytes data/itemgfx/Bottle (Fairy).gif | Bin 0 -> 297 bytes data/itemgfx/Bottle (Green Potion).gif | Bin 0 -> 287 bytes data/itemgfx/Bottle (Red Potion).gif | Bin 0 -> 287 bytes data/itemgfx/Bottle.gif | Bin 0 -> 247 bytes data/itemgfx/Bow.gif | Bin 0 -> 188 bytes data/itemgfx/Bug Net.gif | Bin 0 -> 295 bytes data/itemgfx/Byrna.gif | Bin 0 -> 189 bytes data/itemgfx/Chest.gif | Bin 0 -> 289 bytes data/itemgfx/Chicken.gif | Bin 0 -> 329 bytes data/itemgfx/Compass.gif | Bin 0 -> 333 bytes data/itemgfx/Crystal.gif | Bin 0 -> 230 bytes data/itemgfx/Duck.gif | Bin 0 -> 297 bytes data/itemgfx/Egg.gif | Bin 0 -> 231 bytes data/itemgfx/Ether.gif | Bin 0 -> 267 bytes data/itemgfx/Fairy.gif | Bin 0 -> 336 bytes data/itemgfx/Fighter Sword (Thin).gif | Bin 0 -> 154 bytes data/itemgfx/Fighter Sword.gif | Bin 0 -> 233 bytes data/itemgfx/Fire Rod.gif | Bin 0 -> 215 bytes data/itemgfx/Fire Shield.gif | Bin 0 -> 254 bytes data/itemgfx/Fire.gif | Bin 0 -> 292 bytes data/itemgfx/Flippers.gif | Bin 0 -> 306 bytes data/itemgfx/Frog.gif | Bin 0 -> 342 bytes data/itemgfx/Full Magic.gif | Bin 0 -> 209 bytes data/itemgfx/Golden Sword (Thin).gif | Bin 0 -> 180 bytes data/itemgfx/Golden Sword.gif | Bin 0 -> 283 bytes data/itemgfx/Green Clock.gif | Bin 0 -> 288 bytes data/itemgfx/Green Maiden (Body).gif | Bin 0 -> 313 bytes data/itemgfx/Green Mail.gif | Bin 0 -> 301 bytes data/itemgfx/Green Pendant.gif | Bin 0 -> 326 bytes data/itemgfx/Green Potion (G).gif | Bin 0 -> 316 bytes data/itemgfx/Green Potion.gif | Bin 0 -> 301 bytes data/itemgfx/Green Rupees (20).gif | Bin 0 -> 298 bytes data/itemgfx/Half Magic.gif | Bin 0 -> 301 bytes data/itemgfx/Hammer.gif | Bin 0 -> 198 bytes data/itemgfx/Heart (Blue).gif | Bin 0 -> 146 bytes data/itemgfx/Heart (Green).gif | Bin 0 -> 146 bytes data/itemgfx/Heart Container (Blue).gif | Bin 0 -> 232 bytes data/itemgfx/Heart Container (Green).gif | Bin 0 -> 232 bytes data/itemgfx/Heart Container.gif | Bin 0 -> 232 bytes data/itemgfx/Heart.gif | Bin 0 -> 146 bytes data/itemgfx/Hookshot.gif | Bin 0 -> 211 bytes data/itemgfx/Ice Rod.gif | Bin 0 -> 215 bytes data/itemgfx/Kiki (Body).gif | Bin 0 -> 238 bytes data/itemgfx/Kiki (Head).gif | Bin 0 -> 279 bytes data/itemgfx/Lamp.gif | Bin 0 -> 286 bytes data/itemgfx/Locksmith (Body).gif | Bin 0 -> 311 bytes data/itemgfx/Locksmith (Head).gif | Bin 0 -> 279 bytes data/itemgfx/Lumberjack (Head).gif | Bin 0 -> 332 bytes data/itemgfx/Magic Cape.gif | Bin 0 -> 306 bytes data/itemgfx/Magic Mirror.gif | Bin 0 -> 293 bytes data/itemgfx/Magic Powder.gif | Bin 0 -> 317 bytes data/itemgfx/Maiden (Head).gif | Bin 0 -> 282 bytes data/itemgfx/Map.gif | Bin 0 -> 313 bytes data/itemgfx/Master Key.gif | Bin 0 -> 256 bytes data/itemgfx/Master Sword (Thin).gif | Bin 0 -> 180 bytes data/itemgfx/Master Sword.gif | Bin 0 -> 287 bytes data/itemgfx/Mirror Shield.gif | Bin 0 -> 320 bytes data/itemgfx/Moon Pearl.gif | Bin 0 -> 260 bytes data/itemgfx/Mushroom.gif | Bin 0 -> 287 bytes data/itemgfx/Ocarina.gif | Bin 0 -> 274 bytes data/itemgfx/Old Man (Body).gif | Bin 0 -> 263 bytes data/itemgfx/Old Man (Head).gif | Bin 0 -> 313 bytes data/itemgfx/Open Chest.gif | Bin 0 -> 236 bytes data/itemgfx/Pegasus Boots.gif | Bin 0 -> 286 bytes data/itemgfx/Piece of Heart.gif | Bin 0 -> 255 bytes data/itemgfx/Power Glove.gif | Bin 0 -> 317 bytes data/itemgfx/Power Star.gif | Bin 0 -> 278 bytes data/itemgfx/Progressive Bow.gif | Bin 0 -> 308 bytes data/itemgfx/Pseudoboots.gif | Bin 0 -> 286 bytes data/itemgfx/Pseudolamp.gif | Bin 0 -> 286 bytes data/itemgfx/Purple Chest.gif | Bin 0 -> 316 bytes data/itemgfx/Quake.gif | Bin 0 -> 262 bytes data/itemgfx/Quarter Magic.gif | Bin 0 -> 296 bytes data/itemgfx/Red Boomerang.gif | Bin 0 -> 167 bytes data/itemgfx/Red Clock.gif | Bin 0 -> 288 bytes data/itemgfx/Red Crystal.gif | Bin 0 -> 272 bytes data/itemgfx/Red Maiden (Body).gif | Bin 0 -> 313 bytes data/itemgfx/Red Mail.gif | Bin 0 -> 301 bytes data/itemgfx/Red Pendant.gif | Bin 0 -> 310 bytes data/itemgfx/Red Potion (R).gif | Bin 0 -> 319 bytes data/itemgfx/Red Potion.gif | Bin 0 -> 301 bytes data/itemgfx/Rupee (1).gif | Bin 0 -> 193 bytes data/itemgfx/Rupee (20).gif | Bin 0 -> 193 bytes data/itemgfx/Rupee (5).gif | Bin 0 -> 193 bytes data/itemgfx/Rupees (100).gif | Bin 0 -> 299 bytes data/itemgfx/Rupees (300).gif | Bin 0 -> 298 bytes data/itemgfx/Rupees (50).gif | Bin 0 -> 299 bytes data/itemgfx/Shovel.gif | Bin 0 -> 209 bytes data/itemgfx/Silver Arrows (Ag).gif | Bin 0 -> 263 bytes data/itemgfx/Silver Arrows.gif | Bin 0 -> 305 bytes data/itemgfx/Small Key.gif | Bin 0 -> 188 bytes data/itemgfx/Small Magic.gif | Bin 0 -> 173 bytes data/itemgfx/Somaria.gif | Bin 0 -> 189 bytes data/itemgfx/Super Bomb.gif | Bin 0 -> 299 bytes data/itemgfx/Sword and Shield.gif | Bin 0 -> 271 bytes data/itemgfx/Tempered Sword (Thin).gif | Bin 0 -> 180 bytes data/itemgfx/Tempered Sword.gif | Bin 0 -> 286 bytes data/itemgfx/Titans Mitt.gif | Bin 0 -> 317 bytes data/itemgfx/Triforce.gif | Bin 0 -> 207 bytes data/itemgfx/Warp Tile.gif | Bin 0 -> 272 bytes data/itemgfx/Whirlpool.gif | Bin 0 -> 376 bytes data/itemgfx/Zelda (Body).gif | Bin 0 -> 323 bytes data/itemgfx/Zelda (Head).gif | Bin 0 -> 309 bytes resources/app/cli/args.json | 1 + resources/app/gui/lang/en.json | 5 +- source/classes/CustomSettings.py | 1 + source/classes/ItemGfxSelector.py | 121 ++++++++++++ source/gui/adjust/overview.py | 27 +++ source/gui/bottom.py | 3 + source/gui/loadcliargs.py | 7 + source/gui/randomize/gameoptions.py | 29 +++ source/tools/MysteryUtils.py | 1 + 149 files changed, 354 insertions(+), 102 deletions(-) create mode 100644 data/itemgfx/Apples.gif create mode 100644 data/itemgfx/Arrow Upgrade (+10).gif create mode 100644 data/itemgfx/Arrow Upgrade (+5).gif create mode 100644 data/itemgfx/Arrow Upgrade (70).gif create mode 100644 data/itemgfx/Arrow.gif create mode 100644 data/itemgfx/Arrows (10).gif create mode 100644 data/itemgfx/Bee Trap.gif create mode 100644 data/itemgfx/Big Key.gif create mode 100644 data/itemgfx/Blacksmith.gif create mode 100644 data/itemgfx/Blue Clock.gif create mode 100644 data/itemgfx/Blue Maiden (Body).gif create mode 100644 data/itemgfx/Blue Mail.gif create mode 100644 data/itemgfx/Blue Pendant.gif create mode 100644 data/itemgfx/Blue Potion (B).gif create mode 100644 data/itemgfx/Blue Potion.gif create mode 100644 data/itemgfx/Blue Shield (Thin).gif create mode 100644 data/itemgfx/Blue Shield.gif create mode 100644 data/itemgfx/Bomb Upgrade (+10).gif create mode 100644 data/itemgfx/Bomb Upgrade (+5).gif create mode 100644 data/itemgfx/Bomb Upgrade (50).gif create mode 100644 data/itemgfx/Bomb.gif create mode 100644 data/itemgfx/Bombbag.gif create mode 100644 data/itemgfx/Bombos.gif create mode 100644 data/itemgfx/Bombs (10).gif create mode 100644 data/itemgfx/Bombs (3).gif create mode 100644 data/itemgfx/Book of Mudora.gif create mode 100644 data/itemgfx/Boomerang.gif create mode 100644 data/itemgfx/Bottle (Bee).gif create mode 100644 data/itemgfx/Bottle (Blue Potion).gif create mode 100644 data/itemgfx/Bottle (Fairy).gif create mode 100644 data/itemgfx/Bottle (Green Potion).gif create mode 100644 data/itemgfx/Bottle (Red Potion).gif create mode 100644 data/itemgfx/Bottle.gif create mode 100644 data/itemgfx/Bow.gif create mode 100644 data/itemgfx/Bug Net.gif create mode 100644 data/itemgfx/Byrna.gif create mode 100644 data/itemgfx/Chest.gif create mode 100644 data/itemgfx/Chicken.gif create mode 100644 data/itemgfx/Compass.gif create mode 100644 data/itemgfx/Crystal.gif create mode 100644 data/itemgfx/Duck.gif create mode 100644 data/itemgfx/Egg.gif create mode 100644 data/itemgfx/Ether.gif create mode 100644 data/itemgfx/Fairy.gif create mode 100644 data/itemgfx/Fighter Sword (Thin).gif create mode 100644 data/itemgfx/Fighter Sword.gif create mode 100644 data/itemgfx/Fire Rod.gif create mode 100644 data/itemgfx/Fire Shield.gif create mode 100644 data/itemgfx/Fire.gif create mode 100644 data/itemgfx/Flippers.gif create mode 100644 data/itemgfx/Frog.gif create mode 100644 data/itemgfx/Full Magic.gif create mode 100644 data/itemgfx/Golden Sword (Thin).gif create mode 100644 data/itemgfx/Golden Sword.gif create mode 100644 data/itemgfx/Green Clock.gif create mode 100644 data/itemgfx/Green Maiden (Body).gif create mode 100644 data/itemgfx/Green Mail.gif create mode 100644 data/itemgfx/Green Pendant.gif create mode 100644 data/itemgfx/Green Potion (G).gif create mode 100644 data/itemgfx/Green Potion.gif create mode 100644 data/itemgfx/Green Rupees (20).gif create mode 100644 data/itemgfx/Half Magic.gif create mode 100644 data/itemgfx/Hammer.gif create mode 100644 data/itemgfx/Heart (Blue).gif create mode 100644 data/itemgfx/Heart (Green).gif create mode 100644 data/itemgfx/Heart Container (Blue).gif create mode 100644 data/itemgfx/Heart Container (Green).gif create mode 100644 data/itemgfx/Heart Container.gif create mode 100644 data/itemgfx/Heart.gif create mode 100644 data/itemgfx/Hookshot.gif create mode 100644 data/itemgfx/Ice Rod.gif create mode 100644 data/itemgfx/Kiki (Body).gif create mode 100644 data/itemgfx/Kiki (Head).gif create mode 100644 data/itemgfx/Lamp.gif create mode 100644 data/itemgfx/Locksmith (Body).gif create mode 100644 data/itemgfx/Locksmith (Head).gif create mode 100644 data/itemgfx/Lumberjack (Head).gif create mode 100644 data/itemgfx/Magic Cape.gif create mode 100644 data/itemgfx/Magic Mirror.gif create mode 100644 data/itemgfx/Magic Powder.gif create mode 100644 data/itemgfx/Maiden (Head).gif create mode 100644 data/itemgfx/Map.gif create mode 100644 data/itemgfx/Master Key.gif create mode 100644 data/itemgfx/Master Sword (Thin).gif create mode 100644 data/itemgfx/Master Sword.gif create mode 100644 data/itemgfx/Mirror Shield.gif create mode 100644 data/itemgfx/Moon Pearl.gif create mode 100644 data/itemgfx/Mushroom.gif create mode 100644 data/itemgfx/Ocarina.gif create mode 100644 data/itemgfx/Old Man (Body).gif create mode 100644 data/itemgfx/Old Man (Head).gif create mode 100644 data/itemgfx/Open Chest.gif create mode 100644 data/itemgfx/Pegasus Boots.gif create mode 100644 data/itemgfx/Piece of Heart.gif create mode 100644 data/itemgfx/Power Glove.gif create mode 100644 data/itemgfx/Power Star.gif create mode 100644 data/itemgfx/Progressive Bow.gif create mode 100644 data/itemgfx/Pseudoboots.gif create mode 100644 data/itemgfx/Pseudolamp.gif create mode 100644 data/itemgfx/Purple Chest.gif create mode 100644 data/itemgfx/Quake.gif create mode 100644 data/itemgfx/Quarter Magic.gif create mode 100644 data/itemgfx/Red Boomerang.gif create mode 100644 data/itemgfx/Red Clock.gif create mode 100644 data/itemgfx/Red Crystal.gif create mode 100644 data/itemgfx/Red Maiden (Body).gif create mode 100644 data/itemgfx/Red Mail.gif create mode 100644 data/itemgfx/Red Pendant.gif create mode 100644 data/itemgfx/Red Potion (R).gif create mode 100644 data/itemgfx/Red Potion.gif create mode 100644 data/itemgfx/Rupee (1).gif create mode 100644 data/itemgfx/Rupee (20).gif create mode 100644 data/itemgfx/Rupee (5).gif create mode 100644 data/itemgfx/Rupees (100).gif create mode 100644 data/itemgfx/Rupees (300).gif create mode 100644 data/itemgfx/Rupees (50).gif create mode 100644 data/itemgfx/Shovel.gif create mode 100644 data/itemgfx/Silver Arrows (Ag).gif create mode 100644 data/itemgfx/Silver Arrows.gif create mode 100644 data/itemgfx/Small Key.gif create mode 100644 data/itemgfx/Small Magic.gif create mode 100644 data/itemgfx/Somaria.gif create mode 100644 data/itemgfx/Super Bomb.gif create mode 100644 data/itemgfx/Sword and Shield.gif create mode 100644 data/itemgfx/Tempered Sword (Thin).gif create mode 100644 data/itemgfx/Tempered Sword.gif create mode 100644 data/itemgfx/Titans Mitt.gif create mode 100644 data/itemgfx/Triforce.gif create mode 100644 data/itemgfx/Warp Tile.gif create mode 100644 data/itemgfx/Whirlpool.gif create mode 100644 data/itemgfx/Zelda (Body).gif create mode 100644 data/itemgfx/Zelda (Head).gif create mode 100644 source/classes/ItemGfxSelector.py diff --git a/Adjuster.py b/Adjuster.py index 68ac73ad..ba502c8a 100755 --- a/Adjuster.py +++ b/Adjuster.py @@ -47,6 +47,7 @@ def main(): Alternatively, can be a ALttP Rom patched with a Link sprite that will be extracted. ''') + parser.add_argument('--triforce_gfx', help='Name of the triforce graphics to use.') parser.add_argument('--names', default='', type=str) args = parser.parse_args() diff --git a/AdjusterMain.py b/AdjusterMain.py index 803bed24..6b886a4b 100644 --- a/AdjusterMain.py +++ b/AdjusterMain.py @@ -30,9 +30,11 @@ def adjust(args): if not hasattr(args,"sprite"): args.sprite = None + if not hasattr(args,"triforce_gfx"): + args.triforce_gfx = None apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, - args.sprite, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx, + args.sprite, args.triforce_gfx, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx, args.shuffle_sfxinstruments, args.shuffle_songinstruments, args.msu_resume) output_path.cached_path = args.outputpath @@ -65,10 +67,12 @@ def patch(args): if not hasattr(args, "sprite"): args.sprite = None + if not hasattr(args, "triforce_gfx"): + args.triforce_gfx = None apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, - args.sprite, args.ow_palettes, args.uw_palettes, args.reduce_flashing, args.shuffle_sfx, - args.shuffle_sfxinstruments, args.shuffle_songinstruments, args.msu_resume) + args.sprite, args.triforce_gfx, args.ow_palettes, args.uw_palettes, args.reduce_flashing, + args.shuffle_sfx, args.shuffle_sfxinstruments, args.shuffle_songinstruments, args.msu_resume) output_path.cached_path = args.outputpath rom.write_to_file(output_path('%s.sfc' % outfile_base)) diff --git a/CLI.py b/CLI.py index c6ae7d9f..5eb4f3e2 100644 --- a/CLI.py +++ b/CLI.py @@ -141,7 +141,7 @@ def parse_cli(argv, no_defaults=False): 'skullwoods', 'linked_drops', 'pseudoboots', 'mirrorscroll', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters', 'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots', - 'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', + 'ow_palettes', 'uw_palettes', 'sprite', 'triforce_gfx', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor', 'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle', 'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx', 'shuffle_sfxinstruments', 'shuffle_songinstruments', 'msu_resume', 'collection_rate', 'colorizepots', 'decoupledoors', 'door_type_mode', @@ -264,6 +264,7 @@ def parse_settings(): "heartcolor": "red", "heartbeep": "normal", "sprite": None, + "triforce_gfx": None, "fastmenu": "normal", "ow_palettes": "default", "uw_palettes": "default", diff --git a/Main.py b/Main.py index 2c242384..6b587bf6 100644 --- a/Main.py +++ b/Main.py @@ -299,7 +299,7 @@ def main(args, seed=None, fish=None): world.spoiler.hashes[(player, team)] = get_hash_string(rom.hash) apply_rom_settings(rom, args.heartbeep[player], args.heartcolor[player], args.quickswap[player], - args.fastmenu[player], args.disablemusic[player], args.sprite[player], + args.fastmenu[player], args.disablemusic[player], args.sprite[player], args.triforce_gfx[player], args.ow_palettes[player], args.uw_palettes[player], args.reduce_flashing[player], args.shuffle_sfx[player], args.shuffle_sfxinstruments[player], args.shuffle_songinstruments[player], args.msu_resume[player]) diff --git a/Plando.py b/Plando.py index 2c948435..25003f24 100755 --- a/Plando.py +++ b/Plando.py @@ -76,7 +76,7 @@ def main(args): rom = LocalRom(args.rom) patch_rom(world, rom, 1, 1, False, str(args.rom_header) if args.rom_header else None) - apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, args.sprite, args.ow_palettes, args.uw_palettes) + apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, args.sprite, args.triforce_gfx, args.ow_palettes, args.uw_palettes) for textname, texttype, text in text_patches: if texttype == 'text': diff --git a/Rom.py b/Rom.py index 44381bb7..ad5e488b 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '4397d4085a981cf416b0e8b4f57584a0' +RANDOMIZERBASEHASH = 'fea650d598f4399db790903d9eb16186' class JsonRom(object): @@ -1875,7 +1875,7 @@ def hud_format_text(text): return output[:32] -def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, +def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, sprite, triforce_gfx, ow_palettes, uw_palettes, reduce_flashing, shuffle_sfx, shuffle_sfxinstruments, shuffle_songinstruments, msu_resume): @@ -1933,6 +1933,20 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr # write link sprite if required if sprite is not None: write_sprite(rom, sprite) + + if triforce_gfx is not None: + from Tables import item_gfx_table + if triforce_gfx in item_gfx_table.keys(): + (is_custom, address, palette, pal_addr, size) = item_gfx_table[triforce_gfx] + address = address if is_custom else 0x8000 + address + write_int16(rom, snes_to_pc(0xA2C600+(0x6C*2)), address) + write_int16(rom, snes_to_pc(0xA2C800+(0x6C*2)), address) + rom.write_byte(snes_to_pc(0xA2B100+0x6C), 0 if size == 2 else 4) + rom.write_byte(snes_to_pc(0xA2BA00+0x6C), size) + rom.write_byte(snes_to_pc(0xA2BB00+0x6C), size) + rom.write_byte(snes_to_pc(0xA2BC00+0x6C), palette) + rom.write_byte(snes_to_pc(0xA2BD00+0x6C), palette) + write_int16(rom, snes_to_pc(0xA2BE00+(0x6C*2)), pal_addr) # sprite author credits padded_author = sprite.author_name if sprite is not None else "Nintendo" diff --git a/Tables.py b/Tables.py index 33e1e230..5272f586 100644 --- a/Tables.py +++ b/Tables.py @@ -147,101 +147,140 @@ bonk_prize_lookup = { 'Fairy': (0xe3, 15, None) } -# item name: (custom gfx, address offset, palette) +# item name: (custom gfx, address offset, palette, palette address, size) # decompressed gfx loaded at $7F8000 # custom gfx loaded at $228000 item_gfx_table = { - 'Green Rupees (20)': (False, 0x0000, 0x04), - 'Pegasus Boots': (False, 0x0040, 0x01), - 'Psuedoboots': (False, 0x0040, 0x02), - 'Blue Pendant': (False, 0x0080, 0x02), - 'Red Pendant': (False, 0x0080, 0x01), - 'Warp Tile': (False, 0x00C0, 0x04), - 'Open Chest': (False, 0x0100, 0x02), - 'Chicken': (False, 0x0140, 0x04), - 'Duck': (False, 0x0180, 0x01), - 'Chest': (False, 0x0400, 0x02), - 'Frog': (False, 0x0440, 0x04), - 'Kiki (Head)': (False, 0x0480, 0x04), - 'Purple Chest': (False, 0x0500, 0x04), - 'Super Bomb': (False, 0x0540, 0x04), - 'Blacksmith': (False, 0x0580, 0x04), - 'Bug Net': (False, 0x0860, 0x01), - 'Crystal': (False, 0x08A0, 0x06), - 'Silver Arrows': (False, 0x08E0, 0x01), - 'Bow': (False, 0x0920, 0x02), - 'Bottle (Fairy)': (False, 0x0960, 0x02), - 'Bottle (Bee)': (False, 0x09A0, 0x02), - 'Piece of Heart': (False, 0x0C00, 0x01), - 'Ocarina': (False, 0x0C40, 0x02), - 'Mirror Shield': (False, 0x0C80, 0x04), - 'Rupees (100)': (False, 0x0D20, 0x04), - 'Rupees (50)': (False, 0x0D60, 0x04), - 'Rupees (300)': (False, 0x0DA0, 0x04), - 'Flippers': (False, 0x1000, 0x02), - 'Mirror': (False, 0x1040, 0x02), - 'Bomb': (False, 0x1080, 0x02), - 'Lamp': (False, 0x10C0, 0x01), - 'Psuedolamp': (False, 0x10C0, 0x02), - 'Magic Cape': (False, 0x1100, 0x01), - 'Compass': (False, 0x1140, 0x02), - 'Moon Pearl': (False, 0x1180, 0x01), - 'Ether': (False, 0x1400, 0x04), - 'Bombos': (False, 0x1440, 0x04), - 'Quake': (False, 0x1480, 0x04), - 'Bottle': (False, 0x14C0, 0x01), - 'Bottle (Red Potion)': (False, 0x1500, 0x01), - 'Bottle (Green Potion)': (False, 0x1500, 0x04), - 'Bottle (Blue Potion)': (False, 0x1500, 0x02), - 'Mushroom': (False, 0x1540, 0x04), - 'Map': (False, 0x1580, 0x04), - 'Big Key': (False, 0x15C0, 0x04), - 'Bombs (3)': (False, 0x1840, 0x02), - 'Arrows (10)': (False, 0x1880, 0x02), - 'Heart Container': (False, 0x18C0, 0x01), - 'Green Mail': (False, 0x1900, 0x04), - 'Blue Mail': (False, 0x1900, 0x02), - 'Red Mail': (False, 0x1900, 0x01), - 'Fire Sheild': (False, 0x1980, 0x04), - 'Blue Shield': (False, 0x19C0, 0x02), - 'Magic Powder': (False, 0x1CC0, 0x02), - 'Bombs (10)': (False, 0x1D00, 0x02), - 'Power Glove': (False, 0x1D40, 0x01), - 'Titans Mitts': (False, 0x1D40, 0x04), - 'Book of Mudora': (False, 0x1D80, 0x04), - 'Maiden (Head)': (False, 0x2000, 0x04), - 'Zelda (Head)': (False, 0x2080, 0x04), - 'Old Man (Head)': (False, 0x2140, 0x04), - 'Locksmith (Head)': (False, 0x2180, 0x04), - 'Fire': (False, 0x25C0, 0x04), - 'Apples': (False, 0x30A0, 0x04), - 'Fairy': (False, 0x3140, 0x01), - 'Whirlpool': (False, 0x31C0, 0x01), + 'Green Rupees (20)': (False, 0x0000, 0x04, 0x0000, 2), + 'Pegasus Boots': (False, 0x0040, 0x01, 0x0000, 2), + 'Psuedoboots': (False, 0x0040, 0x02, 0x0000, 2), + 'Blue Pendant': (False, 0x0080, 0x02, 0x0000, 2), + 'Red Pendant': (False, 0x0080, 0x01, 0x0000, 2), + 'Warp Tile': (False, 0x00C0, 0x04, 0x0000, 2), + 'Open Chest': (False, 0x0100, 0x02, 0x0000, 2), + 'Chicken': (False, 0x0140, 0x04, 0x0000, 2), + 'Duck': (False, 0x0180, 0x01, 0x0000, 2), + 'Chest': (False, 0x0400, 0x02, 0x0000, 2), + 'Frog': (False, 0x0440, 0x04, 0x0000, 2), + 'Kiki (Head)': (False, 0x0480, 0x04, 0x0000, 2), + 'Purple Chest': (False, 0x0500, 0x04, 0x0000, 2), + 'Super Bomb': (False, 0x0540, 0x04, 0x0000, 2), + 'Blacksmith': (False, 0x0580, 0x04, 0x0000, 2), + 'Bug Net': (False, 0x0860, 0x01, 0x0000, 2), + 'Crystal': (False, 0x08A0, 0x86, 0xB240, 2), + 'Silver Arrows': (False, 0x08E0, 0x01, 0x0000, 2), + 'Progressive Bow': (False, 0x0920, 0x02, 0x0000, 2), + 'Bottle (Fairy)': (False, 0x0960, 0x02, 0x0000, 2), + 'Bottle (Bee)': (False, 0x09A0, 0x02, 0x0000, 2), + 'Piece of Heart': (False, 0x0C00, 0x01, 0x0000, 2), + 'Ocarina': (False, 0x0C40, 0x02, 0x0000, 2), + 'Mirror Shield': (False, 0x0C80, 0x80, 0xB230, 2), + 'Rupees (100)': (False, 0x0D20, 0x04, 0x0000, 2), + 'Rupees (50)': (False, 0x0D60, 0x04, 0x0000, 2), + 'Rupees (300)': (False, 0x0DA0, 0x04, 0x0000, 2), + 'Flippers': (False, 0x1000, 0x02, 0x0000, 2), + 'Magic Mirror': (False, 0x1040, 0x02, 0x0000, 2), + 'Bomb': (False, 0x1080, 0x02, 0x0000, 2), + 'Lamp': (False, 0x10C0, 0x01, 0x0000, 2), + 'Psuedolamp': (False, 0x10C0, 0x02, 0x0000, 2), + 'Magic Cape': (False, 0x1100, 0x01, 0x0000, 2), + 'Compass': (False, 0x1140, 0x02, 0x0000, 2), + 'Moon Pearl': (False, 0x1180, 0x01, 0x0000, 2), + 'Ether': (False, 0x1400, 0x04, 0x0000, 2), + 'Bombos': (False, 0x1440, 0x04, 0x0000, 2), + 'Quake': (False, 0x1480, 0x04, 0x0000, 2), + 'Bottle': (False, 0x14C0, 0x01, 0x0000, 2), + 'Bottle (Red Potion)': (False, 0x1500, 0x01, 0x0000, 2), + 'Bottle (Green Potion)': (False, 0x1500, 0x04, 0x0000, 2), + 'Bottle (Blue Potion)': (False, 0x1500, 0x02, 0x0000, 2), + 'Mushroom': (False, 0x1540, 0x04, 0x0000, 2), + 'Map': (False, 0x1580, 0x04, 0x0000, 2), + 'Big Key': (False, 0x15C0, 0x04, 0x0000, 2), + 'Green Potion': (False, 0x1800, 0x04, 0x0000, 2), + 'Blue Potion': (False, 0x1800, 0x02, 0x0000, 2), + 'Red Potion': (False, 0x1800, 0x01, 0x0000, 2), + 'Bombs (3)': (False, 0x1840, 0x02, 0x0000, 2), + 'Arrows (10)': (False, 0x1880, 0x02, 0x0000, 2), + 'Heart Container': (False, 0x18C0, 0x01, 0x0000, 2), + 'Heart Container (Green)': (False, 0x18C0, 0x04, 0x0000, 2), + 'Heart Container (Blue)': (False, 0x18C0, 0x02, 0x0000, 2), + 'Green Mail': (False, 0x1900, 0x04, 0x0000, 2), + 'Blue Mail': (False, 0x1900, 0x02, 0x0000, 2), + 'Red Mail': (False, 0x1900, 0x01, 0x0000, 2), + 'Fire Shield': (False, 0x1940, 0x80, 0xB220, 2), + 'Blue Shield': (False, 0x19C0, 0x02, 0x0000, 2), + 'Magic Powder': (False, 0x1CC0, 0x02, 0x0000, 2), + 'Bombs (10)': (False, 0x1D00, 0x02, 0x0000, 2), + 'Power Glove': (False, 0x1D40, 0x01, 0x0000, 2), + 'Titans Mitt': (False, 0x1D40, 0x04, 0x0000, 2), + 'Book of Mudora': (False, 0x1D80, 0x04, 0x0000, 2), + 'Maiden (Head)': (False, 0x2000, 0x04, 0x0000, 2), + 'Zelda (Head)': (False, 0x2080, 0x04, 0x0000, 2), + 'Old Man (Head)': (False, 0x2140, 0x04, 0x0000, 2), + 'Locksmith (Head)': (False, 0x2180, 0x04, 0x0000, 2), + 'Fire': (False, 0x25C0, 0x04, 0x0000, 2), + 'Apples': (False, 0x30A0, 0x04, 0x0000, 2), + 'Fairy': (False, 0x3140, 0x01, 0x0000, 2), + 'Whirlpool': (False, 0x31C0, 0x02, 0x0000, 2), - 'Triforce': (True, 0x0060, 0x04), - 'Fighter Sword': (True, 0x00A0, 0x02), - 'Master Sword': (True, 0x00E0, 0x02), - 'Tempered Sword': (True, 0x0120, 0x01), - 'Golden Sword': (True, 0x0160, 0x04), - 'Half Magic': (True, 0x01A0, 0x04), - 'Quarter Magic': (True, 0x01E0, 0x04), - 'Bomb Upgrade (+5)': (True, 0x0420, 0x04), - 'Bomb Upgrade (+10)': (True, 0x0460, 0x04), - 'Bomb Upgrade (50)': (True, 0x04A0, 0x04), - 'Bombbag': (True, 0x04E0, 0x02), - 'Arrow Upgrade (+5)': (True, 0x0520, 0x02), - 'Arrow Upgrade (+10)': (True, 0x0560, 0x02), - 'Arrows (70)': (True, 0x05A0, 0x02), - 'Silver Arrows (Ag)': (True, 0x05E0, 0x01), - 'Green Pendant': (True, 0x0820, 0x04), - 'Sword and Shield': (True, 0x0860, 0x02), - 'Green Potion': (True, 0x08A0, 0x04), - 'Blue Potion': (True, 0x08E0, 0x02), - 'Red Potion': (True, 0x0920, 0x01), - 'Bee Trap': (True, 0x0960, 0x02), - 'Red Crystal': (True, 0x0C60, 0x01), - 'Egg': (True, 0x1020, 0x02), - 'Master Key': (True, 0x1060, 0x02), - 'Lumberjack (Head)': (True, 0x11A0, 0x02), - 'Power Star': (True, 0x11E0, 0x04), + 'Nothing': (True, 0x0020, 0x01, 0x0000, 2), + 'Triforce': (True, 0x0060, 0x04, 0x0000, 2), + 'Fighter Sword': (True, 0x00A0, 0x02, 0x0000, 2), + 'Master Sword': (True, 0x00E0, 0x02, 0x0000, 2), + 'Tempered Sword': (True, 0x0120, 0x01, 0x0000, 2), + 'Golden Sword': (True, 0x0160, 0x04, 0x0000, 2), + 'Half Magic': (True, 0x01A0, 0x04, 0x0000, 2), + 'Quarter Magic': (True, 0x01E0, 0x04, 0x0000, 2), + 'Bomb Upgrade (+5)': (True, 0x0420, 0x04, 0x0000, 2), + 'Bomb Upgrade (+10)': (True, 0x0460, 0x04, 0x0000, 2), + 'Bomb Upgrade (50)': (True, 0x04A0, 0x04, 0x0000, 2), + 'Bombbag': (True, 0x04E0, 0x02, 0x0000, 2), + 'Arrow Upgrade (+5)': (True, 0x0520, 0x02, 0x0000, 2), + 'Arrow Upgrade (+10)': (True, 0x0560, 0x02, 0x0000, 2), + 'Arrow Upgrade (70)': (True, 0x05A0, 0x02, 0x0000, 2), + 'Silver Arrows (Ag)': (True, 0x05E0, 0x01, 0x0000, 2), + 'Green Pendant': (True, 0x0820, 0x04, 0x0000, 2), + 'Sword and Shield': (True, 0x0860, 0x02, 0xD244, 2), + 'Green Potion (G)': (True, 0x08A0, 0x04, 0x0000, 2), + 'Blue Potion (B)': (True, 0x08E0, 0x02, 0x0000, 2), + 'Red Potion (R)': (True, 0x0920, 0x01, 0x0000, 2), + 'Bee Trap': (True, 0x0960, 0x02, 0x0000, 2), + 'Red Crystal': (True, 0x0C60, 0x01, 0x0000, 2), + 'Green Clock': (True, 0x0DE0, 0x04, 0x0000, 2), + 'Blue Clock': (True, 0x0DE0, 0x02, 0x0000, 2), + 'Red Clock': (True, 0x0DE0, 0x01, 0x0000, 2), + 'Egg': (True, 0x1020, 0x02, 0x0000, 2), + 'Master Key': (True, 0x1060, 0x02, 0x0000, 2), + 'Lumberjack (Head)': (True, 0x11A0, 0x02, 0x0000, 2), + 'Power Star': (True, 0x11E0, 0x04, 0x0000, 2), + + # Thin GFX + 'Rupee (1)': (False, 0x0800, 0x04, 0x0000, 0), + 'Rupees (5)': (False, 0x0800, 0x02, 0x0000, 0), + 'Rupees (20)': (False, 0x0800, 0x01, 0x0000, 0), + 'Blue Shield (Thin)': (False, 0x09E0, 0x02, 0x0000, 0), + 'Heart': (False, 0x0CC0, 0x01, 0x0000, 0), + 'Heart (Green)': (False, 0x0CC0, 0x04, 0x0000, 0), + 'Heart (Blue)': (False, 0x0CC0, 0x02, 0x0000, 0), + 'Small Magic': (False, 0x0CE0, 0x04, 0x0000, 0), + 'Arrow': (False, 0x0D00, 0x02, 0x0000, 0), + 'Nothing (Thin)': (False, 0x0DE0, 0x01, 0x0000, 0), + 'Master Sword (Thin)': (False, 0x11C0, 0x05, 0x0000, 0), + 'Tempered Sword (Thin)': (False, 0x11C0, 0x01, 0x0000, 0), + 'Golden Sword (Thin)': (False, 0x11C0, 0x04, 0x0000, 0), + 'Shovel': (False, 0x11E0, 0x01, 0x0000, 0), + 'Bow': (False, 0x1C00, 0x01, 0x0000, 0), + 'Fighter Sword (Thin)': (False, 0x1C20, 0x02, 0x0000, 0), + 'Somaria': (False, 0x1C40, 0x01, 0x0000, 0), + 'Byrna': (False, 0x1C40, 0x02, 0x0000, 0), + 'Hookshot': (False, 0x1C60, 0x01, 0x0000, 0), + 'Fire Rod': (False, 0x1C80, 0x01, 0x0000, 0), + 'Ice Rod': (False, 0x1C80, 0x02, 0x0000, 0), + 'Hammer': (False, 0x1CA0, 0x01, 0x0000, 0), + 'Small Key': (False, 0x1DC0, 0x04, 0x0000, 0), + 'Boomerang': (False, 0x1DE0, 0x02, 0x0000, 0), + 'Red Boomerang': (False, 0x1DE0, 0x01, 0x0000, 0), + + 'Full Magic': (True, 0x01A0, 0x04, 0x0000, 0), } + \ No newline at end of file diff --git a/data/base2current.bps b/data/base2current.bps index 9dd44444d33227ac5abf8cdcf27c031194e8e0c8..00911e4ea0b104984649b1e074fe0a91c66def38 100644 GIT binary patch delta 38 wcmV+>0NMZSw+QUF2(T&x1Cx(zvn>OX<^f8B!0ETZ=>a4%2%+Hpp^$$oG+Qtc;{X5v delta 38 wcmV+>0NMZSw+QUF2(T&x1C)OX<^f5A!0ETZ=>a4%2t$@P4r?-oz)o!tRsaA1 diff --git a/data/itemgfx/Apples.gif b/data/itemgfx/Apples.gif new file mode 100644 index 0000000000000000000000000000000000000000..53cb2725c786f1f09357f418fdac5beeff391675 GIT binary patch literal 268 zcmV+n0rUPxNk%w1VITk?0D=Gj`1ttv&^VaTa7d6axQHOgFc>H(C;$KeA^8LW000L7 zEC2ui03ZM$06+-Q01pTpNU)&6g9r&4Sjcd|0EP?`7F<}MqQ!~}2@nVnKqE#25(QGc zNb=&skO?84L^;ub$%YRZdMvOK;mDF2HFBI;lO;rv5m^cy8gik4qey!Sy-Cx6!;Azz zqGb9JV$P^dB~rDhGXMYp9Hka@S+c-Yu}jH*d`Yye+qZDz9#jcZ?g67nk18EX_o+&v zOc(m)Sy!vtrh;QaMLYL!Rhc;%8{GP_D`CTB&2IDxHh|=onXm4|x_7c;u936)Je|38 S%EN&RxBYoHsNJ^#0RTIp7HjeV literal 0 HcmV?d00001 diff --git a/data/itemgfx/Arrow Upgrade (+10).gif b/data/itemgfx/Arrow Upgrade (+10).gif new file mode 100644 index 0000000000000000000000000000000000000000..8b9c158b6fa60ee4b8643d4250a1b7a64c2f9802 GIT binary patch literal 260 zcmZ?wbhEHbRA5kGXkuXa0R$H;c62CcXlO7X0mYvzj0_Ac3_2h&kXi?hlMI|3G8zR3 z7@9bQwR|!R92lCpmECfFd{}U#n~jyjfMda8_huQ!2AK)@pN_>oUDwr`#%Gm4lNV)-EdP5?*#; zoyq1V*`GygLRLg@PKd3V`u57U^!s_GD<&AT7&8-tH2^Ky BV!Z$W literal 0 HcmV?d00001 diff --git a/data/itemgfx/Arrow Upgrade (70).gif b/data/itemgfx/Arrow Upgrade (70).gif new file mode 100644 index 0000000000000000000000000000000000000000..db7cff10e413caa30935be527090eaed55ef4019 GIT binary patch literal 263 zcmZ?wbhEHbRA5kGXkuXa0R$H;c62CcXlO7X0mYvzj0_Ac3_2h&kXi?hGYp&@G8zR3 z7@9bQwR|!R92lCpmECfFd{}U#n~jy@#Ey#(fNE{3STZLpacvTjoweu0B!`m|)T535 za9n=qJwYx1QH#ZdbjNP}%2zQf4KjRYa$Ej#nN`wocCnA3RBzOk$H5c5H##lN2ubmq z6BwVp23k6kYM@!THm8%ysT(qP>G z_jY*pqiu!0c1L#>tE6sDQa`M7`sap-y;ZxT_)cF-&N%P(K8>|&mfF*!!rPNnB?K6( E0f~WWYXATM literal 0 HcmV?d00001 diff --git a/data/itemgfx/Arrow.gif b/data/itemgfx/Arrow.gif new file mode 100644 index 0000000000000000000000000000000000000000..fb3656a47e778aa60ecf1e8f3a8a66bffed161d9 GIT binary patch literal 194 zcmZ?wbhEHb6kt$bXkuXa0R$TYCaic7kg-BTLxTYZ6o0ZXGBB_*=zs)3Y8^P*8MrxQ zJQ@xhXy)K%;|LH)bYkL`wv#b%P;_PzQRUjQLx6#ymtR?`M#G`uXp^dHQ;g-O1jl{_ z*?BoHHyk)Ki$yW+NMwQ9=^iU?rn@&Tr~A+G$UYY0#h~Up-O9SIW>#>@rP&@EKk;~p muDZG=X1i4DtV!9CiyU0}wsvk*y1v!5ch!=UMw;gu7_0$7m_dR7 literal 0 HcmV?d00001 diff --git a/data/itemgfx/Arrows (10).gif b/data/itemgfx/Arrows (10).gif new file mode 100644 index 0000000000000000000000000000000000000000..54f0962c9c7c48b9f0e560911f33010277dc92b5 GIT binary patch literal 266 zcmZ?wbhEHbRA5kGXkuXa0R$TYCaic7kg-BTLxTYZ6o0ZXGBB_*=zs)3Y8^PvGjMar zXiQ*WY~m2s^2so8U})x6cFXzkVZo7ZHg=u`GYXY~T6m;bERB}9Hi^hivZ)MIa-XIv zDI}oqK=te-CHtm3oP`PJn{*1h?wk}}=0Ddyd6&uqgO!(B_2(z0Lz_Bu!kkHA*2fe6i6@Jyq@LtDUE+y}q?}Rr&hhy@9{w&T3T{+&|R# zd)C?;mvh5sny-}VnKMlzc7fEvS8H-U6-6`6RBirtA~GX#O;7tQnc3ep!q?5|{FnRE KLj7O^gEasdNM>pP literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bee Trap.gif b/data/itemgfx/Bee Trap.gif new file mode 100644 index 0000000000000000000000000000000000000000..b170637305d17a76c8258596e291afc137aad247 GIT binary patch literal 254 zcmVeQY)SvHh8 zF{sI#2diq_`V{NXuo1~(oq5z^(z9*j%5@8OF3hNQ-?EL{bSB=FeL0qGNl_|Up*p$N z1$vdIW3hz|LiRe-C)&eb#|lP_(`wGijXP^r>{#pO%xO>mm7MzX)V)M0gU$Oka>9TB EJKv;givR!s literal 0 HcmV?d00001 diff --git a/data/itemgfx/Big Key.gif b/data/itemgfx/Big Key.gif new file mode 100644 index 0000000000000000000000000000000000000000..026b6ae55da2a264af00ffc814a19c4c738ebeb5 GIT binary patch literal 287 zcmZ?wbhEHbRA5kGXkuXa0R$H;c62CcXlO7X0mYvzj0_Ac3_2h&kXi?hCk&h%G8PF3 z4m5M{i}|c5XkcJuRPvg`!EoS6JGUg4&W{bsM>-j8(ypwS`1p92pu3UD%uNfN`(YI89?r@w*}!)ZjIVC4L)=m&uF6)9gLPWV{@fo#{0$zLit4B|UUPnEf@KpGBHs zD}8pxv1(t`_MIO*bythz<%H^ov+EWIUn4fnqRmlP4W7OVmAU@) f&Bf5v`^Rc8ExK}d&+A3^?nav2-{Z>6#9$2oeh77E literal 0 HcmV?d00001 diff --git a/data/itemgfx/Blacksmith.gif b/data/itemgfx/Blacksmith.gif new file mode 100644 index 0000000000000000000000000000000000000000..30b372d83cca376c6ee7b926c6e15e8cb87a8ce5 GIT binary patch literal 330 zcmV-Q0k!@|Nk%w1VITk?0D=Gj`1ttnplGm=_}E}zuwW=qaL6bqC;$KeA^8LW000L7 zEC2ui03ZM$06+-;01pTpNKl}Gg9r~6T*&aC009LGBup6bp+bfR4Gh>g00002AVY%m z$Z^2Mg$Dx!h*%LK%ZDrrs62`BfWwD4b6PY|v!Q{RKLdbF8Gt5Agc}b=^vINH#Dhr@ zVmv5vBEqUXdltN@Q-D#e8C!OJnicF#sv<+4En738NR=wFe$7}iYSX4r>(V5uG-iRO zekBH-YjdJlmsY`MOh_=X;-iiqAMLtR@<6VXD@*R1ne5}6WUaO&+}Oa*v}#RzW!sZ) z(4m7_x4jw?uF%w^3zzhWdL)37U-JStaF?lYj(d@sG_bTd0J2e&0}Tw=uj`{KW5Rst cG9u8{h705m3@ueFTG&>xex6vGF~fiWJLKkw+W-In literal 0 HcmV?d00001 diff --git a/data/itemgfx/Blue Clock.gif b/data/itemgfx/Blue Clock.gif new file mode 100644 index 0000000000000000000000000000000000000000..b60111ca48e4cea9b069087eda33c15f50125824 GIT binary patch literal 288 zcmZ?wbhEHbRA5kGXkuXa0R#;j0y0);XlO7X0mYvzj0_Ac3_2h&kXi?hrwp7NG9DWi z9Bk%b=P}@5XmDy}lD3n%VDONEkx44+4hO^IBV8;GLLnW6ix2h6i7UmNEK)u_nSqIA zM#siw4V{9F0wSIbDQzfnotwJKdJvzTUK3MN-nfMfvNMYl<)6u%p877jx4csBT9kP1sgpKm7j3ovVtDMBF!>Roz>zLrMnou4q=A$WCjv;R(56Cy3QwXG5cFh9p+#95i21SU%$QK4 zGPMYkB-Nz_9ahw;aDdkVTy_2&*mEPtjyF}RRd_alO`rypDm*H*u0)<#;VKoXR;}E; z2b~IjDwS;0!iW|nNT2~<5$^zO>KNF(CaYZNx$-+NC^<{h^{(xI>a(rkL1ZcCT91sBe~ LJF(NK0RaFz@k)P= literal 0 HcmV?d00001 diff --git a/data/itemgfx/Blue Mail.gif b/data/itemgfx/Blue Mail.gif new file mode 100644 index 0000000000000000000000000000000000000000..f82bcad36031d1e8077eba8ec2973be1be29fb69 GIT binary patch literal 301 zcmV+|0n+|QNk%w1VITk?0D=Gj`1ttvuuzbw=(u1gP-v(qC@25`00000A^8LW000I6 zEC2ui03ZM$06+-x01XHnNU)&6g9r;KTu6Yx!iNPKLM%W~VZ)0A1ZdodaU(~J4k;S2 zcv0g-g&s9Z6p7H_NtP{1dc+6-08N`EQz~>>V88&77Xt_l@UZ2;i9lZ(UCOknK$1ye zCX5KO=1P)QLGBz$wV}$40vguL`n98gtw?ju)C!TO$(}yr3VrBv~fadOVQl*xt#`4+0$k9jj+yzDtO z>eX!zDy)llDAC6;3%rdh_x9|ciVK=94Kd~Dt&s6{E`AnpMTk)+4*u(WU_byn%NKl} literal 0 HcmV?d00001 diff --git a/data/itemgfx/Blue Pendant.gif b/data/itemgfx/Blue Pendant.gif new file mode 100644 index 0000000000000000000000000000000000000000..acbecc1ad9a92ff7731424fd3bf4a376dff5a1b7 GIT binary patch literal 310 zcmZ?wbhEHbRA5kGXkuXa0R$TYCaic7kg-BTLxTYZ6o0ZXGBB_*=zs)3Y8^O!GjMar zcx+g3u$hHZfJ4Axp+l>HxLJ?KgM}{b9Nca!3=E5%+GGrsLNpdEX<%gbD$>z3TI|%v zBUv?tV^i|cW_`vJOLiD1o$og1efDI>CzVr-y2e>51zR*PE%0IwYRNKObZJhoGt=D+ zZ=Eb zJC+8m$u`Y8x6%0cyS3cni>}Sj+B-}2O>xrW{uIvtEj&|7ZeHlOT_4K3tN8S>IPJ}E zU)?auy)Zd;-&V=;b&023y3IswF0EsD=wAG}ceeS{!aYUxufK8cu>APaFEB1XZbrTX GgEasN|A1Nm literal 0 HcmV?d00001 diff --git a/data/itemgfx/Blue Potion (B).gif b/data/itemgfx/Blue Potion (B).gif new file mode 100644 index 0000000000000000000000000000000000000000..31364657dbdba8fe5d4b1b118c24a8acb96f35da GIT binary patch literal 320 zcmV-G0l)r7Nk%w1VITk?0D=Gj`1ttvuuzbw=ul{=xL_zKC@25`00000A^8LW000I6 zEC2ui03ZM$06+-;01XHnD6oLRg9s54TsY9+fB^^z5C{;!pn!`45*B!9u;9jr5D$U` zi4h~hiyRAh9LaJ($%_U7$egLL;X#QMH6k3@aiPPIKXL}&j#YYBZ{(Yk<;KmLR&vg~DFp*9u(m*3p*`OQC7t=@ z(a<*Q${t!5Ceqb$@zNcgoA1!mrit=ix_I$mmW8d>q}(?-U;sUtBllatDs;$dW+Bi literal 0 HcmV?d00001 diff --git a/data/itemgfx/Blue Potion.gif b/data/itemgfx/Blue Potion.gif new file mode 100644 index 0000000000000000000000000000000000000000..8cc533e82e55e92c879576683c89f886b5fab02f GIT binary patch literal 301 zcmZ?wbhEHbRA5kGXkuXa0R$TYCaic7kg-BTLxTYZ6o0ZXGBB_*=zs)3Y8^N}F>rIp zXiR80*vug)6k~DWK?5TPGYbR5fdviSOhQ5x85$l>I4 ziD081i;auiCMsC#l}JodKh&;KEwp3B>HM5=u9+uYXoAN@4e!>#TDc`z zpVj>4YCA7`lJ#-vwGCl==b8Nc_&jhc`_wj`*CsDdFJ)P)wD-43R@e@$zg%oQp&LRr z$ww!B_1?Vd*2DzqZFi$48{A`x;#JaH`Ek>=jZ@oa&7D(T^sL|Uy4YMENrUvuovrU` xW6hS{TVC*VSE<#dypv0}SO4~to$>DC!y`*Sm7V;)>B@s}ZfQN<>je%B)&RLse^LMd literal 0 HcmV?d00001 diff --git a/data/itemgfx/Blue Shield (Thin).gif b/data/itemgfx/Blue Shield (Thin).gif new file mode 100644 index 0000000000000000000000000000000000000000..2c9f77705eec0d26f77c07e53c83600f3b9903cc GIT binary patch literal 190 zcmZ?wbhEHb6kt$bXkuXa@#DvY6)yrZR%mEwFdzZNpDc_F3@i*fATf|y2aaY2P7WE5 z4G#`5GV^e`>?iiE{Mv{ONMM91PX~b_qXF literal 0 HcmV?d00001 diff --git a/data/itemgfx/Blue Shield.gif b/data/itemgfx/Blue Shield.gif new file mode 100644 index 0000000000000000000000000000000000000000..196c216e18080f2c80ff7f60367bf4fa56c262e6 GIT binary patch literal 212 zcmZ?wbhEHbRA5kGXkuXa@#DvY6)yrZR%mEwFdzZNpDc_F3@i*fATf|y2acHxoE$P9 z8x|aF<`CA3$tXC$z#yRP)$(G3qGP)ND+k8`!v?o5W}PmX&JB+oC#x7TUAS>^F~bBE zeY>6xqh)7jTNK|4dAT9oe}-~smW-9i3Xg@-)^#iapI`Vaax4CI#dGVbtE(e6XQkdK zNeEwOT>Gnst87u^GR0;))hLnNQ(JYX*ZFpsyz}0kWvup8!~AXZ-rCYtD%x9@pJ-sP F1^_#3O#%P_ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bomb Upgrade (+10).gif b/data/itemgfx/Bomb Upgrade (+10).gif new file mode 100644 index 0000000000000000000000000000000000000000..65e0675e323aeedeea0bc9a0d88e9d8b8ca85015 GIT binary patch literal 292 zcmZ?wbhEHbRA5kGXkuXa0R$H;c62CcXlO7X0mYvzj0_Ac3_2h&kXi?hmkgX7G9DWi z9Bk&`<%_UjU}$J%k+pK!5zyeu$Y{j2VMgF0mu>-Jy)Q2&Bpz<(@t(&s^TUGU)414U zL;^l0`A%Sty0=90^0QM@R3gPpEQ?jV7R$9Bia90n@JORStDCLIlyu+8zS(I|Om(N8*BmbpHC(rfuXaD^>N*)+qm?x|;>QQD?7<~OoYJ5BFS_AKU`^V+N| j_Gne2w@-|;>bsi`nV;81SEb+Gw!eGv+1}Cw2L@{Z{4;W$ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bomb Upgrade (+5).gif b/data/itemgfx/Bomb Upgrade (+5).gif new file mode 100644 index 0000000000000000000000000000000000000000..5c9439271e31458d46c32d44218c4501e92d5d9b GIT binary patch literal 296 zcmZ?wbhEHbRA5kGXkuXa0R$H;c62CcXlO7X0mYvzj0_Ac3_2h&kXi?hw+x&dG9DWi z9Bk&`<%_UjU}$J%k+pK!5zyeu$Y{j2VMgF0mu>;!usu62EOu_=^=o*M#VTHt`CIqJoSO3VNTWZio9w9#%L3bc-P5*MEl_Tl zWtn^GiicUl;U0}}zAK($FPye$1_p^#e^$A>*mL@_qr1#v)-ruv@y#@5 m_x8y_@3JK|<8FCXE-tH{`6Fg-c)Ir;-eP^n=giDZ4Aua7sBoeH literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bomb Upgrade (50).gif b/data/itemgfx/Bomb Upgrade (50).gif new file mode 100644 index 0000000000000000000000000000000000000000..7a5b9a3817fcf80444c60597be73a8b8478e78a5 GIT binary patch literal 291 zcmZ?wbhEHbRA5kGXkuXa0R$H;c62CcXlO7X0mYvzj0_Ac3_2h&kXi?h7Yv*nG9DWi z9Bk&`<%_UjU}$J%k+pK!5zyeu$Y{j2VMgF0mu>;!usu62EOu_=m0!j)^TUGU)414U zL=1$M_)KDsx^_fj!4l6YYN0_cGcPG$m~WY=70Xrp$YD9tLOGYrVim7t%En=`7X%x8 z=bERdsmvIMjfr$nQYk2O8 zO|!b9b$D$@`nx$fF(O(e_yR++C2o9Ae`c<#x`Yn(TSbH6i@{<0!)_v)+XR9}T{ je6?X_w0c;kwf@U9rLVv3dmEMX@nP>*E){PB1qN#XrHFH@ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bomb.gif b/data/itemgfx/Bomb.gif new file mode 100644 index 0000000000000000000000000000000000000000..7f578fe69f1995ad294930f58eaf5550a8090702 GIT binary patch literal 269 zcmZ?wbhEHbRA5kGXkuXa@#DvY6)yrZR%mEwFdzZNpDc_F3@i*fATf|y2aZb&oE$P9 z8x|aF<`CqIuwYYG>uCa&~oGfouJ<(m9FpiP$X%pS=v zi##XutzA}g^XuxHy{0?4VrPqKGA;xvo6Cu{&m|(_X8v+_Up+ zW5ZmzORN8 zHZ^IKq|%u>8BYBfHEYJLPk|cLIkhTMt0r@nC3zNPQM5QU4sFZ!ZPK(@!KM@`GOSp# z2?Hne`c<%DuVAZ|#EaPA#;S1%Yn96tt7NGKAX21g(K6wheh)V0S@-T$nsUwBh5MIj zYNLGVnijkE=xVn&@zy4)m^Vz_uW>6rdo}UO+rDSZ6#6qZfY6?q`-K{Pvf;xF0|Ed$ D3G08+ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bombos.gif b/data/itemgfx/Bombos.gif new file mode 100644 index 0000000000000000000000000000000000000000..f5757b083b7c83c99e00f7ff13d2c74994210da7 GIT binary patch literal 271 zcmV+q0r37uNk%w1VITk?0D%Ai_|Q1Gh#)8^C;$KeA^8LW00093EC2ui03ZM$06+-f z00#&hNKl}Fg9r~6TsZI`0003Z26*^TqQ#336%KGn@!~{^AU#IRD1abGkrG3G)W~q7 z0FWw2Qe@fiB}9xjV}67QKqE(<6>(Z5+0r0Fpgj>5Wtb3Y!lg!o>hwso;K`IXhaycH zH7ib@RA(Lqs#U62nLcfzEbF!E!k=w{(u7(w;as{*?cT-f5-!N6c>Q+7>Nc<0pePG> zWxEzD&8srQIxXoEF;%(}c0@Jbl~tnJ zq5b-iai$(642Nd;vRde@DtPMAWi|CtjYW}G<5C~jCf1o@DnZLVen++by81GBi=uJg z*Q#Kx#A9)?PHlI#Cf+{PQ#$SG%`&67xk{4jYoi4l9vq!x%IwfnWb$lx=xM&Cr@y^Q zpInrE-8AyY;+IFZ`?GQIO6NrFsS*CYwrY;a<%iAx`OQ7cVLl zSwJI0g%ne&T$%Bp$B!RF%ADDfpvRXmbHXHPlB3R_IcpZg2^6SMjS7=0U8)q}&5aSG zO0|fws;u3frhZNA-`7op$3 zfBEta{57XonpX9CeW-ORSH(UDOkGKptXav8r9K{b`RvZMT_dYKEYmX9#UDqGEwEW& q=b{(Ynnvw8XkyNV1@DbpV5M)BvpL=!ZnrPd+Np0N)eW~`Kma?5r+UKx literal 0 HcmV?d00001 diff --git a/data/itemgfx/Boomerang.gif b/data/itemgfx/Boomerang.gif new file mode 100644 index 0000000000000000000000000000000000000000..fed694ba29132c73abe1a4f70405dfb681b148c3 GIT binary patch literal 167 zcmZ?wbhEHb6kt$bXk=iRu;N8P#tID$4F(1V#h)yU3=GT+IzTo9NZx^?f`Oew#$&?+ z21X_(7NF=t$7T*ut&|f2i7uU@tTuOkd{}g(mDg14ONXI~W4Ds!sy7*dswaD-J^f59 zjS^4x7&%(WR0uvhHQ%9`tM}%lWdB(Lx##Xw24#9Kvze>sEBRH~bqV|2xVtkir-!f6 S-^gXdWtw?&AuBTzgEasi%Qb@l literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bottle (Bee).gif b/data/itemgfx/Bottle (Bee).gif new file mode 100644 index 0000000000000000000000000000000000000000..d16add0f83e10a2d8060eed30c28f886ff9468c5 GIT binary patch literal 277 zcmZ?wbhEHbRA5kGXkuXa0R$TYb|h#30Rs|H{K>+|z`(+w0}=zNb>O(gz{w%wQP6O( znS)m-=0w2)M+O09ry352MCV2kK{gJB1&bLvWd;3Y4j3dKnyjQfX^+Q&C$7_VeEVD~ z3sO!p8Vl#$$(WGtJ5?w8-;^1~FMJnyG)f)q2v+r-;pl6ZoAq(U<@t)UpKW{3QX25SJ%ziej! literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bottle (Blue Potion).gif b/data/itemgfx/Bottle (Blue Potion).gif new file mode 100644 index 0000000000000000000000000000000000000000..f9c1560b588cc5418d0a5af98a260c2cfa801dc7 GIT binary patch literal 287 zcmZ?wbhEHbRA5kGXkuXa@#DvY6)yrZR%mEwFdzZNpDc_F3@i*fATf|y2aYEUoE$P9 z1q}zAIe3L)P82L~WDrnxs^M@*bZ!)3&A4+SQ29t7lNw*b48bK03>wS@B9(%V8K&`S zM(xokPI2zgOBAc&Jn-b?6b<{lE0UiVxO8$vi`kyqvdDL-N7jsp+4583F}`SG+7$j9{GLy^WW%e8rs=c4zsK>z?ALX2ntqQZs(B}%ktAb`gJ8!2*R zsPUjjgeMP<#CV`2Mwcv0A{0PVK*EX?N#eX&pa6lN1bW_F`BLS?qX=0x40#l(0i^|Z z-b_d|rc{n4t48I>k>*UBS93ZHYw#yRvt*x+ClN6p)Q=NR&PmUnN)y1jvql1jvTnM v0kmZaxHiqxCs3iCTc>pkw}9NViczXIm@@Iw)qI^&Hd;8T;LJDm1_S^*Y^r?t literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bottle (Green Potion).gif b/data/itemgfx/Bottle (Green Potion).gif new file mode 100644 index 0000000000000000000000000000000000000000..bb443f2c05e6063a50eafcf92e2b78d8219580e0 GIT binary patch literal 287 zcmZ?wbhEHbRA5kGXkuXa@#Dvg3k4n%3^X(}7?6PCPZmZ71{MY#kQhj<1IH5vP7WE5 zf`)_59K1p?CkhrgG6*O;)o?f@IyZ{2X52XusC=Z4NsTXIhTxJ01`Xx{kxIeG4AXcu zqxNVNr#N@$C5qK>9(ZzciiUmO70J&FTsk?T#cWS)S>(Iaa;}<>#}u{mD}z^C?XhxD zc3vix{Z52SXocGp?YVt#Uw%#x*d}*XulI%U%itB(%O8bynLfPNDl*$`4rl0_m_uQ% z-%NYVKLj3Y-KqEN)bvlj41t2eD_)i=MleqB-p0#WzT(abyR-j%ydz577vx9YFO4-* fjl47~Ge1N&{PV5bnOmbubFP2Cx37YkiNP8GIIL|m literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bottle (Red Potion).gif b/data/itemgfx/Bottle (Red Potion).gif new file mode 100644 index 0000000000000000000000000000000000000000..3613a148694d09fae65747f6dddbc6b72a347200 GIT binary patch literal 287 zcmZ?wbhEHbRA5kGXkuXa@#DvXf`SbiAi#hG6o0ZXGBB_(=zzpPY8^P9FmQ6ncoZ}o zZ06tz^f*{O!ZA2}K4zH4s~NRN zqd3L6LoZRRhV#IalT$S8^R7sKUf|Nn5iMqWYRe+urIvHmd_1P8onINe+G>xLgR=87 zsqA+mTtX|{rfARYd;9WpdcZcht9rdJgkJ`)uwMQsw9EA2y;hOgZgV(8-^3gWbNy!8 zWBwuVSnE!`XQ!rr@?{7V6khSNR55~ag7-FF&hiy^R@j~W=i?nw;=Uk1@_uQonQG*v cS(*7Evf-a^-Ok(^Rho1C`@MY?%uEc{02jP%6951J literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bottle.gif b/data/itemgfx/Bottle.gif new file mode 100644 index 0000000000000000000000000000000000000000..477de6cfb88d30fa5e697c6eaa45072aa1acb189 GIT binary patch literal 247 zcmZ?wbhEHbRA5kGXk=jc@#BYvh6V!|DE?$&WME)o&;jv4@(vs)7+5)EJPaBRHgoU_ z#hfTu;K(4L>{P?ykm%efq8Zl`VQ}CG1COzqOy`Hku03+vO*tB$mNZP`wcO{ExpDEy znJU4H_Ec_Ma-@SJw$10~=XBqNO2vmtW`<~Ps=6p_zyJ1J^eF z<(jhkLZ9+^qpw+EZ_g}p?O#`$6{>f7ZQRRwN3u#*-(F_<^;)iVK-!J%p~?T=WQ8s9 vY3mo1&$ascE_g;Iqk-HRvGwsQ=2>%>d3@2jdC~c&7tbrPlBk7@j11NQpVniB literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bow.gif b/data/itemgfx/Bow.gif new file mode 100644 index 0000000000000000000000000000000000000000..18ee3d6ce3584914e3c7176c21ea8020b0f45843 GIT binary patch literal 188 zcmV;t07L&rNk%w1VGsZy0D%Ai`1tt9STHCkC;$KeA^8LW00093EC2ui01yBm06++h z00#&hAfTXtfd~fz03fhnfQJDJB3y{jAw-D-C=wI^G2%gm04zSlIFaE%ksbwVY{>EA zN0cNJ!u*&pqsf^iE4Cc@aplI27=7Zj$r30{n?q|FJX(`wOr<+hHeHw$WKowne`2+I qGHOthS9z)gt5qz~u13e|OnWx0RE<^PdOb>YE>yNnH$EL05CA(OYCzWj literal 0 HcmV?d00001 diff --git a/data/itemgfx/Bug Net.gif b/data/itemgfx/Bug Net.gif new file mode 100644 index 0000000000000000000000000000000000000000..2795115f6b93e6509ab49f3998f9cb6f34ce150c GIT binary patch literal 295 zcmZ?wbhEHbRA5kGXkuXa@#Dvi9VaR(I!;6wXlQ6Kz<}aU7DfgJRt6oA07$I^#~TK2 z4jGRP35^UK!b&C?0*VX_eDYo{9t)Hh8JV<_OgaP?JGIC9GNwh{ zi7-fV>9J(~vBYwkwqw71Dc{tc7oJ?$F3Gth=hYO|;3cKr_s(XAzYE-_c6r;`*=Db< zt!xxNG-btC_0XeX@j*E`+g@Mon6z20EXVSV^MD rAMWWX0Xwq)UJB*fz9Mf=1MfRtzXFSokM{SAo2;wJESk*7$Y2csFk*7} literal 0 HcmV?d00001 diff --git a/data/itemgfx/Byrna.gif b/data/itemgfx/Byrna.gif new file mode 100644 index 0000000000000000000000000000000000000000..439ad8289c9a06b2ac5ebd65c54e9039c6a272e7 GIT binary patch literal 189 zcmV;u07CyqNk%w1VGsZy0D%Aikf`WTXs9SCC;$KeA^8LW00093EC2ui01yBm06++i z00#&hAfTYZfddN$SQtPdLjV8@B6J8*BEp0M7FHB6Q2<1S4#{YAFdzUs$Gk#U literal 0 HcmV?d00001 diff --git a/data/itemgfx/Chest.gif b/data/itemgfx/Chest.gif new file mode 100644 index 0000000000000000000000000000000000000000..68e07985a91ffde7a3686744cd68e3aad44699c4 GIT binary patch literal 289 zcmV++0p9*cNk%v~VITk?0D=Gj;NalUs4&22Xn;UKFfcFx0000000000EC2ui03ZM$ z06+-t00{^jNU)&6g9ZTr5GbIbLxBnvGIZDw;=+Le0tg(yv7^9@88>$1_)#N9lOs!l z1SygvfsiLf%6!R^fJ>J!ONvy8vnEHL19YBTxiX?r07QurOvC&rBvSDMMow;&mPpAl~#=SaMtY{`sAlU{TxpsiJz z233kQEBLP0mu@vuZRzr?SDsuSfBh>N>QSv+9a{!VQ)gkFC-d5ET34;+igXi~-5YhT zS(2-Twnn|SZ^XoAGsbN^61G9#U#IGA+ncH3$zX>Q4JxeYu%kkT5Ep{P zxKU#P0w_}sSjloFN|yvOA~dj3BuS1p3nVPi(PIILHG%T%89=5$g(z$Gta-8M#-utA z)=WvDCCr*LrPkbPG%L-aAOS?2__3i+lRZODTuTwG*{(Q!h7B8+BtfM_%Z8jQw&Xyh zDhF`o3KObHs#L8Gc)2)cRIgtL`-M!ovRBDiEi-+)ap`2O7D0{`+SIPrrfSK$HGOwz z=+SIBHihfjr_ix=owg?Gly6Ahv~%n28#ZTa;Uf3W&3yEv^qu0#w}jdi^7Zxw0|Ed$*`bab literal 0 HcmV?d00001 diff --git a/data/itemgfx/Crystal.gif b/data/itemgfx/Crystal.gif new file mode 100644 index 0000000000000000000000000000000000000000..8492f4c7309c824a5f29715ec06e671ed83dc8e4 GIT binary patch literal 230 zcmZ?wbhEHbRA5kGXkuXa@#9BY>lOcul^Plv3`junCkrD30}F!=NDQRbfnzlTCx?v3 zh6M+kIe7Ub1QZw=+8M;ue0BshxH9r8GG*Kdcyy#$)UfEwkB^TJwX1kHrJM*}XnkH5KC??`^s>@s(_6s>LHz{A5WbArPM9TQdmF0GeabF5DZnL#9c_?m8P8vhLO#@5fmsQK2tg_e$rk`#L*(!}%4a ZKdZK8{m@Q6nz;SkS*x3CPBk!C0|1p&T4n$M literal 0 HcmV?d00001 diff --git a/data/itemgfx/Duck.gif b/data/itemgfx/Duck.gif new file mode 100644 index 0000000000000000000000000000000000000000..df8edbf33ff88b2df23defc5288b5d81df1b42e5 GIT binary patch literal 297 zcmV+^0oMLUNk%w1VITk?0D=Gj`1ttv$RJR#koa&g$S@EnC@25`00000A^8LW000I6 zEC2ui03ZM$06+-t01XHnNU)&6g9Hl{2oOM_!-o(R0+>kgAwq=$GHRp<;33104GUZ> zK%gXnhzd(S9KdpbLWD36MohRc07s4wCrZ5e5+=rt6g3J^*m3~Fo(3((T*|bmOp#4d z7QpF{A=R86r)IsGHL2E#8M%hdI@6~^p;U_=h3Zvh0ii-ywp{BKBvJ!P%R1f5x3Ay7 zfbl}4=~U{~noq@xagr1_S^*wq1F8 literal 0 HcmV?d00001 diff --git a/data/itemgfx/Egg.gif b/data/itemgfx/Egg.gif new file mode 100644 index 0000000000000000000000000000000000000000..b848c53c0088045a6a134419ff7e69bccdb0eca7 GIT binary patch literal 231 zcmVn!N>(gFvPGv#1bcPqR-j5(vQ4S>=-akb!N!GYRVvo1Q1N2z`?0Q5!buI= hL`-n6MxS?gmR#9YuK=%@1EWodc`Vw*X2}Kw06R^JSup?r literal 0 HcmV?d00001 diff --git a/data/itemgfx/Ether.gif b/data/itemgfx/Ether.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd3e7294f46551e7901e23e21757681704b81561 GIT binary patch literal 267 zcmV+m0rdVyNk%w1VITk?0D%Ai_|Q1Gh#)8^C;$KeA^8LW00093EC2ui03ZM$06+-b z00#&hNKl}Fg9r~6TsZI`0003ZN__ZGqQ!{-6b^6*5hKNqATI`ZsL`N+iXumLv`A6_ z!-gj*MnpN2Vo8`ZJ<3eUGNa3lF?rU^S@Y(?gdlAqeEAY-QlCZ{aui7vW7Me^KMGZ; z5o^z?cT);lw;C_d`+%}tCX%+j67Q& zP5X6aO2s%G50%UoZPlb(i;krX7PHvHoy~q`tX8yU!IT@9y?MCo<+cS|Bd+|@?b@1? R_r~7*cWL0odie$f06V?wZJ7W7 literal 0 HcmV?d00001 diff --git a/data/itemgfx/Fairy.gif b/data/itemgfx/Fairy.gif new file mode 100644 index 0000000000000000000000000000000000000000..3f461512290bfe38e8597c868dcf23f428be6323 GIT binary patch literal 336 zcmV-W0k8f?Nk%w1VITk?0D=Gj`1ttnplH}&V6c$*uwW=qaL6bqC;$KeA^8LW000L7 zEC2ui03ZM$06+-;01pTp2mpXU0|*leEI9B$L52+@CNw~R073y6Gh#$IpyPmu4h;@O z7$5-00R>VPm{_ut5xAGL}^(*I@J2(3TfY3A3jbsIAHVXi5 zW}2GYO08;_K;PAFAG!|P)New@O9_5%I5BW-yjkPUWZY5Z%HJ+u?j_xua!KQZC02hL i)njtP+9w_re$3k`aJ}S-FMi25ec|)&heie&5CA*FVuuj` literal 0 HcmV?d00001 diff --git a/data/itemgfx/Fighter Sword (Thin).gif b/data/itemgfx/Fighter Sword (Thin).gif new file mode 100644 index 0000000000000000000000000000000000000000..a34335f279bca60394753b5168c9fc91077473b9 GIT binary patch literal 154 zcmZ?wbhEHb6kt$bXk=jc@#9B8#tID$4F(1V#h)yU3=GT+IzTo9NZx@Xn}MA}#$&^R zgNzJ9OcoIV4-Yjnv9QeWC`@u`li;^HqfwxItV2}4NakkXLyvyRz@(5&gGJ60byb5} zI1LvuOtL6`r8D!x63;#z(|dJj=XBJFMZS2{H`8u_MEeA2l|Fh%uu{kP%HT9BDD- z$&VZ_8muUDrOSjgEdscyvZv3PEO(atDKKYEi6I9V75Z~yfQv^5f<)+)qtlv8Z&nS! z^I*=dM3tfh8@8<3vrDZfk%lrY=8g5_2g7!UwEpzd4! literal 0 HcmV?d00001 diff --git a/data/itemgfx/Fire Rod.gif b/data/itemgfx/Fire Rod.gif new file mode 100644 index 0000000000000000000000000000000000000000..fdde5d16b7f4d83d0de0662c42b827fd07de1fde GIT binary patch literal 215 zcmZ?wbhEHb6kt$bXkuXa@#Dvi9VZ?X6l~A{0R|XQ{K>+|z`)9&0}=qKb>Nu8z|A4! zu|T1*k%g0iA)w&lp*9|VwGs(I#Y0VuOg2+0CLU;DWOCyA5wT(M!O3j8VhuY2mpb%F zY46gJ*tGO$lM3&%8czk~(;aq}>)y;XbT~PaOI9wF^Rim-BEN}xr6-GDU7lrRT_<8$ zbRc9-Txr|WofDOgOm;jgWZSiAZNNO&-hFddl<3{u6;dDNJHs&R_`b+|C*D8i&*CN* JGcz$*0{~D?O+x?x literal 0 HcmV?d00001 diff --git a/data/itemgfx/Fire Shield.gif b/data/itemgfx/Fire Shield.gif new file mode 100644 index 0000000000000000000000000000000000000000..b4a151c7d71d07676e3007d4027d4c9b2e2719ef GIT binary patch literal 254 zcmZ?wbhEHbRA5kGXkuXaalv9ohr$U12@MSm1|*>PlZBCifrUW_BnDFJz;T#?lS9U1 z!-9j&9K3uHCpIJ=ZebN?Vo+GH=xDb%GfMBx$WDlSvS z)WfDo3OAhYlUILrrBZn5`S}ikW_NaOR&}0i5WddjS5bopqltTyisgdL5Jo9=ySbU0 zwazhyhX?V#x{!EbbH?RWv8Sgw+}s}5YNWF2a>n^7365GvcNyy4+fe=Up6U#f0@q~~ x^O=@eep?^6B3RzsEy6;(VeJHV_cOB%8$!-iSkh)iZ6gIhndqmv3};o^oaJ^w{2 z43ieS&*Uy_O1XLIna?a?=SebALeG6$MBIdeRoD!qF&Sm z=&Frxk1vQSZ#wJoz3}=mQOl~Uzi)i literal 0 HcmV?d00001 diff --git a/data/itemgfx/Flippers.gif b/data/itemgfx/Flippers.gif new file mode 100644 index 0000000000000000000000000000000000000000..c1cc581452191cc3f4effcc45711c572511d04b5 GIT binary patch literal 306 zcmZ?wbhEHbRA5kGXkuXa@#DvY6)yrZR%mEwFdzZNpDc_F3@i*fATf|y2afLyoE$P9 z1qT|M*!YEFP6#A6Ffg$&FbI5nc(_wck;|aNAj!3tO}SSBa{AC?TgE=orux(vh%KdbbMYS^J$*jlXbi{JGnRUPAFY|`Dn@4Nj$%$ zmcQxui=8Z@yZha>3q}0azH6dB-oKYudi`8<*w4(vD`(ra%`14H_NtVZorS>~0M4^` A(EtDd literal 0 HcmV?d00001 diff --git a/data/itemgfx/Frog.gif b/data/itemgfx/Frog.gif new file mode 100644 index 0000000000000000000000000000000000000000..e3c00a4e291394f1b2059ee9477e4901b0b20af6 GIT binary patch literal 342 zcmV-c0jd5+Nk%w1VITk?0D=Gj`1ttnplGm=_)u`j*kE9=U??akC;$KeA^8LW000L7 zEC2ui03ZM$06+-;01pTpDA0hxg9HyEB*?I!0RjXR7MMtJqC$uU8#)XSz#vDC073%z z*wFyTj2aax956tDO93oZF4TCyU`U$)6y7wjlcqz92Sp0ac@Strj{$(PjCpYB0D}`x z8aQe)DMgu3DN6NOljl&KU#D{IDl{w5vSMi(gjf-)fr=Q@rhG_Xs9gYY)mCkLkfcPd zB@@2AYJjCnr-z>oHaeH1(xq9qj&&?O0?%>uRHmI_PI7< z(Tapyqom3-m;|{51Qskh+9fRNH>W~yF+&?WX8{j`(V`Rm{Kif?3WbYL zPtuXsGI?3_j zRqBA|)m3cU|DAa$oPKax>fx}~&VUye7BR0`RbufyD`+m~#eWM$!~Jtqtsj!ocq zOj1$U{PgrpQ`f#bCnqmIH_y88(4QSe8i(c>#(IfVU49m{TyC40AZum~ftrg~1vCAh$Wn literal 0 HcmV?d00001 diff --git a/data/itemgfx/Golden Sword.gif b/data/itemgfx/Golden Sword.gif new file mode 100644 index 0000000000000000000000000000000000000000..54cd4a1397359821909f704702145e2bc0c04cb6 GIT binary patch literal 283 zcmZ?wbhEHbRA5kGXkuXa0R$H;c62CcXlO7X0mYvzj0_Ac3_2h&kXi?h2MnAXG9DWi z9BgD3(({^3y|xZV`LF z3{8PWuAK_9YD-QSJ9sroh3`_CxmnR`p-Jh!J&{wEo$W9zJm>RDD9d%Fn|RjV%D}`+ z3q*p=VrQ79Ml5vf^z-e$@-%Q#R(91=t?inz%~8+qiJrW=?()*G)OWR3A6F%;YFR9| zEIYXH`oV^oerIP*-{7;~A#~N&&d8U?Hm4ZBvfZ(Hxj%#D&A!k`t9JoAR+>)dsS5cT ab<^H;U#oUl+4Eid)OU;iD=l$gum%7`T5#w9 literal 0 HcmV?d00001 diff --git a/data/itemgfx/Green Clock.gif b/data/itemgfx/Green Clock.gif new file mode 100644 index 0000000000000000000000000000000000000000..9e5a666ea4500230fddb3d9d2d6da5da23ceee52 GIT binary patch literal 288 zcmZ?wbhEHbRA5kGXkuXa@#BZb1cMU>5*ivB3`junCkrD30}F!=NDQRbf#WFyCx?v3 zh6M+kIoNp&I2an7TA8HnWG)yyY+zuN%DThB@c2jjA8F(-?ZPfuoG z;h52}F|DCfkWoOyvmwQ;PdM{l2xsBafY}z2TCt}>R-SCv<3FS$6|&T&%c?p__U8q) z<9()y@6Kplcz%6zg1uEp7I$6c5?XdMfa9h%3X^R&pmb0=Io-a)?W;-Uy@q=Yf0C3 h-8ZWX+s~D9i*LzWHm~^f+3ueuZ}(MyW@BNn1^~#2ahCu9 literal 0 HcmV?d00001 diff --git a/data/itemgfx/Green Maiden (Body).gif b/data/itemgfx/Green Maiden (Body).gif new file mode 100644 index 0000000000000000000000000000000000000000..6c9fad9934f9e0c41d37490b94ee5566e9ab3f47 GIT binary patch literal 313 zcmV-90mlAENk%w1VITk?0D=Gj`1ttn*g%NbFz}#gs8}ERoz>zLrMnou4WPy|rCjv;R(56Cy3QwXG5cFh9p+#91i21SU%$QK4 zGPMYkB-Nz_9ahw;Fo4$pTy_2&*mEPtjyF}RRd{xQO`rvoDm*H*u0)<#;VKoXR;}E; z2b~IjDwS;0!iW|nNT2~<5$^zO>KNF(CaYZNx$-+NC^<{j5S(xI>a(rkL1ZcCT91sBe~ LJF(NK0RaFzXT^Rg literal 0 HcmV?d00001 diff --git a/data/itemgfx/Green Mail.gif b/data/itemgfx/Green Mail.gif new file mode 100644 index 0000000000000000000000000000000000000000..793ec1ad0321c4b783388dc053c776e3272458a3 GIT binary patch literal 301 zcmV+|0n+|QNk%w1VITk?0D=Gj`1ttv&^VaTaJYydNRTinC@25`00000A^8LW000I6 zEC2ui03ZM$06+-x01XHnNU)&6g9r;KTu6Yx!iNPKLM%W~VZ)0A1ZdodaU(~J4k;S2 zcv0g-g&s9Z6p7H_NtP{1dc+6-08N`EQz~>>V88&77Xt_l@UZ2;i9lZ(UCOknK$1ye zCX5KO=1P)QLGBz$wV}$40vguL`n98gtw?ju)C!TO$(}yr3VrBv~fadOVQl*xt#`4+0$k9jj+yzDtO z>eX!zDy)llDAC6;3%rdh_x9|ciVK=94Kd~Dt&s6{E`AnpMTk)+4*u(WU_bynN;iBa literal 0 HcmV?d00001 diff --git a/data/itemgfx/Green Pendant.gif b/data/itemgfx/Green Pendant.gif new file mode 100644 index 0000000000000000000000000000000000000000..9db766fef164ecd4a2f41bb1de8f2efb343719a7 GIT binary patch literal 326 zcmZ?wbhEHbRA5kGXkuXa0R$H;W?U%nm|&oxp}_zHia%Kx85md@bU*?iwGJHr8MrxQ zJQgfC*vP^w=F+htp@D%*-mZjWV#ARxCQZGR8xw#^xmY=FteBvDyos5uBSte}(eZu* z&9s`88y>j#n&t}`L@rQqo~^*Ui)GhG6~>A3uFHHZLoyiVxn)PKk@)!X{B&_ozuFa- zSDc<1y7b(iSs#*v=OoS*YhAS=`~1qhN~Ts$hnGP!1FSdsbed>fY_7boCu_4{?ftop z!rV18BHo0~uWU?n^_iF*u+yZN&35)q<;azDjwjXJF4=VYSzI64ajPb+W WY}MM_b=L{)vb`%;YT}4w^U4kTR&r*&DFs`d?3Soyu_;Nv6f4^F zS(H{`!cAFuZe6Rjo35s76gShwiwBP^eYIxRrA%KIj+&5fRpm5kBE~uRFZ1b&DdRnC Od@p3+j12?<1OPk4+=Uka literal 0 HcmV?d00001 diff --git a/data/itemgfx/Green Potion.gif b/data/itemgfx/Green Potion.gif new file mode 100644 index 0000000000000000000000000000000000000000..591fee95f10c81123d7ff385a9dda295d7a6d4c0 GIT binary patch literal 301 zcmZ?wbhEHbRA5kGXkuXa0R$H;W?U%nm|&oxp}_zHia%Kx85md@bU*?iwGJGg7`QoP zG$u40Y~~OYim|xxpn;KtnT3Jjz=DQuCLy7Uj13QtwF~e!v2+S5AL^FjtdKcb;b^Gtqzd>*)!eQF!eYm=9!m$Ix?+WXriD{P0>UoJMD&nM#-vAH6U0QV zdQKFi9cPeF4AV*46|NMIk{2I zyZ7&<8FjxZs@-cH^ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Half Magic.gif b/data/itemgfx/Half Magic.gif new file mode 100644 index 0000000000000000000000000000000000000000..ae039e5ba6d89651654e59003fa736a3993b0f1a GIT binary patch literal 301 zcmV+|0n+|QNk%w1VITk?0D=Gj`1ttv&^VaTaJYydNRTinC@25`00000A^8LW000I6 zEC2ui03ZM$06+-x01XHnNU)&6g9ZyIT*y!%LWKYTI4sz(VgZ5>BWm2pkN^PzAVY%m zI8k6mju#Cm^ypFKNCG7XW{iokKuZBMDHezrb0tiRBvYE)xly7}l{Q%_&3RH|Pm2r@ z4o#R;>C2!sQ9i8tQz}xPM{C~9ITUKm0cZyV2!NI;)RaDz%I&IiCS0x}mmalC7HLJV zf4vGGT=Q*Mom8#5#HtglSh-i}4%J%s?N-MJ<4VphjE zhm6OD1V$zn291~%1qT>fIh4KTXiQXaVw7N2Fwqc5Z0Kh+<8yhjVadr!O4dRrR!n3# z-mGoB>`BB%g`=~D{a?u_6h1#WQ#^Io5=r65KHaX-`$8&9Rt7Keo!G=zZQ`x|sueUXFmch^EaS{u3*2tb6a6K$?$T0IPBs<>YXIC$Lx%tW literal 0 HcmV?d00001 diff --git a/data/itemgfx/Heart (Blue).gif b/data/itemgfx/Heart (Blue).gif new file mode 100644 index 0000000000000000000000000000000000000000..ead09923bcc1bb5bf529fa10cfde8284796b19e2 GIT binary patch literal 146 zcmZ?wbhEHb6kt$bXk=jc@#DvY6)yrZRxmIyDE?$&WME)s&;ha;K=KY8$qeiqG9DWi z9BgJ`)esR_u<&p@m!Q|2hyumK3}VJy9y>N9x^yWxcgbW-eC*!J%gFGdV&fBrZvIH6 y63b1?&d#xRXraRl3DY#6okkkoy@tv2-mEA|c3mc){_Be8)>j7_7_0%)bTiQa literal 0 HcmV?d00001 diff --git a/data/itemgfx/Heart (Green).gif b/data/itemgfx/Heart (Green).gif new file mode 100644 index 0000000000000000000000000000000000000000..b9cdc4b0dfe51e2537a18c5d475f1db7dfd42eb8 GIT binary patch literal 146 zcmZ?wbhEHb6kt$bXk=jc@#Dvg3k4n%3>X*~6o0ZXGB7YR=m6OaAbAIlWCnH)8IKJM z4mPu}YKRCdSa`UdOVDdhM1kUA1~FqUj~yElUAh#UyJRvZK6Y>AWn}nJvGEB*H-Ds3 yiRGqcXJ=a!w=MZuw9sLOglU@3P9qKPUc=;hZ&s8fyDpPY|8>Q4>#G9|4AuaI%rh|n literal 0 HcmV?d00001 diff --git a/data/itemgfx/Heart Container (Blue).gif b/data/itemgfx/Heart Container (Blue).gif new file mode 100644 index 0000000000000000000000000000000000000000..3fb54bfcb954be6943723a1e1216ce9b9e8e791f GIT binary patch literal 232 zcmVCMz{a2h;(^pUaLi!f z<&cS3aNs~Q3%6EGhk@eZHa0FH1%m~T8k%^yxda3hfJ!A4vqS`p79Z;6=l7c9@o|yk zL{__LK05?c8~bF_xpZcHRz1?en)B~YrE$Z#7U6KYSj&x%0vBnv+qp&rEc0LGXj#Ql zS-Qk`j@xcMnctJsZ!C0Z^*U=My2@!w+H$=uJGVFl?PhspwspnyrI%N`L~fhnEtcrO GU=08alO~U{H literal 0 HcmV?d00001 diff --git a/data/itemgfx/Kiki (Body).gif b/data/itemgfx/Kiki (Body).gif new file mode 100644 index 0000000000000000000000000000000000000000..39305489586cb0de33119022262fe044c5ae164f GIT binary patch literal 238 zcmZ?wbhEHbRA5kGXkuXaupnc@gdaB&5;i1g1QeXm(9mE21I3>#j0_BH3_2hlNUa0M zW(Hmk8IKJM4mNWLYsF-2XgJ)?qU1H_MZiL5ph}({90w9z+L>4?rbJ9!cycn2`!t`( zh9t&b#w4}^&4Sc}?H0wiTuyFYettfC`M)EcmzNx#Av{^g!OKCzu}>?WZ-#`C%Ee`@ z^Sqv}*q9wY*RQcl)_dEUo0~I^wy{c;zPZ{T8TcwB>PiyhvXbfNj-0xr>NC@|)hV|# mRQc+v@Z6%i5e&&8t6LtL-MMA4`1<;Uw@qhfPD^)Sum%7fb6y(& literal 0 HcmV?d00001 diff --git a/data/itemgfx/Kiki (Head).gif b/data/itemgfx/Kiki (Head).gif new file mode 100644 index 0000000000000000000000000000000000000000..232f6c86fce7f666a35296f2187ef057f1a813b0 GIT binary patch literal 279 zcmZ?wbhEHbRA5kGXkuXaupnc@gdZCcGy)1vXlQ6Kz<}aU7DfgJRt6oA07$I^#~lW4 z4jGRP3l27OunH*%ELeD$Q9xPG$D%-yfq{udrzJ!1fLkYvfZmxIA0N3+QnB}2GNWMO z=?OZ#eOFF=NOWmuv^X@y^Fh+_$xID(S0sZUdQW$qtQBh|^5oPK{X(-IkJ1B|n~jal zVl6~fj`k%~&$_c~^8=sB8HSfaBEyz=PtoY#7VEWr-QC?4z5C8&Z&?+(q-3Yp*XpmU zy;oZP{b#ynYg%}RMdvmZf$0pP2d6(5dUGRUx&P@n^?Es5u`Ma{mNasi?v>Dfx*#)r bbE=P!Zp^IZ>glc8+t=MWRP&jQg~1vC@Mvz* literal 0 HcmV?d00001 diff --git a/data/itemgfx/Lamp.gif b/data/itemgfx/Lamp.gif new file mode 100644 index 0000000000000000000000000000000000000000..a48c95be9dd4b0f52bb46f44fb10900408685426 GIT binary patch literal 286 zcmZ?wbhEHbRA5kGXkuXa@#Dvi9VaR(Ivx}hY|sD!1~5?k$->CMz{a2h;(^pUa6D$< z<&g21kkHu7%B2;f@j;=nT|l01hR4T;j%{q*3=9n$8XEeU%;b0k9w;4ald=?>5Fx1K zIa%Gf?u~_U;+Y=V;#V#epBH%aGb#P6$=v+ht3zZmUqj{Q2M7CIX6xPY+^XT$F1UG< zPu9g%hbF2PUt>8vWugC6dHFmUscSFJcL?ux%Z(~s9x|oW`rh1A#qUEG6#wO`(P~Ib zTwn6}mG7F;?9-e4`pw){ZF%i^G^AI^^p4?&`}14uH?{sTRZZNQeNsv9ud(iti>sCQ iFV)$eduDUQ&Rtt_MT&DaPvX>A>hWuRej6hrgEat8lXb@c literal 0 HcmV?d00001 diff --git a/data/itemgfx/Locksmith (Body).gif b/data/itemgfx/Locksmith (Body).gif new file mode 100644 index 0000000000000000000000000000000000000000..9dec6d2feb2676dd2d071a03b0a651bbc914178c GIT binary patch literal 311 zcmV-70m%MGNk%w1VITk?0D=Gj`1ttnplGm=_)u`j*kE9=U??akC;$KeA^8LW000L7 zEC2ui03ZM$06+-*01pTpNU)&6g9r^MT*$DY!-WJH5+I;(zyJXP6i%F|5Tiwn6dPI` zIY427lLbtotVnXCLWBYzHiUUVApigyL&|iR^QOv<85af^8sMbDp$;*sG$=FTLz+;d zO5OPsrcInWsVG=P8s2`K(#VPs%nVbB4Ifz++pD4knz~C z;9xTcyGG234GRyqvWT*AEC^_5XlK^(TT@Z^@ED_@aoLd<7Zy3SFiA2oG!&{HZc*{> ztCFo3||`D9`N%J%bk$K2W`!d zlYG`h=-)XOy*O^^s;L@L>nxRxL$WU`UptrD-sS7P?aQ-EbK2uV@BYlWJ!f$^cY*Yl X%}EP_r1j%|P1yQ)PjD|A3xhQPk?eCq literal 0 HcmV?d00001 diff --git a/data/itemgfx/Lumberjack (Head).gif b/data/itemgfx/Lumberjack (Head).gif new file mode 100644 index 0000000000000000000000000000000000000000..d607b9d8b394d0da2a7428e4bdb25bd8ca945d7b GIT binary patch literal 332 zcmZ?wbhEHbRA5kGXkuXa0R$TYCaic7kg;M%f(8&UfPvyq7DfgJHU=FK52V(C<39s0 zhm1!+LSr)rzgUdLhlBhpuB`Q`m~XQUhS{AW1q6)Vju)lBHF ze){eT*H+c!V`=i@(>h8UB2Ff92OO&u&Iz4r!kWA#ro7O7Ml5@@jPH*x$2O%k3aR}R z&bzSCQCQBm;<{erru@g}Lf_2Jym@!qQmruW2O9Cu&wkX4zqxrw(a}svE#5bw=9dn& cpG_0|pR;3I`TqV&@1Ojy7c&bTl(^ME-NRk_L#$KD)ivzwHK$S=s$HjDlMAkyOrrblU$BKw%fth z^+vuiThsz}#HHT5leOjb!)Z}dyJBNLXy4l4&8xnQyKLpt6EbJ>*s6XNz3LY|e97f( zS+>`Xpw4q^dP=rGo3zWAeTTNu`&+lQe_OR=-B6A0J|;N3glnt*!_&#^>?{n{0E6>+ APXGV_ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Magic Mirror.gif b/data/itemgfx/Magic Mirror.gif new file mode 100644 index 0000000000000000000000000000000000000000..e71a088a7b30b967bfbbf01751213203f25b70e8 GIT binary patch literal 293 zcmZ?wbhEHbRA5kGXkuXa0R$TYCaic7kg;M%f(8&UfPvyq7DfgJHU=FK52V(C;}ruh zhm6OD1qYisxJ4um6aXa{nQUq#J|-S!+tFV&cp(kz525s{!(7C-{Q9gU^ugJ|O&L(+wv(!rEJUy7LzWW)^ nPOZboIuqscW^8|Vf461z?Wf(-pJpEn5xneXcWeFS1_o;Y=yZ3M literal 0 HcmV?d00001 diff --git a/data/itemgfx/Magic Powder.gif b/data/itemgfx/Magic Powder.gif new file mode 100644 index 0000000000000000000000000000000000000000..d805b2645a3349c2336cb5ef30f74a3fd56292f6 GIT binary patch literal 317 zcmZ?wbhEHbRA5kGXkuXau_53`!-gFR8bH8+1QdU=FfuT(FzA59Kx!R0{xfiL$arj6 zaIl$;orgofLD9LDNr@|fgTcY2OH7?l;Khc8hZu!a>tr~MmKdpM}~C zJqGDXsUF`}dd?2-O*5?$)VR4x_42bVoLk?W>dCE^-)(2k!e6}6TNYec)hevL zO{?s|!(&xn*R8D#Srxc0x%1YOT|Za*?eVQY#WOo3IrD(*{aL)TuYb63-Kcfl)Hi{v zk8NM|*zBL@_hlDW?B0EAZS=0Kx%(FE)iafgSQ$V4Oto@7pVZg5CAFO5vANejB`xk} LG=P8s2`K(#VPs%nVbB4Ifz+-KnAknz~C z;9xTcC!d7Ef`tvO+_H8u6ABVs7#W#7?z}KaKHSQtUneu6F!9(V73PjP5gV7DZqjCC zu<$f)@aa@YG%DF4^yu6~3r)E*JB?Nxn4>>gE0klR=B4T4wnax)OiVqrh$$uO>Zy+} zFU}3BW$TUlnt6VTn*TCe=_2);vr_MJ`M$dR{L=1<&#&%UZ&~TO-~0TgR<3PY$2S!J z_L{1OEc=2`qUbMyL(%Tm@F bZA-rr@{nn3*Mt`@uf%a)-_W literal 0 HcmV?d00001 diff --git a/data/itemgfx/Map.gif b/data/itemgfx/Map.gif new file mode 100644 index 0000000000000000000000000000000000000000..c8b90b4749e4695b035aa442d8e2b358bea349a8 GIT binary patch literal 313 zcmZ?wbhEHbRA5kGXkuXa0R$H;c62CcXlO7X0mYvzj0_Ac3_2h&kXi?he+--)G9CpD z2bMw(**Bd>jF6*r<%RM?zb?-Bi?t+x#J95^4TVuWP(ec$b`dn;1rW+m{3O*bq z+hDQ!?EJdh@20G(&_1-ZM^ekJO0YP1ZPwgrvJ-+Iq@BoYue$R3O3~{R#dGUqUQbNA zb15XdT}@jd|JkYh_{~Rrzc08utK#WAQ{P=0-rMVq>*I3wtbc!G(|kR(oQi^wBaDm; F)&P?9fYAT| literal 0 HcmV?d00001 diff --git a/data/itemgfx/Master Key.gif b/data/itemgfx/Master Key.gif new file mode 100644 index 0000000000000000000000000000000000000000..5c4d950a07921541bc6bdb78a4c95a0e91b3003b GIT binary patch literal 256 zcmZ?wbhEHbRA5kGXkuXa0R$TYb|h#30Rs|H{K>+|z`(+w0}=zNb>KM4z{w%wQP6O( znS)m-W`{sx15ipr#9`wi*Dfx}EFX&pitfD%=4Ct$g$^DQ#kHksUR-?Q$)wF((_(ob z>DY8$%WEP9!pl9TsZ{RzVp;I$=nUOXt|t*fi6jI(zez u?%B028^5)#nUegtIce`U74C5L^liEJ&3&4)a_{e%$Uptvn;$6-4AuZ5v0}^s literal 0 HcmV?d00001 diff --git a/data/itemgfx/Master Sword (Thin).gif b/data/itemgfx/Master Sword (Thin).gif new file mode 100644 index 0000000000000000000000000000000000000000..f576631311faf7ee8bd169b931870d89b450d920 GIT binary patch literal 180 zcmZ?wbhEHb6kt$bXkuVk`u|?>l>cijL4W}XDE?$&WME)n&;f~o)H-lfGH`OpXc#y! zG;y#?u`nD+aBAX~maB=lu)wuTRMP5*M4|H0K4DHi355kqPEJ-9j@om=u;JJQe#ayg zh0RY-&op)IyK{2#@^ka73lII-QKWHbj$y2qNY&+MLCfVPo2gobz6xFyzSb=?(nRsX UdS;eB8_zI@Q;iAd*;p8?0Z)iJ7ytkO literal 0 HcmV?d00001 diff --git a/data/itemgfx/Master Sword.gif b/data/itemgfx/Master Sword.gif new file mode 100644 index 0000000000000000000000000000000000000000..a730f0877adfa046be04f518afb04900cc7a9dab GIT binary patch literal 287 zcmZ?wbhEHbRA5kGXkuXa@#DvY6)yrZR%mEwFdzZNpDc_F3@i*fATf|y2aYEUoE$P9 z8x|aFWERr$so0>{*utd5#UbFZh@p*DnCZre!bF!IK0&?*Hv%8J^>BMO@w^mRCC*Q61_iWfT)G=P8s2`K(#VPs%nVbB4Ifz{Ab|gP%&8W zprMgNSjnWqAn_mrBNvyzfeniecJeEmiOdLG1XRlCFvmhr{}|H8&mzKX|gl$I&4w9I72%<&8Nyl>)^By-K?jY#%YcV z6BrGAc3oHzv?ycxJeAj%b37L+Uv$cy{U!I#cD3$Jy3x~@1Wzhn8~4;Ibn%13;j5L> zR{k(>Zf)J_bu4Q}Uc)R)Uzfkzz3cNKv%Ww2g)^5%T3=r+wJGx2Vrlo@oC&X!R!)(x NXWgzPSLncC4FI;ufUp1n literal 0 HcmV?d00001 diff --git a/data/itemgfx/Moon Pearl.gif b/data/itemgfx/Moon Pearl.gif new file mode 100644 index 0000000000000000000000000000000000000000..4622e15445aaeecdb1f8ce88ea9677c20bc5e9b6 GIT binary patch literal 260 zcmZ?wbhEHbRA5kGXkuXa@#DvXf`SbiAi#hG6o0ZXGBB_(=zzpPY8^OEGH`Opcx+g3 zu$hCCDS|_x;cz>jB$J0l!NUedCL^u}iHV9wT19l@WE6}ZpO~nixhh6d$ic0TU$rc! zvT)(C+0x86uFROE%GfDX%O$%?NW*!NeeAOq&dtvc&egY+inaKx+0ZRnZd5y?G|6dV zL}A(5m!(TxHmNr&#h%`__V)II<@VlBH&o?ThR=ACuN z`)a}c)e@{f?%w)p7`ZW!)7qEEa!tg<*=v`z=6q7|JlOA8ZYO(ddCZO+W+nz}05?=$ AVE_OC literal 0 HcmV?d00001 diff --git a/data/itemgfx/Mushroom.gif b/data/itemgfx/Mushroom.gif new file mode 100644 index 0000000000000000000000000000000000000000..b533aeb705a36032187e59cae442d8d40273016b GIT binary patch literal 287 zcmZ?wbhEHbRA5kGXkuXaalv9ohr$U12@MSm1|*>PlZBCifrUW_BnDFJ!108ElS9TM z;6Xz(2ftX1#fJqA?MyOGJPsR`j<$1(d--SxE^=oSGgMNkxS-_9pb2YTy3mML|=n7tw`MF6UV6s@Q*xt_ImqC4o>a#?CZc6r_=~15d#WNw> zX`aQ_B2$UbC0FN2_VS&`5_%OhDcg5hNaV$r(VGI^-fMkbmVb4V{MUW9*2OPkSIA8a z(#^W66}>rmHv*!HGxMgED%+RZT7P@6=NK~+gEau7Vr$0$ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Ocarina.gif b/data/itemgfx/Ocarina.gif new file mode 100644 index 0000000000000000000000000000000000000000..ff68f9244fc3c7c6099fd4bafb6ce62da5ab12cf GIT binary patch literal 274 zcmZ?wbhEHbRA5kGXkuXa@#DvY6)yrZR%mEwFdzZNpDc_F3@i*fATf|y2af9uoE$P9 z8x|aF=HTUvuyAN-U;rv<;3!;pxRr}N;Eu$Bg~$7u4CJ$T!z6~2{Z_@F-gs_V5jbDhG>FAYWTEd;A#JVHS%uF}&R59fYB{;_ z$(d!W8=X>K1!VcJiEG`ZGE3ymt;Ge8PtEn-ur_R)XW=`W(;IS*bc)R1mm?vh^C6B-&C3`junCkrD30}F!=NDQRbf#VDVCx?v3 zh6M+kS=f0P7#tcHS~&!@N=^tUHFh#dSe2}pka(0)+SshdLgA6?1jXPYoy<*3y_+RO zqo#OnUgj`MTX<23ghGQ?yKVBO8qX~&0w=Caza>DfajZ@vO|BmW>GxVQt-~5iHX40mH&FPngO#gm<8F;ww<*8}X H0u0sw{7`0+ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Old Man (Head).gif b/data/itemgfx/Old Man (Head).gif new file mode 100644 index 0000000000000000000000000000000000000000..ca34f42a386909b9f4b83cc40608cbf3ededcd1d GIT binary patch literal 313 zcmZ?wbhEHbRA5kGXkuXa@#Dvb1sNL>G=P8s2`K(#VPs%nVbB4Ifz{A1wcknz~C z;9xTwI}Zbc!$Jl|MkTKl55WV@tvsS!M{X1xINYzG=+(n9Y4NcpKGu*J&ySB7S~x|k zcwT-=In$--{%Xz*!RMzNHAUS-v?i{&IG@A!RLm|D<)9gcGwoV;1*)Bx%j11YWyP0Q z=NNe0ca@yFxbpgXSMea5nV%Fr8FL?=6VWzbcD-Hn<*t^fZBN~&nXP2=vzof<;o+vG zVs3k;q@6vgv9|6=*2l+}X3O4vm14OqIdt>n{cTfk?0k7^XGY~WQ{JfJR}8CDx0US) zUVV90`O~aY*@XO*>CWsuHd1p6-tAeU>wIkOq^Dl@Yp#Z|a8_6bZ0(wP&(7vYLU|)2 HBZD;nnudX1 literal 0 HcmV?d00001 diff --git a/data/itemgfx/Open Chest.gif b/data/itemgfx/Open Chest.gif new file mode 100644 index 0000000000000000000000000000000000000000..5ad6c64a98c2fd6466baa8ef9afa456456c76299 GIT binary patch literal 236 zcmZ?wbh9u|RA5kGXkuV^@ZiCP6$T9sKu}>|V88$aIv@r}jRVI{22Ktcj|~eBHnTA@ zIGp&fz^RF!lV^s<#zn5(Ov+q50uBor`V}m@L^y?>9P48?HH%qk^yuhxePcbJl^d3w zoo!JpBy)1}^7Hcqin(N?j9;8u%o26ZO8QN5Pa*WTMJ@jHq2jJf{9?((Zzdbdhf hhcl&=+dYf=^!WTKrbA}yR{wl*{``DPd0q|%YXIE6T_ykk literal 0 HcmV?d00001 diff --git a/data/itemgfx/Pegasus Boots.gif b/data/itemgfx/Pegasus Boots.gif new file mode 100644 index 0000000000000000000000000000000000000000..5c2503a2c32705845222733a27894276b8c38cd4 GIT binary patch literal 286 zcmZ?wbhEHbRA5kGXkuXa@#Dvi9VZ?X6l~A{0R|XQ{K>+|z`)9&0}=qKb>Mi+z|A4! zv0=f%W)5B<1%m|(of!p`tz33)6 zr{u7?(Q7}cIBd!YSjU{5W|F;0&3C=y=~*V$Q&!&Hl{fX(-RjWv`+Fmj_xicAhGKB=5+<1%e( z(J*%Kn5@lz??^=Pa_=cticGRzTVD9hVd?MESrPKoxkI@A*O?uG4rlw#^p#RqO-&D7 z6Ws2{8$IRq18LPm$K66G_68T~B{se(Pc``)t3xW(o|}0CmA+9{>OV literal 0 HcmV?d00001 diff --git a/data/itemgfx/Power Glove.gif b/data/itemgfx/Power Glove.gif new file mode 100644 index 0000000000000000000000000000000000000000..81752b3d652f111ee2d8629fd341f2585bf39847 GIT binary patch literal 317 zcmV-D0mA-ANk%w1VITk?0D=Gj`1ts^xX8#@FnD-~C@3fZ0000000000A^8LW000F5 zEC2ui03ZM$06+-;01F5lD3AaFf(8u|T*$DY!2tsTNDS~WB1Hlc6*?pUQ6j{I7$=G} zC_sS5h6O5iyjZfNK>z?wZWNi3qeYM?3x=%uF=0uVKx5jJsZ-^EiZz4c%!x1|M2Ia- zCSE z*QP7cwp5#U@xZHHC(B0t)}q{}AVr&X3LG?F*OqUSy(w6)P}hEY%N`7!>fgD62O}m8 Pb@o)ohQl%f4F~``Ik$uA literal 0 HcmV?d00001 diff --git a/data/itemgfx/Power Star.gif b/data/itemgfx/Power Star.gif new file mode 100644 index 0000000000000000000000000000000000000000..89b7b948fd58627ed777ab1d851783d911cf9eda GIT binary patch literal 278 zcmZ?wbhEHbRA5kGXkuXa0R$H;c62CcXlO7X0mYvzj0_Ac3_2h&kXi?h+YFo>G9DWi z9Bk&`<&$7waA;^}6jRgLA+YFZ2eVw*9u0?vBhAvfWp6Z!o*eJwl4P>zEL!M2l~?{4 zkHO_f-qTo|<7zA}J#Ogat}Z*`sjwnokw*7FpHn4?hi7_3?^;v&QPpX=|H`~8k&`s8 z&lRY4J3CV_=lW8I(_MQjzr8xU(d)j^T<`0-cb7ywJa?2!^lfZoMDDM<)>joHRx9ME zP0gIK>e%dtL_5(xH{Jy7kJnDVQ+ac3?xxws VfU6?xcfS1!Gl|^E%*@1K4FLZ{aJ2vc literal 0 HcmV?d00001 diff --git a/data/itemgfx/Progressive Bow.gif b/data/itemgfx/Progressive Bow.gif new file mode 100644 index 0000000000000000000000000000000000000000..b61c67f84addef5f0805037fa9796418460c9f58 GIT binary patch literal 308 zcmV-40n7eJNk%w1VITk?0D=Gj`1ttvuu%Abu#l+exL_zKC@25`00000A^8LW000I6 zEC2ui03ZM$06+-&01XHnNU)&6g9Hl{AV5H&!-WhZN>msi07Z)h5E29c;NnAx3>6xD zSW)4C0U`%-6sRy{#)A)II%HX(qRjvtQyN@ZkR(QzItQ9OiLxd}o-`-EM5s`JfS?H> zLe)r>rp%ELK@#8yH0I5q3XvN47}2A{l1mSYHLH}WOtVqj3N7H&so9ikrKZK|^yJi> zdaI7z3zM+m!-x~VH9UB6%8NGv$JM$OKv$n=lQxV=xvWvRbMvo_abe zTDgb;m(J>$>D$b6Vb3L66m4GJP3zu$`FnHf&jtLZVq|2n1_1mYbM*iK literal 0 HcmV?d00001 diff --git a/data/itemgfx/Pseudolamp.gif b/data/itemgfx/Pseudolamp.gif new file mode 100644 index 0000000000000000000000000000000000000000..2eb31420820d5dc63f78e173e2f73e5380a70b6a GIT binary patch literal 286 zcmV+(0pb2fNk%w1VITk?0D=Gj`1ttvuuzbw=(u1gP-v(qC@25`00000A^8LW000I6 zEC2ui03ZM$06+-i01XHnNRVKGg9QpITqy7$frk(u3YbXo;X#H53jhFsu)u(i12!HE z5a1%lh8j5*kXR8SNs}ite(X3iVa$vjbLvER^PotN10w!>X|v}_h!m3wfO)gv!H-0n zF5F4AC`N}7v$9NT(W=6cC3DsU%aox{l^-8&92(Z>&xjMdMr~Skr&N@6JKmkjbMIB4 zbNvo{I)G+juXOY3O{{fm%d$?7Hb$zn>q*5_jS@B7G4S7?gg>%{{52(EwQI>DF8wnt k#L=rGzojgB=B&hMv@&_S_~O7Wz3fh6#@VdaUw+mJ9{d8`LL)_0XugdJv#KH%%xDH zT70Rns@1DlvEszo@}f_!7IT^usFNp9vq{sUUE7rG#gPm-#*Nuk?8}l}Rl>B{wm{aa zY5!WiOLrzsyoUP#t%@+jT0oZUDKr3%jmN`Y>XbPJi#MD!e37scEH7b-Fk(W8QgVu8gjDc=XG?Z#q@Z Oy=e8xlLZC=1OPkC7Kar8 literal 0 HcmV?d00001 diff --git a/data/itemgfx/Quake.gif b/data/itemgfx/Quake.gif new file mode 100644 index 0000000000000000000000000000000000000000..e86194db9d09cfcf5f7a753072809608fea9de05 GIT binary patch literal 262 zcmV+h0r~z%Nk%w1VITk?0D%Ai_|Q1Gh#)8^C;$KeA^8LW00093EC2ui03ZM$06+-W z00#&hNKl}Fg9r~6TsZI`0003ZN}NcM;zNZ496}86u;a#v9zBBWh|!>chZR#wyeNQS z!;>9VdMx=8rNx*jZH~mKQKiq70B9~u7?LDHmoAAG4SE!*Nu57|3e5;Js!x_raW4JH zG2~8!P@zr~d6Q>Vt2vn_g((&&R;LUTCWK3us@#@!hk{)?x30#vBj2tCd{u41o@gry zrb^iATf}2=D(1@a@5Zf>$yPpFG_%*Po5OPTJlSmHsEZ*dmWr34YR85LOTM|-snVi- M^SZv<8ficPJB#CM8~^|S literal 0 HcmV?d00001 diff --git a/data/itemgfx/Quarter Magic.gif b/data/itemgfx/Quarter Magic.gif new file mode 100644 index 0000000000000000000000000000000000000000..97841b1e8340bd2d5b7c9632c768060f50b133de GIT binary patch literal 296 zcmV+@0oVRVNk%w1VITk?0D=Gj`1ttv&^VaTaJYydNRTinC@25`00000A^8LW000I6 zEC2ui03ZM$06+-s01XHnNU)&6g9ZyIT*y!%LWKYTI4sz(VgZ5>BWm2pkN^PzAVY%m zI8k6mju#Cm^ypFKNCG7XW{iokKuZBMDHezrb0tiRBvYE)DUoPTn=F&&tjSZTN{b8; z4o!$O>C2!@H7(b_ZPkw ze*+8F>Gp5iyDkM_)d^PS-J5zHqwEVcY-6gCEf)=YbL-H{Iy-xHT$yy)tQ#jkMVof* ufWxJILS6j1Xk)l?SsrbATWn&*b0w#qh+AZ4)1Yx5|GJs5-@!2h0suQ}A$ODj literal 0 HcmV?d00001 diff --git a/data/itemgfx/Red Boomerang.gif b/data/itemgfx/Red Boomerang.gif new file mode 100644 index 0000000000000000000000000000000000000000..052dfa99f3c46d13e5b0b325bcf330a4d1119f4a GIT binary patch literal 167 zcmZ?wbhEHb6kt$bXk=h`P*AWz0|Xct7!-f9FfuSOGw1->3?O+2jtT~L4jGRP4;UDk zm{@?K3muy|M72^*2qe06in7|=`SD@Vkyc()u`eBlDvsSsmaE=m1gf6wk@oa6u{26N z*<<8rB~u~z?9_aRX0G0wlal>s3FMx;QyG-$xy)v+p0DIrW!EL_bK~yLyqq4sMt>uh P4VP)=&4sMYObpfluEaFM literal 0 HcmV?d00001 diff --git a/data/itemgfx/Red Clock.gif b/data/itemgfx/Red Clock.gif new file mode 100644 index 0000000000000000000000000000000000000000..9629dccc5aa6d8863bc5c83c19fe8381e036372e GIT binary patch literal 288 zcmZ?wbhEHbRA5kGXkuXa@#Dvd2!jn8Ai#hG6o0ZXGBB_(=zzpPY8^P9GH`Opcx+g3 zu$hCM$AE*O!Ksx=+D_(z!9xZ{CaJ7D91M?-bg?)Hg>)1yKGZ8Gt`u{!Ncr?+1}2sn z9UGT5bP6&GhbvOP@=CdDQR2C$PTHJZwAK2H;q^;WtA8!&+OGR% ebz%FtQf~1rdCTS%pFZ3Dv*hi*>d$N}4Aua}m2ryz literal 0 HcmV?d00001 diff --git a/data/itemgfx/Red Crystal.gif b/data/itemgfx/Red Crystal.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d17df29da65b9d23e80c2fb874018d875bcec21 GIT binary patch literal 272 zcmZ?wbhEHbRA5kGXkuXa@#Dvi9VZ?X6l~A{0R|XQ{K>+|z`)9&0}=qKb>O(lz|A4! zv0=f%W)5B<1qBC&hIR%qHJ=>?4M!Py6`3+_1Ux#@ENWQ9BapE0SUb08olb(0QsY!% z@uHH7OUh>&6?M<$coZ%4XVS{wRAaf}x&H#j7QRra$%?*HTxRmkt-Q4K(u5HIvK}tu zZ1nZ3N!mtA`d>QN39Fu?CSO2o*6qKeeJ!uze4oyZk4(mS2}B>+MRVR zznx^)OisSKHkmURoz>zLrMnou4WPy|rCjv;R(56Cy3QwXO5cFh9p+#91i21SU%$QK4 zGPMYkB-Nz_9ahw;Fo4$pTy_2&*mEPtjyF}RRd`l_O`rvoDm*H*u0)<#;VKoXR;}E; z2b~IjDwS;0!iW|nNT2~<5$^zO>KNF(CaYZNx$-+NC^<{j5S(xI>a(rkL1ZcCT91sBe~ LJF(NK0RaFzg3NwK literal 0 HcmV?d00001 diff --git a/data/itemgfx/Red Mail.gif b/data/itemgfx/Red Mail.gif new file mode 100644 index 0000000000000000000000000000000000000000..0cc9885f81b5a55eff110aebae9d95349ce6f76c GIT binary patch literal 301 zcmV+|0n+|QNk%w1VITk?0D=Gj`1ts^xX5^Th~RK=uqY@fC@25`00000A^8LW000I6 zEC2ui03ZM$06+-x01XHnNU)&6g9r;KTu6Yx!iNPKLM%W~VZ)0A258)faU(~J4k;S2 zcv0g-g&s9Z6p7H_NtP{1dc+6-08N`EQz~>>K!5;{7Xt_l@UZ2;i9lZ(UCOknK$1ye zCX5KO=1P)QLGBz$wV}$40~*%M`nBVLtw?ju)C!TO$(}yr3VrBv~fadOVQl*xt#`4+0$k9jj+yzDtO z>eX!zDy)llDAC6;3%rdh_x9|ciVK=94Kd~Dt&s6{E`AnpMTk)+4*u(WU_bynUe|m% literal 0 HcmV?d00001 diff --git a/data/itemgfx/Red Pendant.gif b/data/itemgfx/Red Pendant.gif new file mode 100644 index 0000000000000000000000000000000000000000..dcf55738ceace7e76e0ff650161cbbc8fb723a62 GIT binary patch literal 310 zcmZ?wbhEHbRA5kGXkuXa@#Dvi9VZ?X6l~A{0R|XQ{K>+|z`)9&0}=qKb>R5Tz|A4! zv0=f%W)@BX4grUS4y^*>W<4Gc7P_=^aJ#WEFf4XzlQC2Z(O9sgfsxs(NJrCXu~Q$9 zWYrXoP02@_^%+kr*7VoCChNpr8&XQOm{Pk zABN2mE*OCtvHSuO1xk zSQ@k@+cfLkM&sk})^dw4x;8&+?=00f#YvC*Q#k*(@JuPWd7Ht-^5aXtz_|Fh8Tk$j F)&P6Jf7$>5 literal 0 HcmV?d00001 diff --git a/data/itemgfx/Red Potion (R).gif b/data/itemgfx/Red Potion (R).gif new file mode 100644 index 0000000000000000000000000000000000000000..a39f20cd1159e06c79313f2dacc79b241eba587d GIT binary patch literal 319 zcmV-F0l@x8Nk%w1VITk?0D=Gj`1ts^xX5^Th~RK=uqY@fC@25`00000A^8LW000I6 zEC2ui03ZM$06+-;01XHnD6oLRg9s54TsY7m0RjjG2nZ0s;DCz*5*B!9u;9jr5D$U` zi4h~hiyRAh9LbVE$%_U7$egLL;X#QMH6k3@aiPPIKXOrdv4dSf$v1L@BA0tlWs#9c0sbSM@HQF@o%8)$E9&B5*D@(a}55A@P@~Bm( zJ@+nc`?mmAhBoucMVwSIQpQ;ethF0AFk-Pe<;IO%cQW3TXgiN(dsL|9plU}K=!-fu z(6m2MzJ`eub!EA9U*Bf>@+48+OC9H>%A5An!h(yNGz+|z`)9&0}=qKb>R5Kz|A3} zF`?mLGl!s1jKzfq4U8PjEDQ_>7BqA-2?#EA~8w*P`gI8(2f<8(@#$`NIZ3?^K-_zW}bAR2_6?Uyjufn<(6c9 zR`Z*y?Y!(s*2ksSHiYe+XY%vo^T4g_Q`>l6o4h=|lx3~b-rpu!VLP<`a$4%EZPHmqxcTRcHvwp|xVsm*U4bm@nw!W*4 xHCuXbdBM|NrB;{nPA=VE{o7A=#=DCTk1YLEcJlkCD-XiCrS*8P7dS9j0{}0ee$oH{ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Rupee (1).gif b/data/itemgfx/Rupee (1).gif new file mode 100644 index 0000000000000000000000000000000000000000..a2d025feb4cda1b292d619ba0150e78d022ddeba GIT binary patch literal 193 zcmV;y06zamNk%w1VGsZy0D%Ain9y)YkT57HC;$KeA^8LW00093EC2ui01yBm06++m z00#&hNU-1l0RjLh1Q4L1Lxd0$G7O;5Aw>WP1tM%%@u2{N2p3}fI56ZwiyTLq?3l7) z#)1(If`lmZphT7dUYbOSGNQ3?O+2j!6vc95Nmo9xyO6 zF=(&|ELiB=A|PzUv*3cFD+33sQclFjg$&Ic;z@rj44yc3%ec>aGhlb1qD{&VzAxi-w$vh4EmfLyb=nnkP5&X=2-lqwad6xgrb sZWW@jWpU)xIQ=LUZb9|)o06>EY_!6j2W^c^yr=uiBrRk)BO`+~0N3F^umAu6 literal 0 HcmV?d00001 diff --git a/data/itemgfx/Rupee (5).gif b/data/itemgfx/Rupee (5).gif new file mode 100644 index 0000000000000000000000000000000000000000..c2744645beec903b8ba7666ac187c369c86d6016 GIT binary patch literal 193 zcmV;y06zamNk%w1VGsZy0D%Aikf`WTXs9SCC;$KeA^8LW00093EC2ui01yBm06++m z00#&hNU-1l0RjLh1Q4L1Lxd0$G7O;5Aw>WP1tM%%@u2{N2p3}fI56ZwiyTLq?3l7) z#)1(If`lmZphT7dUYbOSGNQXiu2RVmb^qno{L}VCnq(cC!q<8&By+0z z)ixR1LvNxkJ@;LbaeUd=Q-(^x3!ERn3b7DccXx@k{W{eR+gHc0bpIb!V;yGTKU-$? zuerYpmONU~v(@j3SJ{E}Lc08-_6qyPW_ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Rupees (300).gif b/data/itemgfx/Rupees (300).gif new file mode 100644 index 0000000000000000000000000000000000000000..6163dd17a3627854a362f987ea1ab51bf206bd69 GIT binary patch literal 298 zcmZ?wbhEHbRA5kGXkuXa@#Dvg3k4n%3^X(}7?6PCPZmZ71{MY#kQhj<1IK#?P7WE5 z4GRu7v#|331se`CFez~*tPoIiYUNS3YtcB6=-MsL?sDYB29=YOxfvJu%$W3uVS<9F zRnLinwBro&iF_)So0fXc*Yo~o;t`Z_alTWmQ0R{!b)QLQQ>{`XjT-`HY0dVVdUE3` zw>eRBKkYfWWzEh0bk?G&8VhnRtjQ05CvtOI=A9`TOZ9YDU(1Q#7tDM-MXO@N#SN{T z4sU0feoUGjQQYPG^24hm#~QE4ZF?#B@iJqebkQ4~iZ{pBPb!_oR&BO6Y5#iTYrb6O sF9WB~s(!Y1ue9#n+j~B8UH={R{lkOu>6h5f-T54UXg%X@J`M(J06yD#nM#-vAH6U0QV zdQKFi9cPeF4AV*46|NMIk{2I zy+-Twn>{wK5?xWC5;e7O>mi@tlipw1?{}VwjWa|)VRGP8 zzPRYEZ(NSn3r5>^Uj1Jnc}ud<}6p*o>}WMuB1&qHMQ4l s^Z7|mKc9t0PfvNXq(V_$MDt_byT?J?>+GzgEiw*e#%@;=5MZzd0NXHhC;$Ke literal 0 HcmV?d00001 diff --git a/data/itemgfx/Shovel.gif b/data/itemgfx/Shovel.gif new file mode 100644 index 0000000000000000000000000000000000000000..fc211be3fba3b0c22c444232dc41f7855b544b94 GIT binary patch literal 209 zcmZ?wbhEHb6kt$bXkuX4vExKVMaPK<0}Txg1|*>PlZBCifrUW_BnDFJz%h-1lS9U0 z!GnfI7Iu~h35JHl?R>mmG71Y8HFUBIN9~y*nCRHXD=#MULr}%JL)kRS=jFsl$EL~( z>-9)%R`KXC@qTnfQ!wTH1RYM1I}%$|FV1jFR8r|Id~~VBb^0q7fvagAvwVExL^D4; z^IH|W{oS9HqNz7p?Th_vvs?*)?!qqr_xoJ6t~~Yb)156PA|b$F4FEa$ BM{ocD literal 0 HcmV?d00001 diff --git a/data/itemgfx/Silver Arrows (Ag).gif b/data/itemgfx/Silver Arrows (Ag).gif new file mode 100644 index 0000000000000000000000000000000000000000..78e77cd45933379757daa22dc6062e6fb384d14f GIT binary patch literal 263 zcmZ?wbhEHbRA5kGXkuXa@#Dvi9VaR(Iy5vi7?6PCPZmZ71{MY#kQhj<1IHN#P7WE3 zf&&aq9Ku>Y83qmv&D_dvIX^x;aOe;cloC-$NOo^#W?(ST5K{J>sH`g{^WZ|F=Tu46 zc}FCQANoua&EFT(Y4p^qNzL(}N&Ac`x>2%iGU81W(wi)d|)Z#6&+_g8oJ)P2sHqFwPi>R{vU zO-EmC(0O>!C*RDjdrRK=1(Pqg`C6L2xW_o(I$FnTTTaH#%!AYJ?K0BvpHlNMNmW9C G!5RPx6lIFZsk$-3gKX2aP4Lm5L#35aiL2a7q8tD3k8RU3C!ADAsj}J54Ib~ zu9FGanC3f$EmTaVbEE3HMlRo3Z#;w@oH}$(g%WOFSnAPXKh-N%>au3Q5_#=kEt#L6 zA6@JdJxOI%$a9}b!fWk%JwIhcZ5QlZWa4eQ(ruaZRUwDlC0SRdS1sp~^VyM=u&OOE zZp+PYua0*_&EB;4<)q9r$1^?6?6SXP-B^~~{ZG`RT&2Sn(soivlTbL|IVf zNP{m2##C9-BuJVoJ)RVhl4JmpJX>nC7!>BvoknYd#F&w(Q>QU|UUayVDp8y^ulgJb q6eriJKC>>(xbP=Zp(R;%Oj{IfPNph>CVh)B?%B0;;kG3h5CA*m(m&Gx literal 0 HcmV?d00001 diff --git a/data/itemgfx/Small Magic.gif b/data/itemgfx/Small Magic.gif new file mode 100644 index 0000000000000000000000000000000000000000..99b4b69da4b584c073abe0f64a3baf58fa79c9e9 GIT binary patch literal 173 zcmZ?wbhEHb6kt$bXkuXaalvB7g@PR&3LX;-G&D3AU_kLF3nK#qD}xS50HoG|qlkf< zL&jr6f+G`$u#!nfK!YL;}euQ3$A1urg<#lmG_#nV#|wDvpr(N TmYy_v8Pw}|xJy?;fWaC7Li;(( literal 0 HcmV?d00001 diff --git a/data/itemgfx/Somaria.gif b/data/itemgfx/Somaria.gif new file mode 100644 index 0000000000000000000000000000000000000000..79327b8abea5c144f655febf31575082924aa657 GIT binary patch literal 189 zcmZ?wbhEHb6kt$bXk=h`P*AWz0|Xct7!-f9FfuSOGw1->3?O+2jy?u<4jF|73l26i zbF)QAI4C+ZFmNfAa0DtHYGD!!6EO&6aB1ULE;_OzaLK`mvffd9JPec%PnA$SB{K8V zQpc(0xmGb56P0|YsW9iT+!9g`oNo|0PetoP%B2~`^=4l=7?xaIWEGot=jH`fzjf-4 p->zhRO1QAlXX2tgE52#mTpqk$t9JJ`wOc!rUT-q(Hc()&1^`DyL6-mk literal 0 HcmV?d00001 diff --git a/data/itemgfx/Super Bomb.gif b/data/itemgfx/Super Bomb.gif new file mode 100644 index 0000000000000000000000000000000000000000..42ae20562b338fe50fb94be353224b8e4b495d40 GIT binary patch literal 299 zcmZ?wbhEHbRA5kGXkuXa@#Dvb1sOLI5;Qb47?6PCPZmZ71{MY#kQhj<1IGsjP7WE5 z4GN459KupD9tj5+7zLEAdNdN0j&?EgL@kk6u=sdChknwPA0Hka?^lvFQhBlADMO2F ztd$Q(!;%wy=FA7aa0EU*(90Ci#d9h+>DW}g_M|U6gVWZ%fn+CA;#s#064 slK4eiUKi=iGG3E$xA5a9vFynuH>Z?z-;eW_*z#;zhbNnyi~xf*01&!%@Bjb+ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Sword and Shield.gif b/data/itemgfx/Sword and Shield.gif new file mode 100644 index 0000000000000000000000000000000000000000..de135c5d60980207b8f65e058bcebc1eeb0490b6 GIT binary patch literal 271 zcmZ?wbhEHbRA5kGXkuXa@#DvY6)yrZR%mEwFdzZNpDc_F3@i*fATf|y2aYQYoE$P9 z8x|aF=3r%t;9z*zz{sa4mvUpngTt*%EG#!96doUHXOT}k!|~~XYn!TIkk1LDhhE*x z8mC+|10S61H|3mj=ETOu40G7zm*seFS#hzGr(djA(nyVAVZdCz&>13X$0kNJiltZ; zEO+aZo9`vkS^6Yked6+0G7X`*!P~tapPK8vUG@4d=J$_O7hF#}w@hob*-^>RSMmFr zc3aK$3|t$xC3UM%&6_FeH|8ht2JO3LoO^EeOwrkKGT6_Mt#h#ATzdASR@-Gvq$Q8HFmxQmLcKX)V doEzzp!fLy}8s9m!v;LeIXU+GpCPqdEYXHO;b-2+NDS~WB1Hlc6*?pUQ6j{I7$=G} zIADOrh6O5iyjZfNK>z?wZWNi3qeYM?3x=%uF=0uVKx5jJsZ*tZiZz4c%!x1|M2Ia- zCSE z*QP7cwp5#U@xZHHC(B0t)}q{}AVr&X3LG?F*OqUSy(w6)P}hEY%N`7!>fgD62O}m8 Pb@o)ohQl%f4F~``7G8qO literal 0 HcmV?d00001 diff --git a/data/itemgfx/Triforce.gif b/data/itemgfx/Triforce.gif new file mode 100644 index 0000000000000000000000000000000000000000..33f4e3d554eb539b71f36ca4553bab5075b04ba6 GIT binary patch literal 207 zcmZ?wbhEHbRA5kGXk=jcalt}ELxTYf6o0ZXGB7YP=zw@2c?XUK46Gb79vc=MZ06u) z<6u~@@Ng@quwIGB#w6zsA<3vaCj^sSnuHlE{&X0m9A{8ro%Li#;S#T2o#e2RpA*wg z^@s=FJ7O99{9L29?yV=9!AtxXxysA2avHC^u$X(X*IciySy$#ql=GeaWu$(+S#f(- z?yIk>8y2|jU$j(Xo6603_Sd(?beW{x-kjgvH8p#BUik82(PykSlk^{K3KQ1er=_64 GU=0AXV@;Lntr-^=48{gb2d)xcrk#q WWFz;?%vi0|skD(F2h6-+Kma?_3v=NB literal 0 HcmV?d00001 diff --git a/data/itemgfx/Whirlpool.gif b/data/itemgfx/Whirlpool.gif new file mode 100644 index 0000000000000000000000000000000000000000..26edb12759862daa688adb3ff95e3bc8f517026a GIT binary patch literal 376 zcmV-;0f+uaNk%w1VITk?0D=Gj`1tsU(D-6uQ zE@kLcCsV5|gI>h=G9poqGgW4kDN*3gi4J`#R4cLPRgyHXJ{7xh0L+C+zh(^@_p8c~ zNo7_=NkAmlw^NfQj0$vYV5@GWQhm5mZc?e30UZ3w(J^1jlZ%!uP!;Ub(WB4a{Ye?M zSA%H#)?IAVZdtcqCkGu`7qDBwaSdy=T9mfOnrbp~LBEerm+|)VmUqvDdoX8uD;)!t=5 WJtf*}rVSUKZLXCDmTF}M1OPh=#+OC_ literal 0 HcmV?d00001 diff --git a/data/itemgfx/Zelda (Body).gif b/data/itemgfx/Zelda (Body).gif new file mode 100644 index 0000000000000000000000000000000000000000..5db7ac8cccf2a6b9f54fa3eee70e2a22e11ff226 GIT binary patch literal 323 zcmV-J0lfZ4Nk%w1VITk?0D=Gj`1ttnplGm=_}E}zuwW=CC@25`00000A^8LW000I6 zEC2ui03ZM$06+-;01XHnNU)&6g9Hl{002NCLje#4C`?!&q5y^t8!prspkn|61QZS! zNphq@kRAhMq^PiEMT-$#x->Wwp-q7`aTe$ZQX#~L5rLj0&~f5GpAujG)R>VW#+EmA z%A5){s@1DUH$Kf-aH>;{I(u$J>Jnncp+-jys<@axZp83!he Vdb0M!im!qQpBmXYRjUC306WlRgL41? literal 0 HcmV?d00001 diff --git a/data/itemgfx/Zelda (Head).gif b/data/itemgfx/Zelda (Head).gif new file mode 100644 index 0000000000000000000000000000000000000000..a5f5d80f19829bf0e18660d2bc092485e892d86b GIT binary patch literal 309 zcmV-50m}YINk%w1VITk?0D=Gj`1ttnplH}&V6b2)P;kg7C@25`00000A^8LW000I6 zEC2ui03ZM$06+-(01XHnNU)&6g9rr{C?G%p00099EL<4zVZ((87X}DGQR2jpA0uky zSb$(hkp&`dT)7fuM3e~!f-Gs^V@#71Q8pyNlfcE49x)aS>G9#njSGzewRsb#(56tM zLhZN_WmS(+KQ^@3&>?`IPlpyj3RGv;lOD<9R7vvT!Mca`cbp!D?Gps$aTBwPEoYql(}x;D7jwNTJm87JOu HARqucDy@S? literal 0 HcmV?d00001 diff --git a/resources/app/cli/args.json b/resources/app/cli/args.json index b0dbf825..8141614a 100644 --- a/resources/app/cli/args.json +++ b/resources/app/cli/args.json @@ -501,6 +501,7 @@ ] }, "sprite": {}, + "triforce_gfx": {}, "create_rom": { "action": "store_false", "type": "bool" diff --git a/resources/app/gui/lang/en.json b/resources/app/gui/lang/en.json index 8632601f..0ad57757 100644 --- a/resources/app/gui/lang/en.json +++ b/resources/app/gui/lang/en.json @@ -42,6 +42,8 @@ "adjust.sprite": "Sprite:", "adjust.sprite.unchanged": "(unchanged)", + "adjust.triforcegfx": "Triforce Piece:", + "adjust.triforcegfx.unchanged": "(unchanged)", "adjust.rom": "Rom to adjust: ", "adjust.rom.romfiles": "Rom Files", @@ -259,7 +261,8 @@ "randomizer.gameoptions.sprite": "Sprite:", "randomizer.gameoptions.sprite.unchanged": "(unchanged)", - + "randomizer.gameoptions.triforcegfx": "Triforce Piece:", + "randomizer.gameoptions.triforcegfx.unchanged": "(unchanged)", "randomizer.generation.bps": "Create BPS Patches", "randomizer.generation.spoiler": "Create Spoiler Log", diff --git a/source/classes/CustomSettings.py b/source/classes/CustomSettings.py index af34f007..ab3738e7 100644 --- a/source/classes/CustomSettings.py +++ b/source/classes/CustomSettings.py @@ -208,6 +208,7 @@ class CustomSettings(object): # rom adjust stuff args.sprite[p] = get_setting(settings['sprite'], args.sprite[p]) + args.triforce_gfx[p] = get_setting(settings['triforce_gfx'], args.triforce_gfx[p]) args.disablemusic[p] = get_setting(settings['disablemusic'], args.disablemusic[p]) args.quickswap[p] = get_setting(settings['quickswap'], args.quickswap[p]) args.reduce_flashing[p] = get_setting(settings['reduce_flashing'], args.reduce_flashing[p]) diff --git a/source/classes/ItemGfxSelector.py b/source/classes/ItemGfxSelector.py new file mode 100644 index 00000000..689ff626 --- /dev/null +++ b/source/classes/ItemGfxSelector.py @@ -0,0 +1,121 @@ +from tkinter import Button, Canvas, Label, LabelFrame, Frame, PhotoImage, Scrollbar, Toplevel, LEFT, BOTTOM, X, RIGHT, TOP +import os +from GuiUtils import ToolTips, set_icon +from Utils import local_path + + +class ItemGfxSelector(object): + def __init__(self, parent, callback, valid_items=None): + self.parent = parent + self.window = Toplevel(parent) + self.window.geometry("800x650") + self.callback = callback + self.valid_items = valid_items if valid_items else [] + + self.window.wm_title("Select Triforce Piece Graphics") + self.window['padx'] = 5 + self.window['pady'] = 5 + + def open_itemgfx_dir(_evt): + from Utils import open_file + itemgfx_dir = local_path(os.path.join("data", "itemgfx")) + if not os.path.isdir(itemgfx_dir): + os.makedirs(itemgfx_dir) + open_file(itemgfx_dir) + + frametitle = Frame(self.window) + title_text = Label(frametitle, text="Item Graphics") + title_text.pack(side=LEFT) + local_title_link = Label(frametitle, text="(open folder)", fg="blue", cursor="hand2") + local_title_link.pack(side=LEFT) + local_title_link.bind("", open_itemgfx_dir) + + self.icon_section(frametitle) + + frame = Frame(self.window) + frame.pack(side=BOTTOM, fill=X, pady=5) + + button = Button(frame, text="Default (Triforce)", command=self.use_default) + button.pack(side=LEFT, padx=(0, 5)) + + set_icon(self.window) + self.window.focus() + + def icon_section(self, frame_label): + frame = LabelFrame(self.window, labelwidget=frame_label, padx=5, pady=5) + canvas = Canvas(frame, borderwidth=0, width=780) + y_scrollbar = Scrollbar(frame, orient="vertical", command=canvas.yview) + y_scrollbar.pack(side="right", fill="y") + content_frame = Frame(canvas) + canvas.pack(side="left", fill="both", expand=True) + canvas.create_window((4, 4), window=content_frame, anchor="nw") + canvas.configure(yscrollcommand=y_scrollbar.set) + + def onFrameConfigure(canvas): + """Reset the scroll region to encompass the inner frame""" + canvas.configure(scrollregion=canvas.bbox("all")) + + content_frame.bind("", lambda event, canvas=canvas: onFrameConfigure(canvas)) + frame.pack(side=TOP, fill="both", expand=True) + + itemgfx_dir = local_path(os.path.join("data", "itemgfx")) + + if not os.path.exists(itemgfx_dir): + label = Label(content_frame, text='No item graphics found in data/itemgfx folder.') + label.pack() + return + + # Get all GIF files (converted from PNG) + gif_files = [] + for file in os.listdir(itemgfx_dir): + if file.lower().endswith('.gif'): + item_name = os.path.splitext(file)[0] + # Only include if it's in the valid_items list + if item_name in self.valid_items: + gif_files.append((file, item_name)) + + # Sort by name + gif_files.sort(key=lambda x: str.lower(x[1])) + + if len(gif_files) == 0: + label = Label(content_frame, text='No valid item graphics found. Items must match names from Tables.py.') + label.pack() + return + + # Calculate how many columns can fit (assuming ~40px per icon with padding) + max_columns = 18 + + i = 0 + for filename, item_name in gif_files: + filepath = os.path.join(itemgfx_dir, filename) + image = self.get_image_for_item(filepath) + if image is None: + continue + + button = Button(content_frame, image=image, command=lambda name=item_name: self.select_item(name)) + ToolTips.register(button, item_name) + button.image = image + button.grid(row=i // max_columns, column=i % max_columns, padx=2, pady=2) + i += 1 + + if i == 0: + label = Label(content_frame, text='No valid item graphics could be loaded.') + label.pack() + + def get_image_for_item(self, filepath): + """Load and prepare an item graphic for display""" + try: + # Load GIF with native Tkinter PhotoImage (no PIL required) + photo = PhotoImage(file=filepath) + return photo + except Exception as e: + print(f"Error loading image {filepath}: {e}") + return None + + def use_default(self): + self.callback("Triforce") + self.window.destroy() + + def select_item(self, item_name): + self.callback(item_name) + self.window.destroy() diff --git a/source/gui/adjust/overview.py b/source/gui/adjust/overview.py index a26bd750..55ce0ffd 100644 --- a/source/gui/adjust/overview.py +++ b/source/gui/adjust/overview.py @@ -2,6 +2,7 @@ from tkinter import ttk, filedialog, messagebox, StringVar, Button, Entry, Frame from AdjusterMain import adjust, patch from argparse import Namespace from source.classes.SpriteSelector import SpriteSelector +from source.classes.ItemGfxSelector import ItemGfxSelector import source.gui.widgets as widgets import json import logging @@ -71,6 +72,30 @@ def adjust_page(top, parent, settings): spriteSelectButton2.pack(side=LEFT) spriteDialogFrame2.pack(anchor=E) + # Triforce Piece GFX Selection + self.triforceGfxNameVar = StringVar() + self.triforceGfxNameVar.set('(unchanged)') + triforceGfxDialogFrame = Frame(self.frames["leftAdjustFrame"]) + triforceGfxLabel = Label(triforceGfxDialogFrame, text='Triforce Piece:') + triforceGfxEntry = Label(triforceGfxDialogFrame, textvariable=self.triforceGfxNameVar) + self.triforce_gfx = None + + def set_triforce_gfx(item_name): + self.triforce_gfx = item_name + self.triforceGfxNameVar.set(item_name if item_name else '(unchanged)') + + def TriforceGfxSelectAdjuster(): + from Tables import item_gfx_table + valid_items = list(item_gfx_table.keys()) + ItemGfxSelector(parent, set_triforce_gfx, valid_items=valid_items) + + triforceGfxSelectButton = Button(triforceGfxDialogFrame, text='...', command=TriforceGfxSelectAdjuster) + + triforceGfxLabel.pack(side=LEFT) + triforceGfxEntry.pack(side=LEFT) + triforceGfxSelectButton.pack(side=LEFT) + triforceGfxDialogFrame.pack(anchor=E) + # Path to game file to Adjust # This one's more-complicated, build it and stuff it adjustRomFrame = Frame(self.frames["bottomAdjustFrame"]) @@ -117,6 +142,7 @@ def adjust_page(top, parent, settings): guiargs.rom = self.romVar2.get() guiargs.baserom = top.pages["randomizer"].pages["generation"].widgets["rom"].storageVar.get() guiargs.sprite = self.sprite + guiargs.triforce_gfx = self.triforce_gfx guiargs.outputpath = os.path.dirname(guiargs.rom) try: adjust(args=guiargs) @@ -171,6 +197,7 @@ def adjust_page(top, parent, settings): guiargs.patch = self.patchVar.get() guiargs.baserom = top.pages["randomizer"].pages["generation"].widgets["rom"].storageVar.get() guiargs.sprite = self.sprite + guiargs.triforce_gfx = self.triforce_gfx guiargs.outputpath = os.path.dirname(guiargs.patch) try: patch(args=guiargs) diff --git a/source/gui/bottom.py b/source/gui/bottom.py index e25c2b2f..35b6c516 100644 --- a/source/gui/bottom.py +++ b/source/gui/bottom.py @@ -345,6 +345,9 @@ def create_guiargs(parent): guiargs.sprite = parent.pages["randomizer"].pages["gameoptions"].widgets["sprite"]["spriteObject"] guiargs.randomSprite = parent.randomSprite.get() + # Get Triforce Piece GFX Selection + guiargs.triforce_gfx = parent.pages["randomizer"].pages["gameoptions"].widgets["triforce_gfx"]["selectedItem"] + # Get output path guiargs.outputpath = parent.settings["outputpath"] diff --git a/source/gui/loadcliargs.py b/source/gui/loadcliargs.py index 9230fe59..6ca7ad60 100644 --- a/source/gui/loadcliargs.py +++ b/source/gui/loadcliargs.py @@ -197,6 +197,13 @@ def loadcliargs(gui, args, settings=None): spriteNameVar=gui.pages["adjust"].content.spriteNameVar2, randomSpriteVar=gui.randomSprite) + # Figure out Triforce GFX Selection + if "triforce_gfx" in args and args["triforce_gfx"] is not None: + gui.pages["randomizer"].pages["gameoptions"].widgets["triforce_gfx"]["selectedItem"] = args["triforce_gfx"] + gui.pages["randomizer"].pages["gameoptions"].widgets["triforce_gfx"]["itemNameVar"].set(args["triforce_gfx"]) + gui.pages["adjust"].content.triforce_gfx = args["triforce_gfx"] + gui.pages["adjust"].content.triforceGfxNameVar.set(args["triforce_gfx"]) + # Load args/settings for Adjust tab def loadadjustargs(gui, settings): options = { diff --git a/source/gui/randomize/gameoptions.py b/source/gui/randomize/gameoptions.py index ac9bdc22..5f3dfddf 100644 --- a/source/gui/randomize/gameoptions.py +++ b/source/gui/randomize/gameoptions.py @@ -1,6 +1,7 @@ from tkinter import ttk, StringVar, Button, Entry, Frame, Label, NE, NW, E, W, LEFT, RIGHT from functools import partial import source.classes.SpriteSelector as spriteSelector +import source.classes.ItemGfxSelector as itemGfxSelector import source.gui.widgets as widgets import json import os @@ -66,6 +67,34 @@ def gameoptions_page(top, parent): spriteSelectButton.pack(side=LEFT) spriteDialogFrame.pack(anchor=E) + ## Triforce Piece graphics selection + triforcegfxDialogFrame = Frame(self.frames["leftRomOptionsFrame"]) + triforceGfxLabel = Label(triforcegfxDialogFrame, text='Triforce Piece:') + + self.widgets["triforce_gfx"] = {} + self.widgets["triforce_gfx"]["selectedItem"] = None + self.widgets["triforce_gfx"]["itemNameVar"] = StringVar() + self.widgets["triforce_gfx"]["itemNameVar"].set('Triforce') + + triforceGfxEntry = Label(triforcegfxDialogFrame, textvariable=self.widgets["triforce_gfx"]["itemNameVar"]) + + def triforce_gfx_setter(item_name): + self.widgets["triforce_gfx"]["selectedItem"] = item_name + self.widgets["triforce_gfx"]["itemNameVar"].set(item_name) + + def triforce_gfx_select(): + # Import Tables to get valid item names + from Tables import item_gfx_table + valid_items = list(item_gfx_table.keys()) + itemGfxSelector.ItemGfxSelector(parent, triforce_gfx_setter, valid_items=valid_items) + + triforceGfxSelectButton = Button(triforcegfxDialogFrame, text='...', command=triforce_gfx_select) + + triforceGfxLabel.pack(side=LEFT) + triforceGfxEntry.pack(side=LEFT) + triforceGfxSelectButton.pack(side=LEFT) + triforcegfxDialogFrame.pack(anchor=E) + return self diff --git a/source/tools/MysteryUtils.py b/source/tools/MysteryUtils.py index c7d811e3..ac130d8b 100644 --- a/source/tools/MysteryUtils.py +++ b/source/tools/MysteryUtils.py @@ -261,6 +261,7 @@ def roll_settings(weights): if 'rom' in weights: romweights = weights['rom'] ret.sprite = get_choice('sprite', romweights) + ret.triforce_gfx = get_choice('triforce_gfx', romweights) ret.disablemusic = get_choice_bool('disablemusic', romweights) ret.quickswap = get_choice_bool('quickswap', romweights) ret.reduce_flashing = get_choice_bool('reduce_flashing', romweights) From 0c50e08cdc736afe4f6c9b8c2271166e3548480d Mon Sep 17 00:00:00 2001 From: aerinon Date: Thu, 20 Nov 2025 10:12:56 -0700 Subject: [PATCH 53/73] feat: rom fixups, update docs --- PastReleaseNotes.md | 10 ++++++++++ RELEASENOTES.md | 24 +++++++++++++----------- Rom.py | 2 +- data/base2current.bps | Bin 118191 -> 118335 bytes docs/Customizer.md | 4 +++- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/PastReleaseNotes.md b/PastReleaseNotes.md index fa8d1286..dbdc2f12 100644 --- a/PastReleaseNotes.md +++ b/PastReleaseNotes.md @@ -5,6 +5,16 @@ # Patch Notes Changelog archive +* 1.4.11 + * Rom fixes (all thanks to Codemann, I believe) + * Pot bug when at sprite limit + * Kodongo AI vanilla in vanilla rooms + * Issue with music silencing across certain room transitions + * Glitched: Some HMG logic fixed. Thanks Muffins! (Sorry it took me forever to get this PR in) + * Glitched: Blind fight VRAM fix. Thanks Mufffins! + * Text: Updated tourney winners. Thanks clearmouse! + * Enemizer: Banned Swamola enemy everywhere as they may be causing crashes + * Enemizer: Enemy bans from Q2 and Q3. Thank you for all the reports. * 1.4.10 * Logic: Changed the rule surrounding the Bumper Cave Ledge Drop (the murderdactyl) to only require Pearl AND (Cape OR Byrna OR a Sword) in OHKO mode for now. This is a temporary solution until a better way to prevent needing to use a framerule to get past the bird is invented. * Helmacopter Fix. diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9e672645..cdcadb7b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -1,13 +1,15 @@ # Patch Notes -* 1.4.11 - * Rom fixes (all thanks to Codemann, I believe) - * Pot bug when at sprite limit - * Kodongo AI vanilla in vanilla rooms - * Issue with music silencing across certain room transitions - * Glitched: Some HMG logic fixed. Thanks Muffins! (Sorry it took me forever to get this PR in) - * Glitched: Blind fight VRAM fix. Thanks Mufffins! - * Text: Updated tourney winners. Thanks clearmouse! - * Enemizer: Banned Swamola enemy everywhere as they may be causing crashes - * Enemizer: Enemy bans from Q2 and Q3. Thank you for all the reports. - +* 1.5.0 + * Logic: Fixed vanilla key logic for GT basement + * Enemy Drop: Added "spies" and shadows for hidden enemies when enemy drop shuffled is enabled + * Keysanity/Keydrop Menu for DR: + * Map is no longer required to see key counts for dungeons if not shuffled. This information is available right away in the menu. + * The key counter on the HUD for the current dungeon now accounts for keys from enemies or pots that are from vanilla key locations. + * The first number on the HUD represents all keys collected either in that dungeon or elsewhere. + * The second number on the HUD is the total keys that can be collected either in that dungeon or elsewhere. + * The key counter on inside the Menu is unchanged. (At the bottom near A button items) + * The first number in the Menu is the current number of keys in your inventory + * The second number is how many keys left to find in chests (not those from pots/enemies unless those item pools are enabled) + * Customizer: free_lamp_cone option added. The logic will account for this, and place the lamp without regard to dark rooms. + * Customizer: force_enemy option added that makes all enemies the specified type if possible. There are known gfx glitches in the overworld. diff --git a/Rom.py b/Rom.py index ec343ee7..e578b626 100644 --- a/Rom.py +++ b/Rom.py @@ -42,7 +42,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'f327962e7f2872c80fd75b35c6f2c985' +RANDOMIZERBASEHASH = '53a99b36f47fcb81c372d03e3559c590' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index f2b1f9252dcd8bf45d222cc667e40bebec06f83d..10648e5996a60f78b6841926803221e6af09f7d3 100644 GIT binary patch delta 6049 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 E{|{Yy;Q#;t delta 5811 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 ma*FEWZE!@yF~ Date: Thu, 20 Nov 2025 18:43:53 +0100 Subject: [PATCH 54/73] Skip unneeded rules in copy_world_premature --- BaseClasses.py | 2 +- Main.py | 2 +- Rules.py | 31 +++++++++++++++---------------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 3abcbdd4..37a698f3 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -65,7 +65,7 @@ class World(object): self.lock_aga_door_in_escape = False self.save_and_quit_from_boss = True self.override_bomb_check = False - self.is_copied_world = False + self.is_premature_copied_world = False self.accessibility = accessibility.copy() self.fix_skullwoods_exit = {} self.fix_palaceofdarkness_exit = {} diff --git a/Main.py b/Main.py index 6b587bf6..873173a1 100644 --- a/Main.py +++ b/Main.py @@ -1026,7 +1026,7 @@ def copy_world_premature(world, player): ret.key_logic = world.key_logic.copy() ret.settings = world.settings - ret.is_copied_world = True + ret.is_premature_copied_world = True create_regions(ret, player) update_world_regions(ret, player) diff --git a/Rules.py b/Rules.py index ee69a481..cd3453d3 100644 --- a/Rules.py +++ b/Rules.py @@ -50,9 +50,11 @@ def set_rules(world, player): ow_bunny_rules(world, player) ow_terrain_rules(world, player) + if world.is_premature_copied_world: + return + if world.mode[player] == 'standard': - if not world.is_copied_world: - standard_rules(world, player) + standard_rules(world, player) else: misc_key_rules(world, player) @@ -91,23 +93,20 @@ def set_rules(world, player): if (world.flute_mode[player] != 'active' and not world.is_tile_swapped(0x18, player) and 'Ocarina (Activated)' not in list(map(str, [i for i in world.precollected_items if i.player == player]))): - if not world.is_copied_world: - # Commented out below, this would be needed for rando implementations where Inverted requires flute activation in bunny territory - # kak_region = self.world.get_region('Kakariko Village', player) - # add_rule(world.get_location('Flute Activation', player), lambda state: state.has('Ocarina', player) and state.is_not_bunny(kak_region, player)) - add_rule(world.get_location('Flute Activation', player), lambda state: state.has('Ocarina', player)) + # Commented out below, this would be needed for rando implementations where Inverted requires flute activation in bunny territory + # kak_region = self.world.get_region('Kakariko Village', player) + # add_rule(world.get_location('Flute Activation', player), lambda state: state.has('Ocarina', player) and state.is_not_bunny(kak_region, player)) + add_rule(world.get_location('Flute Activation', player), lambda state: state.has('Ocarina', player)) # if swamp and dam have not been moved we require mirror for swamp palace if not world.swamp_patch_required[player]: add_rule(world.get_entrance('Swamp Lobby Moat', player), lambda state: state.has_Mirror(player)) - if not world.is_copied_world: - set_bunny_rules(world, player, world.mode[player] == 'inverted') + set_bunny_rules(world, player, world.mode[player] == 'inverted') # These rules go here because they overwrite/add to some of the above rules if world.logic[player] == 'hybridglitches': - if not world.is_copied_world: - underworld_glitches_rules(world, player) + underworld_glitches_rules(world, player) def mirrorless_path_to_location(world, startName, targetName, player): # If Agahnim is defeated then the courtyard needs to be accessible without using the mirror for the mirror offset glitch. @@ -399,7 +398,7 @@ def global_rules(world, player): # bonk items if world.shuffle_bonk_drops[player]: - if not world.is_copied_world: + if not world.is_premature_copied_world: from Regions import bonk_prize_table for location_name, (_, _, aga_required, _, _, _) in bonk_prize_table.items(): loc = world.get_location(location_name, player) @@ -983,7 +982,7 @@ def global_rules(world, player): add_key_logic_rules(world, player) - if world.logic[player] == 'hybridglitches' and not world.is_copied_world: + if world.logic[player] == 'hybridglitches' and not world.is_premature_copied_world: add_hmg_key_logic_rules(world, player) # End of door rando rules. @@ -1490,7 +1489,7 @@ def no_glitches_rules(world, player): set_rule(world.get_entrance('Paradox Cave Push Block Reverse', player), lambda state: False) # no glitches does not require block override set_rule(world.get_entrance('Ice Lake Northeast Pier Hop', player), lambda state: False) forbid_bomb_jump_requirements(world, player) - if not world.is_copied_world: + if not world.is_premature_copied_world: add_conditional_lamps(world, player) @@ -1801,11 +1800,11 @@ def standard_rules(world, player): add_rule(world.get_entrance(entrance, player), lambda state: state.has('Zelda Delivered', player)) if world.shuffle_bonk_drops[player]: - if not world.is_copied_world: + if not world.is_premature_copied_world: add_rule(world.get_location('Hyrule Castle Tree', player), lambda state: state.has('Zelda Delivered', player)) add_rule(world.get_location('Central Bonk Rocks Tree', player), lambda state: state.has('Zelda Delivered', player)) - if not world.is_copied_world: + if not world.is_premature_copied_world: add_rule(world.get_location('Hyrule Castle Courtyard Tree Pull', player), lambda state: state.has('Zelda Delivered', player)) # don't allow bombs to get past here before zelda is rescued From 483e7f49ad99b2bcdf030830d7de3473475e02bb Mon Sep 17 00:00:00 2001 From: Catobat <69204835+Catobat@users.noreply.github.com> Date: Thu, 20 Nov 2025 20:36:51 +0100 Subject: [PATCH 55/73] Fix issues with dynamic flute and mirror exits --- Main.py | 13 ++++---- OverworldShuffle.py | 49 ++++++++++++---------------- source/overworld/EntranceShuffle2.py | 2 +- 3 files changed, 28 insertions(+), 36 deletions(-) diff --git a/Main.py b/Main.py index 873173a1..ff1771d8 100644 --- a/Main.py +++ b/Main.py @@ -17,7 +17,7 @@ from OverworldGlitchRules import create_owg_connections from PotShuffle import shuffle_pots, shuffle_pot_switches from Regions import create_regions, create_shops, mark_light_dark_world_regions, create_dungeon_regions, adjust_locations from OWEdges import create_owedges -from OverworldShuffle import link_overworld, update_world_regions, create_dynamic_exits +from OverworldShuffle import link_overworld, update_world_regions, create_dynamic_flute_exits, create_dynamic_mirror_exits from Rom import patch_rom, patch_race_rom, apply_rom_settings, LocalRom, JsonRom, get_hash_string from Doors import create_doors from DoorShuffle import link_doors, connect_portal, link_doors_prep @@ -172,7 +172,6 @@ def main(args, seed=None, fish=None): create_shops(world, player) update_world_regions(world, player) mark_light_dark_world_regions(world, player) - create_dynamic_exits(world, player) init_districts(world) @@ -809,13 +808,13 @@ def copy_world(world): update_world_regions(ret, player) if world.logic[player] in ('owglitches', 'hybridglitches', 'nologic'): create_owg_connections(ret, player) - create_dynamic_exits(ret, player) create_dungeon_regions(ret, player) create_owedges(ret, player) create_shops(ret, player) - #create_doors(ret, player) create_rooms(ret, player) create_dungeons(ret, player) + create_dynamic_mirror_exits(ret, player) + create_dynamic_flute_exits(ret, player) # there are region references here they must be migrated to preserve integrity # ret.exp_cache = world.exp_cache.copy() @@ -940,7 +939,7 @@ def copy_world(world): return ret -def copy_world_premature(world, player): +def copy_world_premature(world, player, create_flute_exits=True): # ToDo: Not good yet ret = World(world.players, world.owShuffle, world.owCrossed, world.owMixed, world.shuffle, world.doorShuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, @@ -1032,13 +1031,15 @@ def copy_world_premature(world, player): update_world_regions(ret, player) if world.logic[player] in ('owglitches', 'hybridglitches', 'nologic'): create_owg_connections(ret, player) - create_dynamic_exits(ret, player) create_dungeon_regions(ret, player) create_owedges(ret, player) create_shops(ret, player) create_doors(ret, player) create_rooms(ret, player) create_dungeons(ret, player) + create_dynamic_mirror_exits(ret, player) # assumes these have already been added to world + if create_flute_exits: + create_dynamic_flute_exits(ret, player) if world.mode[player] == 'standard': parent = ret.get_region('Menu', player) diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 028f1659..8febdd13 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -200,6 +200,7 @@ def link_overworld(world, player): connect_simple(world, exitname, regionname, player) categorize_world_regions(world, player) + create_dynamic_mirror_exits(world, player) if world.logic[player] in ('owglitches', 'hybridglitches', 'nologic'): create_owg_connections(world, player) @@ -424,8 +425,6 @@ def link_overworld(world, player): assert len(forward_set) == len(back_set) for (forward_edge, back_edge) in zip(forward_set, back_set): connect_two_way(world, forward_edge, back_edge, player, connected_edges) - - world.owsectors[player] = build_sectors(world, player) else: if world.owKeepSimilar[player] and world.owShuffle[player] == 'parallel': for exitname, destname in parallelsimilar_connections: @@ -557,13 +556,14 @@ def link_overworld(world, player): connect_set(forward_edge_sets[0], back_edge_sets[0], connected_edges) remove_connected(forward_edge_sets, back_edge_sets) assert len(connected_edges) == len(default_connections) * 2, connected_edges - - world.owsectors[player] = build_sectors(world, player) + valid_layout = validate_layout(world, player) tries -= 1 assert valid_layout, 'Could not find a valid OW layout' + world.owsectors[player] = build_sectors(world, player) + # flute shuffle logging.getLogger('').debug('Shuffling flute spots') def connect_flutes(flute_destinations): @@ -725,6 +725,8 @@ def link_overworld(world, player): s[0x3a],s[0x3b],s[0x3c], s[0x3f]) world.spoiler.set_map('flute', text_output, new_spots, player) + create_dynamic_flute_exits(world, player) + def connect_custom(world, connected_edges, groups, forced, player): forced_crossed, forced_noncrossed = forced def remove_pair_from_pool(edgename1, edgename2, is_crossed): @@ -1292,7 +1294,7 @@ def adjust_edge_groups(world, trimmed_groups, edges_to_swap, player): groups[(mode, wrld, dir, terrain, parallel, count, group_name)][i].extend(matches) return groups -def create_flute_exits(world, player): +def create_dynamic_flute_exits(world, player): flute_in_pool = True if player not in world.customitemarray else any(i for i, n in world.customitemarray[player].items() if i == 'flute' and n > 0) if not flute_in_pool: return @@ -1303,6 +1305,7 @@ def create_flute_exits(world, player): exit.spot_type = 'Flute' exit.connect(world.get_region('Flute Sky', player)) region.exits.append(exit) + world.initialize_regions() def get_mirror_exit_name(from_region, to_region): if from_region in mirror_connections and to_region in mirror_connections[from_region]: @@ -1329,7 +1332,7 @@ def get_mirror_edges(world, region, player): mirror_exits.append(tuple([get_mirror_exit_name(other_world_region_name, region.name), region.name])) return mirror_exits -def create_mirror_exits(world, player): +def create_dynamic_mirror_exits(world, player): mirror_exits = set() for region in (r for r in world.regions if r.player == player and r.name not in ['Zoras Domain', 'Master Sword Meadow', 'Hobo Bridge']): if region.type == (RegionType.DarkWorld if world.mode[player] != 'inverted' else RegionType.LightWorld): @@ -1350,12 +1353,6 @@ def create_mirror_exits(world, player): region.exits.append(exit) mirror_exits.add(exitname) - elif region.terrain == Terrain.Land: - pass - -def create_dynamic_exits(world, player): - create_flute_exits(world, player) - create_mirror_exits(world, player) world.initialize_regions() def categorize_world_regions(world, player): @@ -1433,7 +1430,7 @@ def build_sectors(world, player): # perform accessibility check on duplicate world for p in range(1, world.players + 1): world.key_logic[p] = {} - base_world = copy_world_premature(world, player) + base_world = copy_world_premature(world, player, create_flute_exits=False) # build lists of contiguous regions accessible with full inventory (excl portals/mirror/flute/entrances) regions = list(OWTileRegions.copy().keys()) @@ -1510,7 +1507,7 @@ def build_accessible_region_list(world, start_region, player, build_copy_world=F if build_copy_world: for p in range(1, world.players + 1): world.key_logic[p] = {} - base_world = copy_world_premature(world, player) + base_world = copy_world_premature(world, player, create_flute_exits=True) base_world.override_bomb_check = True else: base_world = world @@ -1554,11 +1551,9 @@ def validate_layout(world, player): 'Pyramid Area': ['Pyramid Exit Ledge'] } - from Main import copy_world_premature - from Utils import stack_size3a # TODO: Find a better source for the below lists, original sourced was deprecated from source.overworld.EntranceData import default_dungeon_connections, default_connector_connections, default_item_connections, default_shop_connections, default_drop_connections, default_dropexit_connections - + dungeon_entrances = list(zip(*default_dungeon_connections + [('Ganons Tower', '')]))[0] connector_entrances = list(zip(*default_connector_connections))[0] item_entrances = list(zip(*default_item_connections))[0] @@ -1567,12 +1562,11 @@ def validate_layout(world, player): flute_in_pool = True if player not in world.customitemarray else any(i for i, n in world.customitemarray[player].items() if i == 'flute' and n > 0) def explore_region(region_name, region=None): - if stack_size3a() > 500: - raise GenerationException(f'Infinite loop detected for "{region_name}" located at \'validate_layout\'') - - explored_regions.append(region_name) + if region_name in explored_regions: + return + explored_regions.add(region_name) if not region: - region = base_world.get_region(region_name, player) + region = world.get_region(region_name, player) for exit in region.exits: if exit.connected_region is not None and exit.connected_region.name not in explored_regions \ and exit.connected_region.type in [RegionType.LightWorld, RegionType.DarkWorld]: @@ -1586,11 +1580,8 @@ def validate_layout(world, player): for dest_region in sane_connectors[region_name]: if dest_region not in explored_regions: explore_region(dest_region) - - for p in range(1, world.players + 1): - world.key_logic[p] = {} - base_world = copy_world_premature(world, player) - explored_regions = list() + + explored_regions = set() if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull'] or not world.shufflelinks[player]: if not world.is_bombshop_start(player): @@ -1616,14 +1607,14 @@ def validate_layout(world, player): start_region = 'Hyrule Castle Ledge' explore_region(start_region) - unreachable_regions = OrderedDict() + unreachable_regions = {} unreachable_count = -1 while unreachable_count != len(unreachable_regions): # find unreachable regions unreachable_regions = {} for region_name in list(OWTileRegions.copy().keys()): if region_name not in explored_regions and region_name not in isolated_regions: - region = base_world.get_region(region_name, player) + region = world.get_region(region_name, player) unreachable_regions[region_name] = region # loop thru unreachable regions to check if some can be excluded diff --git a/source/overworld/EntranceShuffle2.py b/source/overworld/EntranceShuffle2.py index 777edaec..8ef10110 100644 --- a/source/overworld/EntranceShuffle2.py +++ b/source/overworld/EntranceShuffle2.py @@ -864,7 +864,7 @@ def get_accessible_entrances(start_region, avail, assumed_inventory=[], cross_wo for p in range(1, avail.world.players + 1): avail.world.key_logic[p] = {} - base_world = copy_world_premature(avail.world, avail.player) + base_world = copy_world_premature(avail.world, avail.player, create_flute_exits=True) base_world.override_bomb_check = True connect_simple(base_world, 'Links House S&Q', start_region, avail.player) From 1bb803016e5b9da09999bb6e0bcc3fca6e0ad4bb Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 21 Nov 2025 11:40:42 -0600 Subject: [PATCH 56/73] Remove unneeded world region setting --- Main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Main.py b/Main.py index ff1771d8..03d9e6fc 100644 --- a/Main.py +++ b/Main.py @@ -170,7 +170,6 @@ def main(args, seed=None, fish=None): for player in range(1, world.players + 1): link_overworld(world, player) create_shops(world, player) - update_world_regions(world, player) mark_light_dark_world_regions(world, player) init_districts(world) From a8ac33c09320fce47f522bde835bcf714131e0f4 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 22 Nov 2025 07:31:51 -0600 Subject: [PATCH 57/73] Fix for post-mirror follower sprite gfx --- Rom.py | 2 +- data/base2current.bps | Bin 138220 -> 138254 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index ad5e488b..67e4a122 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = 'fea650d598f4399db790903d9eb16186' +RANDOMIZERBASEHASH = '35f2b275114fcec150981e9cb28de373' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 00911e4ea0b104984649b1e074fe0a91c66def38..d3e9c2e9e457e02f6d4367b11aa849a0d22654ee 100644 GIT binary patch delta 10141 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 delta 9967 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 Date: Fri, 21 Nov 2025 19:36:22 +0100 Subject: [PATCH 58/73] Make placement of dungeon items faster --- BaseClasses.py | 6 +++--- Fill.py | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 37a698f3..b95113bd 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2701,8 +2701,8 @@ class Location(object): self.recursion_count = 0 self.staleness_count = 0 self.locked = False - self.real = True - self.always_allow = lambda item, state: False + self.real = not crystal + self.always_allow = None self.access_rule = lambda state: True self.verbose_rule = None self.item_rule = lambda item: True @@ -2716,7 +2716,7 @@ class Location(object): def can_fill(self, state, item, check_access=True): if not self.valid_multiworld(state, item): return False - return self.always_allow(state, item) or (self.parent_region.can_fill(item) and self.item_rule(item) and (not check_access or self.can_reach(state))) + return (self.always_allow and self.always_allow(state, item)) or (self.parent_region.can_fill(item) and self.item_rule(item) and (not check_access or self.can_reach(state))) def valid_multiworld(self, state, item): if self.type == LocationType.Pot and self.player != item.player: diff --git a/Fill.py b/Fill.py index b6b793db..0fa5868f 100644 --- a/Fill.py +++ b/Fill.py @@ -183,9 +183,13 @@ def fill_restrictive(world, base_state, locations, itempool, key_pool=None, sing spot_to_fill = None item_locations = filter_locations(item_to_place, locations, world, vanilla) + # for dungeon items, it is worth reducing this list further by excluding locations outside of the respective dungeon + reduced_locations = item_locations if not item_to_place.dungeon else \ + [location for location in item_locations if not location.always_allow and location.parent_region.can_fill(item_to_place)] + verify(item_to_place, item_locations, maximum_exploration_state, single_player_placement, perform_access_check, key_pool, world) - for location in item_locations: + for location in reduced_locations: spot_to_fill = verify_spot_to_fill(location, item_to_place, maximum_exploration_state, single_player_placement, perform_access_check, key_pool, world) if spot_to_fill: From e13451df1ecd4b93abe51aa447e3decc37c82746 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 22 Nov 2025 09:23:18 -0600 Subject: [PATCH 59/73] Version bump 0.6.1.3 --- CHANGELOG.md | 9 +++++++++ OverworldShuffle.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7435482..dfa86a1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 0.6.1.3 +- Added new post-gen option to change Triforce Piece GFX +- Added new GFX for 10/11 keys to replace the A/B GFX +- Fixed issue with Follower Sprite GFX after mirroring +- Fixed VRAM issue with Crystal Maiden cutscene +- Some performance updates +- \~Merged in DR v1.4.11~ + - Enemizer bans update + ## 0.6.1.2 - Various fixes for Custom Goal Framework - Added custom gfx for Pedestal and Murahdahla diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 8febdd13..8cb1e68c 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.6.1.2' +version_number = '0.6.1.3' # branch indicator is intentionally different across branches version_branch = '-u' From 2a1eeb25db5d74f6d94c741c7f866520ff451ecb Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sat, 22 Nov 2025 10:19:54 -0600 Subject: [PATCH 60/73] oops --- BaseClasses.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BaseClasses.py b/BaseClasses.py index b95113bd..c102b540 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2701,7 +2701,7 @@ class Location(object): self.recursion_count = 0 self.staleness_count = 0 self.locked = False - self.real = not crystal + self.real = True self.always_allow = None self.access_rule = lambda state: True self.verbose_rule = None From 3f0c3ed810eb9451a76cf29c18e665c51428c1bf Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 2 Dec 2025 09:46:09 -0700 Subject: [PATCH 61/73] fix: perf optimization fix: playthrough calc and drop rules refactor: using compass_mode for map info --- BaseClasses.py | 4 ++-- Fill.py | 2 ++ RELEASENOTES.md | 4 +++- Rom.py | 2 +- Rules.py | 11 ++++++----- data/base2current.bps | Bin 118335 -> 118393 bytes 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index 3b06f10b..3d7e80b5 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -2279,7 +2279,7 @@ class Location(object): self.staleness_count = 0 self.locked = False self.real = not crystal - self.always_allow = lambda item, state: False + self.always_allow = None self.access_rule = lambda state: True self.verbose_rule = None self.item_rule = lambda item: True @@ -2293,7 +2293,7 @@ class Location(object): def can_fill(self, state, item, check_access=True): if not self.valid_multiworld(state, item): return False - return self.always_allow(state, item) or (self.parent_region.can_fill(item) and self.item_rule(item) and (not check_access or self.can_reach(state))) + return (self.always_allow and self.always_allow(state, item)) or (self.parent_region.can_fill(item) and self.item_rule(item) and (not check_access or self.can_reach(state))) def valid_multiworld(self, state, item): if self.type == LocationType.Pot and self.player != item.player: diff --git a/Fill.py b/Fill.py index c6189460..70864fce 100644 --- a/Fill.py +++ b/Fill.py @@ -137,6 +137,8 @@ def fill_restrictive(world, base_state, locations, itempool, key_pool=None, sing spot_to_fill = None item_locations = filter_locations(item_to_place, locations, world, vanilla) + if is_dungeon_item(item_to_place, world): + item_locations = [l for l in item_locations if valid_dungeon_placement(item_to_place, l, world)] verify(item_to_place, item_locations, maximum_exploration_state, single_player_placement, perform_access_check, key_pool, world) for location in item_locations: diff --git a/RELEASENOTES.md b/RELEASENOTES.md index cdcadb7b..a5d2e8a1 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,9 +2,10 @@ * 1.5.0 * Logic: Fixed vanilla key logic for GT basement + * Logic (Playthrough): Fixed an issue where enemy kill rules were not applied during playthrough calculation. (Thanks Catobat for the catch) * Enemy Drop: Added "spies" and shadows for hidden enemies when enemy drop shuffled is enabled * Keysanity/Keydrop Menu for DR: - * Map is no longer required to see key counts for dungeons if not shuffled. This information is available right away in the menu. + * Map key information is now controlled by the Dungeon Chest Counts setting. If set to always on, this information will be available right away in the menu. And will be on the HUD even when the map is not obtained. * The key counter on the HUD for the current dungeon now accounts for keys from enemies or pots that are from vanilla key locations. * The first number on the HUD represents all keys collected either in that dungeon or elsewhere. * The second number on the HUD is the total keys that can be collected either in that dungeon or elsewhere. @@ -13,3 +14,4 @@ * The second number is how many keys left to find in chests (not those from pots/enemies unless those item pools are enabled) * Customizer: free_lamp_cone option added. The logic will account for this, and place the lamp without regard to dark rooms. * Customizer: force_enemy option added that makes all enemies the specified type if possible. There are known gfx glitches in the overworld. + * Optimization: Improved generation performance (Thanks Catobat!) diff --git a/Rom.py b/Rom.py index e578b626..c810534e 100644 --- a/Rom.py +++ b/Rom.py @@ -42,7 +42,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '53a99b36f47fcb81c372d03e3559c590' +RANDOMIZERBASEHASH = '76d6a1915f52950e1b4b6d0fba95296b' class JsonRom(object): diff --git a/Rules.py b/Rules.py index 19dc9922..a1ebe18a 100644 --- a/Rules.py +++ b/Rules.py @@ -996,13 +996,14 @@ def drop_rules(world, player): for super_tile, enemy_list in data_tables.uw_enemy_table.room_map.items(): for enemy in enemy_list: if enemy.location: - rule = defeat_rule_single(world, player, enemy, enemy.location.parent_region) - if enemy.location.parent_region.name in special_rules_check: - rule = special_rules_for_region(world, player, enemy.location.parent_region.name, - enemy.location, rule) + true_location = world.get_location(enemy.location.name, player) + rule = defeat_rule_single(world, player, enemy, true_location.parent_region) + if true_location.parent_region.name in special_rules_check: + rule = special_rules_for_region(world, player, true_location.parent_region.name, + true_location, rule) if rule.rule_lambda is None: raise Exception(f'Bad rule for enemy drop. Need to inspect this case: {hex(enemy.kind)}') - add_rule_new(enemy.location, rule) + add_rule_new(true_location, rule) def ow_inverted_rules(world, player): diff --git a/data/base2current.bps b/data/base2current.bps index 10648e5996a60f78b6841926803221e6af09f7d3..7528406538289ca931deb536e97b8a6718bebb73 100644 GIT binary patch delta 9245 zcmX|Gd0bP+_Rrje5cYkM&2ZU4R(C-~MWlj?idGSoDk>Tm>e{-HxsdVIuID7s9@PMp8)Ll+0FW4~y$baf---F!-6DpD&qe_pTAT!ZRzaYZxBy#f4 z0yj~vf9%5Iub5gTxlYblg6UNy7b|}nkl?J#vK;AI8FRcc3f`2>tX1mRWI1ALB|HU# zwi=NC(OR_mYys4+roNMs37w2VN=BhO{xQA{XPJ{!S&w8>KjTZ8$ct2tM#M0XK|J1%i+H;Mz3fx|pG z9!UKps3bR{8$nU2o8(N3x zp?&0%gU#Z@C6roDsd-RMrWhxU9{_ml|K*1|WyzT)XEvnZ$yRb6iVNn0muN}wDu2sa z6fz&y(z)y4adhlL9iyLEW9W3Idn9snHFzEP#u!X;07ygOA$eG>j)oM0b?8mV7ho1T z75eSC1|#!?Dh-8QWJ`JXh#UyW-tz8tDQQ6UVFhlN&N3qbkdh|g0Tvupkgt$Scr>G3rp(AAJK!DP}jawSj(~Ml~bjBs3U(z z?h_K-hi)-+{GpmO3GFzm_L`cEK7&?FSRg!p4Xf=*Ra6jOn!$c%SV?M5Gb8d^Mc(P_ zEhA|niSNxOtZXA^n6@-0TxRXVrmy^4q~wQ(P4|AtiKBegb>t0PV?=I{_?>3bV3+Ed z*C=`6G$Xee8R1~%;A3T2bcTWM*V#pM3U1n*I zmw;_RV_XrjNXaa5ODaXdVFlTRnEY#|XfX$hIZ|0Fls42c z`HYmTDrxZ*NlDIebaQqvXNaEcj$X}<2k%gDs$Wdyab^S?pgauBX>un9{_e-58e2$xSJ_U#WEzOGwY-bj*S?14@!tj~Y`qgB3=bIX*D1tsTwF%9(nNq31{I~G z=kID>spJvbzUu+FWXvpz1|&z|<6K_aha+7(jrP&Jc>*UGV6 zN*+e@_JpUc$E8LZ#;l0sI~6D9{$(+lL^m8)*@gZ15FIAUTQn>$OLb)CQGS)mzA6%L z@3Cc17#li8m8xc49hRI&U3;d3+vqudcc9?CF~EQp?fpPRbfLxjvh6zPh>w}H5=nvwNZ3{zqQCBBIEkGCMf;VXD3u}5}+ zP^3Px1hg7o9#OH`>NvTvg1W#ZlDmxy%Cm^1!YW2qd%5^>xW!G6(c;iC#ak-NvW2Q8 zLpva;>0}O$3I=n@Gf$c>CJ+`I@=w%XQ3T@9l*%0NC#tM`>7}fYq_V7TZJ`ljX={an zU6Ys6szyhS`3QfnR0WAC?+Y6t<@%FI`g^6>MjIib<~$BRdcjRR#v`?d#njx#q6_=} zq0wV>;bReH|D}jZpp!)s7Gcm#5>fMTk>#b$p+_knEVcbIi=rlLUs7o}d)GfTleIiC zH6K&(51p&^E1{5wbh2<)g@iE=Xm^UJ>0%wp`e!i zkLHfi<(P*2BjswN6;uwUvH#F0?IZ=Y;(zqy7+v{4`e2NHjA>NmSjz!&Z9*lr3UhYZ z7;n+qmr<+#p^7N(xOesCdWF2KhEH72T2t&DnpF5?>c7TPw_zg-0Lg zYK5%c1R^i>K~n}wJEd?Y`{fJ@geUM~Lq{?MI|~-g+M|@5+JXOXo6ze94EwB zo(QnVM~7^=tV&t>t%NtkZ~JsPR9ZPYTS(Ld0I4`qfP(erOU3%#l)-9WsIPooOqP#I z1%-%ZK&^_YL`Wifpa>&46Om2zb;4y8`nq}<7(l@&3izN*6zDm0yzlVq;;0X-O9RKZ zdPk~Dz3D0FFbd-Sb=>N7aR4#MH?f!F1H*JKky4Hi!(v_XR@O{s_bGW+J6(9B?5&vV zL&w3>PxSMlLGqeqWoK2QVKjMm;Gr8kU>~Fz^@w}laSYKOeeD>wdGuYx(BaW%8IyVR zJsFdE_PrmIdG|VFON(H|@nR`Y8tDM76i`vxT@>py>l<11|bcl4UmB&dwHE*;#K< zKz$bc`C3nk|+<&B`HqDY{ZS&hwy#>EM@Y4vyC3ZKPCw8KqaU9-v=pBRpMO z@ZyzHD?3G$n@U9GVsuAQb)~bu)KpjHw-aUp4|?SZ zGaJM32{Xq6@@w*DG$>uIj=irKV~c95rAOy|z+*Z4z{qyHm~yxCbqrRv#~IJZe#LTy7pHGYK2~cz)k49D$pxnnOSY&^`-t|kS&otl`P8^YMmaTpH;r@ z;V*7kBJ>4Vxg7NCvxR}KEy%lJJJ^7ZHtdi8DE^7jcmIQPc!CFWD`cN!3!7LBi=L5O zqQkRk!=Ht3WM)F+D^darn?DOhsv{g{wH_Sp%x`wTF3HM6Yt-vO6S|JvoL56DMpXQ);2HK7_ zs2OW;tbtmT%7v%--?z(ya+y%_+ECNMrnzZHtA)!b$~deE1HpEkOg~4?9)@rG>^qs7 z!flnWD(vk$`W!kL>2P+RQzwc$kqF+R{1Y=bylR)7tK0}BzrJplZGgRBaq&*t)6p3z z0DS(`U%#T`pHTqSQTeopB52kN}2F5e=72A3S9keo0xJ$qB;Y6 z8gz#)$k866*}qEVm?BUjOL=xeQ7ss&VX&>)=u63jj<7Bi8f3d)7dP_*pi&=($sUzh zY_)G%m~)?Ula-6DJk7W$Bx_m<`q87N*~HFNL^g*eP3>X2u5oS$LxWZ2kt#lIwzc|` zAN4Q--9+&KopMX!ppT&)c_no^TftbqCL4X$97H&rLbc8FT_VCDWknez)ahJEocD8c zu*-pepICp2(Xf^Yhlk(A-A4f}0pJjt-a-a!k9yZwO$n;)%1&qKNocTeNZ~0)AA*Jy z8g!s#HenZwdRpS$coE`emnr4azNdQTd8t(R9KCNTSj>ul3?NG|Seen~$VtdBv#e=m z!kTLKv!aFpQ-1{t7_j)sz#7jYgNq#eG`LD`mQc-mLc zyU@`bWw9Nrj`Ctqep^W3y!C(G?YnxfDSr2xVk>8e?<*Jz7MybAT;*%B)+45E>h##? z2aT+WP%5^E&ib8k4_d|cL;NwHuIrv^V|x{^^wtZGn9%XXoUyz?!s;agQmUvNZ#&clI1~qdkcT=tdvfr>2Fds8Cq~Z0+a^?PhMV*_ISl zV9YzkBpolKlP-*Ur#2+OaPtBSDT{{9Y4wz6J;$~TZ-;8MOQkUIu=PSk=%6m#)2>$G zV{y{QYPhwPEwXu@P`29xoz=w>nIECYx)>ojA1Yk0^7SdQYUOjbl_N_*OOv50HyQS4 zzA5&T;TPH6%?M<>UKbCl3Lv#hCaP?&BPSeZav5K=rAI=3Hj1xJqmSKtq^6VhK?nhoGqkxLi&iqztm3p%NP*&(-OgZTXBKBUxRT=ELZKDiPz$(-mE)|(~l>j8&RD;!hZ6h_YxdbQf*s<{!cF@!j_@chEIrDU!jYJ@_1E0 z13mFvA2w#Yk4R4TGv~L@t)_D6O)eupY!#W}+(#6ih5sqcrT1luwFOyd&*>2RtJei% z(>RBJ6)~rMZ5=*>R4}~{^_>nT_9vpD({Yi3nXsRem)om)xSwU<X|i8`!>}mW!tV4_iZrk3`UwWvvGj%r!x`WE&+ci>_I~ZN9Dcx zy+Zj|N|w_rR-*u87SGx556XvLZG(!8djwC-f>stk_=cb_^~++i^KX%6lV3Y3h<>Zu z5&afz$G8vUUW`XD9>!=B^A>Sp-m081I%4#~=!r29V*ti5jG-7~F;0kiTO(Z4uXe>J z$y2oWY%39b1HC;P@4Pnpt+WI=rM|6S zZ>OvUrng@fa0@X*SA%6(}(7~rOwjZQqk1zX6NWTjNIPB(>Giyz8!f74R=R5?eKw0 z8Rq&%v~VX1GR1I%Iz=x6?w}>6Apd|njLaWa&VtfkgK%;Wq%O+NQzZ5d`Ka6!zzy%5 zETTeDhiN0R{2S!bb34fMwm^RqJ1?%XC@95_o-?gNtCJ|nj@QL#!xHpY&yPfKGWypS z6Sxy>-qSN}ki+>jVn2bFo>%7XV88G3VhQvF)OI`s1}E+IWAw6p?-C)o=L?3MQAS;L zZDaaueqe@N$%Znx;x4oDF7xy*v-f+3{R6}Kff0<^Ahd5PR9{VK${VM%@M>HL(e=6M zDD^`6k|jl>e=aT>rR*J`NVQk=?LJY>l+>sGFg~JY*WZJRRvr z&U)_%DsR;li=FiI-V|GQp)Hk^Hyt$|eg2;{Zqu-#N}zM}ia~rR6wv88=;?p<;h5%{ zpPxCbomfth^k$PR_P;3WWze*_v&*S4P5ybbB>^Y!H6%-rfV{Tp$NcE3yp&WFtmx#B28S|QW9 zViC&vmG9-+Wm@YCJEt6%$~I*Sk^N(8RJ9XPzj_IM7C_2J!{Jm&dKo9#-?R-;A%-rh z=tqdvd;&Y;0v$_z*-4ejfoKb)GU*BI3bg)XiFVxz$#}SAr9_nwD^V>h6&DJcV>U=6 zcb+%VQ*5CW*F1=(!sY}28V?t*l!)6i(66mHCZPkeCE3D4)e`&HR0f@W$Zq)M*oX?r zS`=jU9+&(XTu!a&b z>Bj5UbzSYCvej_wl z8C8!f)H^AIIBPWTXS#_1&mAVNFO%M`p$v4uPWm_-{K(4?evka0tMFToI)KC6w_SA>*e?6|Uj{K}K`n$FTBp-xaZbd?(Q()-P7M z^`OW>v~CjZX9rT)2ZYDy)pj5*POuz`cfX-mWc~i%ynmUPO5G3aCYAxmU2=*HI!Dm- z*vLF)<8&tu9;{2J&)I=B#M%Vf-5!JzpBK>6?7_6O$Wu(@sGw%%Qg!c42^5g+JxpHG zHw=j%v@r?3w9$Er-30iG>uz~l;3oJ-79wWG94Q_O{e_ZiBA3!9Xcq@l=?lE~efSrIyE~3SbAdQ%^ z+jPSb+yEYd+p11GG_@k;y(|A-C7d&(Ii1!ygY)iQww08prn%0cX$4~ba-~;prT4jj zI_|tAsm49Y9LIXD_Q=Cv)>?F^JwdC=MWOzSJdlvHtg3EN^V;Uk%?oZc z>n;oo9L5ni7HeQYvv!B{3tv_KKLpx*_|R0)tjXD8qWr;6b^+`S(mQOHZW0bw>D&p~ zrR3s#7wAHqiJ?>0n+}J8TYxu*Uq!u9?G7|8jR0*9{39M^QX7`lPE*J(`xkeJ-)M2l zAL6&VSpsx53?N5MJ`=$xaNf7Gw9fLTP&X6KQDsdsjh_r+0eEj(GzF{%L~%OZJ{3d~ z`AbaSOa-ov{3AQdA3aQE860#%mS)xE;^ARvjl>2fBU>n2fD!{~A`N^ER?>IUaIJ!m z=|9szzSj}1f{LV5j-rJ;1vQS|>Z;Ihb2Sys2R63ubF<#5$)XZ%o>!%)hMN!R1iCB> zT;ffO|D779$L}*OT7=ioZmVOxgbyW}43l~ZXaEFpgic-xGC`!NY$?D8NUX_cIamz1 z3j*s@b5_xU9MAzqOx`O%3*k1~x4zY2;56AmqRGC3cK0#e_!!IvzI-L}+XnlS$6OhU z!&O&C$Ui2(p2erh)nJCOP$oLzIwrz*w>2_R?~d12yQ}=Ze56Wc&h-7&AjtE|ab_$Q8}-2gRG};0 ziLHPRrd@KuRM*?IsLqy!BXqZGWCZL?qgUpFU~-mH>nqGvYTL&~TbJfNFra%IicvK= z*{Xw99{*RmE*C_E91Qn_)NXp}xH`&3<+KGVtXzJ0ZKo?xNe0_kIHu9OntqTA!i71T zHk{; z7Ta$#VdrzSFwf0IlX)N{ZWDvoFsXjZ!HOaT`j| z`H0v4@{pj%(R=bhxI;j_!GYgjXGr1yK)2+92;mQPh9b?}_1;i?%~P{_t2eCU@{4u- zo|@|1p4Ljfl?1B4r6??>#$@;Nt((p?KB2FsL~u_O;WO7Q>xS8FQv?RD#K!>^4DeYSA%}%Z?diV5WQXB=CVoIk! zUJF9p1L{W&>{gaQ2Y_H}Dl3bqr;n`#iG)`M-M1Em`7DXMaV7W#pVdzqLb1G`lm`y+ zHOuHf*MdNHa``Ni|2iMo*(HCh@EzH%RB@^il zg&>aD9Am031Xln#XF<85aE5?kPOVFj*Ik6pmy;|`O-Ewnin38(!8GK3jo!BnY$oP- z)AzT5Kl}~_XcV3Io317pqpnK24-WOI>Py|#ws~DA5v`FfGmMY9f0t5^pjA4O@SqTsV zVuDfQ4b@Uft2M1hTdY=Tt4OO&J*uVs={xBkZ$6)$?>zg=wevjl%=0|?`>=h_VSB?R z05+l?5KsL39eN5*@^c&6e(8@$ON0S?^c69QcV8H)L458+yR-FL>IRz0O$B-+=H`06 zZO}$nD=E)L?eK6)8BOo4l+Hm`?l`BLC)m1(jT#wsr5h#k#=3NMvxWdThJ+0?<%>4) z<^V@@l6N9VaE5h;a*iUqOiFaI;gF_V6cp!4^RP3NrlSLPdq6V!$8I`sLsR%c{I(Sw z`s^aKlE1*U`CE3y0R^P)K7^-(AE49xRImlT=HCP%=qvk8U^ki~nBsKw7Hi=Tr_s`Z zTWG&vB60i{Iwg4GA%Q$JK_|Uq=A&~s;_d-iGecL}xU-FuKDmWioEbjqc{ zzAa0Yf*NfcQ z8;%%Hxjo81H-l<{PVh3IJG$Ui;nwQuMW75s(_^jgAGx?c->d|7@Sf z$JycGgEahH8zz3!d8xgp?y!VdPUb`HO8SQ7I`_GYkU?fUAd5k z$6Bcb6cb8v|XCaT8_BA_1(-tMQq>QcM`av1xD%T#C34b)8n^9-R#_QRB zT6&>XO8Go#hTN?GHLZXRRG*%;@`m5YsM<%(X^@t-(^A}OAMSkjB)S+aCe9nt%$P*} z_A~5{O$X4fm~`SrAG#1z>+pk-9nOIY$_>3ATP+y6#>Uf1tkh3qZ;r<6q4t{Dng+Zi zihqrrTuzr2lr~Um^g~>@`vI(j83*aI3c8GhI_ey9i61kn>N?9LeOi|$Wt`uu|GbI1 z*^P4I=SENe9P8^bRZK7z$$>t02y0_EJ6uz*5O!Z}8BP;R{jN1*Ekmd$J}`ABW)0UE zq*n}V8thU%@*bh`yV)AM;b9(@K8dCMS2qhsUFB|NQt)`6o?rvT3NcmM%`U~?@mIGo zAR!w7PgIbYjE{6f;#T5~0XZd|1IvwHB&{aEQ4~IQB0g5D#=ZtcXvw&6V&EqFWZW}e zT)k9^J{~`f*sL;kj1MDRS6ye%N9>ZMfbyeaYL4;l#2UexS7%i7Kaw46aF437*SSSy zV{L_B_oTSdXC##Bs=wpG?`fGAlu#lyn}2|Yfu%AkThfwB({M;ZF^J9k+!QO}!B(D( zL*!9q4Qw7OqpC|={KPWq8A9e6p}cF%CU^8~MiO|4f>Zt1?K;E`V^cB*1KUllz(8*Q znJUMa0_nWug9>VI9h*0~QYpOEfOqb-d-Xmjg$>0>sL_>jsHR_=hljHt{VuFfPz|`# zH5s)-sdbh}sJE(wxhMLS)bj>(ICTSN9owq(J1xTo8am@m#xHZQ zG7X(YlV@iT7{s$38BoIgK*4wa3*N^b@!#?5p3q9@gU&gN!QsvUOovc8NKLXO_7idX~degpgqjH-k@Lkl!HfBZKlVUtwW-9|B3M~Es zUE2OZ=;T^<_#`cn%eE_I)cRUhh{fn!A)_{+)E$vA^Kh%-!*o*(Exo1U z#ogKv{LD2W6Q2k07}poyW>HT@x|_^_*y^@_kN0Rxz(S%1$IbS)E-dS z$A*h(87mVCVN3mgpI7#hE)$CBWhms+Xt2zf@hKMsVKdJ-`DqT*M`|S0Nn`xxBSW;r zKua#5sa{vm#(kfGLnvWs9O6l`_;+Ip#IThK&*u~YXyuP=% zH`3yv$7pftnCK&uXWK*7!of|D`lORB8W9cTQYU_CzK~2Q?{e`sH$4lk9Y(k5GR*SA#iph~s9l=eA43DWLAiDeI}%y!x+F+KC= zBJuh4r8YWRnxgF`aWBKR+di zWuDdMaoUthdJ%4IudtE!T2}?V`2WdV8@U9NdunW4zP7lAUW!TZU*j09KtV72fAW}( zT>k&$eH-~cCS$5>eFJN>$yM|UOmoX^bc@!poL>1KsqjS4Wf{b#DwI-vJt(;j1t@86 zM*Nw*-tCz|e3+yE=cz%g4}X^Vi#>S~3Yi^+sA^?q{(@;k0@rS#YZ2!cnku%R>MqF|9l zz4`zxI`Lsx11&-u&!g#z$+53%S<5dX?87l(AN8u-7u}Q!2FbQ(lZ^gQL=Y>+BA?o;#Jcy2EmhpV$|42B>x+&ZqrNHW- zi;R{Zknnw(MA-d{J{=mQFF00i_AWGnCd}AY^wlQVQ^>GQ!=rkNF~oZI)M6;~>}kW$ z;n{P}#`Em?+Q#$h8MN`ddj7KUym}nb=0lT!4{AHKCCNLtUm7IkDqg8L`+>ysz$6# z`h60KzO9SEKF6CnvG@EYR=+5x#QYAQ+t61MQ8Op&Wfqb%JL7&kGDtE`t8Utf>u==c zl;B~1JJJKp2Hf<&D#vWNk&{zmQYTzTt2WOq`z*V^wjs)EM8hJ#GJ1KZnEpp4 zrgJg=i>5V{&FoTFTAj0A{-&1Kd%(26B%-RU&Q{j!VBwS3TFCt7&Wq61;*|B$nSB}c zN{HS_L>e!tu2+qlQIB69A?KoZ4gM((P^4d%Qxaou^*00j5&y7e0z>LiGZ(|RN6kD7 z$gA5u>WI?a>U{Aoi=1T22ktd5FaD<8jFvT0glIbYq%oneAoNl7xJD_E@R?0B`>yBP zxBABjtd6>5i9mN$;s6D@$xPy`K6L=3c}Pr4m@z9a(sLTerw+>IWO4{5^Zkp;R6N6p zquPV?Wv!oh3GFLBvM%7Ex<=zFrc?D?T9VeREv1(tXI03|5sj5w1jiRO#!Wde9g^x6 z@~wt?bfBz;OZK#oyITIMdvy&E7Pr>FVxZNb)!poD;F1@c`|*zvm7Ytl+p*J%&cwtTbf-IAP=x+L=9X9GIUZf(U7S;*{oujvriSvKWjQ7OYFy|z@`X7iwq8up&~;0cJ|8QolYVVZNzjN! zj$xoPx$3$NKJwv{LY$&JabqAVsbPV_jZ9F>N`)<4ZRMk2t{o`J{{6l#0 z3qC%wtI_$Rp(SQQl!0#nuGNm@cS0`tcSk{<=2J~ouX@4XbVhTr*R9s3f`(+`JSDl; z{H-YD9@^wNaIvIetD7i8K(%$UH53`zshze&j0!gWXinx>90y4qAxYAuNahTZ(FG!P zj+%Bx>+2f~+{thhbVDCIKos(atOk>a0;TelM@JR4BHLI7`?__0w0wy(YzT)2`SusZ zn&X`Vsso`I%m!pA-^v0b0@ZiGUERTVHp(rvc422jsUtVlOb z($Az^mpbX=m^}N^2A#dg_Fm0H3QaI^qYHIw(%q79?!k(3LZMFQM&WmMEuryoKOPM` z&Z;?!ONNGCfB0j=gAh*5&FGOY#@bm=5vc?udI=6Ul?%DO3>PhKp#pbCzdlk+i)tOp zyEF6@G+21l?BlFH3=JyQp_-N%ghxF3rX|TEB~qf9J)uI@qtmmG%VZ^;$fGrXtRV5{ zR*q<(szbw-F<|TRmMA!GsyrQ?Ku=a3zo28Iry+1f+gh?)X+hy^zb#=AP zNlctnJ-#@|`2W1jR=&DamxZf(l%3|{zyS`U_psf~^U4O!p5IR!Av%MQ2 ztlm<>>Y?$`qIB&net8Y6vZIhpn-I6(Xy(;`sUmW}QS`vi!D6Rx$|(^EE|WO4FgQl{ zaQeG5@lS+;3G}Nr-fq%$`3L{v*d!!)MFM1enj|80DZ6ndgdAcC+D*AcgL=WM8Ozf9^=aEpl;HdjsWjh|OjF(0Y@U+B<^dwvnIRO|sSiYqVxG ziI@)3eX)r-C}))-LB_zKJDQ)0u6D!{8{*N64l^I5Ks0L>y4<-eaP8>~Y>Fr3lrWni zv(WK}CKvrQ+q}~ll8eS2i}7B2npyZBtV_!3lIPEbXom-sZ*VnkJLV5S5IWf9AF*U6 z2TD&!h%lHlivyMVx}1`!Q{^(HPA%c+#M5v@C(U+2Uv>Elrp)2MEb)7D(9^C^;Evpm zujH+~oE?NdKE52dpex6Rh$XjCmp+78(}cd(M>$R}dLzZTDOE}?dZ(8WdvZ{<;RE7v zANtc!k(AcQLNB~=`;3&wuyk1;d+y^|wRA2s$#wXTVguv*??!qP+H_)-%VLjurM&R7;+_vp zsU*66Vg^n!dK;sBKJfor;Rp_Q@KgowzfmZEmQfW<)C#oNm@UZj`o}-wOMavK7vZQwXazJT;)nDp7#}_`jZOc%P&#f zsU+8=m{+oTSlC+2fofg?Dmazvv^wpfOn7XhTs1ijT|bq*bkBRQ8rM1~D-G(7;~I(6 z*PTa>A4cIbUTK_WywZ#Di^g-3K~m+K@=7x5RPBMzES$2+YvpJ;Jw_s#mRwG5^n{Yt zUpKZ@oo42zzM@w%DKpTf(;C;C7PiLGBG4bcRD9zb3ko*HxQKl4S~0CZf-*LtrKY$U zS3AW|`f$Ufu9{2!How}jtM-z=toD+Q!;#folHXBG{sZ&n0kG;lDEs3ouI_;J1^GGp zE9|eD(IrzL|3>EoF?}69Fs&p0{RX9OU@O)rYk z_yuU}*}KG!Dah?yJinOxhH>Mendj1o41mhdDRXBKZ@Rp(8WB+2@czX2!gszN z1F68XEH$;9zU9ILNb0@;4%gN2c z(K?Hu&W#XX^-4#(&(9ebx@F`aa?1$q=mf>8o#LCj#B~!>e+_^jtYI-+vg0vr_d=BO z?NrEjhqEE)liz!|9_Wwr{=~EIkkf^57iR4_<+JZDCmS5=79K+>7byPhDRd<94&`6i zL44|uez@=cKB;JxZ^palOTQ%*Da3g^!&*jBGe(Kqd5jgDyXg9X08A69JPhlR6Gh zULlc>V*=3I$4Q~{*HlQ{N6;9A-kbM!|y-{evP$W(_?HXFc z4X|g8cZTEutVSD#Gl)zpG7Ja!j7x_K-&WS{C=-ioW^PT`WF{gVJsdvi6F^q9>WU>U z`q?jwEnCn>RkRQDX%OoCZIy>3wqeQ4QoUjT-v{~3&Sl8=_gy&8D*OGBlhcF>nqoGX zk%kw8|HDPCO)&ug@t#g@g2n%GuDj@I|qOU+FK$ zSRk^6Oz~)AI;4HoJYJ>rBI_c5%giS#CD2VZ=ON-~j$(ISq~kR8x~M{U5PbycEGC{? ziJVqQwT{cBA@I}XQk5`4s>&>r6o@o&A4;X)JZ@$j?cJaZcP&Dbpk~hxA+QL=TSq&E ze>(KkwweM;jB>0#qut&~)9~@1nhF`gZxXA|w`97O7OAs0pc3mG*Qo{lP04ttx!I?l zpqc2VHJliiZv5N2#?@t$u(DybvbEoDBZtXE`R`(!*3PVyQFXsU)yl2L`gdCh@3qO* z3MWw$>r`9S5Tw^&Z^Y}yXeN*VD+5+~R(B1O*bFLZgKP&^RL6@}%BKv{@rYz<2$1Nr z`wWZcjZ*K;sQ$UKX)|q*WRD1y%q;>ucKRT%Ty~?5HZYl6m@l~CuE4+e4w~{v6~*Xy zAc6Sz5c53`EF~OfFo||ROst&CoUj8152v}+t!A7o;1%eAsDN4VF|&gYC?Yn&#PC5S zAT6g@#%Q(*^vke-hyqao^%Ig(Be0C|&Z=g3+00AfO+cC_054Z(gArkO=^ezb#v)+8&BGMP+soxo;5Y~03}oIx6q zzr*xDXYdv9oL5-g?bO_g*f;Lv_f>G_RLyqgt}8e zPD8GdHQDLQpBIaCq)N0})|EaWuqB2nV^Xb?m{q^5Hl_N5*&sQ4Np-_~&1%gC&D^gv zy7T@0`#79S98Q0~+G&gIte-0HKLXmld)J(gvm+Z##sKh>L*STovTwK?-FTc)(~TnJ zm!=ixxj{GLL>yC?XF47Mt^>iA&}#aniVQIwhyra+WSn=o%#LGqQ2W@G|G*z4k62vt z2FX?rOQ5cf1(e1#ZyXo_u3=lt8Z0jhbkpHXRnY{~q6r`YfTO08iC`rla?+WBNg$eV zU1Z`-2JX(}t}PW0AEa^&PP!6~dPQ&X&=9mn>wr81=V<1lDS^!RH1IWuWw`0Mm-`AP zAsys-$Ji_AXeQ+V+Km&__=zziy(omTHCGRpL5+9%O{f*=%r0 z;GFaqJ;dzTX)2kIW$57T(kLaNRK3%5V<9*Uh~@j3O^ZMlSZX@E2;dv#j%nT!umJFP z1vjWX-)EYZf)0R88OuNm;W24+W2?cyYj%J{vtuRW=x6%h`(Os}3sNHgLfALW=E_){ zF1xcOInDi)hoM?2fkuLCZAJy+1RR& zr!|}k=1`r7SX)v#=A8wo!k4|4SOGJiNy`P3+^;d>273-pB3`SL6R@+8smcYR)HJ2m zujGBDw%zs#4QW38{km7-7*$ErtU72FkiRou=YpuJ0}8_ zbfAr+-gAIi&G@YXkzfHcV-@iC0(Gh+LZ!en9b(XjkalJQxy+_jz%NiEFEh3@uJkUG zL2KlIHfZsm4awx<`pe0!npEcKDlj@&z(m`^?Ve+dwuAhU!PUx46e&hQi(h@Wc@Fda zDiALCg3*rTsl9j%PY4z`dYZ6HIZ_}zcbX9jK^V5XPzZc|@|vXr{Y!b7&f+nctn-zu ze)fQ1Jee*bh;$m=XmBDgHyBdLTg-hSh?;tH~LrkB?{Jk1P5TOYSxdwQJ zMuvWQJM>8ir;ju^ZJdOm1}7^fiw2YZo+Y_InOl)>TDAs^@SVJPuTK{Q9uI@-mz#3e zgRxw9x8-Vugy@MjsCMV7(f;ww;R29IcqN#w6@bqG*u+#9;_Jlg3ZpLs8wgKt##aRX z9vd30R&?HLzMO1K`b^qYW6x|0{#*L?OuK4o@ZVL3Ka)igI2R-0q>*X8X*mlXEYM^y zvpxo6-KTG@P(G@CRNGmA##J(_3rwXSgFC+b+0;c8lyAx_1!LX#!f6kg-7`(~2_2{%l`vB5Gt?$ From 8b40c13d1ccf465335f88a7745130feecbd366de Mon Sep 17 00:00:00 2001 From: aerinon Date: Tue, 2 Dec 2025 11:10:56 -0700 Subject: [PATCH 62/73] fix: crash --- RELEASENOTES.md | 3 ++- Rom.py | 2 +- data/base2current.bps | Bin 118393 -> 118398 bytes 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a5d2e8a1..b614f702 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -4,8 +4,9 @@ * Logic: Fixed vanilla key logic for GT basement * Logic (Playthrough): Fixed an issue where enemy kill rules were not applied during playthrough calculation. (Thanks Catobat for the catch) * Enemy Drop: Added "spies" and shadows for hidden enemies when enemy drop shuffled is enabled + * Pottery: Pots will uncolor when the item inside is collected next time the room is loaded * Keysanity/Keydrop Menu for DR: - * Map key information is now controlled by the Dungeon Chest Counts setting. If set to always on, this information will be available right away in the menu. And will be on the HUD even when the map is not obtained. + * Map key information is now controlled by the Dungeon Chest Counts setting. If set to always on, this information will be available right away in the menu and will be on the HUD even when the map is not obtained. * The key counter on the HUD for the current dungeon now accounts for keys from enemies or pots that are from vanilla key locations. * The first number on the HUD represents all keys collected either in that dungeon or elsewhere. * The second number on the HUD is the total keys that can be collected either in that dungeon or elsewhere. diff --git a/Rom.py b/Rom.py index c810534e..f71b43c4 100644 --- a/Rom.py +++ b/Rom.py @@ -42,7 +42,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '76d6a1915f52950e1b4b6d0fba95296b' +RANDOMIZERBASEHASH = '98131bfbcb4f2f305befa7a0ae7dc44d' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 7528406538289ca931deb536e97b8a6718bebb73..fb4e4e514484792328e6b83dc0ba822036337a57 100644 GIT binary patch delta 686 zcmWkpYe-XZ9R2_9)jia7x`$H(uaBmEY7`myT;V5?ATwf{E9rsRj6_PJmv<|rscYF~ z{x%m)&3TU(>aH8;GFa4rF8G5G)&QSy!Hr} zNS{cY@$mT{xl^BqIZS@iTY6I`WPFodm6s&#CX#P!S0he$9b9ksd>73D_d< z+S@m^xo$4|2D?-?MX`K5d0sKt!Sp_l)#hTo5lTCnT=pTwzU809+-TQ~h#5YY51xY1Zl0h^iiKw_&m|}ukidD3Gr6f+*uJ*eq zHgp<$Opupf;pVj+MmImUzs6gwSzZqQDiqOotV{^9f{fY1RTC5y-PNgBTN@tF^4ijT z2b$PELBbsJgi^uhSRW-^$K(CUcn-B@&_NwmnIT(A_xq%juTQM(NA5CfOTpXNVuq}P z0asUKWWcEIa*FTP`MkOxUOiLqnb!wiSL2YF$V$TEd%M>4xk=>5nGF1P3nAvIB`a)qQPBefnIcFf8%q)7t z<;)sxG(b`5nm63)H(b)Nor@~}g=P)wl`xNjODg{h)7yZ-pCF3wD!(1ih?e__sCHDL z`(oU0z$y!9CGv+#c1DjD3*@Q`GQ4hiAZbNGu!E ztjz{e3%F!~qoBkc3z+Dtr{&S}7eRjw3bAVe3c(N!Ex=zoQ9^v2F**^0MTzXJG3uF~ HtR(*dpnw|f delta 782 zcmW-dT}%^c6o$WV2IxQqE0zlWB*TwYl9d377{y>U#tYIIL)?qDpvHt%tcxo#Y$OU_ zo0d3GtS~93)1t$wWf+N>3B5q$5>}LLF&dhU2^->Ok=4X29aoLo_&0cU&Xf0?llMJe zh72Ev3@Sy_&GrbNNpH*iJuH>{#qXwVc%1jrP6kJ$%@;!@miROJeGWbyf0FmG0N2Ik zvZw2Cd%V}SqXv89f3~+T6|y0I?Flkdt58Hr8K+IdU2Nb|!p_1$2j0Fy7cSaA66}s&k2ngt`}DL6Qfb3$p_2VEJY5;P zwy)u}KW2b_E=`Q!^Cy$y8IPFh5q*!0u(>1cUYJrqy21VndfQXaTfKZK{O!W!hFOr( zN5ocO8u7V`=3)Kw)sdQxo|~z1Mf)nv3~MIkfBvVd9HYDqcFU<%OO^5(f78oF3W{L7 z5nGMxBdU>|5!9XRJp9*)H+9Vm>M!D+!xrMdZx$Ub79wP^o$`!X9B|%>*~APTUYJEM z9MGkZPp1#&vGe-)_Z<&2z-%O9z+afH_~H!VWB=zw)k)>? F&^Ix{Q;Glp From 0bf6f5f0da02faced888801eb8bf58d584c15e23 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 3 Dec 2025 10:53:30 -0600 Subject: [PATCH 63/73] Merged in DR v1.5.0 --- Rom.py | 2 +- data/base2current.bps | Bin 138591 -> 138568 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index f4ffb56e..673bafd8 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '59b577d7bbbde676a16f0ff779be9e58' +RANDOMIZERBASEHASH = '5d9af807fe843aa8af4dd3fd0a539dd8' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 5dc37ae738ded32dfe265d76ebed9716e9ee0e4d..aad0f7ece26cb5d4ca243fb61cb91a85b6ef972c 100644 GIT binary patch delta 2116 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 From f9a11484a93c0fca14144e8be6857e4a5b804f48 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Wed, 3 Dec 2025 10:53:30 -0600 Subject: [PATCH 64/73] Merged in DR v1.5.0 --- Main.py | 2 +- Rom.py | 2 +- data/base2current.bps | Bin 138591 -> 138568 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Main.py b/Main.py index bc2d4eb3..a25f6bc0 100644 --- a/Main.py +++ b/Main.py @@ -969,7 +969,6 @@ def copy_world_premature(world, player, create_flute_exits=True): ret.can_take_damage = world.can_take_damage ret.difficulty_requirements = world.difficulty_requirements.copy() ret.fix_fake_world = world.fix_fake_world.copy() - ret.lamps_needed_for_dark_rooms = world.lamps_needed_for_dark_rooms ret.mapshuffle = world.mapshuffle.copy() ret.compassshuffle = world.compassshuffle.copy() ret.keyshuffle = world.keyshuffle.copy() @@ -978,6 +977,7 @@ def copy_world_premature(world, player, create_flute_exits=True): ret.bombbag = world.bombbag.copy() ret.flute_mode = world.flute_mode.copy() ret.bow_mode = world.bow_mode.copy() + ret.free_lamp_cone = world.free_lamp_cone.copy() ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy() ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy() ret.crystals_ganon_orig = world.crystals_ganon_orig.copy() diff --git a/Rom.py b/Rom.py index f4ffb56e..673bafd8 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '59b577d7bbbde676a16f0ff779be9e58' +RANDOMIZERBASEHASH = '5d9af807fe843aa8af4dd3fd0a539dd8' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 5dc37ae738ded32dfe265d76ebed9716e9ee0e4d..aad0f7ece26cb5d4ca243fb61cb91a85b6ef972c 100644 GIT binary patch delta 2116 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 From e3e65f0540fca5be496d2415d09f16e1314254ab Mon Sep 17 00:00:00 2001 From: codemann8 Date: Thu, 4 Dec 2025 19:51:51 -0600 Subject: [PATCH 65/73] Some fixes for DR v1.5.0 --- Rom.py | 2 +- data/base2current.bps | Bin 138568 -> 138590 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 673bafd8..e9c5aeb6 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '5d9af807fe843aa8af4dd3fd0a539dd8' +RANDOMIZERBASEHASH = '9d085dce549f626cc98c69fa7c9b846c' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index aad0f7ece26cb5d4ca243fb61cb91a85b6ef972c..429fb90aa295145575593140cd5a9fab10914ff2 100644 GIT binary patch delta 516 zcmV+f0{i{Qx(MF72(U5(1cw56{gXBWHU$ltry?VhaRWdC1DTVv16c@Cnx`m^l_F=e z6a=da0hhDD4}EI^(}O;Hw?2CTbq)c0m$Zoirz&-UNZPMZs;KY~z$EYttqcT8s+iwp zx2Vt%gaV)>qJ+W_B0IpK;t-?)mu`vyDI46Fr?2q;r^TS~5U=u+B7unruk??Gh0r0d zQQ<|y`gMnC=d0&{J0MJjb`tYalA(swcn3GGF5{vJ^^8u z`k?`;P!{M&xt2u+fz4R}4c!2{&;w{VV9IFV0MG&$V9JvOg28~-7^NHV3a>%(ej@|$ zA2?v!GlIb*1MmVkU|^Xb4!a^4xQ*}+s%rO*|Cv||7nk#*0XP9pw=AOp6nY3tNCf23 G{U+>=P1w!= delta 452 zcmV;#0XzQQx(LX+2(U5(1j!3F^piFNHU;*Wry>lKaRWdC?3k0Y16c?=nx`m^l_F5H z6a=da0f4i>4}EI^yn{Y_w?2CTbq)b!m$ZoirxO{0z$DNQNZP4{s=^Q=JHVjg5SN9D z0Vx~Bn5VDs|EI;E@DQ)^lXQTI2(R>yhK0}}uO*ksiUCy%R+_L2Ape=LJRlL5DT@Io z4iTELaGy3{7J!As6rW9(UW)-5Fhpt=fR%(GeyR8rt8ri!fS)#C7Jz{Wk_aV$pNxeV z39p2+2!M&H{GGpleG`DYCYPv-0Us0ra+rw;r3#a3kCIdsmx-XsHn%L7+lv7sD^{BN zumhz4YpDSNYiU3LOgx&Z4TFJLmrGxmp#acNuln$(@FACAUYL^|mnn<^a0fewLVkdk zHMgLQ0Wb^@Er6u}fC@^gr2yY$x2Vt%m)@8G9|JWzh_;ylnFj$gmztmfy8$zoR-plT z0brNVp#eStV3!Y~0je_<=t#MiMFxS%SpW^)0K3ovIAF?X-~iA97+}hi0)oMS*chc7 u@CvU%@_r)&@EA0XP9nw?d-<6nY5Px#*@Ujg?zzgSs97 From bd94cfa43f518a7576089b43ef8e0805b82d6506 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 5 Dec 2025 02:54:57 -0600 Subject: [PATCH 66/73] Minor GUI fixes for triforce gfx --- source/classes/ItemGfxSelector.py | 11 ++++++++++- source/gui/adjust/overview.py | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/source/classes/ItemGfxSelector.py b/source/classes/ItemGfxSelector.py index 689ff626..ee5d528d 100644 --- a/source/classes/ItemGfxSelector.py +++ b/source/classes/ItemGfxSelector.py @@ -5,12 +5,13 @@ from Utils import local_path class ItemGfxSelector(object): - def __init__(self, parent, callback, valid_items=None): + def __init__(self, parent, callback, valid_items=None, adjuster=False): self.parent = parent self.window = Toplevel(parent) self.window.geometry("800x650") self.callback = callback self.valid_items = valid_items if valid_items else [] + self.adjuster = adjuster self.window.wm_title("Select Triforce Piece Graphics") self.window['padx'] = 5 @@ -38,6 +39,10 @@ class ItemGfxSelector(object): button = Button(frame, text="Default (Triforce)", command=self.use_default) button.pack(side=LEFT, padx=(0, 5)) + if adjuster: + button = Button(frame, text="Current triforce from rom", command=self.use_default_unchanged) + button.pack(side=LEFT, padx=(0, 5)) + set_icon(self.window) self.window.focus() @@ -116,6 +121,10 @@ class ItemGfxSelector(object): self.callback("Triforce") self.window.destroy() + def use_default_unchanged(self): + self.callback(None) + self.window.destroy() + def select_item(self, item_name): self.callback(item_name) self.window.destroy() diff --git a/source/gui/adjust/overview.py b/source/gui/adjust/overview.py index 55ce0ffd..2d062c8a 100644 --- a/source/gui/adjust/overview.py +++ b/source/gui/adjust/overview.py @@ -87,7 +87,7 @@ def adjust_page(top, parent, settings): def TriforceGfxSelectAdjuster(): from Tables import item_gfx_table valid_items = list(item_gfx_table.keys()) - ItemGfxSelector(parent, set_triforce_gfx, valid_items=valid_items) + ItemGfxSelector(parent, set_triforce_gfx, valid_items=valid_items, adjuster=True) triforceGfxSelectButton = Button(triforceGfxDialogFrame, text='...', command=TriforceGfxSelectAdjuster) From 72f370de4aeb38120ceac8c7770729dc7a0d6e1d Mon Sep 17 00:00:00 2001 From: codemann8 Date: Fri, 5 Dec 2025 03:04:32 -0600 Subject: [PATCH 67/73] Version bump 0.6.1.4 --- CHANGELOG.md | 7 +++++++ OverworldShuffle.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfa86a1e..66bfcb7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 0.6.1.4 +- Fixes for Glitched Rain State (Bonk Shuffle included) +- \~Merged in DR v1.5.0~ + - GT Key Logic fix + - New HUD key count behavior + - Pot uncoloring on collection + ## 0.6.1.3 - Added new post-gen option to change Triforce Piece GFX - Added new GFX for 10/11 keys to replace the A/B GFX diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 8cb1e68c..aefa4ae6 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.6.1.3' +version_number = '0.6.1.4' # branch indicator is intentionally different across branches version_branch = '-u' From 6cdcc800e0684a6908530d7fd7c580c9776f487a Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 7 Dec 2025 00:00:14 -0600 Subject: [PATCH 68/73] Fixed error with non-prize shuffle --- Fill.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Fill.py b/Fill.py index b1a7c188..c47a2f3d 100644 --- a/Fill.py +++ b/Fill.py @@ -183,7 +183,7 @@ def fill_restrictive(world, base_state, locations, itempool, key_pool=None, sing spot_to_fill = None item_locations = filter_locations(item_to_place, locations, world, vanilla) - if is_dungeon_item(item_to_place, world): + if is_dungeon_item(item_to_place, world) and not (item_to_place.prize and world.prizeshuffle[item_to_place.player] == 'none'): item_locations = [l for l in item_locations if valid_dungeon_placement(item_to_place, l, world)] verify(item_to_place, item_locations, maximum_exploration_state, single_player_placement, perform_access_check, key_pool, world) From 159e7e3785882caeae4e8038af955a6eb0e1f877 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Sun, 7 Dec 2025 00:01:53 -0600 Subject: [PATCH 69/73] Version bump 0.6.1.5 --- CHANGELOG.md | 3 +++ OverworldShuffle.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66bfcb7c..826bffee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.6.1.5 +- Fixed error with non-prize shuffle + ## 0.6.1.4 - Fixes for Glitched Rain State (Bonk Shuffle included) - \~Merged in DR v1.5.0~ diff --git a/OverworldShuffle.py b/OverworldShuffle.py index aefa4ae6..c78c0c4e 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.6.1.4' +version_number = '0.6.1.5' # branch indicator is intentionally different across branches version_branch = '-u' From d40334f7903a48d8f54e346ff26c1ba2dfee7e96 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 9 Dec 2025 09:25:55 -0600 Subject: [PATCH 70/73] Fixed key counts being off --- Rom.py | 2 +- data/base2current.bps | Bin 138590 -> 138598 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index e9c5aeb6..1fb5434b 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '9d085dce549f626cc98c69fa7c9b846c' +RANDOMIZERBASEHASH = '209b3984c9238e7b37b8f39e783eabd9' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 429fb90aa295145575593140cd5a9fab10914ff2..8b81a644d83bea73e87a40713eab6198007809d1 100644 GIT binary patch delta 2071 zcmW+#3s4hj5>96_Gl7V_Ih03+L;?uNLq*qB7Zh0pR0Op+^frPi1k2mjs9e zX64U=7);EOz*51TI|s}ml%DHyb=Kv!*0sc4y;FREO2t>*in_Vf)nC=!)nC`w)nE62 z@3Q#uWwGWe{Ce?P3BVFAQWyrJXGF+5HUrDRLv=l}MD`GtDVFGZ;ycx{es%~e7H`$} z#Gg4UJHUmAD<*oDxaIDTq>SRk30x)hqXj4m)v@8Mk|AB|IseX=BA>u0fN~S zX=JFKx6xwR?+0yVQ&Us2=DJH$O{$;SGHD8I;WSbS3CGwjg#x0uYl?aRHJ2OT4e*kk zOc;vz=7pKY@;@3&Xq_yF?{LaEdKVqacktl-7)Sr~0ty@BWa*-pEdY@7e!m*T8!2 z=$hXy!W&s?_o3hfM8fo8| z3Rw=T)RcrIld|geZX=4TwaeJk-Nsa5X%Tl@^B*x3u|v9K$l;#o9*JNBck^7iZ*(&0 zh@2iU1V_+@@)0KJVJ$EDs{yaOo;#dLdI>k!DJbF&+A9dJyW>y*gm+y04hU}SVlU*I@Zh-A`@cO`S!uT>(S%t>nW=>v*-ifADW2z8lg2?i6V_R|eB zWeAfuF)~!me{>0Hf8XBfy^}{LnaMMgeUpQej-od;bKAUTM(Kz}bCXXqv8JkF){kmp zV%b_Iwym~pe;uls+r%hP>=i~~%Duww^nwa6sA#KIDc;ne9IDAUewDIzy8<6{Mo?Yt z9&e*Ftei%A5yS{jrlVmItOf!B4!?mNXbui>a0zAM5CRn1f3&@!WQ%bhn27n zB@wU;wxTZxpw?D|HaC=RwR}>b8dBN?#!0{ia|av^wV*axolir=XvizUvAc_>O3Qc=q+001=_E9Mm(qc za?oKh?4JGka)Q=5JSLCB!yCfULouwzF&{hHg%W*W9?1DZA6OU$3sAij5+Rcxkb<8O zUh-FBKn~sw|9d_*;lcqC`7dU{0z~8AhM2 zr)uoKg!HBC45R;Fz=%77AN&xvW3{ey92MNKg6EJwB$kcNDASgZ1}`m%f4 zIyQwORrgp1zX#oI0eRvP{mcMn6)5ch%F0YZ!8U!bUma6|e9E-v1+EQ_8F!C621W1C zvfEHXD;yMm*0`#MM#uK^=UZV=rR)mS-35zc2qzsqN@&E| zrIUofM&m<4PTJ2(W75!?1Lv5?&dgbz zOsHW!T5E&@5P^n_kOigay%CZ_$*fLO;PyHu*A%_IuJdTfnbpB{Rs4!`utWsQ(GfFb zKot7g49N+@^lk4a_H|^vs*z)E>C&>h3u_skfq?lz zCn_}dAXx0#NECUBiA}{Zna6^Mo4``HgpBl?ay<4_S8e+WRn#2Q4VE zsU)W?9XnKve`nyFVT&ATAAyRjI%#91rYaQw7|!~Z?6Rq)9;wH)k-za6egr&TX+tD$ zehQ1g-zVns`G=m@o+sY-PfIy^Gzov0rC4+CtjBZP!+KCAUp@t|(#3CIzsuY9?QPNj E0Bs3bu>b%7 delta 2117 zcmWMl4Ny~e63^!43nJfvDxe7u44~xr6wq=E73C19AfQF@DsuJ&(JIzjKWKQ5?|?DE zSNM|z2qrQla5VAW)kmNR#d?*SI;C@M9nqt``b8*kskN=gY2RgbX7{)IoB8eR&hFz; z(cGv=I|VCOZ}M>52rnP8lr1bQ;H~x77FtwysWNFSl+s$MSP1V>-EukL^bL6ffQrtJ>I3+Naz;Bs zm?aZ|<-Y7GA#`{a)92zXbWtgXh+As>Rcd_0VyJG!;?`V=jf}s=r+FpeiPxjQh{%! zs#R7{+}9Jw-M^E*qy4uCc2W+V0=CjmbdPvYOyBN3Mh{X(^m&ESfWmS z^u)cv{nvH^%+fNIcHBT+~TDMzu_Nx8A`I#uN+p9h<{{6sXugUmI) zn)Wn8G0ivj499V%<2bHpB6!-1gDR1P50OD*3)Xan?o+nPG08@=|Itmdjwxyb+Qo-F zC`G+|*a2l|o)78p28tBGmfAh2@+I<@62tjFDQ5(&!5Vk0pu(gC8EnYEMUFEk16v#S z?=ffQsT@^SPS2!Q_Og59&zJ0KIx1HsB?1amhJF8Ptf(@+CnHqvE}AB4WCVGR!U(g+ zoRsh{P&HbzH9u4Nr7azx$uFp_Fzn56lG#Y~igQVWz7s$qBp`_pB4ghBo=UqjHnLXZgymQ6o2sS43WAruGM)d>RY zvN};Ge=HL2=~C6R6NacgUC2$e z-(V-$=Ai;~Oay=O-jyaGbT-z=+E~Vbqd5^|^1VE)=qQqVKm_7Bw4HO16IA+AA_dn?S&R3>U6Y;hS$eUSS50|)nVR(a4 zz%)j|Q3XFGylKdn`DHishCl`CsD>j@d+j77dqN^gseuiU&Xm_co)?@)HWds6y-Q}# z+6o3OF5k%r*Q()Fyqv+VZ{I@Itsp@ytq>h@ziYteVh3*axqNL;DV$V^Y|k`JjWc1k zBJ_DH>=qx>+r_dVy**79g<{$ua!Zune!_UDEQo0QRAM}TB#6)nWJ>EziSg3Dk^T%L z&z;OmjCJUwo9bwAXU`==(t|;S@eoqC!D@j*8936C>ZF2D%Sb8TjOBjHz6cRGjpb36RV6?ud;HBR|brObg3;2X@h!nd_e zNBU~Cs+|stkuO2pyWrfm^jWkvp12&)&zZK(#M;^n+!9q!KZo$l8SLkvigVhZZMz38 z3c1k5!;d{NtyEM^+gyv&5w7_aoNjOKGDoNAk%tZ{1tw;wOg4ee=wJ-?pd>vU_w(0m4FGjJhR6(|uZe+HPNW<&TqVw1UYHJD2buT7_OWKs@)w zC?X8*3(Z9z8X#>`xp!aN!{L<*BF_weaS3%l3MmyiYkmtengyZSo?(|T+K1ygh|b15 zvkE4-V-|up;fbqY8Zg75Gi zBfRJhDaJOXP zU4lZkNKjmKJ&sY_hH!5W zPp99SakB#TJpz?bdEP=wjYm-2W9aZKFSn?rtdupDGG9D~Z-AdrWkG(-;5;OOPpxe9 u@&ooK_KDlRFz-W4PIzZk-1fN+mc7GLEJ|jMF2K_SQEoQx;g>Jvi~k4ZvwL0u From b983b52252a222e6ccc11ceae01c7de8b98ec653 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 9 Dec 2025 09:27:13 -0600 Subject: [PATCH 71/73] Version bump 0.6.1.6 --- CHANGELOG.md | 5 +++++ OverworldShuffle.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 826bffee..cc866d98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.6.1.6 +- Fixed bonk drop sparkles in DW +- \~Merged in DR v1.5.1~ + - Fixed key count issues + ## 0.6.1.5 - Fixed error with non-prize shuffle diff --git a/OverworldShuffle.py b/OverworldShuffle.py index c78c0c4e..53c5815e 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.6.1.5' +version_number = '0.6.1.6' # branch indicator is intentionally different across branches version_branch = '-u' From e003c25dc0865bd97810929e82a426962b550316 Mon Sep 17 00:00:00 2001 From: codemann8 Date: Tue, 9 Dec 2025 18:00:56 -0600 Subject: [PATCH 72/73] Merged in DR v1.5.2 --- Rom.py | 2 +- data/base2current.bps | Bin 138598 -> 138619 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Rom.py b/Rom.py index 1fb5434b..687805ab 100644 --- a/Rom.py +++ b/Rom.py @@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings JAP10HASH = '03a63945398191337e896e5771f77173' -RANDOMIZERBASEHASH = '209b3984c9238e7b37b8f39e783eabd9' +RANDOMIZERBASEHASH = 'b2b8b42d575dd9825f2d8c424a4abb21' class JsonRom(object): diff --git a/data/base2current.bps b/data/base2current.bps index 8b81a644d83bea73e87a40713eab6198007809d1..5ec6d04bb9922f4431f4ef9b1adee07a008182d4 100644 GIT binary patch delta 6082 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 NpNNJupP9NK;{S$|ot*#x delta 6020 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 x#bvQ@#g#LS#Vr+h Date: Tue, 9 Dec 2025 18:01:48 -0600 Subject: [PATCH 73/73] Version bump 0.6.1.7 --- CHANGELOG.md | 4 ++++ OverworldShuffle.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc866d98..277596e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.6.1.7 +- \~Merged in DR v1.5.2~ + - Reverted key count update + ## 0.6.1.6 - Fixed bonk drop sparkles in DW - \~Merged in DR v1.5.1~ diff --git a/OverworldShuffle.py b/OverworldShuffle.py index 53c5815e..873256f0 100644 --- a/OverworldShuffle.py +++ b/OverworldShuffle.py @@ -8,7 +8,7 @@ from OWEdges import OWTileRegions, OWEdgeGroups, OWEdgeGroupsTerrain, OWExitType from OverworldGlitchRules import create_owg_connections from Utils import bidict -version_number = '0.6.1.6' +version_number = '0.6.1.7' # branch indicator is intentionally different across branches version_branch = '-u'