Merge branch 'OverworldShuffleDev' into OverworldShuffle

This commit is contained in:
codemann8
2025-11-22 09:23:40 -06:00
161 changed files with 498 additions and 264 deletions

View File

@@ -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()

View File

@@ -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))

View File

@@ -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 = {}
@@ -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:

View File

@@ -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

3
CLI.py
View File

@@ -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",

View File

@@ -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:

20
Main.py
View File

@@ -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
@@ -40,7 +40,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}'
@@ -170,9 +170,7 @@ 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)
create_dynamic_exits(world, player)
init_districts(world)
@@ -299,7 +297,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])
@@ -809,13 +807,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 +938,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,
@@ -1026,19 +1024,21 @@ 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)
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)

View File

@@ -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 = ''
@@ -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:
@@ -558,12 +557,13 @@ def link_overworld(world, player):
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,8 +1551,6 @@ 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
@@ -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]:
@@ -1587,10 +1581,7 @@ def validate_layout(world, player):
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

View File

@@ -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!)

View File

@@ -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':

View File

@@ -141,8 +141,14 @@ These are now independent of retro mode and have three options: None, Random, an
# 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
* 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.

18
Rom.py
View File

@@ -43,7 +43,7 @@ from source.enemizer.Enemizer import write_enemy_shuffle_settings
JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = '2039c11b935d3b81f78810d9f4be19d6'
RANDOMIZERBASEHASH = '35f2b275114fcec150981e9cb28de373'
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):
@@ -1934,6 +1934,20 @@ def apply_rom_settings(rom, beep, color, quickswap, fastmenu, disable_music, spr
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"
padded_author = padded_author[:28] if len(padded_author) > 28 else padded_author

View File

@@ -50,8 +50,10 @@ 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)
else:
misc_key_rules(world, player)
@@ -91,7 +93,6 @@ 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))
@@ -101,12 +102,10 @@ def set_rules(world, player):
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')
# 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)
def mirrorless_path_to_location(world, startName, targetName, player):
@@ -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

225
Tables.py
View File

@@ -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),
}

View File

@@ -192,7 +192,7 @@ 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",
"SRL or rtGG?\nI prefer the\nStepladder",
"Ladders are\nalways up\nto something",
"Zelda's\nfashion is\nvery chic",
"Zombie geese\nare waterfoul.\n",

Binary file not shown.

BIN
data/itemgfx/Apples.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

BIN
data/itemgfx/Arrow.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

BIN
data/itemgfx/Bee Trap.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

BIN
data/itemgfx/Big Key.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

BIN
data/itemgfx/Blacksmith.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

BIN
data/itemgfx/Blue Clock.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

BIN
data/itemgfx/Blue Mail.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

BIN
data/itemgfx/Bomb.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

BIN
data/itemgfx/Bombbag.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

BIN
data/itemgfx/Bombos.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

BIN
data/itemgfx/Bombs (10).gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

BIN
data/itemgfx/Bombs (3).gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

BIN
data/itemgfx/Boomerang.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

BIN
data/itemgfx/Bottle.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

BIN
data/itemgfx/Bow.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

BIN
data/itemgfx/Bug Net.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

BIN
data/itemgfx/Byrna.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

BIN
data/itemgfx/Chest.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

BIN
data/itemgfx/Chicken.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

BIN
data/itemgfx/Compass.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

BIN
data/itemgfx/Crystal.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

BIN
data/itemgfx/Duck.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

BIN
data/itemgfx/Egg.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

BIN
data/itemgfx/Ether.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

BIN
data/itemgfx/Fairy.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

BIN
data/itemgfx/Fire Rod.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

BIN
data/itemgfx/Fire.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

BIN
data/itemgfx/Flippers.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

BIN
data/itemgfx/Frog.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

BIN
data/itemgfx/Full Magic.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

BIN
data/itemgfx/Green Mail.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

BIN
data/itemgfx/Half Magic.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

BIN
data/itemgfx/Hammer.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

BIN
data/itemgfx/Heart.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

BIN
data/itemgfx/Hookshot.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

BIN
data/itemgfx/Ice Rod.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

BIN
data/itemgfx/Lamp.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

BIN
data/itemgfx/Magic Cape.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

BIN
data/itemgfx/Map.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

BIN
data/itemgfx/Master Key.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Some files were not shown because too many files have changed in this diff Show More