Merge branch 'DoorDev' into DoorShuffleStandardModeDev

This commit is contained in:
tolmar
2019-09-07 16:44:26 -07:00
13 changed files with 159 additions and 59 deletions

View File

@@ -284,7 +284,7 @@ class World(object):
def has_beaten_game(self, state, player=None): def has_beaten_game(self, state, player=None):
if player: if player:
return state.has('Triforce', player) or (self.goal in ['triforcehunt'] and (state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) > self.treasure_hunt_count)) return state.has('Triforce', player)
else: else:
return all((self.has_beaten_game(state, p) for p in range(1, self.players + 1))) return all((self.has_beaten_game(state, p) for p in range(1, self.players + 1)))
@@ -862,7 +862,8 @@ class Door(object):
layer = 4 * (self.layer ^ 1 if toggle else self.layer) layer = 4 * (self.layer ^ 1 if toggle else self.layer)
return [self.roomIndex, layer + self.doorIndex] return [self.roomIndex, layer + self.doorIndex]
if self.type == DoorType.SpiralStairs: if self.type == DoorType.SpiralStairs:
bitmask = 0x10 * int(self.zeroHzCam) bitmask = int(self.layer) << 2
bitmask += 0x10 * int(self.zeroHzCam)
bitmask += 0x20 * int(self.zeroVtCam) bitmask += 0x20 * int(self.zeroVtCam)
return [self.roomIndex, bitmask + self.quadrant, self.shiftX, self.shiftY] return [self.roomIndex, bitmask + self.quadrant, self.shiftX, self.shiftY]

View File

@@ -119,11 +119,11 @@ def can_place_boss(world, boss, dungeon_name, level=None):
if world.swords in ['swordless'] and boss == 'Kholdstare' and dungeon_name != 'Ice Palace': if world.swords in ['swordless'] and boss == 'Kholdstare' and dungeon_name != 'Ice Palace':
return False return False
if dungeon_name == 'Ganons Tower' and level == 'top': if dungeon_name in ['Ganons Tower', 'Inverted Ganons Tower'] and level == 'top':
if boss in ["Armos Knights", "Arrghus", "Blind", "Trinexx", "Lanmolas"]: if boss in ["Armos Knights", "Arrghus", "Blind", "Trinexx", "Lanmolas"]:
return False return False
if dungeon_name == 'Ganons Tower' and level == 'middle': if dungeon_name in ['Ganons Tower', 'Inverted Ganons Tower'] and level == 'middle':
if boss in ["Blind"]: if boss in ["Blind"]:
return False return False

View File

@@ -16,6 +16,12 @@ A = 0
S = 1 S = 1
Z = 2 Z = 2
X = 3 X = 3
# Layer transitions
HTH = 0 # High to High 00
HTL = 1 # High to Low 01
LTH = 2 # Low to High 10
LTL = 3 # Low to Low 11
def create_doors(world, player): def create_doors(world, player):
@@ -38,12 +44,12 @@ def create_doors(world, player):
create_dir_door(player, 'Hyrule Castle West Hall S', DoorType.Normal, Direction.South, 0x50, Right, Low), create_dir_door(player, 'Hyrule Castle West Hall S', DoorType.Normal, Direction.South, 0x50, Right, Low),
create_dir_door(player, 'Hyrule Castle Back Hall W', DoorType.Normal, Direction.West, 0x01, Top, Low), create_dir_door(player, 'Hyrule Castle Back Hall W', DoorType.Normal, Direction.West, 0x01, Top, Low),
create_dir_door(player, 'Hyrule Castle Back Hall E', DoorType.Normal, Direction.East, 0x01, Top, Low), create_dir_door(player, 'Hyrule Castle Back Hall E', DoorType.Normal, Direction.East, 0x01, Top, Low),
create_spiral_stairs(player, 'Hyrule Castle Back Hall Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x01, 0, Low, A, 0x37, 0xf8), create_spiral_stairs(player, 'Hyrule Castle Back Hall Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x01, 0, HTL, A, 0x2a, 0x00),
create_dir_door(player, 'Hyrule Castle Throne Room N', DoorType.Normal, Direction.North, 0x51, Mid, High), create_dir_door(player, 'Hyrule Castle Throne Room N', DoorType.Normal, Direction.North, 0x51, Mid, High),
create_dir_door(player, 'Hyrule Castle Throne Room South Stairs', DoorType.StraightStairs, Direction.South, 0x51, Mid, Low), create_dir_door(player, 'Hyrule Castle Throne Room South Stairs', DoorType.StraightStairs, Direction.South, 0x51, Mid, Low),
# hyrule dungeon level # hyrule dungeon level
create_spiral_stairs(player, 'Hyrule Dungeon Map Room Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x72, 0, High, A, 0x4f, 0xf8), create_spiral_stairs(player, 'Hyrule Dungeon Map Room Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x72, 0, LTH, A, 0x4b, 0xec),
create_small_key_door(player, 'Hyrule Dungeon Map Room Key Door S', DoorType.Interior, Direction.South, 0x71, Right, High), create_small_key_door(player, 'Hyrule Dungeon Map Room Key Door S', DoorType.Interior, Direction.South, 0x71, Right, High),
create_small_key_door(player, 'Hyrule Dungeon North Abyss Key Door N', DoorType.Interior, Direction.North, 0x71, Right, High), create_small_key_door(player, 'Hyrule Dungeon North Abyss Key Door N', DoorType.Interior, Direction.North, 0x71, Right, High),
create_dir_door(player, 'Hyrule Dungeon North Abyss South Edge', DoorType.Open, Direction.South, 0x72, None, Low), create_dir_door(player, 'Hyrule Dungeon North Abyss South Edge', DoorType.Open, Direction.South, 0x72, None, Low),
@@ -58,15 +64,15 @@ def create_doors(world, player):
create_dir_door(player, 'Hyrule Dungeon Armory S', DoorType.Normal, Direction.South, 0x71, Left, Low), # not sure what the layer should be here create_dir_door(player, 'Hyrule Dungeon Armory S', DoorType.Normal, Direction.South, 0x71, Left, Low), # not sure what the layer should be here
create_small_key_door(player, 'Hyrule Dungeon Armory Interior Key Door N', DoorType.Interior, Direction.North, 0x71, Left, High), create_small_key_door(player, 'Hyrule Dungeon Armory Interior Key Door N', DoorType.Interior, Direction.North, 0x71, Left, High),
create_small_key_door(player, 'Hyrule Dungeon Armory Interior Key Door S', DoorType.Interior, Direction.South, 0x71, Left, High), create_small_key_door(player, 'Hyrule Dungeon Armory Interior Key Door S', DoorType.Interior, Direction.South, 0x71, Left, High),
create_spiral_stairs(player, 'Hyrule Dungeon Armory Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x71, 0, Low, A, 0x1e, 0xa0, True), create_spiral_stairs(player, 'Hyrule Dungeon Armory Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x71, 0, HTL, A, 0x11, 0xa8, True),
create_spiral_stairs(player, 'Hyrule Dungeon Staircase Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x70, 2, High, A, 0x36, 0xa0, True), create_spiral_stairs(player, 'Hyrule Dungeon Staircase Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x70, 2, LTH, A, 0x32, 0x94, True),
create_spiral_stairs(player, 'Hyrule Dungeon Staircase Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x70, 1, High, A, 0x1f, 0x50), create_spiral_stairs(player, 'Hyrule Dungeon Staircase Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x70, 1, HTH, A, 0x11, 0x58),
create_spiral_stairs(player, 'Hyrule Dungeon Cellblock Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x80, 0, Low, A, 0x1f, 0x50), create_spiral_stairs(player, 'Hyrule Dungeon Cellblock Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x80, 0, HTH, A, 0x1a, 0x44),
# sewers # sewers
create_blocked_door(player, 'Sewers Behind Tapestry S', DoorType.Normal, Direction.South, 0x41, Mid, High), create_blocked_door(player, 'Sewers Behind Tapestry S', DoorType.Normal, Direction.South, 0x41, Mid, High),
create_spiral_stairs(player, 'Sewers Behind Tapestry Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x41, 0, High, S, 0x1f, 0xa8), create_spiral_stairs(player, 'Sewers Behind Tapestry Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x41, 0, HTH, S, 0x12, 0xb0),
create_spiral_stairs(player, 'Sewers Rope Room Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x42, 0, High, S, 0x1f, 0xa8), create_spiral_stairs(player, 'Sewers Rope Room Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x42, 0, HTH, S, 0x1b, 0x9c),
create_dir_door(player, 'Sewers Rope Room North Stairs', DoorType.StraightStairs, Direction.North, 0x42, Mid, High), create_dir_door(player, 'Sewers Rope Room North Stairs', DoorType.StraightStairs, Direction.North, 0x42, Mid, High),
create_dir_door(player, 'Sewers Dark Cross South Stairs', DoorType.StraightStairs, Direction.South, 0x32, Mid, High), create_dir_door(player, 'Sewers Dark Cross South Stairs', DoorType.StraightStairs, Direction.South, 0x32, Mid, High),
create_dir_door(player, 'Sewers Dark Cross Key Door N', DoorType.Normal, Direction.North, 0x32, Mid, High), create_dir_door(player, 'Sewers Dark Cross Key Door N', DoorType.Normal, Direction.North, 0x32, Mid, High),
@@ -75,8 +81,8 @@ def create_doors(world, player):
create_dir_door(player, 'Sewers Key Rat E', DoorType.Normal, Direction.East, 0x21, Bot, High), create_dir_door(player, 'Sewers Key Rat E', DoorType.Normal, Direction.East, 0x21, Bot, High),
create_small_key_door(player, 'Sewers Key Rat Key Door N', DoorType.Normal, Direction.North, 0x21, Right, High), create_small_key_door(player, 'Sewers Key Rat Key Door N', DoorType.Normal, Direction.North, 0x21, Right, High),
create_small_key_door(player, 'Sewers Secret Room Key Door S', DoorType.Normal, Direction.South, 0x11, Right, High), create_small_key_door(player, 'Sewers Secret Room Key Door S', DoorType.Normal, Direction.South, 0x11, Right, High),
create_spiral_stairs(player, 'Sewers Secret Room Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x11, 0, High, S, 0x37, 0x78), create_spiral_stairs(player, 'Sewers Secret Room Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x11, 0, LTH, S, 0x33, 0x6c, True),
create_spiral_stairs(player, 'Sewers Pull Switch Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x02, 0, High, S, 0x1f, 0x78), create_spiral_stairs(player, 'Sewers Pull Switch Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x02, 0, HTL, S, 0x12, 0x80),
create_toggle_door(player, 'Sewers Pull Switch S', DoorType.Normal, Direction.South, 0x02, Mid, Low), create_toggle_door(player, 'Sewers Pull Switch S', DoorType.Normal, Direction.South, 0x02, Mid, Low),
# logically one way the sanc, but should be linked - also toggle # logically one way the sanc, but should be linked - also toggle
create_blocked_door(player, 'Sanctuary N', DoorType.Normal, Direction.North, 0x12, Mid, 0, True), create_blocked_door(player, 'Sanctuary N', DoorType.Normal, Direction.North, 0x12, Mid, 0, True),
@@ -108,8 +114,8 @@ def create_doors(world, player):
create_small_key_door(player, 'Eastern Big Key EN', DoorType.Normal, Direction.East, 0xb8, Top, High), create_small_key_door(player, 'Eastern Big Key EN', DoorType.Normal, Direction.East, 0xb8, Top, High),
create_dir_door(player, 'Eastern Big Key NE', DoorType.Normal, Direction.North, 0xb8, Right, High), create_dir_door(player, 'Eastern Big Key NE', DoorType.Normal, Direction.North, 0xb8, Right, High),
create_small_key_door(player, 'Eastern Darkness S', DoorType.Normal, Direction.South, 0x99, Mid, High), create_small_key_door(player, 'Eastern Darkness S', DoorType.Normal, Direction.South, 0x99, Mid, High),
create_spiral_stairs(player, 'Eastern Darkness Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x99, 0, High, Z, 0x1e, 0x78, False, True), create_spiral_stairs(player, 'Eastern Darkness Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x99, 0, HTH, Z, 0x1a, 0x6c, False, True),
create_spiral_stairs(player, 'Eastern Attic Start Down Stairs', DoorType.SpiralStairs, Direction.Down, 0xda, 0, High, Z, 0x1f, 0x78, False, True), create_spiral_stairs(player, 'Eastern Attic Start Down Stairs', DoorType.SpiralStairs, Direction.Down, 0xda, 0, HTH, Z, 0x11, 0x80, False, True),
create_dir_door(player, 'Eastern Attic Start WS', DoorType.Normal, Direction.West, 0xda, Bot, High), create_dir_door(player, 'Eastern Attic Start WS', DoorType.Normal, Direction.West, 0xda, Bot, High),
create_dir_door(player, 'Eastern Attic Switches ES', DoorType.Normal, Direction.East, 0xd9, Bot, High), create_dir_door(player, 'Eastern Attic Switches ES', DoorType.Normal, Direction.East, 0xd9, Bot, High),
create_dir_door(player, 'Eastern Attic Switches WS', DoorType.Normal, Direction.West, 0xd9, Bot, High), create_dir_door(player, 'Eastern Attic Switches WS', DoorType.Normal, Direction.West, 0xd9, Bot, High),

View File

@@ -3507,8 +3507,8 @@ inverted_default_connections = [('Waterfall of Wishing', 'Waterfall of Wishing'
('Bumper Cave (Top)', 'Dark Death Mountain Healer Fairy'), ('Bumper Cave (Top)', 'Dark Death Mountain Healer Fairy'),
('Bumper Cave Exit (Top)', 'Death Mountain Return Ledge'), ('Bumper Cave Exit (Top)', 'Death Mountain Return Ledge'),
('Bumper Cave Exit (Bottom)', 'Light World'), ('Bumper Cave Exit (Bottom)', 'Light World'),
('Death Mountain Return Cave (East)', 'Bumper Cave'), ('Death Mountain Return Cave (West)', 'Bumper Cave'),
('Death Mountain Return Cave (West)', 'Death Mountain Return Cave'), ('Death Mountain Return Cave (East)', 'Death Mountain Return Cave'),
('Death Mountain Return Cave Exit (West)', 'Death Mountain'), ('Death Mountain Return Cave Exit (West)', 'Death Mountain'),
('Death Mountain Return Cave Exit (East)', 'Death Mountain'), ('Death Mountain Return Cave Exit (East)', 'Death Mountain'),
('Hookshot Cave Exit (South)', 'Dark Death Mountain'), ('Hookshot Cave Exit (South)', 'Dark Death Mountain'),

View File

@@ -137,6 +137,23 @@ def generate_itempool(world, player):
else: else:
world.push_item(world.get_location('Ganon', player), ItemFactory('Triforce', player), False) world.push_item(world.get_location('Ganon', player), ItemFactory('Triforce', player), False)
if world.goal in ['triforcehunt']:
if world.mode == 'inverted':
region = world.get_region('Light World',player)
else:
region = world.get_region('Hyrule Castle Courtyard', player)
loc = Location(player, "Murahdahla", parent=region)
loc.access_rule = lambda state: state.item_count('Triforce Piece', player) + state.item_count('Power Star', player) > state.world.treasure_hunt_count
region.locations.append(loc)
world.dynamic_locations.append(loc)
world.clear_location_cache()
world.push_item(loc, ItemFactory('Triforce', player), False)
loc.event = True
loc.locked = True
world.get_location('Ganon', player).event = True world.get_location('Ganon', player).event = True
world.get_location('Ganon', player).locked = True world.get_location('Ganon', player).locked = True
world.push_item(world.get_location('Agahnim 1', player), ItemFactory('Beat Agahnim 1', player), False) world.push_item(world.get_location('Agahnim 1', player), ItemFactory('Beat Agahnim 1', player), False)

View File

@@ -285,6 +285,11 @@ def copy_dynamic_regions_and_locations(world, ret):
for location in world.dynamic_locations: for location in world.dynamic_locations:
new_reg = ret.get_region(location.parent_region.name, location.parent_region.player) new_reg = ret.get_region(location.parent_region.name, location.parent_region.player)
new_loc = Location(location.player, location.name, location.address, location.crystal, location.hint_text, new_reg) new_loc = Location(location.player, location.name, location.address, location.crystal, location.hint_text, new_reg)
# todo: this is potentially dangerous. later refactor so we
# can apply dynamic region rules on top of copied world like other rules
new_loc.access_rule = location.access_rule
new_loc.always_allow = location.always_allow
new_loc.item_rule = location.item_rule
new_reg.locations.append(new_loc) new_reg.locations.append(new_loc)
ret.clear_location_cache() ret.clear_location_cache()

11
Rom.py
View File

@@ -18,7 +18,7 @@ from EntranceShuffle import door_addresses
JAP10HASH = '03a63945398191337e896e5771f77173' JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = 'fdfff1a9046506a57dbcbe23fb5fd386' RANDOMIZERBASEHASH = 'efb85e71cf7d9bc0401c6683992d6e2f'
class JsonRom(object): class JsonRom(object):
@@ -842,6 +842,7 @@ def patch_rom(world, player, rom):
# set up goals for treasure hunt # set up goals for treasure hunt
rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon == 'Triforce Piece' else [0x0D, 0x28]) rom.write_bytes(0x180165, [0x0E, 0x28] if world.treasure_hunt_icon == 'Triforce Piece' else [0x0D, 0x28])
rom.write_byte(0x180167, world.treasure_hunt_count % 256) rom.write_byte(0x180167, world.treasure_hunt_count % 256)
rom.write_byte(0x180194, 1) # Must turn in triforced pieces (instant win not enabled)
# TODO: a proper race rom mode should be implemented, that changes the following flag, and rummages the table (or uses the future encryption feature, etc) # TODO: a proper race rom mode should be implemented, that changes the following flag, and rummages the table (or uses the future encryption feature, etc)
rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed rom.write_bytes(0x180213, [0x00, 0x01]) # Not a Tournament Seed
@@ -1282,17 +1283,18 @@ def write_strings(rom, world, player):
random.shuffle(silverarrows) random.shuffle(silverarrows)
silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!' silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
prog_bow_locs = world.find_items('Progressive Bow', player) prog_bow_locs = world.find_items('Progressive Bow', player)
distinguished_prog_bow_loc = next((location for location in prog_bow_locs if location.item.code == 0x65), None) distinguished_prog_bow_loc = next((location for location in prog_bow_locs if location.item.code == 0x65), None)
if distinguished_prog_bow_loc: if distinguished_prog_bow_loc:
prog_bow_locs.remove(distinguished_prog_bow_loc) prog_bow_locs.remove(distinguished_prog_bow_loc)
silverarrow_hint = (' %s?' % hint_text(distinguished_prog_bow_loc).replace('Ganon\'s', 'my')) silverarrow_hint = (' %s?' % hint_text(distinguished_prog_bow_loc).replace('Ganon\'s', 'my'))
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
if any(prog_bow_locs): if any(prog_bow_locs):
silverarrow_hint = (' %s?' % hint_text(random.choice(prog_bow_locs)).replace('Ganon\'s', 'my')) silverarrow_hint = (' %s?' % hint_text(random.choice(prog_bow_locs)).replace('Ganon\'s', 'my'))
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!' silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
@@ -1323,6 +1325,7 @@ def write_strings(rom, world, player):
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.' tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.'
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.' tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!' tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!'
tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\ninvisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\nhidden in a hollow tree. If you bring\n%d triforce pieces, I can reassemble it." % world.treasure_hunt_count
elif world.goal in ['pedestal']: elif world.goal in ['pedestal']:
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Your goal is at the pedestal.' tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Your goal is at the pedestal.'
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.' tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
@@ -1406,8 +1409,6 @@ def set_inverted_mode(world, rom):
rom.write_int16s(snes_to_pc(0x02E849), [0x0043, 0x0056, 0x0058, 0x006C, 0x006F, 0x0070, 0x007B, 0x007F, 0x001B]) # dw flute rom.write_int16s(snes_to_pc(0x02E849), [0x0043, 0x0056, 0x0058, 0x006C, 0x006F, 0x0070, 0x007B, 0x007F, 0x001B]) # dw flute
rom.write_int16(snes_to_pc(0x02E8D5), 0x07C8) rom.write_int16(snes_to_pc(0x02E8D5), 0x07C8)
rom.write_int16(snes_to_pc(0x02E8F7), 0x01F8) rom.write_int16(snes_to_pc(0x02E8F7), 0x01F8)
rom.write_byte(0x7A943, 0xF0)
rom.write_byte(0x7A96D, 0xD0)
rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph proof rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph proof
# the following bytes should only be written in vanilla # the following bytes should only be written in vanilla
# or they'll overwrite the randomizer's shuffles # or they'll overwrite the randomizer's shuffles

View File

@@ -1890,5 +1890,6 @@ class TextTable(object):
text['ganon_phase_3_no_silvers_alt'] = CompressedTextMapper.convert("You can't best me without silver arrows!") text['ganon_phase_3_no_silvers_alt'] = CompressedTextMapper.convert("You can't best me without silver arrows!")
text['ganon_phase_3_no_silvers'] = CompressedTextMapper.convert("You can't best me without silver arrows!") 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['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['end_pad_data'] = bytearray([0xfb]) text['end_pad_data'] = bytearray([0xfb])
text['terminator'] = bytearray([0xFF, 0xFF]) text['terminator'] = bytearray([0xFF, 0xFF])

View File

@@ -122,6 +122,26 @@ c2 21 ae b6 0a bf 1b
Trap doors:
0468 - flag is set when doors are down (1 = down? 0 = up?)
$690 - 7 for open - 0 for down
IntraRoom: ->
Dungeon_IntraRoomTransShutDoors (maybe should be Open)
stz $0468
#$07 -> $0690
Dungeon_IntraRoomTransOpenDoors (maybe should be Shut)
10D71 -> A
A -> 0468
0468++
0 -> 0690
Other transition stuff Other transition stuff
Overworld_LoadTransGfx -> LoadTransAuxGfx Overworld_LoadTransGfx -> LoadTransAuxGfx

View File

@@ -27,9 +27,10 @@ NotLinkDoor2:
; Staircase routine ; Staircase routine
;org $02a1e7 ;(PC: 121e7)
org $01c3d4 ;(PC: c3d4) org $01c3d4 ;(PC: c3d4)
jsl SpiralWarp : nop jsl RecordStairType : nop
org $02a1e7 ;(PC: 121e7)
jsl SpiralWarp
; Graphics fix ; Graphics fix
@@ -333,5 +334,12 @@ ShiftQuadIndex:
db 2, 1 ; see ShiftQuad func (relates to $a9,$aa) db 2, 1 ; see ShiftQuad func (relates to $a9,$aa)
CamBoundIndex: ; Horizontal 1st CamBoundIndex: ; Horizontal 1st
db 0, 4 ; Camera Bounds $0618-$61f 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 is not right yet
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
incsrc doortables.asm incsrc doortables.asm

View File

@@ -1,14 +1,19 @@
SpiralWarp: RecordStairType: {
{ pha
lda $0e : sta $045e
pla : sta $a0 : lda $063d, x
rtl
}
pha : lda $040c : cmp.b #$ff : beq .abort ; abort if not in dungeon SpiralWarp: {
lda $040c : cmp.b #$ff : beq .abort ; abort if not in dungeon
cmp #$06 : bcs .abort ; abort if not supported yet -- todo: this needs to be altered/removed as more dungeons are implemented cmp #$06 : bcs .abort ; abort if not supported yet -- todo: this needs to be altered/removed as more dungeons are implemented
lda $0e : cmp #$5e : beq .gtg ; abort if not spiral - intended room is in A! lda $045e : cmp #$5e : beq .gtg ; abort if not spiral - intended room is in A!
cmp #$5f : beq .gtg cmp #$5f : beq .gtg
.abort pla : sta $a0 : bra .end .abort
lda $a2 : and #$0f : rtl ; run highjack code and get out
.gtg .gtg
pla
phb : phk : plb : phx : phy ; push stuff phb : phk : plb : phx : phy ; push stuff
jsr LookupSpiralOffset jsr LookupSpiralOffset
rep #$30 : and #$00FF : asl #2 : tax rep #$30 : and #$00FF : asl #2 : tax
@@ -29,25 +34,29 @@ SpiralWarp:
ldy #$01 : jsr ShiftQuadSimple ldy #$01 : jsr ShiftQuadSimple
.skipYQuad .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 ; shift lower coordinates
lda $02 : sta $22 lda $02 : sta $22 : bne .adjY : inc $23
lda $03 : sta $20 .adjY lda $03 : sta $20 : bne .set53 : inc $21
.set53 ldx #$08
lda $0462 : and #$04 : beq .upStairs
ldx #$fd
.upStairs
txa : !add $22 : sta $53
ldy #$00 : jsr SetCamera ; todo: figure out camera jazz lda $01 : and #$10 : sta $07 ; zeroHzCam check
ldy #$00 : jsr SetCamera
lda $01 : and #$20 : sta $07 ; zeroVtCam check
ldy #$01 : jsr SetCamera ldy #$01 : jsr SetCamera
ply : plx : plb ; pull the stuff we pushed ply : plx : plb ; pull the stuff we pushed
lda $a2 : and #$0f ; this is the code we are hijacking
.end
; this is the code we are hijacking
; lda $a0 - we overwrote this behavior
lda $063d, x
rtl rtl
} }
;Sets the offset in A ;Sets the offset in A
LookupSpiralOffset: LookupSpiralOffset: {
{
;where link currently is in $a2: quad in a8 & #$03 ;where link currently is in $a2: quad in a8 & #$03
;count doors ;count doors
stz $00 : ldx #$00 : stz $01 stz $00 : ldx #$00 : stz $01
@@ -84,43 +93,65 @@ LookupSpiralOffset:
rts rts
} }
ShiftQuadSimple: ShiftQuadSimple: {
{
lda CoordIndex,y : tax lda CoordIndex,y : tax
lda $20,x : beq .skip
lda $21,x : !add $06 : sta $21,x ; coordinate update lda $21,x : !add $06 : sta $21,x ; coordinate update
.skip
lda CamQuadIndex,y : tax lda CamQuadIndex,y : tax
lda $0601,x : !add $06 : sta $0601,x lda $0601,x : !add $06 : sta $0601,x
lda $0605,x : !add $06 : sta $0605,x ; high bytes of these guys lda $0605,x : !add $06 : sta $0605,x ; high bytes of these guys
rts rts
} }
SetCamera: SetCamera: {
{ stz $04
stz $04 : sty $05
lda $01 : and #$10 : !add $05 : cmp #$10 : beq .done ; zeroHzCam check (10+0 = 10)
lda $01 : and #$20 : !add $05 : cmp #$21 : beq .done ; zeroVtCam check (20+1 = 21)
tyx : lda $a9,x : bne .nonZeroHalf tyx : lda $a9,x : bne .nonZeroHalf
lda CamQuadIndex,y : tax : lda $607,x : pha lda CamQuadIndex,y : tax : lda $607,x : pha
lda CameraIndex,y : tax : pla : cmp $e3, x : bne .noQuadAdj lda CameraIndex,y : tax : pla : cmp $e3, x : bne .noQuadAdj
dec $e3,x dec $e3,x
.noQuadAdj .noQuadAdj
lda $07 : bne .adj0
lda CoordIndex,y : tax lda CoordIndex,y : tax
lda $20,x : cmp #$79 : bcc .adjust lda $20,x : beq .oddQuad
!sub #$78 : sta $04 : bra .adjust 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 .nonZeroHalf ;meaning either right half or bottom half
lda $07 : bne .setQuad
lda CoordIndex,y : tax lda CoordIndex,y : tax
lda $20,x : cmp #$78 : bcs .setQuad lda $20,x : cmp #$78 : bcs .setQuad
!add #$78 : sta $04 : bra .adjust !add #$78 : sta $04
.adj1
tya : asl : !add #$08 : tax : jsr AdjCamBounds : bra .done
.setQuad .setQuad
lda CamQuadIndex,y : tax : lda $0607, x : pha lda CamQuadIndex,y : tax : lda $0607, x : pha
lda CameraIndex,y : tax : pla : sta $e3, x : bra .done lda CameraIndex,y : tax : pla : sta $e3, x
tya : asl : !add #$0c : tax : jsr AdjCamBounds : bra .done
.adjust .done
lda CameraIndex,y : tax lda CameraIndex,y : tax
.done lda $04 : sta $e2,x 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 CamBoundBaseLine, x : sta $05
lda $04 : and #$00ff : beq .common
lda CoordIndex,y : tax
lda $20, x : and #$00ff : !add $05 : sta $05
.common
lda OppCamBoundIndex,y : tax
lda $05 : sta $0618, x
inc #2 : sta $061A, x : sep #$20
rts rts
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,9 @@
Notes: Notes:
Zero camera out skips quad logic
The armory guard room and the room above have fake layers. Shutter doors
The armory guard room and the room above have fake layers. Maybe not???
@@ -13,4 +13,14 @@ Notes 2:
(Fixed partially )Guardroom N Door is set to $8000, I think it was supposed to be Eastern Compass Area SW $02a8 that how this get teleported back to HC. Wrong room index. Still might be a toggle door (Fixed partially )Guardroom N Door is set to $8000, I think it was supposed to be Eastern Compass Area SW $02a8 that how this get teleported back to HC. Wrong room index. Still might be a toggle door
(Fixed) Courtyard N is set to $02D8 - typo (Fixed) Courtyard N is set to $02D8 - typo
(Fixed) Sanc N is $0650 but should be $0250 which I think is right. typo again on the wrong layer (Fixed) Sanc N is $0650 but should be $0250 which I think is right. typo again on the wrong layer
(Fixed) Eastern boss had wrong room (Fixed) Eastern boss had wrong room
Pairing Notes
30-34 4f-37 #$18,-24
30-34 37-1f #$18,-24
30-34 1f-1f???
30-35 1f-1f
30-34 36-1e #$18,-24
30-34 1e-1f
inconsistencies are caused by $0492 being set wrong