2017-05-25 15:47:15 +00:00
from Dungeons import dungeon_music_addresses
2017-11-05 04:06:00 +00:00
from Text import string_to_alttp_text , text_addresses , Credits
2017-05-25 13:58:35 +00:00
from Text import Uncle_texts , Ganon1_texts , PyramidFairy_texts , TavernMan_texts , Sahasrahla2_texts , Triforce_texts , Blind_texts , BombShop2_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
2017-05-25 10:09:50 +00:00
import random
2017-06-03 12:20:39 +00:00
import json
import hashlib
import logging
JAP10HASH = ' 03a63945398191337e896e5771f77173 '
2017-10-28 22:38:10 +00:00
RANDOMIZERBASEHASH = ' 1deebb05eccefd2ab68297c6e9c0d25f '
2017-05-25 10:09:50 +00:00
2017-07-14 12:37:34 +00:00
class JsonRom ( object ) :
def __init__ ( self ) :
self . patches = { }
def write_byte ( self , address , value ) :
self . patches [ str ( address ) ] = [ value ]
def write_bytes ( self , startaddress , values ) :
self . patches [ str ( startaddress ) ] = list ( values )
2017-11-19 01:43:37 +00:00
2017-11-11 21:25:56 +00:00
def write_int16_to_rom ( self , address , value ) :
self . write_bytes ( address , int16_as_bytes ( value ) )
2017-11-19 01:43:37 +00:00
2017-11-11 21:25:56 +00:00
def write_int32_to_rom ( self , address , value ) :
self . write_bytes ( address , int32_as_bytes ( value ) )
2017-07-14 12:37:34 +00:00
def write_to_file ( self , file ) :
json . dump ( [ self . patches ] , open ( file , ' w ' ) )
class LocalRom ( object ) :
def __init__ ( self , file ) :
self . buffer = bytearray ( open ( file , ' rb ' ) . read ( ) )
self . patch_base_rom ( )
def write_byte ( self , address , value ) :
self . buffer [ address ] = value
def write_bytes ( self , startaddress , values ) :
for i , value in enumerate ( values ) :
self . write_byte ( startaddress + i , value )
2017-11-11 21:25:56 +00:00
def write_int16_to_rom ( self , address , value ) :
self . write_bytes ( address , int16_as_bytes ( value ) )
2017-11-19 01:43:37 +00:00
2017-11-11 21:25:56 +00:00
def write_int32_to_rom ( self , address , value ) :
self . write_bytes ( address , int32_as_bytes ( value ) )
2017-07-14 12:37:34 +00:00
def write_to_file ( self , file ) :
with open ( file , ' wb ' ) as outfile :
outfile . write ( self . buffer )
def patch_base_rom ( self ) :
# verify correct checksum of baserom
basemd5 = hashlib . md5 ( )
basemd5 . update ( self . buffer )
if not JAP10HASH == basemd5 . hexdigest ( ) :
logging . getLogger ( ' ' ) . warning ( ' Supplied Base Rom does not match known MD5 for JAP(1.0) release. Will try to patch anyway. ' )
# extend to 2MB
self . buffer . extend ( bytearray ( [ 0x00 ] * ( 2097152 - len ( self . buffer ) ) ) )
# load randomizer patches
2017-11-23 17:38:28 +00:00
patches = json . load ( open ( ' data/base2current.json ' , ' r ' ) )
2017-07-14 12:37:34 +00:00
for patch in patches :
if isinstance ( patch , dict ) :
for baseaddress , values in patch . items ( ) :
self . write_bytes ( int ( baseaddress ) , values )
# verify md5
patchedmd5 = hashlib . md5 ( )
patchedmd5 . update ( self . buffer )
if not RANDOMIZERBASEHASH == patchedmd5 . hexdigest ( ) :
2017-11-04 18:23:57 +00:00
raise RuntimeError ( ' Provided Base Rom unsuitable for patching. Please provide a JAP(1.0) " Zelda no Densetsu - Kamigami no Triforce (Japan).sfc " rom to use as a base. ' )
2017-07-14 12:37:34 +00:00
def write_crc ( self ) :
2017-11-10 10:08:59 +00:00
crc = ( sum ( self . buffer [ : 0x7FDC ] + self . buffer [ 0x7FE0 : ] ) + 0x01FE ) & 0xFFFF
2017-07-14 12:37:34 +00:00
inv = crc ^ 0xFFFF
self . write_bytes ( 0x7FDC , [ inv & 0xFF , ( inv >> 8 ) & 0xFF , crc & 0xFF , ( crc >> 8 ) & 0xFF ] )
2017-11-11 21:25:56 +00:00
def int16_as_bytes ( value ) :
value = value & 0xFFFF
return [ value & 0xFF , ( value >> 8 ) & 0xFF ]
2017-11-19 01:43:37 +00:00
2017-11-11 21:25:56 +00:00
def int32_as_bytes ( value ) :
value = value & 0xFFFFFFFF
return [ value & 0xFF , ( value >> 8 ) & 0xFF , ( value >> 16 ) & 0xFF , ( value >> 24 ) & 0xFF ]
2017-07-14 12:37:34 +00:00
2017-08-01 17:43:46 +00:00
def patch_rom ( world , rom , hashtable , beep = ' normal ' , sprite = None ) :
2017-05-25 10:09:50 +00:00
# patch items
for location in world . get_locations ( ) :
itemid = location . item . code if location . item is not None else 0x5A
2017-06-17 12:40:37 +00:00
if itemid is None or location . address is None :
continue
2017-05-25 15:47:15 +00:00
locationaddress = location . address
if not location . crystal :
2017-11-04 18:23:57 +00:00
# Keys in their native dungeon should use the orignal item code for keys
2017-10-15 20:04:58 +00:00
if location . parent_region . dungeon :
2017-11-04 18:23:57 +00:00
dungeon = location . parent_region . dungeon
2017-11-10 10:08:59 +00:00
if location . item is not None and location . item . key and dungeon . is_dungeon_item ( location . item ) :
2017-11-04 18:23:57 +00:00
if location . item . type == " BigKey " :
itemid = 0x32
if location . item . type == " SmallKey " :
itemid = 0x24
2017-07-14 12:37:34 +00:00
rom . write_byte ( locationaddress , itemid )
2017-05-25 15:47:15 +00:00
else :
2017-05-25 10:09:50 +00:00
# crystals
for address , value in zip ( locationaddress , itemid ) :
2017-07-14 12:37:34 +00:00
rom . write_byte ( address , value )
2017-05-25 10:09:50 +00:00
# patch music
music_addresses = dungeon_music_addresses [ location . name ]
2017-10-28 22:34:37 +00:00
if world . keysanity :
music = random . choice ( [ 0x11 , 0x16 ] )
else :
music = 0x11 if ' Pendant ' in location . item . name else 0x16
2017-05-25 10:09:50 +00:00
for music_address in music_addresses :
2017-07-14 12:37:34 +00:00
rom . write_byte ( music_address , music )
2017-11-04 18:23:57 +00:00
2017-10-28 22:34:37 +00:00
if world . keysanity :
2017-11-04 18:23:57 +00:00
rom . write_byte ( 0x155C9 , random . choice ( [ 0x11 , 0x16 ] ) ) # Randomize GT music too in keysanity mode
2017-06-17 11:16:13 +00:00
2017-05-25 10:09:50 +00:00
# patch entrances
for region in world . regions :
for exit in region . exits :
if exit . target is not None :
2017-06-03 13:33:11 +00:00
addresses = [ exit . addresses ] if isinstance ( exit . addresses , int ) else exit . addresses
for address in addresses :
2017-07-14 12:37:34 +00:00
rom . write_byte ( address , exit . target )
2017-06-17 11:16:13 +00:00
2017-05-25 10:09:50 +00:00
# patch medallion requirements
if world . required_medallions [ 0 ] == ' Bombos ' :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180022 , 0x00 ) # requirement
rom . write_byte ( 0x4FF2 , 0x31 ) # sprite
rom . write_byte ( 0x50D1 , 0x80 )
rom . write_byte ( 0x51B0 , 0x00 )
2017-05-25 10:09:50 +00:00
elif world . required_medallions [ 0 ] == ' Quake ' :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180022 , 0x02 ) # requirement
rom . write_byte ( 0x4FF2 , 0x31 ) # sprite
rom . write_byte ( 0x50D1 , 0x88 )
rom . write_byte ( 0x51B0 , 0x00 )
2017-05-25 10:09:50 +00:00
if world . required_medallions [ 1 ] == ' Bombos ' :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180023 , 0x00 ) # requirement
rom . write_byte ( 0x5020 , 0x31 ) # sprite
rom . write_byte ( 0x50FF , 0x90 )
rom . write_byte ( 0x51DE , 0x00 )
2017-05-25 10:09:50 +00:00
elif world . required_medallions [ 1 ] == ' Ether ' :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180023 , 0x01 ) # requirement
rom . write_byte ( 0x5020 , 0x31 ) # sprite
rom . write_byte ( 0x50FF , 0x98 )
rom . write_byte ( 0x51DE , 0x00 )
2017-05-25 10:09:50 +00:00
# set open mode:
2017-06-24 16:48:03 +00:00
if world . mode in [ ' open ' , ' swordless ' ] :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180032 , 0x01 ) # open mode
2017-05-25 10:09:50 +00:00
# disable sword sprite from uncle
2017-07-14 12:37:34 +00:00
rom . write_bytes ( 0x6D263 , [ 0x00 , 0x00 , 0xf6 , 0xff , 0x00 , 0x0E ] )
rom . write_bytes ( 0x6D26B , [ 0x00 , 0x00 , 0xf6 , 0xff , 0x00 , 0x0E ] )
rom . write_bytes ( 0x6D293 , [ 0x00 , 0x00 , 0xf6 , 0xff , 0x00 , 0x0E ] )
rom . write_bytes ( 0x6D29B , [ 0x00 , 0x00 , 0xf7 , 0xff , 0x00 , 0x0E ] )
rom . write_bytes ( 0x6D2B3 , [ 0x00 , 0x00 , 0xf6 , 0xff , 0x02 , 0x0E ] )
rom . write_bytes ( 0x6D2BB , [ 0x00 , 0x00 , 0xf6 , 0xff , 0x02 , 0x0E ] )
rom . write_bytes ( 0x6D2E3 , [ 0x00 , 0x00 , 0xf7 , 0xff , 0x02 , 0x0E ] )
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 ] )
2017-05-25 10:09:50 +00:00
else :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180032 , 0x00 ) # standard mode
2017-06-03 13:46:05 +00:00
# set light cones
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180038 , 0x01 if world . sewer_light_cone else 0x00 )
rom . write_byte ( 0x180039 , 0x01 if world . light_world_light_cone else 0x00 )
rom . write_byte ( 0x18003A , 0x01 if world . dark_world_light_cone else 0x00 )
2017-05-25 10:09:50 +00:00
# handle difficulty
2017-06-04 12:44:23 +00:00
if world . difficulty == ' hard ' :
2017-05-25 10:09:50 +00:00
# Powdered Fairies Prize
2017-11-10 10:08:59 +00:00
rom . write_byte ( 0x36DD0 , 0xD8 ) # One Heart
# potion heal amount
rom . write_byte ( 0x180084 , 0x28 ) # Five Hearts
# potion magic restore amount
rom . write_byte ( 0x180085 , 0x40 ) # Half Magic
#Cape magic cost
rom . write_bytes ( 0x3ADA7 , [ 0x02 , 0x02 , 0x02 ] )
#Byrna residual magic cost
rom . write_bytes ( 0x3ADA7 , [ 0x08 , 0x08 , 0x08 ] )
#Disable catching fairies
rom . write_byte ( 0x34FD6 , 0x80 )
2017-11-11 21:25:56 +00:00
#Set overflow items for progressive equipment
rom . write_bytes ( 0x180090 , [ 0x03 , 0x47 , 0x02 , 0x47 , 0x01 , 0x47 , 0x02 , 0x47 ] )
#Make Blue Shield more expensive
rom . write_bytes ( 0xF73D2 , [ 0xFC , 0xFF ] )
rom . write_bytes ( 0xF73DA , [ 0x04 , 0x00 ] )
rom . write_bytes ( 0xF73E2 , [ 0x0C , 0x00 ] )
rom . write_byte ( 0xF73D6 , 0x31 )
rom . write_byte ( 0xF73DE , 0x30 )
rom . write_byte ( 0xF73E6 , 0x30 )
rom . write_byte ( 0xF7201 , 0x00 )
rom . write_byte ( 0xF71FF , 0x64 )
#Make Red Shield more expensive
rom . write_bytes ( 0xF73FA , [ 0xFC , 0xFF ] )
rom . write_bytes ( 0xF7402 , [ 0x04 , 0x00 ] )
rom . write_bytes ( 0xF740A , [ 0x0C , 0x00 ] )
rom . write_byte ( 0xF73FE , 0x33 )
rom . write_byte ( 0xF7406 , 0x33 )
rom . write_byte ( 0xF740E , 0x33 )
rom . write_byte ( 0xF7241 , 0x03 )
rom . write_byte ( 0xF723F , 0xE7 )
2017-11-10 10:08:59 +00:00
elif world . difficulty == ' expert ' :
# Powdered Fairies Prize
rom . write_byte ( 0x36DD0 , 0x79 ) # Bees
2017-05-25 10:09:50 +00:00
# potion heal amount
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180084 , 0x08 ) # One Heart
2017-05-25 10:09:50 +00:00
# potion magic restore amount
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180085 , 0x20 ) # Quarter Magic
2017-11-10 10:08:59 +00:00
#Cape magic cost
rom . write_bytes ( 0x3ADA7 , [ 0x02 , 0x02 , 0x02 ] )
#Byrna residual magic cost
rom . write_bytes ( 0x3ADA7 , [ 0x08 , 0x08 , 0x08 ] )
#Disable catching fairies
rom . write_byte ( 0x34FD6 , 0x80 )
2017-11-11 21:25:56 +00:00
#Set overflow items for progressive equipment
rom . write_bytes ( 0x180090 , [ 0x02 , 0x47 , 0x00 , 0x47 , 0x00 , 0x47 , 0x01 , 0x47 ] )
#Make Blue Shield more expensive
rom . write_bytes ( 0xF73D2 , [ 0xFC , 0xFF ] )
rom . write_bytes ( 0xF73DA , [ 0x04 , 0x00 ] )
rom . write_bytes ( 0xF73E2 , [ 0x0C , 0x00 ] )
rom . write_byte ( 0xF73D6 , 0x3C )
rom . write_byte ( 0xF73DE , 0x3C )
rom . write_byte ( 0xF73E6 , 0x3C )
rom . write_byte ( 0xF7201 , 0x27 )
rom . write_byte ( 0xF71FF , 0x06 )
#Make Red Shield more expensive
rom . write_bytes ( 0xF73FA , [ 0xFC , 0xFF ] )
rom . write_bytes ( 0xF7402 , [ 0x04 , 0x00 ] )
rom . write_bytes ( 0xF740A , [ 0x0C , 0x00 ] )
rom . write_byte ( 0xF73FE , 0x3C )
rom . write_byte ( 0xF7406 , 0x3C )
rom . write_byte ( 0xF740E , 0x3C )
rom . write_byte ( 0xF7241 , 0x27 )
rom . write_byte ( 0xF723F , 0x06 )
2017-11-10 10:08:59 +00:00
elif world . difficulty == ' insane ' :
# Powdered Fairies Prize
rom . write_byte ( 0x36DD0 , 0x79 ) # Bees
# potion heal amount
rom . write_byte ( 0x180084 , 0x00 ) # No healing
# potion magic restore amount
rom . write_byte ( 0x180085 , 0x00 ) # No healing
#Cape magic cost
rom . write_bytes ( 0x3ADA7 , [ 0x02 , 0x02 , 0x02 ] )
#Byrna residual magic cost
rom . write_bytes ( 0x3ADA7 , [ 0x08 , 0x08 , 0x08 ] )
#Disable catching fairies
rom . write_byte ( 0x34FD6 , 0x80 )
2017-11-11 21:25:56 +00:00
#Set overflow items for progressive equipment
rom . write_bytes ( 0x180090 , [ 0x02 , 0x47 , 0x00 , 0x47 , 0x00 , 0x47 , 0x01 , 0x47 ] )
#Make Blue Shield more expensive
rom . write_bytes ( 0xF73D2 , [ 0xFC , 0xFF ] )
rom . write_bytes ( 0xF73DA , [ 0x04 , 0x00 ] )
rom . write_bytes ( 0xF73E2 , [ 0x0C , 0x00 ] )
rom . write_byte ( 0xF73D6 , 0x3C )
rom . write_byte ( 0xF73DE , 0x3C )
rom . write_byte ( 0xF73E6 , 0x3C )
rom . write_byte ( 0xF7201 , 0x27 )
rom . write_byte ( 0xF71FF , 0x10 )
#Make Red Shield more expensive
rom . write_bytes ( 0xF73FA , [ 0xFC , 0xFF ] )
rom . write_bytes ( 0xF7402 , [ 0x04 , 0x00 ] )
rom . write_bytes ( 0xF740A , [ 0x0C , 0x00 ] )
rom . write_byte ( 0xF73FE , 0x3C )
rom . write_byte ( 0xF7406 , 0x3C )
rom . write_byte ( 0xF740E , 0x3C )
rom . write_byte ( 0xF7241 , 0x27 )
rom . write_byte ( 0xF723F , 0x10 )
2017-06-04 12:44:23 +00:00
else :
# Powdered Fairies Prize
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x36DD0 , 0xE3 ) # fairy
2017-06-04 12:44:23 +00:00
# potion heal amount
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180084 , 0xA0 ) # full
2017-06-04 12:44:23 +00:00
# potion magic restore amount
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180085 , 0x80 ) # full
2017-11-11 21:25:56 +00:00
#Set overflow items for progressive equipment
if world . goal == ' triforcehunt ' :
rom . write_bytes ( 0x180090 , [ 0x04 , 0x6C , 0x03 , 0x6C , 0x02 , 0x6C , 0x04 , 0x6C ] )
elif world . timer in [ ' timed ' , ' timed-countdown ' , ' timed-ohko ' ] :
rom . write_bytes ( 0x180090 , [ 0x04 , 0x5D , 0x03 , 0x5D , 0x02 , 0x5D , 0x04 , 0x5D ] )
else :
rom . write_bytes ( 0x180090 , [ 0x04 , 0x47 , 0x03 , 0x47 , 0x02 , 0x47 , 0x04 , 0x47 ] )
2017-05-25 10:09:50 +00:00
# set up game internal RNG seed
for i in range ( 1024 ) :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x178000 + i , random . randint ( 0 , 255 ) )
2017-05-25 10:09:50 +00:00
# shuffle prize packs
prizes = [ 0xD8 , 0xD8 , 0xD8 , 0xD8 , 0xD9 , 0xD8 , 0xD8 , 0xD9 , 0xDA , 0xD9 , 0xDA , 0xDB , 0xDA , 0xD9 , 0xDA , 0xDA , 0xE0 , 0xDF , 0xDF , 0xDA , 0xE0 , 0xDF , 0xD8 , 0xDF ,
0xDC , 0xDC , 0xDC , 0xDD , 0xDC , 0xDC , 0xDE , 0xDC , 0xE1 , 0xD8 , 0xE1 , 0xE2 , 0xE1 , 0xD8 , 0xE1 , 0xE2 , 0xDF , 0xD9 , 0xD8 , 0xE1 , 0xDF , 0xDC , 0xD9 , 0xD8 ,
0xD8 , 0xE3 , 0xE0 , 0xDB , 0xDE , 0xD8 , 0xDB , 0xE2 , 0xD9 , 0xDA , 0xDB , 0xD9 , 0xDB , 0xD9 , 0xDB ]
random . shuffle ( prizes )
# write tree pull prizes
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0xEFBD4 , prizes . pop ( ) )
rom . write_byte ( 0xEFBD5 , prizes . pop ( ) )
rom . write_byte ( 0xEFBD6 , prizes . pop ( ) )
2017-05-25 10:09:50 +00:00
# rupee crab prizes
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x329C8 , prizes . pop ( ) ) # first prize
rom . write_byte ( 0x329C4 , prizes . pop ( ) ) # final prize
2017-05-25 10:09:50 +00:00
# stunned enemy prize
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x37993 , prizes . pop ( ) )
2017-05-25 10:09:50 +00:00
# saved fish prize
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0xE82CC , prizes . pop ( ) )
2017-05-25 10:09:50 +00:00
# fill enemy prize packs
2017-07-14 12:37:34 +00:00
rom . write_bytes ( 0x37A78 , prizes )
2017-05-25 10:09:50 +00:00
# prize pack drop chances
2017-11-10 10:08:59 +00:00
if world . difficulty in [ ' hard ' , ' expert ' , ' insane ' ] :
2017-05-25 10:09:50 +00:00
droprates = [ 0x01 , 0x02 , 0x03 , 0x03 , 0x03 , 0x04 , 0x04 ] # 50%, 25%, 3* 12.5%, 2* 6.25%
2017-06-04 12:44:23 +00:00
else :
droprates = [ 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 ] # 50%
2017-05-25 10:09:50 +00:00
random . shuffle ( droprates )
2017-07-14 12:37:34 +00:00
rom . write_bytes ( 0x37A62 , droprates )
vanilla_prize_pack_assignment = [ 131 , 150 , 132 , 128 , 128 , 128 , 128 , 128 , 2 , 0 , 2 , 128 , 160 , 131 , 151 , 128 , 128 , 148 , 145 , 7 , 0 , 128 , 0 , 128 , 146 , 150 , 128 , 160 , 0 , 0 , 0 , 128 , 4 , 128 ,
130 , 6 , 6 , 0 , 0 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 0 , 0 , 128 , 128 , 144 , 128 , 145 , 145 ,
145 , 151 , 145 , 149 , 149 , 147 , 151 , 20 , 145 , 146 , 129 , 130 , 130 , 128 , 133 , 128 , 128 , 128 , 4 , 4 , 128 , 145 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 0 , 128 ,
128 , 130 , 138 , 128 , 128 , 128 , 128 , 146 , 145 , 128 , 130 , 129 , 129 , 128 , 129 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128 , 151 , 128 , 128 , 128 , 128 , 194 ,
128 , 21 , 21 , 23 , 6 , 0 , 128 , 0 , 192 , 19 , 64 , 0 , 2 , 6 , 16 , 20 , 0 , 0 , 64 , 0 , 0 , 0 , 0 , 19 , 70 , 17 , 128 , 128 , 0 , 0 , 0 , 16 , 0 , 0 , 0 , 22 , 22 , 22 , 129 , 135 , 130 ,
0 , 128 , 128 , 0 , 0 , 0 , 0 , 128 , 128 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 128 , 0 , 0 , 0 , 23 , 0 , 18 , 0 , 0 , 0 , 0 , 0 , 16 , 23 , 0 , 64 , 1 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 128 , 0 , 0 , 0 , 0 , 0 , 0 ]
2017-05-25 10:09:50 +00:00
2017-05-25 13:58:35 +00:00
# shuffle enemies to prize packs
2017-05-25 10:09:50 +00:00
for i in range ( 243 ) :
2017-07-14 12:37:34 +00:00
if vanilla_prize_pack_assignment [ i ] & 0x0F != 0x00 :
rom . write_byte ( 0x6B632 + i , ( vanilla_prize_pack_assignment [ i ] & 0xF0 ) | random . randint ( 1 , 7 ) )
2017-05-25 10:09:50 +00:00
# set bonk prizes
2017-07-14 12:37:34 +00:00
if world . shuffle_bonk_prizes :
bonk_prizes = [ 0x79 , 0xE3 , 0x79 , 0xAC , 0xAC , 0xE0 , 0xDC , 0xAC , 0xE3 , 0xE3 , 0xDA , 0xE3 , 0xDA , 0xD8 , 0xAC , 0xAC , 0xE3 , 0xD8 , 0xE3 , 0xE3 , 0xE3 , 0xE3 , 0xE3 , 0xE3 , 0xDC , 0xDB , 0xE3 , 0xDA , 0x79 , 0x79 , 0xE3 , 0xE3 ,
0xDA , 0x79 , 0xAC , 0xAC , 0x79 , 0xE3 , 0x79 , 0xAC , 0xAC , 0xE0 , 0xDC , 0xE3 , 0x79 , 0xDE , 0xE3 , 0xAC , 0xDB , 0x79 , 0xE3 , 0xD8 , 0xAC , 0x79 , 0xE3 , 0xDB , 0xDB , 0xE3 , 0xE3 , 0x79 , 0xD8 , 0xDD ]
bonk_addresses = [ 0x4CF6C , 0x4CFBA , 0x4CFE0 , 0x4CFFB , 0x4D018 , 0x4D01B , 0x4D028 , 0x4D03C , 0x4D059 , 0x4D07A , 0x4D09E , 0x4D0A8 , 0x4D0AB , 0x4D0AE , 0x4D0BE , 0x4D0DD ,
0x4D16A , 0x4D1E5 , 0x4D1EE , 0x4D20B , 0x4CBBF , 0x4CBBF , 0x4CC17 , 0x4CC1A , 0x4CC4A , 0x4CC4D , 0x4CC53 , 0x4CC69 , 0x4CC6F , 0x4CC7C , 0x4CCEF , 0x4CD51 ,
0x4CDC0 , 0x4CDC3 , 0x4CDC6 , 0x4CE37 , 0x4D2DE , 0x4D32F , 0x4D355 , 0x4D367 , 0x4D384 , 0x4D387 , 0x4D397 , 0x4D39E , 0x4D3AB , 0x4D3AE , 0x4D3D1 , 0x4D3D7 ,
0x4D3F8 , 0x4D416 , 0x4D420 , 0x4D423 , 0x4D42D , 0x4D449 , 0x4D48C , 0x4D4D9 , 0x4D4DC , 0x4D4E3 , 0x4D504 , 0x4D507 , 0x4D55E , 0x4D56A ]
random . shuffle ( bonk_prizes )
for prize , address in zip ( bonk_prizes , bonk_addresses ) :
rom . write_byte ( address , prize )
2017-05-25 10:09:50 +00:00
2017-05-25 15:52:31 +00:00
# set Fountain bottle exchange items
2017-11-11 21:25:56 +00:00
if world . difficulty in [ ' hard ' , ' expert ' , ' insane ' ] :
rom . write_byte ( 0x348FF , [ 0x16 , 0x2B , 0x2C , 0x2D , 0x3C , 0x48 ] [ random . randint ( 0 , 5 ) ] )
rom . write_byte ( 0x3493B , [ 0x16 , 0x2B , 0x2C , 0x2D , 0x3C , 0x48 ] [ random . randint ( 0 , 5 ) ] )
else :
rom . write_byte ( 0x348FF , [ 0x16 , 0x2B , 0x2C , 0x2D , 0x3C , 0x3D , 0x48 ] [ random . randint ( 0 , 6 ) ] )
rom . write_byte ( 0x3493B , [ 0x16 , 0x2B , 0x2C , 0x2D , 0x3C , 0x3D , 0x48 ] [ random . randint ( 0 , 6 ) ] )
2017-06-03 12:20:39 +00:00
# set Fat Fairy Bow/Sword prizes to be disappointing
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x34914 , 0x3A ) # Bow and Arrow
rom . write_byte ( 0x180028 , 0x49 ) # Fighter Sword
2017-08-01 15:25:08 +00:00
# enable Waterfall fairy chests
rom . write_bytes ( 0xE9AE , [ 0x14 , 0x01 ] )
rom . write_bytes ( 0xE9CF , [ 0x14 , 0x01 ] )
2017-08-03 21:45:14 +00:00
rom . write_bytes ( 0x1F714 , [ 225 , 0 , 16 , 172 , 13 , 41 , 154 , 1 , 88 , 152 , 15 , 17 , 177 , 97 , 252 , 77 , 129 , 32 , 218 , 2 , 44 , 225 , 97 , 252 , 190 , 129 , 97 , 177 , 98 , 84 , 218 , 2 ,
253 , 141 , 131 , 68 , 225 , 98 , 253 , 30 , 131 , 49 , 165 , 201 , 49 , 164 , 105 , 49 , 192 , 34 , 77 , 164 , 105 , 49 , 198 , 249 , 73 , 198 , 249 , 16 , 153 , 160 , 92 , 153 ,
162 , 11 , 152 , 96 , 13 , 232 , 192 , 85 , 232 , 192 , 11 , 146 , 0 , 115 , 152 , 96 , 254 , 105 , 0 , 152 , 163 , 97 , 254 , 107 , 129 , 254 , 171 , 133 , 169 , 200 , 97 , 254 ,
174 , 129 , 255 , 105 , 2 , 216 , 163 , 98 , 255 , 107 , 131 , 255 , 43 , 135 , 201 , 200 , 98 , 255 , 46 , 131 , 254 , 161 , 0 , 170 , 33 , 97 , 254 , 166 , 129 , 255 , 33 , 2 ,
202 , 33 , 98 , 255 , 38 , 131 , 187 , 35 , 250 , 195 , 35 , 250 , 187 , 43 , 250 , 195 , 43 , 250 , 187 , 83 , 250 , 195 , 83 , 250 , 176 , 160 , 61 , 152 , 19 , 192 , 152 , 82 ,
192 , 136 , 0 , 96 , 144 , 0 , 96 , 232 , 0 , 96 , 240 , 0 , 96 , 152 , 202 , 192 , 216 , 202 , 192 , 216 , 19 , 192 , 216 , 82 , 192 , 252 , 189 , 133 , 253 , 29 , 135 , 255 ,
255 , 255 , 255 , 240 , 255 , 128 , 46 , 97 , 14 , 129 , 14 , 255 , 255 ] )
2017-10-14 18:45:59 +00:00
# set Waterfall fairy prizes to be disappointing
rom . write_byte ( 0x348DB , 0x3A ) # Red Boomerang becomes Red Boomerang
rom . write_byte ( 0x348EB , 0x05 ) # Blue Shield becomes Blue Shield
2017-06-03 12:20:39 +00:00
2017-06-23 19:33:04 +00:00
# set swordless mode settings
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x18003F , 0x01 if world . mode == ' swordless ' else 0x00 ) # hammer can harm ganon
rom . write_byte ( 0x180040 , 0x01 if world . mode == ' swordless ' else 0x00 ) # open curtains
rom . write_byte ( 0x180041 , 0x01 if world . mode == ' swordless ' else 0x00 ) # swordless medallions
2017-07-17 01:06:21 +00:00
rom . write_byte ( 0x180043 , 0xFF if world . mode == ' swordless ' else 0x00 ) # starting sword for link
2017-10-14 18:45:59 +00:00
rom . write_byte ( 0x180044 , 0x01 if world . mode == ' swordless ' else 0x00 ) # hammer activates tablets
2017-06-23 19:33:04 +00:00
2017-06-04 11:10:22 +00:00
# set up clocks for timed modes
if world . clock_mode == ' off ' :
2017-07-14 12:37:34 +00:00
rom . write_bytes ( 0x180190 , [ 0x00 , 0x00 , 0x00 ] ) # turn off clock mode
2017-11-19 01:36:42 +00:00
rom . write_int32_to_rom ( 0x180200 , 0 ) # red clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x180204 , 0 ) # blue clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x180208 , 0 ) # green clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x18020C , 0 ) # starting time (in frames, sint32)
2017-06-04 11:10:22 +00:00
elif world . clock_mode == ' ohko ' :
2017-07-14 12:37:34 +00:00
rom . write_bytes ( 0x180190 , [ 0x01 , 0x02 , 0x01 ] ) # ohko timer with resetable timer functionality
2017-11-19 01:36:42 +00:00
rom . write_int32_to_rom ( 0x180200 , 0 ) # red clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x180204 , 0 ) # blue clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x180208 , 0 ) # green clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x18020C , 0 ) # starting time (in frames, sint32)
elif world . clock_mode == ' countdown-ohko ' :
rom . write_bytes ( 0x180190 , [ 0x01 , 0x02 , 0x01 ] ) # ohko timer with resetable timer functionality
rom . write_int32_to_rom ( 0x180200 , - 100 * 60 * 60 * 60 ) # red clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x180204 , 2 * 60 * 60 ) # blue clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x180208 , 4 * 60 * 60 ) # green clock adjustment time (in frames, sint32)
2017-11-12 02:19:29 +00:00
if world . difficulty == ' easy ' :
2017-11-19 01:36:42 +00:00
rom . write_int32_to_rom ( 0x18020C , 20 * 60 * 60 ) # starting time (in frames, sint32)
2017-11-12 02:19:29 +00:00
elif world . difficulty == ' normal ' :
2017-11-19 01:36:42 +00:00
rom . write_int32_to_rom ( 0x18020C , 10 * 60 * 60 ) # starting time (in frames, sint32)
2017-11-12 02:19:29 +00:00
else :
2017-11-19 01:36:42 +00:00
rom . write_int32_to_rom ( 0x18020C , 5 * 60 * 60 ) # starting time (in frames, sint32)
2017-06-04 11:10:22 +00:00
if world . clock_mode == ' stopwatch ' :
2017-07-14 12:37:34 +00:00
rom . write_bytes ( 0x180190 , [ 0x02 , 0x01 , 0x00 ] ) # set stopwatch mode
2017-11-19 01:36:42 +00:00
rom . write_int32_to_rom ( 0x180200 , - 2 * 60 * 60 ) # red clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x180204 , 2 * 60 * 60 ) # blue clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x180208 , 4 * 60 * 60 ) # green clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x18020C , 0 ) # starting time (in frames, sint32)
2017-06-04 11:10:22 +00:00
if world . clock_mode == ' countdown ' :
2017-07-14 12:37:34 +00:00
rom . write_bytes ( 0x180190 , [ 0x01 , 0x01 , 0x00 ] ) # set countdown, with no reset available
2017-11-19 01:36:42 +00:00
rom . write_int32_to_rom ( 0x180200 , - 2 * 60 * 60 ) # red clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x180204 , 2 * 60 * 60 ) # blue clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x180208 , 4 * 60 * 60 ) # green clock adjustment time (in frames, sint32)
rom . write_int32_to_rom ( 0x18020C , 40 * 60 * 60 ) # starting time (in frames, sint32)
2017-06-04 11:10:22 +00:00
# set up goals for treasure hunt
2017-07-14 12:37:34 +00:00
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 )
2017-06-04 11:10:22 +00:00
2017-06-03 12:20:39 +00:00
# assorted fixes
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180030 , 0x00 ) # Disable SRAM trace
rom . write_byte ( 0x180036 , 0x0A ) # Rupoor negative value
rom . write_byte ( 0x180169 , 0x01 if world . lock_aga_door_in_escape else 0x00 ) # Lock or unlock aga tower door during escape sequence.
2017-11-13 22:12:28 +00:00
rom . write_byte ( 0x180171 , 0x01 if world . ganon_at_pyramid else 0x00 ) # Enable respawning on pyramid after ganon death
2017-11-10 10:08:59 +00:00
rom . write_byte ( 0x180168 , 0x08 ) # Spike Cave Damage
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180086 , 0x00 if world . aga_randomness else 0x01 ) # set blue ball and ganon warp randomness
rom . write_byte ( 0x1800A1 , 0x01 ) # enable overworld screen transition draining for water level inside swamp
2017-07-17 16:04:24 +00:00
if world . goal in [ ' ganon ' ] :
2017-08-01 17:07:44 +00:00
rom . write_byte ( 0x18003E , 0x03 ) # make ganon invincible until all crystals and aga 2 are collected
elif world . goal in [ ' pedestal ' , ' triforcehunt ' ] :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x18003E , 0x01 ) # make ganon invincible
2017-06-23 19:33:04 +00:00
elif world . goal in [ ' dungeons ' ] :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x18003E , 0x02 ) # make ganon invincible until all dungeons are beat
2017-08-01 17:07:44 +00:00
elif world . goal in [ ' crystals ' ] :
rom . write_byte ( 0x18003E , 0x04 ) # make ganon invincible until all crystals
2017-10-28 22:34:37 +00:00
rom . write_byte ( 0x18016A , 0x01 if world . keysanity else 0x00 ) # free roaming item text boxes
rom . write_byte ( 0x18003B , 0x01 if world . keysanity else 0x00 ) # maps showing crystals on overworld
2017-11-04 18:23:57 +00:00
2017-10-28 22:34:37 +00:00
# compasses showing dungeon count
if world . clock_mode != ' off ' :
2017-11-04 18:23:57 +00:00
rom . write_byte ( 0x18003C , 0x00 ) # Currently must be off if timer is on, because they use same HUD location
2017-11-10 10:50:50 +00:00
elif world . difficulty == ' easy ' :
rom . write_byte ( 0x18003C , 0x02 ) # always on
2017-10-28 22:34:37 +00:00
elif world . keysanity :
2017-11-04 18:23:57 +00:00
rom . write_byte ( 0x18003C , 0x01 ) # show on pickup
2017-10-28 22:34:37 +00:00
else :
rom . write_byte ( 0x18003C , 0x00 )
2017-11-04 18:23:57 +00:00
2017-11-12 10:38:41 +00:00
rom . write_byte ( 0x180045 , 0xFF if world . keysanity else 0x00 ) # free roaming items in menu
2017-06-23 19:33:04 +00:00
digging_game_rng = random . randint ( 1 , 30 ) # set rng for digging game
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180020 , digging_game_rng )
rom . write_byte ( 0xEFD95 , digging_game_rng )
rom . write_byte ( 0x1800A3 , 0x01 ) # enable correct world setting behaviour after agahnim kills
rom . write_byte ( 0x180042 , 0x01 if world . save_and_quite_from_boss else 0x00 ) # Allow Save and Quite after boss kill
2017-06-03 12:20:39 +00:00
# remove shield from uncle
2017-07-14 12:37:34 +00:00
rom . write_bytes ( 0x6D253 , [ 0x00 , 0x00 , 0xf6 , 0xff , 0x00 , 0x0E ] )
rom . write_bytes ( 0x6D25B , [ 0x00 , 0x00 , 0xf6 , 0xff , 0x00 , 0x0E ] )
rom . write_bytes ( 0x6D283 , [ 0x00 , 0x00 , 0xf6 , 0xff , 0x00 , 0x0E ] )
rom . write_bytes ( 0x6D28B , [ 0x00 , 0x00 , 0xf7 , 0xff , 0x00 , 0x0E ] )
rom . write_bytes ( 0x6D2CB , [ 0x00 , 0x00 , 0xf6 , 0xff , 0x02 , 0x0E ] )
rom . write_bytes ( 0x6D2FB , [ 0x00 , 0x00 , 0xf7 , 0xff , 0x02 , 0x0E ] )
rom . write_bytes ( 0x6D313 , [ 0x00 , 0x00 , 0xe4 , 0xff , 0x08 , 0x0E ] )
2017-05-25 15:52:31 +00:00
2017-05-25 10:09:50 +00:00
if world . swamp_patch_required :
# patch swamp: Need to enable permanent drain of water as dam or swamp were moved
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x18003D , 0x01 )
2017-05-25 10:09:50 +00:00
# set correct flag for hera basement item
2017-10-29 03:42:35 +00:00
if world . get_location ( ' Tower of Hera - Basement Cage ' ) . item is not None and world . get_location ( ' Tower of Hera - Basement Cage ' ) . item . name == ' Small Key (Tower of Hera) ' :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x4E3BB , 0xE4 )
2017-05-25 10:09:50 +00:00
else :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x4E3BB , 0xEB )
2017-05-25 10:50:42 +00:00
2017-05-28 13:40:59 +00:00
# fix trock doors for reverse entrances
2017-06-17 11:16:13 +00:00
if world . fix_trock_doors :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0xFED31 , 0x0E ) # preopen bombable exit
rom . write_byte ( 0xFEE41 , 0x0E ) # preopen bombable exit
rom . write_byte ( 0xFE465 , 0x1E ) # remove small key door on backside of big key door
2017-05-28 13:40:59 +00:00
2017-06-24 17:11:00 +00:00
# Thanks to Zarby89 for finding these values
# fix skull woods exit point
if world . fix_skullwoods_exit :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x15E0D , 0xF8 )
2017-06-24 17:11:00 +00:00
# fix palace of darkness exit point
if world . fix_palaceofdarkness_exit :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x15E03 , 0x40 )
2017-06-24 17:11:00 +00:00
# fix turtle rock exit point
if world . fix_trock_exit :
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x15E1D , 0x34 )
2017-06-24 17:11:00 +00:00
2017-07-14 14:11:07 +00:00
# fix ganons tower exit point
if world . fix_gtower_exit :
rom . write_byte ( 0x15E25 , 0xA4 )
# todo fix screen scrolling
2017-11-04 18:23:57 +00:00
# enable instant item menu
if world . fastmenu :
2017-10-14 16:00:41 +00:00
rom . write_byte ( 0x180048 , 0x01 )
# Sound twekas for fastmenu:
rom . write_byte ( 0x6DD9A , 0x20 )
rom . write_byte ( 0x6DF2A , 0x20 )
rom . write_byte ( 0x6E0E9 , 0x20 )
2017-11-04 18:23:57 +00:00
2017-05-25 10:50:42 +00:00
# enable quick item swapping with L and R (ported by Amazing Ampharos)
2017-08-01 17:43:46 +00:00
if world . quickswap :
2017-07-14 12:37:34 +00:00
rom . write_bytes ( 0x107fb , [ 0x22 , 0x50 , 0xFF , 0x1F ] )
rom . write_bytes ( 0x12451 , [ 0x22 , 0x50 , 0xFF , 0x1F ] )
rom . write_bytes ( 0xfff50 , [ 0x20 , 0x58 , 0xFF , 0xA5 , 0xF6 , 0x29 , 0x40 , 0x6B , 0xA5 , 0xF6 , 0x89 , 0x10 , 0xF0 , 0x03 , 0x4C , 0x69 ,
2017-11-04 18:23:57 +00:00
0xFF , 0x89 , 0x20 , 0xF0 , 0x03 , 0x4C , 0xAA , 0xFF , 0x60 , 0xAD , 0x02 , 0x02 , 0xF0 , 0x3B , 0xDA , 0xAA ,
0xE0 , 0x0F , 0xF0 , 0x14 , 0xE0 , 0x10 , 0xF0 , 0x14 , 0xE0 , 0x14 , 0xD0 , 0x02 , 0xA2 , 0x00 , 0xE8 , 0xBF ,
0x3F , 0xF3 , 0x7E , 0xF0 , 0xEB , 0x4C , 0xEB , 0xFF , 0xA2 , 0x01 , 0x80 , 0x0A , 0xAF , 0x4F , 0xF3 , 0x7E ,
0xAA , 0xE0 , 0x04 , 0xF0 , 0x10 , 0xE8 , 0xBF , 0x5B , 0xF3 , 0x7E , 0xF0 , 0xF5 , 0x8A , 0x8F , 0x4F , 0xF3 ,
0x7E , 0xA2 , 0x10 , 0x80 , 0xE0 , 0xA2 , 0x11 , 0x80 , 0xD6 , 0x60 , 0xAD , 0x02 , 0x02 , 0xF0 , 0x3B , 0xDA ,
0xAA , 0xE0 , 0x11 , 0xF0 , 0x14 , 0xE0 , 0x10 , 0xF0 , 0x14 , 0xE0 , 0x01 , 0xD0 , 0x02 , 0xA2 , 0x15 , 0xCA ,
0xBF , 0x3F , 0xF3 , 0x7E , 0xF0 , 0xEB , 0x4C , 0xEB , 0xFF , 0xA2 , 0x04 , 0x80 , 0x0A , 0xAF , 0x4F , 0xF3 ,
0x7E , 0xAA , 0xE0 , 0x01 , 0xF0 , 0x10 , 0xCA , 0xBF , 0x5B , 0xF3 , 0x7E , 0xF0 , 0xF5 , 0x8A , 0x8F , 0x4F ,
0xF3 , 0x7E , 0xA2 , 0x10 , 0x80 , 0xE0 , 0xA2 , 0x0F , 0x80 , 0xD6 , 0x60 , 0xA9 , 0x20 , 0x8D , 0x2F , 0x01 ,
0x8E , 0x02 , 0x02 , 0x22 , 0x7F , 0xDB , 0x0D , 0xFA , 0x60 , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ] )
2017-05-25 10:50:42 +00:00
2017-05-25 13:58:35 +00:00
write_strings ( rom , world )
2017-05-25 10:09:50 +00:00
2017-05-25 15:47:15 +00:00
# set rom name
2017-05-30 05:33:23 +00:00
# 21 bytes
2017-11-12 02:19:29 +00:00
rom . write_bytes ( 0x7FC0 , bytearray ( ' ER_050_ %09d \0 ' % world . seed , ' utf8 ' ) + world . option_identifier . to_bytes ( 4 , ' big ' ) )
2017-05-25 15:47:15 +00:00
# set heart beep rate
2017-07-14 12:37:34 +00:00
rom . write_byte ( 0x180033 , { ' off ' : 0x00 , ' half ' : 0x40 , ' quarter ' : 0x80 , ' normal ' : 0x20 } [ beep ] )
2017-05-25 15:47:15 +00:00
2017-05-25 19:41:37 +00:00
# store hash table for main menu hash
2017-07-14 21:32:40 +00:00
rom . write_bytes ( 0x187F00 , hashtable )
2017-05-25 19:41:37 +00:00
2017-05-26 16:39:32 +00:00
# write link sprite if required
if sprite is not None :
2017-07-14 12:37:34 +00:00
write_sprite ( rom , sprite )
2017-05-25 10:09:50 +00:00
2017-07-14 12:37:34 +00:00
if isinstance ( rom , LocalRom ) :
rom . write_crc ( )
2017-05-25 10:09:50 +00:00
2017-07-14 12:37:34 +00:00
return rom
2017-05-25 10:09:50 +00:00
2017-07-14 12:37:34 +00:00
def write_sprite ( rom , sprite ) :
if len ( sprite ) == 0x7000 :
# sprite file with graphics and without palette data
rom . write_bytes ( 0x80000 , sprite [ : 0x7000 ] )
elif len ( sprite ) == 0x7078 :
# sprite file with graphics and palette data
rom . write_bytes ( 0x80000 , sprite [ : 0x7000 ] )
rom . write_bytes ( 0xDD308 , sprite [ 0x7000 : ] )
2017-07-14 15:47:34 +00:00
rom . write_bytes ( 0xDEDF5 , sprite [ 0x7036 : 0x7038 ] )
rom . write_bytes ( 0xDEDF7 , sprite [ 0x7054 : 0x7056 ] )
2017-07-14 12:37:34 +00:00
elif len ( sprite ) in [ 0x100000 , 0x200000 ] :
# full rom with patched sprite, extract it
rom . write_bytes ( 0x80000 , sprite [ 0x80000 : 0x87000 ] )
rom . write_bytes ( 0xDD308 , sprite [ 0xDD308 : 0xDD380 ] )
2017-07-14 15:47:34 +00:00
rom . write_bytes ( 0xDEDF5 , sprite [ 0xDEDF5 : 0xDEDF9 ] )
2017-05-25 10:09:50 +00:00
def write_string_to_rom ( rom , target , string ) :
address , maxbytes = text_addresses [ target ]
2017-07-14 12:37:34 +00:00
rom . write_bytes ( address , string_to_alttp_text ( string , maxbytes ) )
2017-05-25 13:58:35 +00:00
def write_strings ( rom , world ) :
2017-05-25 15:47:15 +00:00
silverarrows = world . find_items ( ' Silver Arrows ' )
2017-06-03 12:20:39 +00:00
silverarrow_hint = ( ' %s ? ' % silverarrows [ 0 ] . hint_text ) if silverarrows else ' ? \n I think not! '
write_string_to_rom ( rom , ' Ganon2 ' , ' Did you find the silver arrows %s ' % silverarrow_hint )
2017-05-25 15:47:15 +00:00
crystal5 = world . find_items ( ' Crystal 5 ' ) [ 0 ]
crystal6 = world . find_items ( ' Crystal 6 ' ) [ 0 ]
write_string_to_rom ( rom , ' BombShop1 ' , ' Big Bomb? \n My supply is blocked until you clear %s and %s . ' % ( crystal5 . hint_text , crystal6 . hint_text ) )
greenpendant = world . find_items ( ' Green Pendant ' ) [ 0 ]
write_string_to_rom ( rom , ' Sahasrahla1 ' , ' I lost my family heirloom in %s ' % greenpendant . hint_text )
2017-05-25 13:58:35 +00:00
write_string_to_rom ( rom , ' Uncle ' , Uncle_texts [ random . randint ( 0 , len ( Uncle_texts ) - 1 ) ] )
write_string_to_rom ( rom , ' Triforce ' , Triforce_texts [ random . randint ( 0 , len ( Triforce_texts ) - 1 ) ] )
write_string_to_rom ( rom , ' BombShop2 ' , BombShop2_texts [ random . randint ( 0 , len ( BombShop2_texts ) - 1 ) ] )
write_string_to_rom ( rom , ' PyramidFairy ' , PyramidFairy_texts [ random . randint ( 0 , len ( PyramidFairy_texts ) - 1 ) ] )
write_string_to_rom ( rom , ' Sahasrahla2 ' , Sahasrahla2_texts [ random . randint ( 0 , len ( Sahasrahla2_texts ) - 1 ) ] )
write_string_to_rom ( rom , ' Blind ' , Blind_texts [ random . randint ( 0 , len ( Blind_texts ) - 1 ) ] )
2017-08-01 17:07:44 +00:00
if world . goal in [ ' pedestal ' , ' triforcehunt ' ] :
2017-07-17 16:04:24 +00:00
write_string_to_rom ( rom , ' Ganon1Invincible ' , ' Why are you even here? \n You can \' t even hurt me! ' )
write_string_to_rom ( rom , ' Ganon2Invincible ' , ' Seriously? Go Away, I will not Die. ' )
2017-06-03 19:27:34 +00:00
else :
write_string_to_rom ( rom , ' Ganon1 ' , Ganon1_texts [ random . randint ( 0 , len ( Ganon1_texts ) - 1 ) ] )
2017-07-17 16:04:24 +00:00
write_string_to_rom ( rom , ' Ganon1Invincible ' , ' You cannot defeat me until you finish your goal! ' )
write_string_to_rom ( rom , ' Ganon2Invincible ' , ' Got wax in \n your ears? \n I can not die! ' )
2017-05-25 13:58:35 +00:00
write_string_to_rom ( rom , ' TavernMan ' , TavernMan_texts [ random . randint ( 0 , len ( TavernMan_texts ) - 1 ) ] )
2017-10-29 03:42:35 +00:00
pedestalitem = world . get_location ( ' Master Sword Pedestal ' ) . item
pedestal_text = ' Some Hot Air ' if pedestalitem is None else pedestalitem . pedestal_hint_text if pedestalitem . pedestal_hint_text is not None else ' Unknown Item '
write_string_to_rom ( rom , ' Pedestal ' , pedestal_text )
pedestal_credit_text = ' and the Hot Air ' if pedestalitem is None else pedestalitem . pedestal_credit_text if pedestalitem . pedestal_credit_text is not None else ' and the Unknown Item '
2017-05-25 13:58:35 +00:00
2017-07-14 21:32:40 +00:00
etheritem = world . get_location ( ' Ether Tablet ' ) . item
2017-10-29 03:42:35 +00:00
ether_text = ' Some Hot Air ' if etheritem is None else etheritem . pedestal_hint_text if etheritem . pedestal_hint_text is not None else ' Unknown Item '
2017-07-14 21:32:40 +00:00
write_string_to_rom ( rom , ' EtherTablet ' , ether_text )
bombositem = world . get_location ( ' Bombos Tablet ' ) . item
2017-10-29 03:42:35 +00:00
bombos_text = ' Some Hot Air ' if bombositem is None else bombositem . pedestal_hint_text if bombositem . pedestal_hint_text is not None else ' Unknown Item '
2017-07-14 21:32:40 +00:00
write_string_to_rom ( rom , ' BombosTablet ' , bombos_text )
2017-11-05 04:06:00 +00:00
credits = Credits ( )
2017-05-25 13:58:35 +00:00
sickkiditem = world . get_location ( ' Sick Kid ' ) . item
2017-11-05 04:06:00 +00:00
sickkiditem_text = random . choice ( SickKid_texts ) if sickkiditem is None or sickkiditem . sickkid_credit_text is None else sickkiditem . sickkid_credit_text
2017-11-04 18:23:57 +00:00
2017-05-25 13:58:35 +00:00
zoraitem = world . get_location ( ' King Zora ' ) . item
2017-11-05 04:06:00 +00:00
zoraitem_text = random . choice ( Zora_texts ) if zoraitem is None or zoraitem . zora_credit_text is None else zoraitem . zora_credit_text
2017-11-04 18:23:57 +00:00
2017-10-29 03:42:35 +00:00
magicshopitem = world . get_location ( ' Potion Shop ' ) . item
2017-11-05 04:06:00 +00:00
magicshopitem_text = random . choice ( MagicShop_texts ) if magicshopitem is None or magicshopitem . magicshop_credit_text is None else magicshopitem . magicshop_credit_text
2017-11-04 18:23:57 +00:00
2017-11-14 10:25:12 +00:00
fluteboyitem = world . get_location ( ' Flute Spot ' ) . item
2017-11-05 04:06:00 +00:00
fluteboyitem_text = random . choice ( FluteBoy_texts ) if fluteboyitem is None or fluteboyitem . fluteboy_credit_text is None else fluteboyitem . fluteboy_credit_text
credits . update_credits_line ( ' castle ' , 0 , random . choice ( KingsReturn_texts ) )
credits . update_credits_line ( ' sancturary ' , 0 , random . choice ( Sanctuary_texts ) )
credits . update_credits_line ( ' kakariko ' , 0 , random . choice ( Kakariko_texts ) )
credits . update_credits_line ( ' desert ' , 0 , random . choice ( DesertPalace_texts ) )
credits . update_credits_line ( ' hera ' , 0 , random . choice ( MountainTower_texts ) )
credits . update_credits_line ( ' house ' , 0 , random . choice ( LinksHouse_texts ) )
credits . update_credits_line ( ' zora ' , 0 , zoraitem_text )
credits . update_credits_line ( ' witch ' , 0 , magicshopitem_text )
credits . update_credits_line ( ' lumberjacks ' , 0 , random . choice ( Lumberjacks_texts ) )
credits . update_credits_line ( ' grove ' , 0 , fluteboyitem_text )
credits . update_credits_line ( ' well ' , 0 , random . choice ( WishingWell_texts ) )
credits . update_credits_line ( ' smithy ' , 0 , random . choice ( Blacksmiths_texts ) )
credits . update_credits_line ( ' kakariko2 ' , 0 , sickkiditem_text )
credits . update_credits_line ( ' bridge ' , 0 , random . choice ( DeathMountain_texts ) )
credits . update_credits_line ( ' woods ' , 0 , random . choice ( LostWoods_texts ) )
credits . update_credits_line ( ' pedestal ' , 0 , pedestal_credit_text )
( pointers , data ) = credits . get_bytes ( )
rom . write_bytes ( 0x181500 , data )
rom . write_bytes ( 0x76CC0 , [ byte for p in pointers for byte in [ p & 0xFF , p >> 8 & 0xFF ] ] )