Palette refinement
Sanctuary starting dungeon and mirror target Sanctuary limited to LW in open mode (non-crossed/insanity ER)
This commit is contained in:
@@ -1467,6 +1467,7 @@ class Portal(object):
|
||||
self.default = True
|
||||
self.destination = False
|
||||
self.deadEnd = False
|
||||
self.light_world = False
|
||||
|
||||
def change_door(self, new_door):
|
||||
if new_door != self.door:
|
||||
@@ -1555,6 +1556,7 @@ class DungeonInfo(object):
|
||||
self.name = name
|
||||
self.total = 0
|
||||
self.required_passage = {}
|
||||
self.sole_entrance = None
|
||||
# self.dead_ends = 0 total - 1 - req = dead_ends possible
|
||||
|
||||
|
||||
|
||||
@@ -327,13 +327,22 @@ def choose_portals(world, player):
|
||||
for dungeon, portal_list in dungeon_portals.items():
|
||||
info = DungeonInfo(dungeon)
|
||||
region_map = defaultdict(list)
|
||||
reachable_portals = []
|
||||
for portal in portal_list:
|
||||
placeholder = world.get_region(portal + ' Placeholder', player)
|
||||
portal_place = placeholder.exits[0].connected_region.name
|
||||
if portal_place in world.inaccessible_regions[player]:
|
||||
region_map[portal_place].append(portal)
|
||||
portal_region = placeholder.exits[0].connected_region
|
||||
if portal_region.type == RegionType.LightWorld:
|
||||
world.get_portal(portal, player).light_world = True
|
||||
if portal_region.name in world.inaccessible_regions[player]:
|
||||
region_map[portal_region.name].append(portal)
|
||||
else:
|
||||
reachable_portals.append(portal)
|
||||
info.total = len(portal_list)
|
||||
info.required_passage = region_map
|
||||
if len(reachable_portals) == 0:
|
||||
raise Exception('please inspect this case')
|
||||
if len(reachable_portals) == 1:
|
||||
info.sole_entrance = reachable_portals[0]
|
||||
info_map[dungeon] = info
|
||||
|
||||
master_door_list = [x for x in world.doors if x.player == player and x.portalAble]
|
||||
@@ -352,7 +361,8 @@ def choose_portals(world, player):
|
||||
dead_end_choices = info.total - 1 - len(portal_assignment[dungeon])
|
||||
for i in range(0, dead_end_choices):
|
||||
candidates = find_portal_candidates(master_door_list, dungeon, dead_end_allowed=True, crossed=cross_flag)
|
||||
choice, portal = assign_portal(candidates, outstanding_portals, world, player)
|
||||
possible_portals = outstanding_portals if not info.sole_entrance else [x for x in outstanding_portals if x != info.sole_entrance]
|
||||
choice, portal = assign_portal(candidates, possible_portals, world, player)
|
||||
if choice.deadEnd:
|
||||
portal.deadEnd = True
|
||||
clean_up_portal_assignment(portal_assignment, dungeon, portal, master_door_list, outstanding_portals)
|
||||
@@ -759,7 +769,7 @@ def cross_dungeon(world, player):
|
||||
possible_portals = []
|
||||
for portal_name in dungeon_portals[d_name]:
|
||||
portal = world.get_portal(portal_name, player)
|
||||
if portal.door == 'Sanctuary S':
|
||||
if portal.door == 'Sanctuary S':
|
||||
possible_portals.clear()
|
||||
possible_portals.append(portal)
|
||||
break
|
||||
@@ -779,6 +789,24 @@ def cross_dungeon(world, player):
|
||||
reachable_portals.append(portal)
|
||||
world.sanc_portal[player] = random.choice(reachable_portals)
|
||||
|
||||
for portal in world.dungeon_portals[player]:
|
||||
if portal.door.roomIndex >= 0:
|
||||
room = world.get_room(portal.door.roomIndex, player)
|
||||
if room.palette is None:
|
||||
name = portal.door.entrance.parent_region.dungeon.name
|
||||
room.palette = palette_map[name]
|
||||
|
||||
for name, builder in dungeon_builders.items():
|
||||
for region in builder.master_sector.regions:
|
||||
for ext in region.exits:
|
||||
if ext.door and ext.door.roomIndex >= 0:
|
||||
room = world.get_room(ext.door.roomIndex, player)
|
||||
if room.palette is None:
|
||||
room.palette = palette_map[name]
|
||||
eastfairies = world.get_room(0x89, player)
|
||||
eastfairies.palette = palette_map[world.get_region('Eastern Courtyard', player).dungeon.name]
|
||||
# other ones that could use programmatic treatment: Skull Boss x29, Hera Fairies xa7, Ice Boss xde
|
||||
|
||||
if world.hints[player]:
|
||||
refine_hints(dungeon_builders)
|
||||
|
||||
@@ -2305,20 +2333,11 @@ boss_indicator = {
|
||||
'Ganons Tower': (0x1a, 'GT Agahnim 2 SW')
|
||||
}
|
||||
|
||||
# For compass boss indicator
|
||||
boss_indicator = {
|
||||
'Eastern Palace': (0x04, 'Eastern Boss SE'),
|
||||
'Desert Palace': (0x06, 'Desert Boss SW'),
|
||||
'Agahnims Tower': (0x08, 'Tower Agahnim 1 SW'),
|
||||
'Swamp Palace': (0x0a, 'Swamp Boss SW'),
|
||||
'Palace of Darkness': (0x0c, 'PoD Boss SE'),
|
||||
'Misery Mire': (0x0e, 'Mire Boss SW'),
|
||||
'Skull Woods': (0x10, 'Skull Spike Corner SW'),
|
||||
'Ice Palace': (0x12, 'Ice Antechamber NE'),
|
||||
'Tower of Hera': (0x14, 'Hera Boss Down Stairs'),
|
||||
'Thieves Town': (0x16, 'Thieves Boss SE'),
|
||||
'Turtle Rock': (0x18, 'TR Boss SW'),
|
||||
'Ganons Tower': (0x1a, 'GT Agahnim 2 SW')
|
||||
palette_map = {
|
||||
'Hyrule Castle': 0x0, 'Eastern Palace': 0xb, 'Desert Palace': 0x4, 'Agahnims Tower': 0xc,
|
||||
'Swamp Palace': 0x8, 'Palace of Darkness': 0x10, 'Misery Mire': 0x11, 'Skull Woods': 0xe,
|
||||
'Ice Palace': 0x14, 'Tower of Hera': 0x6, 'Thieves Town': 0x17, 'Turtle Rock': 0x19,
|
||||
'Ganons Tower': 0x1b
|
||||
}
|
||||
|
||||
# todo: inverted
|
||||
|
||||
2
Doors.py
2
Doors.py
@@ -1314,6 +1314,8 @@ def create_doors(world, player):
|
||||
world.get_door('GT Petting Zoo SE', player).deadEnd = True
|
||||
world.get_door('GT DMs Room SW', player).deadEnd = True
|
||||
world.get_door("GT Bob\'s Room SE", player).passage = False
|
||||
# can't unlink from boss right now
|
||||
world.get_door("Hera Lobby S", player).dungeonLink = 'Tower of Hera'
|
||||
|
||||
world.get_door('Ice Spike Cross SE', player).dungeonLink = 'linkIceFalls'
|
||||
world.get_door('Ice Tall Hint SE', player).dungeonLink = 'linkIceFalls'
|
||||
|
||||
@@ -69,6 +69,7 @@ def generate_dungeon_main(builder, entrance_region_names, split_dungeon, world,
|
||||
proposed_map = builder.valid_proposal
|
||||
else:
|
||||
proposed_map = generate_dungeon_find_proposal(builder, entrance_region_names, split_dungeon, world, player)
|
||||
builder.valid_proposal = proposed_map
|
||||
queue = collections.deque(proposed_map.items())
|
||||
while len(queue) > 0:
|
||||
a, b = queue.popleft()
|
||||
@@ -1245,7 +1246,19 @@ def create_dungeon_builders(all_sectors, connections_tuple, world, player,
|
||||
identify_destination_sectors(accessible_sectors, reverse_d_map, dungeon_map, connections,
|
||||
dungeon_entrances, split_dungeon_entrances)
|
||||
for name, builder in dungeon_map.items():
|
||||
calc_allowance_and_dead_ends(builder, connections_tuple)
|
||||
calc_allowance_and_dead_ends(builder, connections_tuple, world.dungeon_portals[player])
|
||||
|
||||
if world.mode[player] == 'open' and world.shuffle[player] not in ['crossed', 'insanity']:
|
||||
sanc = find_sector('Sanctuary', candidate_sectors)
|
||||
lw_builders = []
|
||||
for name, portal_list in dungeon_portals.items():
|
||||
for portal_name in portal_list:
|
||||
if world.get_portal(portal_name, player).light_world:
|
||||
lw_builders.append(dungeon_map[name])
|
||||
break
|
||||
# portals only - not drops for mirror stuff
|
||||
sanc_builder = random.choice(lw_builders)
|
||||
assign_sector(sanc, sanc_builder, candidate_sectors, global_pole)
|
||||
|
||||
free_location_sectors = {}
|
||||
crystal_switches = {}
|
||||
@@ -1336,11 +1349,12 @@ def identify_destination_sectors(accessible_sectors, reverse_d_map, dungeon_map,
|
||||
break
|
||||
|
||||
|
||||
def calc_allowance_and_dead_ends(builder, connections_tuple):
|
||||
def calc_allowance_and_dead_ends(builder, connections_tuple, portals):
|
||||
entrances_map, potentials, connections = connections_tuple
|
||||
needed_connections = [x for x in builder.all_entrances if x not in entrances_map[builder.name]]
|
||||
starting_allowance = 0
|
||||
used_sectors = set()
|
||||
destination_entrances = [x.door.entrance.parent_region.name for x in portals if x.destination]
|
||||
for entrance in entrances_map[builder.name]:
|
||||
sector = find_sector(entrance, builder.sectors)
|
||||
outflow_target = 0 if entrance not in drop_entrances_allowance else 1
|
||||
@@ -3741,12 +3755,6 @@ dead_entrances = [
|
||||
'TR Big Chest Entrance'
|
||||
]
|
||||
|
||||
destination_entrances = [
|
||||
'Sanctuary', 'Hyrule Castle West Lobby', 'Hyrule Castle East Lobby', 'Sewers Rat Path', 'Desert East Lobby',
|
||||
'Desert West Lobby', 'Skull Pinball', 'Skull Pot Circle', 'Skull Left Drop', 'Skull 2 West Lobby',
|
||||
'Skull Back Drop', 'TR Big Chest Entrance', 'TR Eye Bridge', 'TR Lazy Eyes'
|
||||
]
|
||||
|
||||
split_check_entrance_invalid = [
|
||||
'Desert East Lobby', 'Skull 2 West Lobby'
|
||||
]
|
||||
|
||||
7
Rom.py
7
Rom.py
@@ -22,7 +22,7 @@ from EntranceShuffle import door_addresses, exit_ids
|
||||
|
||||
|
||||
JAP10HASH = '03a63945398191337e896e5771f77173'
|
||||
RANDOMIZERBASEHASH = '7d7ea5b59d05926be23a3963e31cb0f0'
|
||||
RANDOMIZERBASEHASH = '63d1141460fd237a6ce17ccc6e293985'
|
||||
|
||||
|
||||
class JsonRom(object):
|
||||
@@ -617,12 +617,15 @@ def patch_rom(world, rom, player, team, enemized):
|
||||
rom.write_byte(0x15270, 2)
|
||||
sanctuary = world.get_region('Sanctuary', player)
|
||||
rom.write_byte(0x1597b, sanctuary.dungeon.dungeon_id*2)
|
||||
if world.sanc_portal[player]:
|
||||
if player in world.sanc_portal.keys():
|
||||
rom.write_byte(0x159a6, world.sanc_portal[player].ent_offset)
|
||||
if compass_code_good(rom):
|
||||
update_compasses(rom, world, player)
|
||||
else:
|
||||
logging.getLogger('').warning('Randomizer rom update! Compasses in crossed are borken')
|
||||
for room in world.rooms:
|
||||
if room.player == player and room.palette is not None:
|
||||
rom.write_byte(0x13f200+room.index, room.palette)
|
||||
if world.doorShuffle[player] == 'basic':
|
||||
rom.write_byte(0x139004, 1)
|
||||
for door in world.doors:
|
||||
|
||||
12
RoomData.py
12
RoomData.py
@@ -9,7 +9,9 @@ def create_rooms(world, player):
|
||||
# Room(player, 0x03, 0x509cf).door(Position.SouthW, DoorKind.CaveEntrance),
|
||||
Room(player, 0x04, 0xfe25c).door(Position.NorthW, DoorKind.StairKey2).door(Position.InteriorW, DoorKind.Dashable).door(Position.InteriorS, DoorKind.Dashable).door(Position.InteriorE, DoorKind.TrapTriggerable).door(Position.SouthW, DoorKind.Normal),
|
||||
Room(player, 0x06, 0xfa192).door(Position.SouthW, DoorKind.Trap),
|
||||
Room(player, 0x07, None),
|
||||
# Room(player, 0x08, 0x5064f).door(Position.InteriorS2, DoorKind.CaveEntranceLow08).door(Position.SouthE, DoorKind.CaveEntrance).door(Position.SouthW2, DoorKind.NormalLow2).door(Position.SouthW2, DoorKind.ToggleFlag),
|
||||
Room(player, 0x09, None),
|
||||
Room(player, 0x0a, 0xfa734).door(Position.North, DoorKind.StairKey),
|
||||
Room(player, 0x0b, 0xfabf0).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.InteriorS, DoorKind.Trap2).door(Position.InteriorN, DoorKind.SmallKey),
|
||||
Room(player, 0x0c, 0xfef53).door(Position.South, DoorKind.DungeonEntrance),
|
||||
@@ -23,6 +25,7 @@ def create_rooms(world, player):
|
||||
Room(player, 0x14, 0xfe464).door(Position.SouthE, DoorKind.SmallKey).door(Position.WestS, DoorKind.SmallKey).door(Position.NorthW, DoorKind.Normal).door(Position.WestN, DoorKind.Normal).door(Position.SouthW, DoorKind.Normal).door(Position.EastN, DoorKind.Normal).door(Position.EastS, DoorKind.Normal),
|
||||
Room(player, 0x15, 0xfe63e).door(Position.WestS, DoorKind.Trap).door(Position.WestN, DoorKind.Normal),
|
||||
Room(player, 0x16, 0xfa150).door(Position.InteriorV, DoorKind.Bombable).door(Position.InteriorW, DoorKind.SmallKey).door(Position.InteriorE, DoorKind.Normal).door(Position.NorthW, DoorKind.Normal),
|
||||
Room(player, 0x17, None),
|
||||
# Room(player, 0x18, 0x506e5).door(Position.NorthW2, DoorKind.NormalLow).door(Position.NorthW2, DoorKind.ToggleFlag),
|
||||
Room(player, 0x19, 0xfacc6).door(Position.East, DoorKind.Bombable).door(Position.EastN, DoorKind.SmallKey),
|
||||
Room(player, 0x1a, 0xfa670).door(Position.InteriorE, DoorKind.SmallKey).door(Position.WestN, DoorKind.SmallKey).door(Position.West, DoorKind.Bombable).door(Position.SouthW, DoorKind.SmallKey).door(Position.InteriorN, DoorKind.Normal).door(Position.SouthE, DoorKind.Normal),
|
||||
@@ -38,6 +41,7 @@ def create_rooms(world, player):
|
||||
Room(player, 0x23, 0xfed30).door(Position.SouthE, DoorKind.BombableEntrance).door(Position.EastS, DoorKind.Normal),
|
||||
Room(player, 0x24, 0xfe6ee).door(Position.NorthE, DoorKind.BigKey).door(Position.InteriorN, DoorKind.Trap2).door(Position.InteriorW, DoorKind.Trap2).door(Position.InteriorE, DoorKind.Trap2).door(Position.SouthE, DoorKind.DungeonEntrance).door(Position.NorthW, DoorKind.Normal).door(Position.WestS, DoorKind.Normal).door(Position.InteriorS, DoorKind.Normal),
|
||||
Room(player, 0x26, 0xf9cbb).door(Position.South, DoorKind.SmallKey).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.InteriorE, DoorKind.TrapTriggerable).door(Position.InteriorN, DoorKind.Normal),
|
||||
Room(player, 0x27, None),
|
||||
Room(player, 0x28, 0xf92a8).door(Position.NorthW, DoorKind.StairKey2).door(Position.South, DoorKind.DungeonEntrance),
|
||||
Room(player, 0x2a, 0xfa594).door(Position.NorthE, DoorKind.Trap).door(Position.NorthW, DoorKind.SmallKey).door(Position.EastS, DoorKind.Bombable).door(Position.East2, DoorKind.NormalLow).door(Position.SouthW, DoorKind.Normal).door(Position.SouthE, DoorKind.Normal),
|
||||
Room(player, 0x2b, 0xfaaa7).door(Position.InteriorS, DoorKind.Bombable).door(Position.WestS, DoorKind.Bombable).door(Position.NorthW, DoorKind.Trap).door(Position.West2, DoorKind.NormalLow),
|
||||
@@ -66,6 +70,7 @@ def create_rooms(world, player):
|
||||
|
||||
Room(player, 0x40, 0xf8eea).door(Position.InteriorS2, DoorKind.NormalLow2),
|
||||
Room(player, 0x41, 0x50f15).door(Position.South, DoorKind.Trap),
|
||||
Room(player, 0x42, None),
|
||||
Room(player, 0x43, 0xf87f8).door(Position.NorthW, DoorKind.BigKey).door(Position.InteriorE, DoorKind.SmallKey).door(Position.SouthE, DoorKind.SmallKey),
|
||||
Room(player, 0x44, 0xfdbcd).door(Position.InteriorN, DoorKind.Trap2).door(Position.InteriorS, DoorKind.SmallKey).door(Position.EastN, DoorKind.Normal).door(Position.EastS, DoorKind.Normal),
|
||||
Room(player, 0x45, 0xfdcae).door(Position.WestN, DoorKind.Trap).door(Position.InteriorW, DoorKind.Normal).door(Position.WestS, DoorKind.Normal).door(Position.InteriorS, DoorKind.Normal),
|
||||
@@ -82,6 +87,7 @@ def create_rooms(world, player):
|
||||
Room(player, 0x51, 0x51029).door(Position.North, DoorKind.Normal).door(Position.North, DoorKind.DungeonChanger),
|
||||
Room(player, 0x52, 0x51230).door(Position.WestN2, DoorKind.Warp).door(Position.SouthW2, DoorKind.NormalLow2).door(Position.South, DoorKind.Normal),
|
||||
Room(player, 0x53, 0xf88ad).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.InteriorS, DoorKind.Trap2).door(Position.NorthE, DoorKind.SmallKey),
|
||||
Room(player, 0x54, None),
|
||||
# Room(player, 0x55, 0x50166).door(Position.InteriorW2, DoorKind.NormalLow).door(Position.SouthW, DoorKind.Normal).door(Position.SouthW, DoorKind.IncognitoEntrance),
|
||||
Room(player, 0x56, 0xfbb4e).door(Position.InteriorW, DoorKind.SmallKey).door(Position.SouthW, DoorKind.DungeonEntrance).door(Position.InteriorS, DoorKind.Normal).door(Position.EastS, DoorKind.Normal),
|
||||
Room(player, 0x57, 0xfbbd2).door(Position.InteriorN, DoorKind.Bombable).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.EastS, DoorKind.SmallKey).door(Position.SouthW, DoorKind.DungeonEntrance).door(Position.WestS, DoorKind.Normal).door(Position.SouthE, DoorKind.Normal),
|
||||
@@ -109,6 +115,7 @@ def create_rooms(world, player):
|
||||
Room(player, 0x6d, 0xffa4e).door(Position.NorthW, DoorKind.Trap).door(Position.InteriorW, DoorKind.Trap).door(Position.WestS, DoorKind.Trap),
|
||||
Room(player, 0x6e, 0xfc74b).door(Position.NorthE, DoorKind.Trap),
|
||||
|
||||
Room(player, 0x70, None),
|
||||
Room(player, 0x71, 0x52341).door(Position.InteriorW, DoorKind.SmallKey).door(Position.SouthW2, DoorKind.TrapTriggerableLow).door(Position.InteriorS2, DoorKind.TrapTriggerableLow),
|
||||
Room(player, 0x72, 0x51fda).door(Position.InteriorV, DoorKind.SmallKey),
|
||||
Room(player, 0x73, 0xf8972).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.InteriorS, DoorKind.Trap2).door(Position.InteriorE, DoorKind.Normal),
|
||||
@@ -122,11 +129,14 @@ def create_rooms(world, player):
|
||||
Room(player, 0x7e, 0xfc7c6).door(Position.SouthE, DoorKind.SmallKey).door(Position.InteriorS, DoorKind.TrapTriggerable).door(Position.EastN, DoorKind.Normal),
|
||||
Room(player, 0x7f, 0xfc827).door(Position.WestN, DoorKind.Trap).door(Position.InteriorW, DoorKind.Normal),
|
||||
|
||||
Room(player, 0x80, None),
|
||||
Room(player, 0x81, 0x5224b).door(Position.NorthW2, DoorKind.NormalLow2),
|
||||
Room(player, 0x82, None),
|
||||
Room(player, 0x83, 0xf8bba).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.SouthW, DoorKind.DungeonEntrance).door(Position.InteriorS, DoorKind.Normal),
|
||||
Room(player, 0x84, 0xf8cb7).door(Position.South, DoorKind.DungeonEntrance),
|
||||
Room(player, 0x85, 0xf8d7d).door(Position.NorthE, DoorKind.Trap).door(Position.InteriorN, DoorKind.SmallKey).door(Position.SouthE, DoorKind.DungeonEntrance).door(Position.InteriorS, DoorKind.Normal),
|
||||
Room(player, 0x87, 0xfd1b7).door(Position.InteriorN, DoorKind.Trap2).door(Position.InteriorE, DoorKind.Normal),
|
||||
Room(player, 0x89, None),
|
||||
Room(player, 0x8b, 0xff33f).door(Position.InteriorN, DoorKind.TrapTriggerable).door(Position.InteriorS, DoorKind.SmallKey).door(Position.EastN, DoorKind.Normal).door(Position.SouthW, DoorKind.Normal).door(Position.NorthW, DoorKind.Normal),
|
||||
Room(player, 0x8c, 0xff3ef).door(Position.EastN, DoorKind.Trap).door(Position.InteriorW, DoorKind.Trap2).door(Position.InteriorN, DoorKind.SmallKey).door(Position.WestN, DoorKind.Normal).door(Position.SouthW, DoorKind.Normal).door(Position.SouthE, DoorKind.Normal),
|
||||
Room(player, 0x8d, 0xff4e0).door(Position.SouthE, DoorKind.Trap).door(Position.InteriorN, DoorKind.SmallKey).door(Position.WestN, DoorKind.Normal).door(Position.NorthE, DoorKind.Normal).door(Position.InteriorS, DoorKind.Normal),
|
||||
@@ -153,6 +163,7 @@ def create_rooms(world, player):
|
||||
Room(player, 0xa3, 0xfb667).door(Position.West, DoorKind.Normal).door(Position.SouthW, DoorKind.Normal),
|
||||
Room(player, 0xa4, 0xfe741).door(Position.SouthW, DoorKind.Trap),
|
||||
Room(player, 0xa5, 0xffb7f).door(Position.NorthE, DoorKind.Trap).door(Position.InteriorE, DoorKind.Trap2).door(Position.InteriorW, DoorKind.Trap2),
|
||||
Room(player, 0xa6, None),
|
||||
Room(player, 0xa8, 0x51887).door(Position.InteriorS, DoorKind.Trap2).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.SouthE, DoorKind.SmallKey).door(Position.InteriorN2, DoorKind.NormalLow2).door(Position.EastN2, DoorKind.NormalLow2).door(Position.East, DoorKind.Normal),
|
||||
Room(player, 0xa9, 0x519c9).door(Position.West, DoorKind.Trap).door(Position.East, DoorKind.Trap).door(Position.North, DoorKind.BigKey).door(Position.WestN2, DoorKind.NormalLow2).door(Position.EastN2, DoorKind.NormalLow2).door(Position.South, DoorKind.Normal),
|
||||
Room(player, 0xaa, 0x51b29).door(Position.InteriorE, DoorKind.Trap2).door(Position.WestN2, DoorKind.NormalLow2).door(Position.InteriorN, DoorKind.Normal).door(Position.InteriorS, DoorKind.Normal).door(Position.West, DoorKind.Normal).door(Position.SouthW, DoorKind.Normal),
|
||||
@@ -250,6 +261,7 @@ class Room(object):
|
||||
self.doorListAddress = address
|
||||
self.doorList = []
|
||||
self.modified = False
|
||||
self.palette = None
|
||||
|
||||
def kind(self, door):
|
||||
return self.doorList[door.doorListPos][1]
|
||||
|
||||
1
Rules.py
1
Rules.py
@@ -183,6 +183,7 @@ def global_rules(world, player):
|
||||
set_defeat_dungeon_boss_rule(world.get_location('Palace of Darkness - Prize', player))
|
||||
|
||||
set_rule(world.get_entrance('Swamp Lobby Moat', player), lambda state: state.has('Flippers', player) and state.has('Open Floodgate', player))
|
||||
set_rule(world.get_entrance('Swamp Entrance Moat', player), lambda state: state.has('Flippers', player) and state.has('Open Floodgate', player))
|
||||
set_rule(world.get_entrance('Swamp Trench 1 Approach Dry', player), lambda state: not state.has('Trench 1 Filled', player))
|
||||
set_rule(world.get_entrance('Swamp Trench 1 Key Ledge Dry', player), lambda state: not state.has('Trench 1 Filled', player))
|
||||
set_rule(world.get_entrance('Swamp Trench 1 Departure Dry', player), lambda state: not state.has('Trench 1 Filled', player))
|
||||
|
||||
37
Tables.py
37
Tables.py
@@ -87,3 +87,40 @@ divisor_lookup = {
|
||||
0xa0: {0x8: 7, 0x10: 6, 0x18: 7, 0x20: 4, 0x30: 6, 0x50: 1, 0xa0: 0},
|
||||
}
|
||||
|
||||
# I don't need this right now, but I don't want to throw it away either
|
||||
# Note: this value + 0x028000 is where the header is for the room (PC not SNES addressing)
|
||||
|
||||
# room_header_lookup = {
|
||||
# 0x0: 0x462, 0x1: 0x46c, 0x2: 0x47a, 0x3: 0x5dd, 0x4: 0x485, 0x5: 0x490, 0x6: 0x490, 0x7: 0x497,
|
||||
# 0x8: 0x4a2, 0x9: 0x4a9, 0xa: 0x4b5, 0xb: 0x4c0, 0xc: 0x4cb, 0xd: 0x4d8, 0xe: 0x4df, 0xf: 0x4ea,
|
||||
# 0x10: 0x4ea, 0x11: 0x4f1, 0x12: 0x4fc, 0x13: 0x503, 0x14: 0x511, 0x15: 0x518, 0x16: 0x523, 0x17: 0x52e,
|
||||
# 0x18: 0xc73, 0x19: 0x53a, 0x1a: 0x541, 0x1b: 0x54d, 0x1c: 0x558, 0x1d: 0x563, 0x1e: 0x56e, 0x1f: 0x579,
|
||||
# 0x20: 0x584, 0x21: 0x58b, 0x22: 0x58b, 0x23: 0x503, 0x24: 0x592, 0x25: 0x599, 0x26: 0x599, 0x27: 0x5a6,
|
||||
# 0x28: 0x5b2, 0x29: 0x5bd, 0x2a: 0x5c4, 0x2b: 0x5cb, 0x2c: 0xc73, 0x2d: 0x5d6, 0x2e: 0x5d6, 0x2f: 0x5dd,
|
||||
# 0x30: 0x5e4, 0x31: 0x5ef, 0x32: 0x5fb, 0x33: 0x606, 0x34: 0x60d, 0x35: 0x618, 0x36: 0x61f, 0x37: 0x618,
|
||||
# 0x38: 0x626, 0x39: 0x631, 0x3a: 0x63b, 0x3b: 0x646, 0x3c: 0x651, 0x3d: 0x658, 0x3e: 0x663, 0x3f: 0x66e,
|
||||
# 0x40: 0x67a, 0x41: 0x686, 0x42: 0x691, 0x43: 0x69d, 0x44: 0x6a4, 0x45: 0x6ab, 0x46: 0x6b6, 0x47: 0x6bd,
|
||||
# 0x48: 0x6bd, 0x49: 0x6bd, 0x4a: 0x6c4, 0x4b: 0x6d0, 0x4c: 0x6da, 0x4d: 0x6e5, 0x4e: 0x6f0, 0x4f: 0x6fb,
|
||||
# 0x50: 0x705, 0x51: 0x713, 0x52: 0x71e, 0x53: 0x72c, 0x54: 0x737, 0x55: 0x742, 0x56: 0x749, 0x57: 0x750,
|
||||
# 0x58: 0x757, 0x59: 0x75e, 0x5a: 0x765, 0x5b: 0x76c, 0x5c: 0x773, 0x5d: 0x77e, 0x5e: 0x789, 0x5f: 0x794,
|
||||
# 0x60: 0x7a0, 0x61: 0x7a7, 0x62: 0x7a0, 0x63: 0x7b2, 0x64: 0x7bd, 0x65: 0x7c8, 0x66: 0x7d2, 0x67: 0x7dd,
|
||||
# 0x68: 0x7e4, 0x69: 0x7eb, 0x6a: 0x7eb, 0x6b: 0x7f7, 0x6c: 0x802, 0x6d: 0x80d, 0x6e: 0x814, 0x6f: 0x81f,
|
||||
# 0x70: 0x81f, 0x71: 0x82b, 0x72: 0x836, 0x73: 0x841, 0x74: 0x848, 0x75: 0x84f, 0x76: 0x856, 0x77: 0x863,
|
||||
# 0x78: 0x870, 0x79: 0x870, 0x7a: 0x870, 0x7b: 0x870, 0x7c: 0x87a, 0x7d: 0x881, 0x7e: 0x88b, 0x7f: 0x896,
|
||||
# 0x80: 0x8a1, 0x81: 0x8ac, 0x82: 0x8ac, 0x83: 0x8b3, 0x84: 0x8ba, 0x85: 0x8c1, 0x86: 0x8c8, 0x87: 0x8c8,
|
||||
# 0x88: 0x8d4, 0x89: 0x8d4, 0x8a: 0x8de, 0x8b: 0x8de, 0x8c: 0x8e5, 0x8d: 0x8f2, 0x8e: 0x8f9, 0x8f: 0x904,
|
||||
# 0x90: 0x904, 0x91: 0x90b, 0x92: 0x916, 0x93: 0x91d, 0x94: 0x928, 0x95: 0x928, 0x96: 0x92f, 0x97: 0x93a,
|
||||
# 0x98: 0x945, 0x99: 0x950, 0x9a: 0x95b, 0x9b: 0x95b, 0x9c: 0x965, 0x9d: 0x96c, 0x9e: 0x976, 0x9f: 0x981,
|
||||
# 0xa0: 0x988, 0xa1: 0x993, 0xa2: 0x99a, 0xa3: 0x993, 0xa4: 0x9a5, 0xa5: 0x9ac, 0xa6: 0x9b7, 0xa7: 0x9c2,
|
||||
# 0xa8: 0x9cc, 0xa9: 0x9d3, 0xaa: 0x9dd, 0xab: 0x9e4, 0xac: 0x9ef, 0xad: 0x9f6, 0xae: 0x9f6, 0xaf: 0xa01,
|
||||
# 0xb0: 0xa08, 0xb1: 0xa14, 0xb2: 0xa1e, 0xb3: 0xa25, 0xb4: 0xa2c, 0xb5: 0xa37, 0xb6: 0xa42, 0xb7: 0x50a,
|
||||
# 0xb8: 0xa4d, 0xb9: 0xa54, 0xba: 0xa5b, 0xbb: 0xa62, 0xbc: 0xa69, 0xbd: 0xa74, 0xbe: 0xa74, 0xbf: 0xa7f,
|
||||
# 0xc0: 0xa86, 0xc1: 0xa92, 0xc2: 0xa99, 0xc3: 0xaa0, 0xc4: 0xaa7, 0xc5: 0xab2, 0xc6: 0x50a, 0xc7: 0xab9,
|
||||
# 0xc8: 0xac0, 0xc9: 0xac7, 0xca: 0xace, 0xcb: 0xace, 0xcc: 0xace, 0xcd: 0xad5, 0xce: 0xad5, 0xcf: 0xadf,
|
||||
# 0xd0: 0xadf, 0xd1: 0xaeb, 0xd2: 0xaf6, 0xd3: 0xb01, 0xd4: 0xb01, 0xd5: 0xab2, 0xd6: 0x50a, 0xd7: 0xb01,
|
||||
# 0xd8: 0xb01, 0xd9: 0xb08, 0xda: 0xb0f, 0xdb: 0xace, 0xdc: 0xace, 0xdd: 0xb1a, 0xde: 0xb1a, 0xdf: 0xb21,
|
||||
# 0xe0: 0xb2c, 0xe1: 0xb37, 0xe2: 0xb3e, 0xe3: 0xb45, 0xe4: 0xb4c, 0xe5: 0xb4c, 0xe6: 0xb53, 0xe7: 0xb53,
|
||||
# 0xe8: 0xb5a, 0xe9: 0xb68, 0xea: 0xb68, 0xeb: 0xb73, 0xec: 0xb7e, 0xed: 0xb7e, 0xee: 0xb8a, 0xef: 0xb94,
|
||||
# 0xf0: 0xb53, 0xf1: 0xb53, 0xf2: 0xba0, 0xf3: 0xba0, 0xf4: 0xba5, 0xf5: 0xba5, 0xf6: 0xbac, 0xf7: 0xbac,
|
||||
# 0xf8: 0xbac, 0xf9: 0xbba, 0xfa: 0xbc1, 0xfb: 0xbcc, 0xfc: 0xbd7, 0xfd: 0xbd7, 0xfe: 0xbba, 0xff: 0xbe3
|
||||
# }
|
||||
|
||||
44
Utils.py
44
Utils.py
@@ -4,6 +4,7 @@ import re
|
||||
import subprocess
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections import defaultdict
|
||||
|
||||
def int16_as_bytes(value):
|
||||
value = value & 0xFFFF
|
||||
@@ -225,6 +226,47 @@ def read_entrance_data(old_rom='Zelda no Densetsu - Kamigami no Triforce (Japan)
|
||||
print(string)
|
||||
|
||||
|
||||
def room_palette_data(old_rom):
|
||||
with open(old_rom, 'rb') as stream:
|
||||
old_rom_data = bytearray(stream.read())
|
||||
|
||||
offset = defaultdict(list)
|
||||
for i in range(0, 256):
|
||||
pointer_offset = 0x0271e2+i*2
|
||||
header_offset = old_rom_data[pointer_offset + 1] << 8
|
||||
header_offset += old_rom_data[pointer_offset]
|
||||
header_offset -= 0x8000
|
||||
header_offset += 0x020000
|
||||
offset[header_offset].append(i)
|
||||
# print(f'{hex(i)}: {hex(old_rom_data[header_offset+1])}')
|
||||
for header_offset, rooms in offset.items():
|
||||
print(f'{hex(header_offset)}: {[hex(x) for x in rooms]}')
|
||||
|
||||
|
||||
|
||||
# Palette notes:
|
||||
# HC: 0
|
||||
# Sewer/Dungeon: 1
|
||||
# AT: 0xc near boss, 0x0 (other) 26 (f4, f1)
|
||||
# Sanc: 0x1d
|
||||
# Hera: 0x6
|
||||
# Desert: 0x4 (boss and near boss), 0x9 (desert tiles 1 + desert main)
|
||||
# Eastern: 0xb
|
||||
# Pod: 0xf, x10 (boss)
|
||||
# Swamp: 0x8 (boss), 0xa (other)
|
||||
# Skull: 0xe (boss), 0xd (other)
|
||||
# TT: 0x17, 0x23 (attic)
|
||||
# Ice: 0x13, 0x14 (boss)
|
||||
# Mire: 0x11 (other) , 0x12 (boss/preroom)
|
||||
# TR: 0x18, 0x19 (boss+pre)
|
||||
# GT: 0x28 (entrance + B1), 0x1a (other) 0x24 (Gauntlet - Lanmo) 0x25 (conveyor-torch-wizzrode moldorm pit f5?)
|
||||
# Aga2: 0x1b, 0x1b (Pre aga2)
|
||||
# Caves: 0x7, 0x20
|
||||
# Uncle: 0x1
|
||||
# Ganon: 0x21
|
||||
# Houses: 0x2
|
||||
|
||||
|
||||
def print_wiki_doors_by_region(d_regions, world, player):
|
||||
for d, region_list in d_regions.items():
|
||||
tile_map = {}
|
||||
@@ -418,4 +460,4 @@ def print_graph(world):
|
||||
if __name__ == '__main__':
|
||||
# make_new_base2current()
|
||||
# read_entrance_data(old_rom=sys.argv[1])
|
||||
read_layout_data(old_rom=sys.argv[1])
|
||||
room_palette_data(old_rom=sys.argv[1])
|
||||
|
||||
@@ -619,5 +619,25 @@ 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
|
||||
|
||||
;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
|
||||
|
||||
@@ -59,6 +59,9 @@ rts
|
||||
nop #5
|
||||
.done
|
||||
|
||||
org $01b618 ; Bank01.asm : 7963 Dungeon_LoadHeader (REP #$20 : INY : LDA [$0D], Y)
|
||||
nop : jsl OverridePaletteHeader
|
||||
|
||||
org $00d377 ;Bank 00 line 3185
|
||||
DecompDungAnimatedTiles:
|
||||
org $00fda4 ;Bank 00 line 8882
|
||||
|
||||
12
asm/gfx.asm
12
asm/gfx.asm
@@ -54,4 +54,14 @@ CgramAuxToMain: ; ripped this from bank02 because it ended with rts
|
||||
; tell NMI to upload new CGRAM data
|
||||
inc $15
|
||||
rts
|
||||
}
|
||||
}
|
||||
|
||||
OverridePaletteHeader:
|
||||
lda.l DRMode : cmp #$02 : 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
|
||||
@@ -93,6 +93,7 @@ CutoffEntranceRug:
|
||||
lda $04 : cmp #$000A : bne +
|
||||
lda $a0 : cmp #$00BC : beq .check ;; TT Alcove
|
||||
cmp #$00A2 : beq .check ; Mire Bridges
|
||||
cmp #$001A : beq .check ; pod falling
|
||||
cmp #$00C2 : bne + ; Mire Hub
|
||||
.check
|
||||
lda $0c : cmp #$0007 : !bge .skip
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user