Patch from base J1.0 rom now.

This commit is contained in:
LLCoolDave 2017-06-03 14:20:39 +02:00
parent d0196cbe41
commit 7949da8d07
4 changed files with 54 additions and 4 deletions

View File

@ -1,7 +1,7 @@
from BaseClasses import World, CollectionState, Item
from Regions import create_regions
from EntranceShuffle import link_entrances
from Rom import patch_rom
from Rom import patch_rom, patch_base_rom
from Rules import set_rules
from Dungeons import fill_dungeons
from Items import ItemFactory
@ -77,6 +77,7 @@ def main(args, seed=None):
sprite = None
rom = bytearray(open(args.rom, 'rb').read())
patch_base_rom(rom)
patched_rom = patch_rom(world, rom, bytearray(logic_hash), args.quickswap, args.heartbeep, sprite)
outfilebase = 'ER_%s_%s_%s_%s' % (world.mode, world.goal, world.shuffle, world.seed)
@ -392,7 +393,7 @@ if __name__ == '__main__':
'Madness decouples entrances and exits from each other and shuffles them freely, only ensuring that no fake Light/Dark World happens and all locations are reachable.\n'
'Insanity is Madness without the world restrictions. Mirror and Pearl are provided early to ensure Filling algorithm works properly. Deal with Fake LW/DW at your discretion. Experimental.\n'
'The dungeon variants only mix up dungeons and keep the rest of the overworld vanilla.')
parser.add_argument('--rom', default='Base_Rom.sfc', help='Path to a VT21 standard normal difficulty rom to use as a base.')
parser.add_argument('--rom', default='Zelda no Densetsu - Kamigami no Triforce (Japan).sfc', help='Path to an ALttP JAP(1.0) rom to use as a base.')
parser.add_argument('--loglevel', default='info', const='info', nargs='?', choices=['error', 'info', 'warning', 'debug'], help='Select level of logging for output.')
parser.add_argument('--seed', help='Define seed number to generate.', type=int)
parser.add_argument('--count', help='Use to batch generate multiple seeds with same settings. If --seed is provided, it will be used for the first seed, then used to derive the next seed (i.e. generating 10 seeds with --seed given will produce the same 10 (different) roms each time).', type=int)

51
Rom.py
View File

@ -4,6 +4,12 @@ from Text import string_to_alttp_text, text_addresses, credits_addresses, string
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
import random
import json
import hashlib
import logging
JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = 'de0100dc53a8e755a0fa9a3f15f1d100'
def patch_rom(world, rom, hashtable, quickswap=False, beep='normal', sprite=None):
@ -187,6 +193,22 @@ def patch_rom(world, rom, hashtable, quickswap=False, beep='normal', sprite=None
# set Fountain bottle exchange items
write_byte(rom, 0x348FF, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x3D, 0x48][random.randint(0, 6)])
write_byte(rom, 0x3493B, [0x16, 0x2B, 0x2C, 0x2D, 0x3C, 0x3D, 0x48][random.randint(0, 6)])
# set Fat Fairy Bow/Sword prizes to be disappointing
write_byte(rom, 0x34914, 0x3A) # Bow and Arrow
write_byte(rom, 0x180028, 0x49) # Fighter Sword
# assorted fixes
write_byte(rom, 0x180030, 0x00) # Disable SRAM trace
write_byte(rom, 0x180036, 0x0A) # Rupoor negative value
# remove shield from uncle
write_bytes(rom, 0x6D253, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
write_bytes(rom, 0x6D25B, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
write_bytes(rom, 0x6D283, [0x00, 0x00, 0xf6, 0xff, 0x00, 0x0E])
write_bytes(rom, 0x6D28B, [0x00, 0x00, 0xf7, 0xff, 0x00, 0x0E])
write_bytes(rom, 0x6D2CB, [0x00, 0x00, 0xf6, 0xff, 0x02, 0x0E])
write_bytes(rom, 0x6D2FB, [0x00, 0x00, 0xf7, 0xff, 0x02, 0x0E])
write_bytes(rom, 0x6D313, [0x00, 0x00, 0xe4, 0xff, 0x08, 0x0E])
if world.swamp_patch_required:
# patch swamp: Need to enable permanent drain of water as dam or swamp were moved
@ -202,6 +224,7 @@ def patch_rom(world, rom, hashtable, quickswap=False, beep='normal', sprite=None
write_byte(rom, 0x4E3BB, 0xEB)
# disable open door sprites when exiting caves
# this does not seem to work completely yet
if world.shuffle not in ['default', 'dungeonssimple', 'dungeonsfull']:
for i in range(0x85):
write_byte(rom, 0x15274 + i, 0x00)
@ -268,8 +291,8 @@ def write_credits_string_to_rom(rom, target, string):
def write_strings(rom, world):
silverarrows = world.find_items('Silver Arrows')
silverarrow_hint = ('in %s?' % silverarrows[0].hint_text) if silverarrows else '?\nI think not!'
write_string_to_rom(rom, 'Ganon2', 'Did you find the silver arrows %s' % silverarrow_hint)
silverarrow_hint = (' %s?' % silverarrows[0].hint_text) if silverarrows else '?\nI think not!'
write_string_to_rom(rom, 'Ganon2', 'Did you find the silver arrows%s' % silverarrow_hint)
crystal5 = world.find_items('Crystal 5')[0]
crystal6 = world.find_items('Crystal 6')[0]
@ -320,3 +343,27 @@ def write_strings(rom, world):
fluteboyitem = world.get_location('Flute Boy').item
fluteboyitem_text = FluteBoy_texts[random.randint(0, len(FluteBoy_texts) - 1)] if fluteboyitem is None or fluteboyitem.fluteboy_credit_text is None else fluteboyitem.fluteboy_credit_text
write_credits_string_to_rom(rom, 'FluteBoy', fluteboyitem_text)
def patch_base_rom(rom):
# verify correct checksum of baserom
basemd5 = hashlib.md5()
basemd5.update(rom)
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
rom.extend(bytearray([0x00]*(2097152 - len(rom))))
# load randomizer patches
patches = json.load(open('romreset.json', 'r')) + json.load(open('base2current.json', 'r'))
for patch in patches:
if isinstance(patch, dict):
for baseaddress, values in patch.items():
write_bytes(rom, int(baseaddress), values)
# verify md5
patchedmd5 = hashlib.md5()
patchedmd5.update(rom)
if not RANDOMIZERBASEHASH == patchedmd5.hexdigest():
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.')

1
base2current.json Normal file

File diff suppressed because one or more lines are too long

1
romreset.json Normal file

File diff suppressed because one or more lines are too long