Adjuster support
These are the basic adjuster files setting up for a new feature in the next release. Already randomized ROMs can be adjusted after the fact and have quickswap, fast menu, disable music, heartbeep rate, or a custom sprite applied or removed at the user's discretion with the checksum being properly updated. For now, the validity check for a randomized ROM is simply that it is exactly 2 MiB long and has a file name that ends in .sfc (while .smc is a valid SNES ROM file extension, no existing randomizer programs use it for output). This feature will need more updating with the new v28 features before it's ready for primetime; KevinCathcart's sprite selector will be an important part of this feature, and I believe variable speed fastmenu will be supported by the v28 base ROM so I'd want to make that selectable as well. For now, this should work as building blocks.
This commit is contained in:
parent
d9182a4adb
commit
704d9eb6c8
|
@ -0,0 +1,49 @@
|
|||
import argparse
|
||||
import os
|
||||
import logging
|
||||
import textwrap
|
||||
import sys
|
||||
|
||||
from AdjusterMain import adjust
|
||||
|
||||
class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter):
|
||||
|
||||
def _get_help_string(self, action):
|
||||
return textwrap.dedent(action.help)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
|
||||
|
||||
parser.add_argument('--rom', default='ER_base.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('--fastmenu', help='Enable instant menu', action='store_true')
|
||||
parser.add_argument('--quickswap', help='Enable quick item swapping with L and R.', action='store_true')
|
||||
parser.add_argument('--disablemusic', help='Disables game music.', action='store_true')
|
||||
parser.add_argument('--heartbeep', default='normal', const='normal', nargs='?', choices=['normal', 'half', 'quarter', 'off'],
|
||||
help='''\
|
||||
Select the rate at which the heart beep sound is played at
|
||||
low health. (default: %(default)s)
|
||||
''')
|
||||
parser.add_argument('--sprite', help='''\
|
||||
Path to a sprite sheet to use for Link. Needs to be in
|
||||
binary format and have a length of 0x7000 (28672) bytes,
|
||||
or 0x7078 (28792) bytes including palette data.
|
||||
Alternatively, can be a ALttP Rom patched with a Link
|
||||
sprite that will be extracted.
|
||||
''')
|
||||
args = parser.parse_args()
|
||||
|
||||
# ToDo: Validate files further than mere existance
|
||||
if not os.path.isfile(args.rom):
|
||||
input('Could not find valid base rom for patching at expected path %s. Please run with -h to see help for further information. \nPress Enter to exit.' % args.rom)
|
||||
sys.exit(1)
|
||||
if args.sprite is not None and not os.path.isfile(args.sprite):
|
||||
input('Could not find link sprite sheet at given location. \nPress Enter to exit.' % args.sprite)
|
||||
sys.exit(1)
|
||||
|
||||
# set up logger
|
||||
loglevel = {'error': logging.ERROR, 'info': logging.INFO, 'warning': logging.WARNING, 'debug': logging.DEBUG}[args.loglevel]
|
||||
logging.basicConfig(format='%(message)s', level=loglevel)
|
||||
|
||||
adjust(args=args)
|
|
@ -0,0 +1,286 @@
|
|||
from collections import OrderedDict
|
||||
from Utils import output_path
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
|
||||
class LocalRom(object):
|
||||
|
||||
def __init__(self, file):
|
||||
if (os.stat(file).st_size == 2097152 and os.path.splitext(file)[-1].lower() == '.sfc'):
|
||||
self.buffer = bytearray(open(file, 'rb').read())
|
||||
else:
|
||||
raise RuntimeError('Provided Rom is not a valid Link to the Past Randomizer Rom. Please provide one for adjusting.')
|
||||
|
||||
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)
|
||||
|
||||
def write_int16_to_rom(self, address, value):
|
||||
self.write_bytes(address, int16_as_bytes(value))
|
||||
|
||||
def write_int32_to_rom(self, address, value):
|
||||
self.write_bytes(address, int32_as_bytes(value))
|
||||
|
||||
def write_to_file(self, file):
|
||||
with open(file, 'wb') as outfile:
|
||||
outfile.write(self.buffer)
|
||||
|
||||
def write_crc(self):
|
||||
crc = (sum(self.buffer[:0x7FDC] + self.buffer[0x7FE0:]) + 0x01FE) & 0xFFFF
|
||||
inv = crc ^ 0xFFFF
|
||||
self.write_bytes(0x7FDC, [inv & 0xFF, (inv >> 8) & 0xFF, crc & 0xFF, (crc >> 8) & 0xFF])
|
||||
|
||||
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:])
|
||||
rom.write_bytes(0xDEDF5, sprite[0x7036:0x7038])
|
||||
rom.write_bytes(0xDEDF7, sprite[0x7054:0x7056])
|
||||
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])
|
||||
rom.write_bytes(0xDEDF5, sprite[0xDEDF5:0xDEDF9])
|
||||
|
||||
def patch_rom(rom, fastmenu=False, quickswap=False, disable_music=False, beep='normal', sprite=None):
|
||||
# enable instant item menu
|
||||
if fastmenu:
|
||||
rom.write_byte(0x180048, 0x01)
|
||||
# Sound twekas for fastmenu:
|
||||
rom.write_byte(0x6DD9A, 0x20)
|
||||
rom.write_byte(0x6DF2A, 0x20)
|
||||
rom.write_byte(0x6E0E9, 0x20)
|
||||
else:
|
||||
rom.write_byte(0x180048, 0x00)
|
||||
# Sound twekas for fastmenu:
|
||||
rom.write_byte(0x6DD9A, 0x11)
|
||||
rom.write_byte(0x6DF2A, 0x12)
|
||||
rom.write_byte(0x6E0E9, 0x12)
|
||||
|
||||
# enable quick item swapping with L and R (ported by Amazing Ampharos)
|
||||
if quickswap:
|
||||
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,
|
||||
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])
|
||||
else:
|
||||
rom.write_bytes(0x107fb, [0xa5, 0xf6, 0x29, 0x40])
|
||||
rom.write_bytes(0x12451, [0xa5, 0xf6, 0x29, 0x40])
|
||||
rom.write_bytes(0xfff50, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
||||
|
||||
if disable_music:
|
||||
volumeaddresses = [0xD373B, 0xD375B, 0xD90F8, 0xDA710, 0xDA7A4, 0xDA7BB, 0xDA7D2, 0xD5954, 0xD653B, 0xDA736, 0xDA752, 0xDA772, 0xDA792,
|
||||
0xD5B47, 0xD5B5E, 0xD4306, 0xD6878, 0xD6883, 0xD6E48, 0xD6E76, 0xD6EFB, 0xD6F2D, 0xDA211, 0xDA35B, 0xDA37B, 0xDA38E,
|
||||
0xDA39F, 0xDA5C3, 0xDA691, 0xDA6A8, 0xDA6DF, 0xD2349, 0xD3F45, 0xD42EB, 0xD48B9, 0xD48FF, 0xD543F, 0xD5817, 0xD5957,
|
||||
0xD5ACB, 0xD5AE8, 0xD5B4A, 0xDA5DE, 0xDA608, 0xDA635, 0xDA662, 0xDA71F, 0xDA7AF, 0xDA7C6, 0xDA7DD, 0xD2F00, 0xDA3D5,
|
||||
0xD249C, 0xD24CD, 0xD2C09, 0xD2C53, 0xD2CAF, 0xD2CEB, 0xD2D91, 0xD2EE6, 0xD38ED, 0xD3C91, 0xD3CD3, 0xD3CE8, 0xD3F0C,
|
||||
0xD3F82, 0xD405F, 0xD4139, 0xD4198, 0xD41D5, 0xD41F6, 0xD422B, 0xD4270, 0xD42B1, 0xD4334, 0xD4371, 0xD43A6, 0xD43DB,
|
||||
0xD441E, 0xD4597, 0xD4B3C, 0xD4BAB, 0xD4C03, 0xD4C53, 0xD4C7F, 0xD4D9C, 0xD5424, 0xD65D2, 0xD664F, 0xD6698, 0xD66FF,
|
||||
0xD6985, 0xD6C5C, 0xD6C6F, 0xD6C8E, 0xD6CB4, 0xD6D7D, 0xD827D, 0xD960C, 0xD9828, 0xDA233, 0xDA3A2, 0xDA49E, 0xDA72B,
|
||||
0xDA745, 0xDA765, 0xDA785, 0xDABF6, 0xDAC0D, 0xDAEBE, 0xDAFAC, 0xD9A02, 0xD9BD6, 0xD21CD, 0xD2279, 0xD2E66, 0xD2E70,
|
||||
0xD2EAB, 0xD3B97, 0xD3BAC, 0xD3BE8, 0xD3C0D, 0xD3C39, 0xD3C68, 0xD3C9F, 0xD3CBC, 0xD401E, 0xD4290, 0xD443E, 0xD456F,
|
||||
0xD47D3, 0xD4D43, 0xD4DCC, 0xD4EBA, 0xD4F0B, 0xD4FE5, 0xD5012, 0xD54BC, 0xD54D5, 0xD54F0, 0xD5509, 0xD57D8, 0xD59B9,
|
||||
0xD5A2F, 0xD5AEB, 0xD5E5E, 0xD5FE9, 0xD658F, 0xD674A, 0xD6827, 0xD69D6, 0xD69F5, 0xD6A05, 0xD6AE9, 0xD6DCF, 0xD6E20,
|
||||
0xD6ECB, 0xD71D4, 0xD71E6, 0xD7203, 0xD721E, 0xD8724, 0xD8732, 0xD9652, 0xD9698, 0xD9CBC, 0xD9DC0, 0xD9E49, 0xDAA68,
|
||||
0xDAA77, 0xDAA88, 0xDAA99, 0xDAF04, 0xD1D28, 0xD1D41, 0xD1D5C, 0xD1D77, 0xD1EEE, 0xD311D, 0xD31D1, 0xD4148, 0xD5543,
|
||||
0xD5B6F, 0xD65B3, 0xD6760, 0xD6B6B, 0xD6DF6, 0xD6E0D, 0xD73A1, 0xD814C, 0xD825D, 0xD82BE, 0xD8340, 0xD8394, 0xD842C,
|
||||
0xD8796, 0xD8903, 0xD892A, 0xD91E8, 0xD922B, 0xD92E0, 0xD937E, 0xD93C1, 0xDA958, 0xDA971, 0xDA98C, 0xDA9A7, 0xD1D92,
|
||||
0xD1DBD, 0xD1DEB, 0xD1F5D, 0xD1F9F, 0xD1FBD, 0xD1FDC, 0xD1FEA, 0xD20CA, 0xD21BB, 0xD22C9, 0xD2754, 0xD284C, 0xD2866,
|
||||
0xD2887, 0xD28A0, 0xD28BA, 0xD28DB, 0xD28F4, 0xD293E, 0xD2BF3, 0xD2C1F, 0xD2C69, 0xD2CA1, 0xD2CC5, 0xD2D05, 0xD2D73,
|
||||
0xD2DAF, 0xD2E3D, 0xD2F36, 0xD2F46, 0xD2F6F, 0xD2FCF, 0xD2FDF, 0xD302B, 0xD3086, 0xD3099, 0xD30A5, 0xD30CD, 0xD30F6,
|
||||
0xD3154, 0xD3184, 0xD333A, 0xD33D9, 0xD349F, 0xD354A, 0xD35E5, 0xD3624, 0xD363C, 0xD3672, 0xD3691, 0xD36B4, 0xD36C6,
|
||||
0xD3724, 0xD3767, 0xD38CB, 0xD3B1D, 0xD3B2F, 0xD3B55, 0xD3B70, 0xD3B81, 0xD3BBF, 0xD3D34, 0xD3D55, 0xD3D6E, 0xD3DC6,
|
||||
0xD3E04, 0xD3E38, 0xD3F65, 0xD3FA6, 0xD404F, 0xD4087, 0xD417A, 0xD41A0, 0xD425C, 0xD4319, 0xD433C, 0xD43EF, 0xD440C,
|
||||
0xD4452, 0xD4494, 0xD44B5, 0xD4512, 0xD45D1, 0xD45EF, 0xD4682, 0xD46C3, 0xD483C, 0xD4848, 0xD4855, 0xD4862, 0xD486F,
|
||||
0xD487C, 0xD4A1C, 0xD4A3B, 0xD4A60, 0xD4B27, 0xD4C7A, 0xD4D12, 0xD4D81, 0xD4E90, 0xD4ED6, 0xD4EE2, 0xD5005, 0xD502E,
|
||||
0xD503C, 0xD5081, 0xD51B1, 0xD51C7, 0xD51CF, 0xD51EF, 0xD520C, 0xD5214, 0xD5231, 0xD5257, 0xD526D, 0xD5275, 0xD52AF,
|
||||
0xD52BD, 0xD52CD, 0xD52DB, 0xD549C, 0xD5801, 0xD58A4, 0xD5A68, 0xD5A7F, 0xD5C12, 0xD5D71, 0xD5E10, 0xD5E9A, 0xD5F8B,
|
||||
0xD5FA4, 0xD651A, 0xD6542, 0xD65ED, 0xD661D, 0xD66D7, 0xD6776, 0xD68BD, 0xD68E5, 0xD6956, 0xD6973, 0xD69A8, 0xD6A51,
|
||||
0xD6A86, 0xD6B96, 0xD6C3E, 0xD6D4A, 0xD6E9C, 0xD6F80, 0xD717E, 0xD7190, 0xD71B9, 0xD811D, 0xD8139, 0xD816B, 0xD818A,
|
||||
0xD819E, 0xD81BE, 0xD829C, 0xD82E1, 0xD8306, 0xD830E, 0xD835E, 0xD83AB, 0xD83CA, 0xD83F0, 0xD83F8, 0xD844B, 0xD8479,
|
||||
0xD849E, 0xD84CB, 0xD84EB, 0xD84F3, 0xD854A, 0xD8573, 0xD859D, 0xD85B4, 0xD85CE, 0xD862A, 0xD8681, 0xD87E3, 0xD87FF,
|
||||
0xD887B, 0xD88C6, 0xD88E3, 0xD8944, 0xD897B, 0xD8C97, 0xD8CA4, 0xD8CB3, 0xD8CC2, 0xD8CD1, 0xD8D01, 0xD917B, 0xD918C,
|
||||
0xD919A, 0xD91B5, 0xD91D0, 0xD91DD, 0xD9220, 0xD9273, 0xD9284, 0xD9292, 0xD92AD, 0xD92C8, 0xD92D5, 0xD9311, 0xD9322,
|
||||
0xD9330, 0xD934B, 0xD9366, 0xD9373, 0xD93B6, 0xD97A6, 0xD97C2, 0xD97DC, 0xD97FB, 0xD9811, 0xD98FF, 0xD996F, 0xD99A8,
|
||||
0xD99D5, 0xD9A30, 0xD9A4E, 0xD9A6B, 0xD9A88, 0xD9AF7, 0xD9B1D, 0xD9B43, 0xD9B7C, 0xD9BA9, 0xD9C84, 0xD9C8D, 0xD9CAC,
|
||||
0xD9CE8, 0xD9CF3, 0xD9CFD, 0xD9D46, 0xDA35E, 0xDA37E, 0xDA391, 0xDA478, 0xDA4C3, 0xDA4D7, 0xDA4F6, 0xDA515, 0xDA6E2,
|
||||
0xDA9C2, 0xDA9ED, 0xDAA1B, 0xDAA57, 0xDABAF, 0xDABC9, 0xDABE2, 0xDAC28, 0xDAC46, 0xDAC63, 0xDACB8, 0xDACEC, 0xDAD08,
|
||||
0xDAD25, 0xDAD42, 0xDAD5F, 0xDAE17, 0xDAE34, 0xDAE51, 0xDAF2E, 0xDAF55, 0xDAF6B, 0xDAF81, 0xDB14F, 0xDB16B, 0xDB180,
|
||||
0xDB195, 0xDB1AA, 0xD2B88, 0xD364A, 0xD369F, 0xD3747, 0xD213F, 0xD2174, 0xD229E, 0xD2426, 0xD4731, 0xD4753, 0xD4774,
|
||||
0xD4795, 0xD47B6, 0xD4AA5, 0xD4AE4, 0xD4B96, 0xD4CA5, 0xD5477, 0xD5A3D, 0xD6566, 0xD672C, 0xD67C0, 0xD69B8, 0xD6AB1,
|
||||
0xD6C05, 0xD6DB3, 0xD71AB, 0xD8E2D, 0xD8F0D, 0xD94E0, 0xD9544, 0xD95A8, 0xD9982, 0xD9B56, 0xDA694, 0xDA6AB, 0xDAE88,
|
||||
0xDAEC8, 0xDAEE6, 0xDB1BF, 0xD210A, 0xD22DC, 0xD2447, 0xD5A4D, 0xD5DDC, 0xDA251, 0xDA26C, 0xD945E, 0xD967D, 0xD96C2,
|
||||
0xD9C95, 0xD9EE6, 0xDA5C6, 0xD2047, 0xD24C2, 0xD24EC, 0xD25A4, 0xD3DAA, 0xD51A8, 0xD51E6, 0xD524E, 0xD529E, 0xD6045,
|
||||
0xD81DE, 0xD821E, 0xD94AA, 0xD9A9E, 0xD9AE4, 0xDA289, 0xD2085, 0xD21C5, 0xD5F28]
|
||||
for address in volumeaddresses:
|
||||
rom.write_byte(address, 0x00)
|
||||
else:
|
||||
volumeaddresses1 = [0xD373B, 0xD375B, 0xD90F8]
|
||||
for address in volumeaddresses1:
|
||||
rom.write_byte(address, 0x00)
|
||||
volumeaddresses2 = [0xDA710, 0xDA7A4, 0xDA7BB, 0xDA7D2]
|
||||
for address in volumeaddresses2:
|
||||
rom.write_byte(address, 0x14)
|
||||
|
||||
volumeaddresses3 = [0xD5954, 0xD653B, 0xDA736, 0xDA752, 0xDA772, 0xDA792]
|
||||
for address in volumeaddresses3:
|
||||
rom.write_byte(address, 0x3C)
|
||||
|
||||
volumeaddresses4 = [0xD5B47, 0xD5B5E]
|
||||
for address in volumeaddresses4:
|
||||
rom.write_byte(address, 0x50)
|
||||
|
||||
rom.write_byte(0xD4306, 0x5A)
|
||||
|
||||
volumeaddresses5 = [0xD6878, 0xD6883, 0xD6E48, 0xD6E76, 0xD6EFB, 0xD6F2D, 0xDA211, 0xDA35B, 0xDA37B, 0xDA38E, 0xDA39F, 0xDA5C3, 0xDA691, 0xDA6A8, 0xDA6DF]
|
||||
for address in volumeaddresses5:
|
||||
rom.write_byte(address, 0x64)
|
||||
|
||||
volumeaddresses6 = [0xD2349, 0xD3F45, 0xD42EB, 0xD48B9, 0xD48FF, 0xD543F, 0xD5817, 0xD5957, 0xD5ACB, 0xD5AE8, 0xD5B4A, 0xDA5DE, 0xDA608, 0xDA635,
|
||||
0xDA662, 0xDA71F, 0xDA7AF, 0xDA7C6, 0xDA7DD]
|
||||
for address in volumeaddresses6:
|
||||
rom.write_byte(address, 0x78)
|
||||
|
||||
volumeaddresses7 = [0xD2F00, 0xDA3D5]
|
||||
for address in volumeaddresses7:
|
||||
rom.write_byte(address, 0x82)
|
||||
|
||||
volumeaddresses8 = [0xD249C, 0xD24CD, 0xD2C09, 0xD2C53, 0xD2CAF, 0xD2CEB, 0xD2D91, 0xD2EE6, 0xD38ED, 0xD3C91, 0xD3CD3, 0xD3CE8, 0xD3F0C,
|
||||
0xD3F82, 0xD405F, 0xD4139, 0xD4198, 0xD41D5, 0xD41F6, 0xD422B, 0xD4270, 0xD42B1, 0xD4334, 0xD4371, 0xD43A6, 0xD43DB,
|
||||
0xD441E, 0xD4597, 0xD4B3C, 0xD4BAB, 0xD4C03, 0xD4C53, 0xD4C7F, 0xD4D9C, 0xD5424, 0xD65D2, 0xD664F, 0xD6698, 0xD66FF,
|
||||
0xD6985, 0xD6C5C, 0xD6C6F, 0xD6C8E, 0xD6CB4, 0xD6D7D, 0xD827D, 0xD960C, 0xD9828, 0xDA233, 0xDA3A2, 0xDA49E, 0xDA72B,
|
||||
0xDA745, 0xDA765, 0xDA785, 0xDABF6, 0xDAC0D, 0xDAEBE, 0xDAFAC]
|
||||
for address in volumeaddresses8:
|
||||
rom.write_byte(address, 0xA0)
|
||||
|
||||
volumeaddresses9 = [0xD9A02, 0xD9BD6]
|
||||
for address in volumeaddresses9:
|
||||
rom.write_byte(address, 0xAA)
|
||||
|
||||
volumeaddressesA = [0xD21CD, 0xD2279, 0xD2E66, 0xD2E70, 0xD2EAB, 0xD3B97, 0xD3BAC, 0xD3BE8, 0xD3C0D, 0xD3C39, 0xD3C68, 0xD3C9F, 0xD3CBC,
|
||||
0xD401E, 0xD4290, 0xD443E, 0xD456F, 0xD47D3, 0xD4D43, 0xD4DCC, 0xD4EBA, 0xD4F0B, 0xD4FE5, 0xD5012, 0xD54BC, 0xD54D5,
|
||||
0xD54F0, 0xD5509, 0xD57D8, 0xD59B9, 0xD5A2F, 0xD5AEB, 0xD5E5E, 0xD5FE9, 0xD658F, 0xD674A, 0xD6827, 0xD69D6, 0xD69F5,
|
||||
0xD6A05, 0xD6AE9, 0xD6DCF, 0xD6E20, 0xD6ECB, 0xD71D4, 0xD71E6, 0xD7203, 0xD721E, 0xD8724, 0xD8732, 0xD9652, 0xD9698,
|
||||
0xD9CBC, 0xD9DC0, 0xD9E49, 0xDAA68, 0xDAA77, 0xDAA88, 0xDAA99, 0xDAF04]
|
||||
for address in volumeaddressesA:
|
||||
rom.write_byte(address, 0xB4)
|
||||
|
||||
volumeaddressesB = [0xD1D28, 0xD1D41, 0xD1D5C, 0xD1D77, 0xD1EEE, 0xD311D, 0xD31D1, 0xD4148, 0xD5543, 0xD5B6F, 0xD65B3, 0xD6760, 0xD6B6B,
|
||||
0xD6DF6, 0xD6E0D, 0xD73A1, 0xD814C, 0xD825D, 0xD82BE, 0xD8340, 0xD8394, 0xD842C, 0xD8796, 0xD8903, 0xD892A, 0xD91E8,
|
||||
0xD922B, 0xD92E0, 0xD937E, 0xD93C1, 0xDA958, 0xDA971, 0xDA98C, 0xDA9A7]
|
||||
for address in volumeaddressesB:
|
||||
rom.write_byte(address, 0x8C)
|
||||
|
||||
volumeaddressesC = [0xD1D92, 0xD1DBD, 0xD1DEB, 0xD1F5D, 0xD1F9F, 0xD1FBD, 0xD1FDC, 0xD1FEA, 0xD20CA, 0xD21BB, 0xD22C9, 0xD2754, 0xD284C,
|
||||
0xD2866, 0xD2887, 0xD28A0, 0xD28BA, 0xD28DB, 0xD28F4, 0xD293E, 0xD2BF3, 0xD2C1F, 0xD2C69, 0xD2CA1, 0xD2CC5, 0xD2D05,
|
||||
0xD2D73, 0xD2DAF, 0xD2E3D, 0xD2F36, 0xD2F46, 0xD2F6F, 0xD2FCF, 0xD2FDF, 0xD302B, 0xD3086, 0xD3099, 0xD30A5, 0xD30CD,
|
||||
0xD30F6, 0xD3154, 0xD3184, 0xD333A, 0xD33D9, 0xD349F, 0xD354A, 0xD35E5, 0xD3624, 0xD363C, 0xD3672, 0xD3691, 0xD36B4,
|
||||
0xD36C6, 0xD3724, 0xD3767, 0xD38CB, 0xD3B1D, 0xD3B2F, 0xD3B55, 0xD3B70, 0xD3B81, 0xD3BBF, 0xD3D34, 0xD3D55, 0xD3D6E,
|
||||
0xD3DC6, 0xD3E04, 0xD3E38, 0xD3F65, 0xD3FA6, 0xD404F, 0xD4087, 0xD417A, 0xD41A0, 0xD425C, 0xD4319, 0xD433C, 0xD43EF,
|
||||
0xD440C, 0xD4452, 0xD4494, 0xD44B5, 0xD4512, 0xD45D1, 0xD45EF, 0xD4682, 0xD46C3, 0xD483C, 0xD4848, 0xD4855, 0xD4862,
|
||||
0xD486F, 0xD487C, 0xD4A1C, 0xD4A3B, 0xD4A60, 0xD4B27, 0xD4C7A, 0xD4D12, 0xD4D81, 0xD4E90, 0xD4ED6, 0xD4EE2, 0xD5005,
|
||||
0xD502E, 0xD503C, 0xD5081, 0xD51B1, 0xD51C7, 0xD51CF, 0xD51EF, 0xD520C, 0xD5214, 0xD5231, 0xD5257, 0xD526D, 0xD5275,
|
||||
0xD52AF, 0xD52BD, 0xD52CD, 0xD52DB, 0xD549C, 0xD5801, 0xD58A4, 0xD5A68, 0xD5A7F, 0xD5C12, 0xD5D71, 0xD5E10, 0xD5E9A,
|
||||
0xD5F8B, 0xD5FA4, 0xD651A, 0xD6542, 0xD65ED, 0xD661D, 0xD66D7, 0xD6776, 0xD68BD, 0xD68E5, 0xD6956, 0xD6973, 0xD69A8,
|
||||
0xD6A51, 0xD6A86, 0xD6B96, 0xD6C3E, 0xD6D4A, 0xD6E9C, 0xD6F80, 0xD717E, 0xD7190, 0xD71B9, 0xD811D, 0xD8139, 0xD816B,
|
||||
0xD818A, 0xD819E, 0xD81BE, 0xD829C, 0xD82E1, 0xD8306, 0xD830E, 0xD835E, 0xD83AB, 0xD83CA, 0xD83F0, 0xD83F8, 0xD844B,
|
||||
0xD8479, 0xD849E, 0xD84CB, 0xD84EB, 0xD84F3, 0xD854A, 0xD8573, 0xD859D, 0xD85B4, 0xD85CE, 0xD862A, 0xD8681, 0xD87E3,
|
||||
0xD87FF, 0xD887B, 0xD88C6, 0xD88E3, 0xD8944, 0xD897B, 0xD8C97, 0xD8CA4, 0xD8CB3, 0xD8CC2, 0xD8CD1, 0xD8D01, 0xD917B,
|
||||
0xD918C, 0xD919A, 0xD91B5, 0xD91D0, 0xD91DD, 0xD9220, 0xD9273, 0xD9284, 0xD9292, 0xD92AD, 0xD92C8, 0xD92D5, 0xD9311,
|
||||
0xD9322, 0xD9330, 0xD934B, 0xD9366, 0xD9373, 0xD93B6, 0xD97A6, 0xD97C2, 0xD97DC, 0xD97FB, 0xD9811, 0xD98FF, 0xD996F,
|
||||
0xD99A8, 0xD99D5, 0xD9A30, 0xD9A4E, 0xD9A6B, 0xD9A88, 0xD9AF7, 0xD9B1D, 0xD9B43, 0xD9B7C, 0xD9BA9, 0xD9C84, 0xD9C8D,
|
||||
0xD9CAC, 0xD9CE8, 0xD9CF3, 0xD9CFD, 0xD9D46, 0xDA35E, 0xDA37E, 0xDA391, 0xDA478, 0xDA4C3, 0xDA4D7, 0xDA4F6, 0xDA515,
|
||||
0xDA6E2, 0xDA9C2, 0xDA9ED, 0xDAA1B, 0xDAA57, 0xDABAF, 0xDABC9, 0xDABE2, 0xDAC28, 0xDAC46, 0xDAC63, 0xDACB8, 0xDACEC,
|
||||
0xDAD08, 0xDAD25, 0xDAD42, 0xDAD5F, 0xDAE17, 0xDAE34, 0xDAE51, 0xDAF2E, 0xDAF55, 0xDAF6B, 0xDAF81, 0xDB14F, 0xDB16B,
|
||||
0xDB180, 0xDB195, 0xDB1AA]
|
||||
for address in volumeaddressesC:
|
||||
rom.write_byte(address, 0xC8)
|
||||
|
||||
volumeaddressesD = [0xD2B88, 0xD364A, 0xD369F, 0xD3747]
|
||||
for address in volumeaddressesD:
|
||||
rom.write_byte(address, 0xD2)
|
||||
|
||||
volumeaddressesE = [0xD213F, 0xD2174, 0xD229E, 0xD2426, 0xD4731, 0xD4753, 0xD4774, 0xD4795, 0xD47B6, 0xD4AA5, 0xD4AE4, 0xD4B96, 0xD4CA5,
|
||||
0xD5477, 0xD5A3D, 0xD6566, 0xD672C, 0xD67C0, 0xD69B8, 0xD6AB1, 0xD6C05, 0xD6DB3, 0xD71AB, 0xD8E2D, 0xD8F0D, 0xD94E0,
|
||||
0xD9544, 0xD95A8, 0xD9982, 0xD9B56, 0xDA694, 0xDA6AB, 0xDAE88, 0xDAEC8, 0xDAEE6, 0xDB1BF]
|
||||
for address in volumeaddressesE:
|
||||
rom.write_byte(address, 0xDC)
|
||||
|
||||
volumeaddressesF = [0xD210A, 0xD22DC, 0xD2447, 0xD5A4D, 0xD5DDC, 0xDA251, 0xDA26C]
|
||||
for address in volumeaddressesF:
|
||||
rom.write_byte(address, 0xE6)
|
||||
|
||||
volumeaddressesG = [0xD945E, 0xD967D, 0xD96C2, 0xD9C95, 0xD9EE6, 0xDA5C6]
|
||||
for address in volumeaddressesG:
|
||||
rom.write_byte(address, 0xF0)
|
||||
|
||||
volumeaddressesH = [0xD2047, 0xD24C2, 0xD24EC, 0xD25A4, 0xD3DAA, 0xD51A8, 0xD51E6, 0xD524E, 0xD529E, 0xD6045, 0xD81DE, 0xD821E, 0xD94AA,
|
||||
0xD9A9E, 0xD9AE4, 0xDA289]
|
||||
for address in volumeaddressesG:
|
||||
rom.write_byte(address, 0xFA)
|
||||
|
||||
volumeaddressesI = [0xD2085, 0xD21C5, 0xD5F28]
|
||||
for address in volumeaddressesI:
|
||||
rom.write_byte(address, 0xFF)
|
||||
|
||||
|
||||
# set heart beep rate
|
||||
rom.write_byte(0x180033, {'off': 0x00, 'half': 0x40, 'quarter': 0x80, 'normal': 0x20}[beep])
|
||||
|
||||
# write link sprite if required
|
||||
if sprite is not None:
|
||||
write_sprite(rom, sprite)
|
||||
|
||||
if isinstance(rom, LocalRom):
|
||||
rom.write_crc()
|
||||
|
||||
return rom
|
||||
|
||||
def adjust(args):
|
||||
start = time.clock()
|
||||
logger = logging.getLogger('')
|
||||
logger.info('Patching ROM.')
|
||||
|
||||
if args.sprite is not None:
|
||||
sprite = bytearray(open(args.sprite, 'rb').read())
|
||||
else:
|
||||
sprite = None
|
||||
|
||||
outfilebase = 'ER_adjusted'
|
||||
|
||||
rom = LocalRom(args.rom)
|
||||
patch_rom(rom, args.fastmenu, args.quickswap, args.disablemusic, args.heartbeep, sprite)
|
||||
|
||||
rom.write_to_file(output_path('%s.sfc' % outfilebase))
|
||||
|
||||
logger.info('Done. Enjoy.')
|
||||
logger.debug('Total Time: %s' % (time.clock() - start))
|
||||
|
||||
return args
|
106
Gui.py
106
Gui.py
|
@ -1,11 +1,12 @@
|
|||
from Main import main, __version__ as ESVersion
|
||||
from AdjusterMain import adjust
|
||||
from Utils import is_bundled, local_path, output_path, open_file
|
||||
from argparse import Namespace
|
||||
import random
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
from tkinter import Checkbutton, OptionMenu, Tk, LEFT, RIGHT, BOTTOM, TOP, StringVar, IntVar, Frame, Label, W, E, X, Entry, Spinbox, Button, filedialog, messagebox, PhotoImage
|
||||
from tkinter import Checkbutton, OptionMenu, Tk, LEFT, RIGHT, BOTTOM, TOP, StringVar, IntVar, Frame, Label, W, E, X, Entry, Spinbox, Button, filedialog, messagebox, PhotoImage, ttk
|
||||
|
||||
|
||||
def guiMain(args=None):
|
||||
|
@ -14,7 +15,14 @@ def guiMain(args=None):
|
|||
|
||||
set_icon(mainWindow)
|
||||
|
||||
topFrame = Frame(mainWindow)
|
||||
notebook = ttk.Notebook(mainWindow)
|
||||
randomizerWindow = ttk.Frame(notebook)
|
||||
adjustWindow = ttk.Frame(notebook)
|
||||
notebook.add(randomizerWindow, text='Randomize')
|
||||
notebook.add(adjustWindow, text='Adjust')
|
||||
notebook.pack()
|
||||
|
||||
topFrame = Frame(randomizerWindow)
|
||||
rightHalfFrame = Frame(topFrame)
|
||||
checkBoxFrame = Frame(rightHalfFrame)
|
||||
|
||||
|
@ -168,8 +176,8 @@ def guiMain(args=None):
|
|||
shuffleFrame.pack(expand=True, anchor=E)
|
||||
heartbeepFrame.pack(expand=True, anchor=E)
|
||||
|
||||
bottomFrame = Frame(mainWindow)
|
||||
farBottomFrame = Frame(mainWindow)
|
||||
bottomFrame = Frame(randomizerWindow)
|
||||
farBottomFrame = Frame(randomizerWindow)
|
||||
|
||||
seedLabel = Label(bottomFrame, text='Seed #')
|
||||
seedVar = StringVar()
|
||||
|
@ -243,6 +251,96 @@ def guiMain(args=None):
|
|||
farBottomFrame.pack(side=BOTTOM, fill=X, padx=5, pady=5)
|
||||
bottomFrame.pack(side=BOTTOM)
|
||||
|
||||
topFrame2 = Frame(adjustWindow)
|
||||
rightHalfFrame2 = Frame(topFrame2)
|
||||
checkBoxFrame2 = Frame(rightHalfFrame2)
|
||||
|
||||
quickSwapVar2 = IntVar()
|
||||
quickSwapCheckbutton2 = Checkbutton(checkBoxFrame2, text="Enabled L/R Item quickswapping", variable=quickSwapVar2)
|
||||
fastMenuVar2 = IntVar()
|
||||
fastMenuCheckbutton2 = Checkbutton(checkBoxFrame2, text="Enable instant menu", variable=fastMenuVar2)
|
||||
disableMusicVar2 = IntVar()
|
||||
disableMusicCheckbutton2 = Checkbutton(checkBoxFrame2, text="Disable game music", variable=disableMusicVar2)
|
||||
|
||||
quickSwapCheckbutton2.pack(expand=True, anchor=W)
|
||||
fastMenuCheckbutton2.pack(expand=True, anchor=W)
|
||||
disableMusicCheckbutton2.pack(expand=True, anchor=W)
|
||||
|
||||
fileDialogFrame2 = Frame(rightHalfFrame2)
|
||||
|
||||
romDialogFrame2 = Frame(fileDialogFrame2)
|
||||
baseRomLabel2 = Label(romDialogFrame2, text='Rom to adjust')
|
||||
romVar2 = StringVar()
|
||||
romEntry2 = Entry(romDialogFrame2, textvariable=romVar2)
|
||||
|
||||
def RomSelect2():
|
||||
rom = filedialog.askopenfilename()
|
||||
romVar2.set(rom)
|
||||
romSelectButton2 = Button(romDialogFrame2, text='Select Rom', command=RomSelect2)
|
||||
|
||||
baseRomLabel2.pack(side=LEFT)
|
||||
romEntry2.pack(side=LEFT)
|
||||
romSelectButton2.pack(side=LEFT)
|
||||
|
||||
spriteDialogFrame2 = Frame(fileDialogFrame2)
|
||||
baseSpriteLabel2 = Label(spriteDialogFrame2, text='Link Sprite')
|
||||
spriteVar2 = StringVar()
|
||||
spriteEntry2 = Entry(spriteDialogFrame2, textvariable=spriteVar2)
|
||||
|
||||
def SpriteSelect2():
|
||||
sprite = filedialog.askopenfilename()
|
||||
spriteVar2.set(sprite)
|
||||
|
||||
spriteSelectButton2 = Button(spriteDialogFrame2, text='Select Sprite', command=SpriteSelect2)
|
||||
|
||||
baseSpriteLabel2.pack(side=LEFT)
|
||||
spriteEntry2.pack(side=LEFT)
|
||||
spriteSelectButton2.pack(side=LEFT)
|
||||
|
||||
romDialogFrame2.pack()
|
||||
spriteDialogFrame2.pack()
|
||||
|
||||
checkBoxFrame2.pack()
|
||||
fileDialogFrame2.pack()
|
||||
|
||||
drowDownFrame2 = Frame(topFrame2)
|
||||
|
||||
heartbeepFrame2 = Frame(drowDownFrame2)
|
||||
heartbeepVar2 = StringVar()
|
||||
heartbeepVar2.set('normal')
|
||||
heartbeepOptionMenu2 = OptionMenu(heartbeepFrame2, heartbeepVar2, 'normal', 'half', 'quarter', 'off')
|
||||
heartbeepOptionMenu2.pack(side=RIGHT)
|
||||
heartbeepLabel2 = Label(heartbeepFrame2, text='Heartbeep sound rate')
|
||||
heartbeepLabel2.pack(side=LEFT)
|
||||
|
||||
heartbeepFrame2.pack(expand=True, anchor=E)
|
||||
|
||||
bottomFrame2 = Frame(topFrame2)
|
||||
|
||||
def adjustRom():
|
||||
guiargs = Namespace
|
||||
guiargs.heartbeep = heartbeepVar2.get()
|
||||
guiargs.fastmenu = bool(fastMenuVar2.get())
|
||||
guiargs.quickswap = bool(quickSwapVar2.get())
|
||||
guiargs.disablemusic = bool(disableMusicVar2.get())
|
||||
guiargs.rom = romVar2.get()
|
||||
guiargs.sprite = spriteVar2.get() if spriteVar2.get() else None
|
||||
try:
|
||||
adjust(args=guiargs)
|
||||
except Exception as e:
|
||||
messagebox.showerror(title="Error while creating seed", message=str(e))
|
||||
else:
|
||||
messagebox.showinfo(title="Success", message="Rom patched successfully")
|
||||
|
||||
adjustButton = Button(bottomFrame2, text='Adjust Rom', command=adjustRom)
|
||||
|
||||
adjustButton.pack(side=LEFT, padx=(5,0))
|
||||
|
||||
drowDownFrame2.pack(side=LEFT, pady=(0,40))
|
||||
rightHalfFrame2.pack(side=RIGHT)
|
||||
topFrame2.pack(side=TOP, pady=30)
|
||||
bottomFrame2.pack(side=BOTTOM, pady=(180,0))
|
||||
|
||||
if args is not None:
|
||||
# load values from commandline args
|
||||
createSpoilerVar.set(int(args.create_spoiler))
|
||||
|
|
Loading…
Reference in New Issue