Inverted Mode (#5)

Merging in Cassidoxa's inverted mode.

I've still not fully reviewed the logic used in this mode, so it should be considered experimental, pending an in depth review by either myself or AA.
This commit is contained in:
cassidoxa
2019-07-27 09:13:13 -04:00
committed by Kevin Cathcart
parent 6d5a0a004d
commit 18f1275050
12 changed files with 3223 additions and 113 deletions

278
Rom.py
View File

@@ -3,17 +3,18 @@ import json
import hashlib
import logging
import os
import random
import struct
import subprocess
import random
from BaseClasses import ShopType, Region, Location, Item
from Dungeons import dungeon_music_addresses
from Text import MultiByteTextMapper, text_addresses, Credits, TextTable
from Text import MultiByteTextMapper, CompressedTextMapper, text_addresses, Credits, TextTable
from Text import Uncle_texts, Ganon1_texts, TavernMan_texts, Sahasrahla2_texts, Triforce_texts, Blind_texts, BombShop2_texts, junk_texts
from Text import KingsReturn_texts, Sanctuary_texts, Kakariko_texts, Blacksmiths_texts, DeathMountain_texts, LostWoods_texts, WishingWell_texts, DesertPalace_texts, MountainTower_texts, LinksHouse_texts, Lumberjacks_texts, SickKid_texts, FluteBoy_texts, Zora_texts, MagicShop_texts, Sahasrahla_names
from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes
from Utils import output_path, local_path, int16_as_bytes, int32_as_bytes, snes_to_pc
from Items import ItemFactory, item_table
from EntranceShuffle import door_addresses
JAP10HASH = '03a63945398191337e896e5771f77173'
@@ -37,6 +38,10 @@ class JsonRom(object):
def write_int16(self, address, value):
self.write_bytes(address, int16_as_bytes(value))
def write_int16s(self, startaddress, values):
byte_list = [int16_as_bytes(value) for value in values]
self.patches[str(startaddress)] = [byte for bytes in byte_list for byte in bytes]
def write_int32(self, address, value):
self.write_bytes(address, int32_as_bytes(value))
@@ -70,9 +75,17 @@ class LocalRom(object):
def write_int16(self, address, value):
self.write_bytes(address, int16_as_bytes(value))
def write_int16s(self, startaddress, values):
for i, value in enumerate(values):
self.write_int16(startaddress + (i * 2), value)
def write_int32(self, address, value):
self.write_bytes(address, int32_as_bytes(value))
def write_int32s(self, startaddress, values):
for i, value in enumerate(values):
self.write_int32(startaddress + (i * 2), value)
def write_to_file(self, file):
with open(file, 'wb') as outfile:
outfile.write(self.buffer)
@@ -218,14 +231,21 @@ def get_enemizer_patch(world, player, rom, baserom_path, enemizercli, shuffleene
'IcePalace': world.get_dungeon("Ice Palace", player).boss.enemizer_name,
'MiseryMire': world.get_dungeon("Misery Mire", player).boss.enemizer_name,
'TurtleRock': world.get_dungeon("Turtle Rock", player).boss.enemizer_name,
'GanonsTower1': world.get_dungeon('Ganons Tower', player).bosses['bottom'].enemizer_name,
'GanonsTower2': world.get_dungeon('Ganons Tower', player).bosses['middle'].enemizer_name,
'GanonsTower3': world.get_dungeon('Ganons Tower', player).bosses['top'].enemizer_name,
'GanonsTower4': 'Agahnim2',
'Ganon': 'Ganon',
}
}
if world.mode != 'inverted':
options['ManualBosses']['GanonsTower1'] = world.get_dungeon('Ganons Tower', player).bosses['bottom'].enemizer_name
options['ManualBosses']['GanonsTower2'] = world.get_dungeon('Ganons Tower', player).bosses['middle'].enemizer_name
options['ManualBosses']['GanonsTower3'] = world.get_dungeon('Ganons Tower', player).bosses['top'].enemizer_name
else:
options['ManualBosses']['GanonsTower1'] = world.get_dungeon('Inverted Ganons Tower', player).bosses['bottom'].enemizer_name
options['ManualBosses']['GanonsTower2'] = world.get_dungeon('Inverted Ganons Tower', player).bosses['middle'].enemizer_name
options['ManualBosses']['GanonsTower3'] = world.get_dungeon('Inverted Ganons Tower', player).bosses['top'].enemizer_name
rom.write_to_file(randopatch_path)
with open(options_path, 'w') as f:
@@ -501,7 +521,9 @@ def patch_rom(world, player, rom):
else:
# patch door table
rom.write_byte(0xDBB73 + exit.addresses, exit.target)
if world.mode == 'inverted':
patch_shuffled_dark_sanc(world, rom, player)
write_custom_shops(rom, world, player)
# patch medallion requirements
@@ -527,7 +549,7 @@ def patch_rom(world, player, rom):
rom.write_byte(0x51DE, 0x00)
# set open mode:
if world.mode in ['open', 'swordless']:
if world.mode in ['open', 'swordless', 'inverted']:
rom.write_byte(0x180032, 0x01) # open mode
# disable sword sprite from uncle
@@ -541,7 +563,9 @@ def patch_rom(world, player, rom):
rom.write_bytes(0x6D2EB, [0x00, 0x00, 0xf7, 0xff, 0x02, 0x0E])
rom.write_bytes(0x6D31B, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
rom.write_bytes(0x6D323, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
else:
if world.mode == 'inverted':
set_inverted_mode(world, rom)
elif world.mode == 'standard':
rom.write_byte(0x180032, 0x00) # standard mode
# set light cones
@@ -855,6 +879,8 @@ def patch_rom(world, player, rom):
# assorted fixes
rom.write_byte(0x1800A2, 0x01) # remain in real dark world when dying in dark word dungion before killing aga1
rom.write_byte(0x180169, 0x01 if world.lock_aga_door_in_escape else 0x00) # Lock or unlock aga tower door during escape sequence.
if world.mode == 'inverted':
rom.write_byte(0x180169, 0x02) # lock aga/ganon tower door with crystals in inverted
rom.write_byte(0x180171, 0x01 if world.ganon_at_pyramid[player] else 0x00) # Enable respawning on pyramid after ganon death
rom.write_byte(0x180173, 0x01) # Bob is enabled
rom.write_byte(0x180168, 0x08) # Spike Cave Damage
@@ -877,12 +903,12 @@ def patch_rom(world, player, rom):
rom.write_byte(0x18302C, 0x18) # starting max health
rom.write_byte(0x18302D, 0x18) # starting current health
rom.write_byte(0x183039, 0x68) # starting abilities, bit array
rom.write_byte(0x18004A, 0x00) # Inverted mode (off)
rom.write_byte(0x18004A, 0x00 if world.mode != 'inverted' else 0x01) # Inverted mode
rom.write_byte(0x18005D, 0x00) # Hammer always breaks barrier
rom.write_byte(0x2AF79, 0xD0) # vortexes: Normal (D0=light to dark, F0=dark to light, 42 = both)
rom.write_byte(0x3A943, 0xD0) # Mirror: Normal (D0=Dark to Light, F0=light to dark, 42 = both)
rom.write_byte(0x3A96D, 0xF0) # Residual Portal: Normal (F0= Light Side, D0=Dark Side, 42 = both (Darth Vader))
rom.write_byte(0x3A9A7, 0xD0) # Residual Portal: Normal (D0= Light Side, F0=Dark Side, 42 = both (Darth Vader))
rom.write_byte(0x2AF79, 0xD0 if world.mode != 'inverted' else 0xF0) # vortexes: Normal (D0=light to dark, F0=dark to light, 42 = both)
rom.write_byte(0x3A943, 0xD0 if world.mode != 'inverted' else 0xF0) # Mirror: Normal (D0=Dark to Light, F0=light to dark, 42 = both)
rom.write_byte(0x3A96D, 0xF0 if world.mode != 'inverted' else 0xD0) # Residual Portal: Normal (F0= Light Side, D0=Dark Side, 42 = both (Darth Vader))
rom.write_byte(0x3A9A7, 0xD0 if world.mode != 'inverted' else 0xF0) # Residual Portal: Normal (D0= Light Side, F0=Dark Side, 42 = both (Darth Vader))
rom.write_bytes(0x180080, [50, 50, 70, 70]) # values to fill for Capacity Upgrades (Bomb5, Bomb10, Arrow5, Arrow10)
@@ -1321,6 +1347,18 @@ def write_strings(rom, world, player):
bombos_text = 'Some Hot Air' if bombositem is None else hint_text(bombositem, True) if bombositem.pedestal_hint_text is not None else 'Unknown Item'
tt['tablet_bombos_book'] = bombos_text
# inverted spawn menu changes
if world.mode == 'inverted':
tt['menu_start_2'] = "{MENU}\n{SPEED0}\n≥@'s house\n Dark Chapel\n{CHOICE3}"
tt['menu_start_3'] = "{MENU}\n{SPEED0}\n≥@'s house\n Dark Chapel\n Mountain Cave\n{CHOICE2}"
tt['intro_main'] = CompressedTextMapper.convert(
"{INTRO}\n Episode III\n{PAUSE3}\n A Link to\n the Past\n"
+ "{PAUSE3}\nInverted\n Randomizer\n{PAUSE3}\nAfter mostly disregarding what happened in the first two games.\n"
+ "{PAUSE3}\nLink has been transported to the Dark World\n{PAUSE3}\nWhile he was slumbering\n"
+ "{PAUSE3}\nWhatever will happen?\n{PAUSE3}\n{CHANGEPIC}\nGanon has moved around all the items in Hyrule.\n"
+ "{PAUSE7}\nYou will have to find all the items necessary to beat Ganon.\n"
+ "{PAUSE7}\nThis is your chance to be a hero.\n{PAUSE3}\n{CHANGEPIC}\n"
+ "You must get the 7 crystals to beat Ganon.\n{PAUSE9}\n{CHANGEPIC}", False)
rom.write_bytes(0xE0000, tt.getBytes())
credits = Credits()
@@ -1359,6 +1397,218 @@ def write_strings(rom, world, player):
rom.write_bytes(0x181500, data)
rom.write_bytes(0x76CC0, [byte for p in pointers for byte in [p & 0xFF, p >> 8 & 0xFF]])
def set_inverted_mode(world, rom):
rom.write_byte(snes_to_pc(0x0283E0), 0xF0) # residual portals
rom.write_byte(snes_to_pc(0x02B34D), 0xF0)
rom.write_byte(snes_to_pc(0x06DB78), 0x8B)
rom.write_byte(snes_to_pc(0x0DB3C5), 0xC6)
rom.write_byte(snes_to_pc(0x07A3F4), 0xF0) # duck
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(0x02E8F7), 0x01F8)
rom.write_byte(snes_to_pc(0x08D40C), 0xD0) # morph proof
# the following bytes should only be written in vanilla
# or they'll overwrite the randomizer's shuffles
if world.shuffle == 'vanilla':
rom.write_byte(0x15B8C, 0x6C)
rom.write_byte(0xDBB73 + 0x00, 0x53) # switch bomb shop and links house
rom.write_byte(0xDBB73 + 0x52, 0x01)
rom.write_byte(0xDBB73 + 0x23, 0x37) # switch AT and GT
rom.write_byte(0xDBB73 + 0x36, 0x24)
rom.write_int16(0x15AEE + 2*0x38, 0x00E0)
rom.write_int16(0x15AEE + 2*0x25, 0x000C)
rom.write_byte(0xDBB73 + 0x15, 0x06) # bumper and old man cave
rom.write_int16(0x15AEE + 2*0x17, 0x00F0)
rom.write_byte(0xDBB73 + 0x05, 0x16)
rom.write_int16(0x15AEE + 2*0x07, 0x00FB)
rom.write_byte(0xDBB73 + 0x2D, 0x17)
rom.write_int16(0x15AEE + 2*0x2F, 0x00EB)
rom.write_byte(0xDBB73 + 0x06, 0x2E)
rom.write_int16(0x15AEE + 2*0x08, 0x00E6)
rom.write_byte(0xDBB73 + 0x16, 0x5E)
rom.write_byte(0xDBB73 + 0x6F, 0x07) # DDM fairy to old man cave
rom.write_int16(0x15AEE + 2*0x18, 0x00F1)
rom.write_byte(0x15B8C + 0x18, 0x43)
rom.write_int16(0x15BDB + 2 * 0x18, 0x1400)
rom.write_int16(0x15C79 + 2 * 0x18, 0x0294)
rom.write_int16(0x15D17 + 2 * 0x18, 0x0600)
rom.write_int16(0x15DB5 + 2 * 0x18, 0x02E8)
rom.write_int16(0x15E53 + 2 * 0x18, 0x0678)
rom.write_int16(0x15EF1 + 2 * 0x18, 0x0303)
rom.write_int16(0x15F8F + 2 * 0x18, 0x0685)
rom.write_byte(0x1602D + 0x18, 0x0A)
rom.write_byte(0x1607C + 0x18, 0xF6)
rom.write_int16(0x160CB + 2 * 0x18, 0x0000)
rom.write_int16(0x16169 + 2 * 0x18, 0x0000)
rom.write_int16(0x15AEE + 2 * 0x3D, 0x0003) # pyramid exit and houlihan
rom.write_byte(0x15B8C + 0x3D, 0x5B)
rom.write_int16(0x15BDB + 2 * 0x3D, 0x0B0E)
rom.write_int16(0x15C79 + 2 * 0x3D, 0x075A)
rom.write_int16(0x15D17 + 2 * 0x3D, 0x0674)
rom.write_int16(0x15DB5 + 2 * 0x3D, 0x07A8)
rom.write_int16(0x15E53 + 2 * 0x3D, 0x06E8)
rom.write_int16(0x15EF1 + 2 * 0x3D, 0x07C7)
rom.write_int16(0x15F8F + 2 * 0x3D, 0x06F3)
rom.write_byte(0x1602D + 0x3D, 0x06)
rom.write_byte(0x1607C + 0x3D, 0xFA)
rom.write_int16(0x160CB + 2 * 0x3D, 0x0000)
rom.write_int16(0x16169 + 2 * 0x3D, 0x0000)
rom.write_int16(snes_to_pc(0x02D8D4), 0x112) # change sactuary spawn point to dark sanc
rom.write_bytes(snes_to_pc(0x02D8E8), [0x22, 0x22, 0x22, 0x23, 0x04, 0x04, 0x04, 0x05])
rom.write_int16(snes_to_pc(0x02D91A), 0x0400)
rom.write_int16(snes_to_pc(0x02D928), 0x222E)
rom.write_int16(snes_to_pc(0x02D936), 0x229A)
rom.write_int16(snes_to_pc(0x02D944), 0x0480)
rom.write_int16(snes_to_pc(0x02D952), 0x00A5)
rom.write_int16(snes_to_pc(0x02D960), 0x007F)
rom.write_byte(snes_to_pc(0x02D96D), 0x14)
rom.write_byte(snes_to_pc(0x02D974), 0x00)
rom.write_byte(snes_to_pc(0x02D97B), 0xFF)
rom.write_byte(snes_to_pc(0x02D982), 0x00)
rom.write_byte(snes_to_pc(0x02D989), 0x02)
rom.write_byte(snes_to_pc(0x02D990), 0x00)
rom.write_int16(snes_to_pc(0x02D998), 0x0000)
rom.write_int16(snes_to_pc(0x02D9A6), 0x005A)
rom.write_byte(snes_to_pc(0x02D9B3), 0x12)
# keep the old man spawn point at old man house unless shuffle is vanilla
if world.shuffle == 'vanilla':
rom.write_bytes(snes_to_pc(0x308350), [0x00, 0x00, 0x01])
rom.write_int16(snes_to_pc(0x02D8DE), 0x00F1)
rom.write_bytes(snes_to_pc(0x02D910), [0x1F, 0x1E, 0x1F, 0x1F, 0x03, 0x02, 0x03, 0x03])
rom.write_int16(snes_to_pc(0x02D924), 0x0300)
rom.write_int16(snes_to_pc(0x02D932), 0x1F10)
rom.write_int16(snes_to_pc(0x02D940), 0x1FC0)
rom.write_int16(snes_to_pc(0x02D94E), 0x0378)
rom.write_int16(snes_to_pc(0x02D95C), 0x0187)
rom.write_int16(snes_to_pc(0x02D96A), 0x017F)
rom.write_byte(snes_to_pc(0x02D972), 0x06)
rom.write_byte(snes_to_pc(0x02D979), 0x00)
rom.write_byte(snes_to_pc(0x02D980), 0xFF)
rom.write_byte(snes_to_pc(0x02D987), 0x00)
rom.write_byte(snes_to_pc(0x02D98E), 0x22)
rom.write_byte(snes_to_pc(0x02D995), 0x12)
rom.write_int16(snes_to_pc(0x02D9A2), 0x0000)
rom.write_int16(snes_to_pc(0x02D9B0), 0x0007)
rom.write_byte(snes_to_pc(0x02D9B8), 0x12)
rom.write_bytes(0x180247, [0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00])
rom.write_int16(0x15AEE + 2 * 0x06, 0x0020) # post aga hyrule castle spawn
rom.write_byte(0x15B8C + 0x06, 0x1B)
rom.write_int16(0x15BDB + 2 * 0x06, 0x00AE)
rom.write_int16(0x15C79 + 2 * 0x06, 0x0610)
rom.write_int16(0x15D17 + 2 * 0x06, 0x077E)
rom.write_int16(0x15DB5 + 2 * 0x06, 0x0672)
rom.write_int16(0x15E53 + 2 * 0x06, 0x07F8)
rom.write_int16(0x15EF1 + 2 * 0x06, 0x067D)
rom.write_int16(0x15F8F + 2 * 0x06, 0x0803)
rom.write_byte(0x1602D + 0x06, 0x00)
rom.write_byte(0x1607C + 0x06, 0xF2)
rom.write_int16(0x160CB + 2 * 0x06, 0x0000)
rom.write_int16(0x16169 + 2 * 0x06, 0x0000)
rom.write_int16(snes_to_pc(0x02E87B), 0x00AE) # move flute splot 9
rom.write_int16(snes_to_pc(0x02E89D), 0x0610)
rom.write_int16(snes_to_pc(0x02E8BF), 0x077E)
rom.write_int16(snes_to_pc(0x02E8E1), 0x0672)
rom.write_int16(snes_to_pc(0x02E903), 0x07F8)
rom.write_int16(snes_to_pc(0x02E925), 0x067D)
rom.write_int16(snes_to_pc(0x02E947), 0x0803)
rom.write_int16(snes_to_pc(0x02E969), 0x0000)
rom.write_int16(snes_to_pc(0x02E98B), 0xFFF2)
rom.write_byte(snes_to_pc(0x1AF696), 0xF0) # bat sprite retreat
rom.write_byte(snes_to_pc(0x1AF6B2), 0x33)
rom.write_bytes(snes_to_pc(0x1AF730), [0x6A, 0x9E, 0x0C, 0x00, 0x7A, 0x9E, 0x0C,
0x00, 0x8A, 0x9E, 0x0C, 0x00, 0x6A, 0xAE,
0x0C, 0x00, 0x7A, 0xAE, 0x0C, 0x00, 0x8A,
0xAE, 0x0C, 0x00, 0x67, 0x97, 0x0C, 0x00,
0x8D, 0x97, 0x0C, 0x00])
rom.write_int16s(snes_to_pc(0x0FF1C8), [0x190F, 0x190F, 0x190F, 0x194C, 0x190F,
0x194B, 0x190F, 0x195C, 0x594B, 0x194C,
0x19EE, 0x19EE, 0x194B, 0x19EE, 0x19EE,
0x19EE, 0x594B, 0x190F, 0x595C, 0x190F,
0x190F, 0x195B, 0x190F, 0x190F, 0x19EE,
0x19EE, 0x195C, 0x19EE, 0x19EE, 0x19EE,
0x19EE, 0x595C, 0x595B, 0x190F, 0x190F,
0x190F])
rom.write_int16s(snes_to_pc(0x0FA480), [0x190F, 0x196B, 0x9D04, 0x9D04, 0x196B,
0x190F, 0x9D04, 0x9D04])
rom.write_int16s(snes_to_pc(0x1bb810), [0x00BE, 0x00C0, 0x013E])
rom.write_int16s(snes_to_pc(0x1bb836), [0x001B, 0x001B, 0x001B])
rom.write_int16(snes_to_pc(0x308300), 0x0140)
rom.write_int16(snes_to_pc(0x308320), 0x001B)
if world.shuffle == 'vanilla':
rom.write_byte(snes_to_pc(0x308340), 0x7B)
rom.write_int16(snes_to_pc(0x1af504), 0x148B)
rom.write_int16(snes_to_pc(0x1af50c), 0x149B)
rom.write_int16(snes_to_pc(0x1af514), 0x14A4)
rom.write_int16(snes_to_pc(0x1af51c), 0x1489)
rom.write_int16(snes_to_pc(0x1af524), 0x14AC)
rom.write_int16(snes_to_pc(0x1af52c), 0x54AC)
rom.write_int16(snes_to_pc(0x1af534), 0x148C)
rom.write_int16(snes_to_pc(0x1af53c), 0x548C)
rom.write_int16(snes_to_pc(0x1af544), 0x1484)
rom.write_int16(snes_to_pc(0x1af54c), 0x5484)
rom.write_int16(snes_to_pc(0x1af554), 0x14A2)
rom.write_int16(snes_to_pc(0x1af55c), 0x54A2)
rom.write_int16(snes_to_pc(0x1af564), 0x14A0)
rom.write_int16(snes_to_pc(0x1af56c), 0x54A0)
rom.write_int16(snes_to_pc(0x1af574), 0x148E)
rom.write_int16(snes_to_pc(0x1af57c), 0x548E)
rom.write_int16(snes_to_pc(0x1af584), 0x14AE)
rom.write_int16(snes_to_pc(0x1af58c), 0x54AE)
rom.write_byte(snes_to_pc(0x00DB9D), 0x1A) # castle hole graphics
rom.write_byte(snes_to_pc(0x00DC09), 0x1A)
rom.write_byte(snes_to_pc(0x00D009), 0x31)
rom.write_byte(snes_to_pc(0x00D0e8), 0xE0)
rom.write_byte(snes_to_pc(0x00D1c7), 0x00)
rom.write_int16(snes_to_pc(0x1BE8DA), 0x39AD)
rom.write_byte(0xF6E58, 0x80) # no whirlpool under castle gate
rom.write_bytes(0x0086E, [0x5C, 0x00, 0xA0, 0xA1]) # TR tail
rom.write_bytes(snes_to_pc(0x1BC67A), [0x2E, 0x0B, 0x82]) # add warps under rocks
rom.write_bytes(snes_to_pc(0x1BC81E), [0x94, 0x1D, 0x82])
rom.write_bytes(snes_to_pc(0x1BC655), [0x4A, 0x1D, 0x82])
rom.write_bytes(snes_to_pc(0x1BC80D), [0xB2, 0x0B, 0x82])
rom.write_bytes(snes_to_pc(0x1BC3DF), [0xD8, 0xD1])
rom.write_bytes(snes_to_pc(0x1BD1D8), [0xA8, 0x02, 0x82, 0xFF, 0xFF])
rom.write_bytes(snes_to_pc(0x1BC85A), [0x50, 0x0F, 0x82])
rom.write_int16(0xDB96F + 2 * 0x35, 0x001B) # move pyramid exit door
rom.write_int16(0xDBA71 + 2 * 0x35, 0x06A4)
if world.shuffle == 'vanilla':
rom.write_byte(0xDBB73 + 0x35, 0x36)
rom.write_byte(snes_to_pc(0x09D436), 0xF3) # remove castle gate warp
if world.shuffle == 'vanilla':
rom.write_int16(0x15AEE + 2 * 0x37, 0x0010) # pyramid exit to new hc area
rom.write_byte(0x15B8C + 0x37, 0x1B)
rom.write_int16(0x15BDB + 2 * 0x37, 0x0418)
rom.write_int16(0x15C79 + 2 * 0x37, 0x0679)
rom.write_int16(0x15D17 + 2 * 0x37, 0x06B4)
rom.write_int16(0x15DB5 + 2 * 0x37, 0x06C6)
rom.write_int16(0x15E53 + 2 * 0x37, 0x0738)
rom.write_int16(0x15EF1 + 2 * 0x37, 0x06E6)
rom.write_int16(0x15F8F + 2 * 0x37, 0x0733)
rom.write_byte(0x1602D + 0x37, 0x07)
rom.write_byte(0x1607C + 0x37, 0xF9)
rom.write_int16(0x160CB + 2 * 0x37, 0x0000)
rom.write_int16(0x16169 + 2 * 0x37, 0x0000)
rom.write_bytes(snes_to_pc(0x1BC387), [0xDD, 0xD1])
rom.write_bytes(snes_to_pc(0x1BD1DD), [0xA4, 0x06, 0x82, 0x9E, 0x06, 0x82, 0xFF, 0xFF])
rom.write_byte(0x180089, 0x01) # open TR after exit
rom.write_byte(snes_to_pc(0x0ABFBB), 0x90)
rom.write_byte(snes_to_pc(0x0280A6), 0xD0)
rom.write_bytes(snes_to_pc(0x06B2AB), [0xF0, 0xE1, 0x05])
def patch_shuffled_dark_sanc(world, rom, player):
dark_sanc_entrance = str(world.get_region('Inverted Dark Sanctuary', player).entrances[0].name)
room_id, ow_area, vram_loc, scroll_y, scroll_x, link_y, link_x, camera_y, camera_x, unknown_1, unknown_2, door_1, door_2 = door_addresses[dark_sanc_entrance][1]
if dark_sanc_entrance == 'Skull Woods Final Section':
link_y = 0x00F8
door_index = door_addresses[str(dark_sanc_entrance)][0]
rom.write_byte(0x180241, 0x01)
rom.write_byte(0x180248, door_index + 1)
rom.write_int16(0x180250, room_id)
rom.write_byte(0x180252, ow_area)
rom.write_int16s(0x180253, [vram_loc, scroll_y, scroll_x, link_y, link_x, camera_y, camera_x])
rom.write_bytes(0x180262, [unknown_1, unknown_2, 0x00])
InconvenientEntrances = {'Turtle Rock': 'Turtle Rock Main',
'Misery Mire': 'Misery Mire',
'Ice Palace': 'Ice Palace',