| 
									
										
										
										
											2018-01-01 13:11:11 -05:00
										 |  |  | #!/usr/bin/env python3 | 
					
						
							| 
									
										
										
										
											2017-12-12 08:17:52 -06:00
										 |  |  | import argparse | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import logging | 
					
						
							|  |  |  | import textwrap | 
					
						
							|  |  |  | import sys | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  | import time | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  | from tkinter import Tk | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from Gui import update_sprites | 
					
						
							|  |  |  | from GuiUtils import BackgroundTaskProgress | 
					
						
							| 
									
										
										
										
											2017-12-12 08:17:52 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 20:15:07 +01:00
										 |  |  | from worlds.alttp.Rom import Sprite, LocalRom, apply_rom_settings | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  | from Utils import output_path | 
					
						
							| 
									
										
										
										
											2017-12-12 08:17:52 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-27 07:12:08 -07:00
										 |  |  | class AdjusterWorld(object): | 
					
						
							|  |  |  |     def __init__(self, sprite_pool): | 
					
						
							|  |  |  |         import random | 
					
						
							|  |  |  |         self.sprite_pool = {1: sprite_pool} | 
					
						
							|  |  |  |         self.rom_seeds = {1: random} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 08:17:52 -06:00
										 |  |  | class ArgumentDefaultsHelpFormatter(argparse.RawTextHelpFormatter): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _get_help_string(self, action): | 
					
						
							|  |  |  |         return textwrap.dedent(action.help) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 00:25:46 -05:00
										 |  |  | def main(): | 
					
						
							| 
									
										
										
										
											2017-12-12 08:17:52 -06:00
										 |  |  |     parser = argparse.ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-24 13:45:28 +02:00
										 |  |  |     parser.add_argument('--rom', default='ER_base.sfc', help='Path to an ALttP rom to adjust.') | 
					
						
							|  |  |  |     parser.add_argument('--baserom', default='Zelda no Densetsu - Kamigami no Triforce (Japan).sfc', | 
					
						
							|  |  |  |                         help='Path to an ALttP JAP(1.0) rom to use as a base.') | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  |     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', default='normal', const='normal', nargs='?', | 
					
						
							|  |  |  |                         choices=['normal', 'instant', 'double', 'triple', 'quadruple', 'half'], | 
					
						
							| 
									
										
										
										
											2018-01-05 16:53:29 -06:00
										 |  |  |                         help='''\
 | 
					
						
							|  |  |  |                              Select the rate at which the menu opens and closes. | 
					
						
							|  |  |  |                              (default: %(default)s) | 
					
						
							|  |  |  |                              ''')
 | 
					
						
							| 
									
										
										
										
											2017-12-12 08:17:52 -06:00
										 |  |  |     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') | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  |     parser.add_argument('--triforcehud', default='hide_goal', const='hide_goal', nargs='?', | 
					
						
							|  |  |  |                         choices=['normal', 'hide_goal', 'hide_required', 'hide_both'], | 
					
						
							|  |  |  |                         help='''\
 | 
					
						
							| 
									
										
										
										
											2021-01-29 15:42:00 -06:00
										 |  |  |                             Hide the triforce hud in certain circumstances. | 
					
						
							| 
									
										
										
										
											2021-02-05 20:37:27 -06:00
										 |  |  |                             hide_goal will hide the hud until finding a triforce piece, hide_required will hide the total amount needed to win | 
					
						
							|  |  |  |                             (Both can be revealed when speaking to Murahalda) | 
					
						
							| 
									
										
										
										
											2021-01-29 15:42:00 -06:00
										 |  |  |                             (default: %(default)s) | 
					
						
							|  |  |  |                             ''')
 | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  |     parser.add_argument('--enableflashing', | 
					
						
							|  |  |  |                         help='Reenable flashing animations (unfriendly to epilepsy, always disabled in race roms)', | 
					
						
							|  |  |  |                         action='store_false', dest="reduceflashing") | 
					
						
							|  |  |  |     parser.add_argument('--heartbeep', default='normal', const='normal', nargs='?', | 
					
						
							|  |  |  |                         choices=['double', 'normal', 'half', 'quarter', 'off'], | 
					
						
							| 
									
										
										
										
											2017-12-12 08:17:52 -06:00
										 |  |  |                         help='''\
 | 
					
						
							|  |  |  |                              Select the rate at which the heart beep sound is played at | 
					
						
							|  |  |  |                              low health. (default: %(default)s) | 
					
						
							|  |  |  |                              ''')
 | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  |     parser.add_argument('--heartcolor', default='red', const='red', nargs='?', | 
					
						
							|  |  |  |                         choices=['red', 'blue', 'green', 'yellow', 'random'], | 
					
						
							| 
									
										
										
										
											2018-02-27 20:26:33 -06:00
										 |  |  |                         help='Select the color of Link\'s heart meter. (default: %(default)s)') | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  |     parser.add_argument('--ow_palettes', default='default', | 
					
						
							|  |  |  |                         choices=['default', 'random', 'blackout', 'puke', 'classic', 'grayscale', 'negative', 'dizzy', | 
					
						
							|  |  |  |                                  'sick']) | 
					
						
							|  |  |  |     parser.add_argument('--link_palettes', default='default', | 
					
						
							|  |  |  |                         choices=['default', 'random', 'blackout', 'puke', 'classic', 'grayscale', 'negative', 'dizzy', | 
					
						
							|  |  |  |                                  'sick']) | 
					
						
							|  |  |  |     parser.add_argument('--shield_palettes', default='default', | 
					
						
							|  |  |  |                         choices=['default', 'random', 'blackout', 'puke', 'classic', 'grayscale', 'negative', 'dizzy', | 
					
						
							|  |  |  |                                  'sick']) | 
					
						
							|  |  |  |     parser.add_argument('--sword_palettes', default='default', | 
					
						
							|  |  |  |                         choices=['default', 'random', 'blackout', 'puke', 'classic', 'grayscale', 'negative', 'dizzy', | 
					
						
							|  |  |  |                                  'sick']) | 
					
						
							|  |  |  |     parser.add_argument('--hud_palettes', default='default', | 
					
						
							|  |  |  |                         choices=['default', 'random', 'blackout', 'puke', 'classic', 'grayscale', 'negative', 'dizzy', | 
					
						
							|  |  |  |                                  'sick']) | 
					
						
							|  |  |  |     parser.add_argument('--uw_palettes', default='default', | 
					
						
							|  |  |  |                         choices=['default', 'random', 'blackout', 'puke', 'classic', 'grayscale', 'negative', 'dizzy', | 
					
						
							|  |  |  |                                  'sick']) | 
					
						
							| 
									
										
										
										
											2017-12-12 08:17:52 -06:00
										 |  |  |     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. | 
					
						
							|  |  |  |                              ''')
 | 
					
						
							| 
									
										
										
										
											2019-12-09 19:27:56 +01:00
										 |  |  |     parser.add_argument('--names', default='', type=str) | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  |     parser.add_argument('--update_sprites', action='store_true', help='Update Sprite Database, then exit.') | 
					
						
							| 
									
										
										
										
											2017-12-12 08:17:52 -06:00
										 |  |  |     args = parser.parse_args() | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  |     if args.update_sprites: | 
					
						
							|  |  |  |         run_sprite_update() | 
					
						
							|  |  |  |         sys.exit() | 
					
						
							| 
									
										
										
										
											2017-12-12 08:17:52 -06:00
										 |  |  |     # set up logger | 
					
						
							| 
									
										
										
										
											2020-04-26 15:14:30 +02:00
										 |  |  |     loglevel = {'error': logging.ERROR, 'info': logging.INFO, 'warning': logging.WARNING, 'debug': logging.DEBUG}[ | 
					
						
							|  |  |  |         args.loglevel] | 
					
						
							| 
									
										
										
										
											2017-12-12 08:17:52 -06:00
										 |  |  |     logging.basicConfig(format='%(message)s', level=loglevel) | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if not os.path.isfile(args.rom): | 
					
						
							|  |  |  |         adjustGUI() | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         if args.sprite is not None and not os.path.isfile(args.sprite) and not Sprite.get_sprite_from_name(args.sprite): | 
					
						
							|  |  |  |             input('Could not find link sprite sheet at given location. \nPress Enter to exit.') | 
					
						
							|  |  |  |             sys.exit(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         args, path = adjust(args=args) | 
					
						
							|  |  |  |         from Utils import persistent_store | 
					
						
							|  |  |  |         if isinstance(args.sprite, Sprite): | 
					
						
							|  |  |  |             args.sprite = args.sprite.name | 
					
						
							|  |  |  |         persistent_store("adjuster", "last_settings_3", args) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def adjust(args): | 
					
						
							|  |  |  |     start = time.perf_counter() | 
					
						
							|  |  |  |     logger = logging.getLogger('Adjuster') | 
					
						
							|  |  |  |     logger.info('Patching ROM.') | 
					
						
							|  |  |  |     vanillaRom = args.baserom | 
					
						
							| 
									
										
										
										
											2021-03-03 02:02:41 +01:00
										 |  |  |     if os.path.splitext(args.rom)[-1].lower() == '.apbp': | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |         import Patch | 
					
						
							|  |  |  |         meta, args.rom = Patch.create_rom_file(args.rom) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if os.stat(args.rom).st_size in (0x200000, 0x400000) and os.path.splitext(args.rom)[-1].lower() == '.sfc': | 
					
						
							|  |  |  |         rom = LocalRom(args.rom, patch=False, vanillaRom=vanillaRom) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         raise RuntimeError( | 
					
						
							|  |  |  |             'Provided Rom is not a valid Link to the Past Randomizer Rom. Please provide one for adjusting.') | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  |     palettes_options = {} | 
					
						
							|  |  |  |     palettes_options['dungeon'] = args.uw_palettes | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  |     palettes_options['overworld'] = args.ow_palettes | 
					
						
							|  |  |  |     palettes_options['hud'] = args.hud_palettes | 
					
						
							|  |  |  |     palettes_options['sword'] = args.sword_palettes | 
					
						
							|  |  |  |     palettes_options['shield'] = args.shield_palettes | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |     # palettes_options['link']=args.link_palettesvera | 
					
						
							| 
									
										
										
										
											2021-03-27 07:12:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |     racerom = rom.read_byte(0x180213) > 0 | 
					
						
							| 
									
										
										
										
											2021-03-27 07:12:08 -07:00
										 |  |  |     world = None | 
					
						
							|  |  |  |     if hasattr(args, "world"): | 
					
						
							|  |  |  |         world = getattr(args, "world") | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     apply_rom_settings(rom, args.heartbeep, args.heartcolor, args.quickswap, args.fastmenu, args.disablemusic, | 
					
						
							| 
									
										
										
										
											2021-03-27 07:12:08 -07:00
										 |  |  |                        args.sprite, palettes_options, reduceflashing=args.reduceflashing or racerom, world=world) | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |     path = output_path(f'{os.path.basename(args.rom)[:-4]}_adjusted.sfc') | 
					
						
							|  |  |  |     rom.write_to_file(path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     logger.info('Done. Enjoy.') | 
					
						
							|  |  |  |     logger.debug('Total Time: %s', time.perf_counter() - start) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return args, path | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  | def adjustGUI(): | 
					
						
							| 
									
										
										
										
											2021-05-24 12:48:18 +02:00
										 |  |  |     from tkinter import Tk, LEFT, BOTTOM, TOP, \ | 
					
						
							|  |  |  |         StringVar, Frame, Label, X, Entry, Button, filedialog, messagebox, ttk | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |     from Gui import get_rom_options_frame, get_rom_frame | 
					
						
							|  |  |  |     from GuiUtils import set_icon | 
					
						
							|  |  |  |     from argparse import Namespace | 
					
						
							|  |  |  |     from Main import __version__ as MWVersion | 
					
						
							|  |  |  |     adjustWindow = Tk() | 
					
						
							| 
									
										
										
										
											2021-02-25 18:23:19 +01:00
										 |  |  |     adjustWindow.wm_title("Archipelago %s LttP Adjuster" % MWVersion) | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |     set_icon(adjustWindow) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rom_options_frame, rom_vars, set_sprite = get_rom_options_frame(adjustWindow) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bottomFrame2 = Frame(adjustWindow) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     romFrame, romVar = get_rom_frame(adjustWindow) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     romDialogFrame = Frame(adjustWindow) | 
					
						
							|  |  |  |     baseRomLabel2 = Label(romDialogFrame, text='Rom to adjust') | 
					
						
							|  |  |  |     romVar2 = StringVar() | 
					
						
							|  |  |  |     romEntry2 = Entry(romDialogFrame, textvariable=romVar2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def RomSelect2(): | 
					
						
							| 
									
										
										
										
											2021-03-03 02:02:41 +01:00
										 |  |  |         rom = filedialog.askopenfilename(filetypes=[("Rom Files", (".sfc", ".smc", ".apbp")), ("All Files", "*")]) | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |         romVar2.set(rom) | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |     romSelectButton2 = Button(romDialogFrame, text='Select Rom', command=RomSelect2) | 
					
						
							|  |  |  |     romDialogFrame.pack(side=TOP, expand=True, fill=X) | 
					
						
							|  |  |  |     baseRomLabel2.pack(side=LEFT) | 
					
						
							|  |  |  |     romEntry2.pack(side=LEFT, expand=True, fill=X) | 
					
						
							|  |  |  |     romSelectButton2.pack(side=LEFT) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def adjustRom(): | 
					
						
							|  |  |  |         guiargs = Namespace() | 
					
						
							|  |  |  |         guiargs.heartbeep = rom_vars.heartbeepVar.get() | 
					
						
							|  |  |  |         guiargs.heartcolor = rom_vars.heartcolorVar.get() | 
					
						
							|  |  |  |         guiargs.fastmenu = rom_vars.fastMenuVar.get() | 
					
						
							|  |  |  |         guiargs.ow_palettes = rom_vars.owPalettesVar.get() | 
					
						
							|  |  |  |         guiargs.uw_palettes = rom_vars.uwPalettesVar.get() | 
					
						
							|  |  |  |         guiargs.hud_palettes = rom_vars.hudPalettesVar.get() | 
					
						
							|  |  |  |         guiargs.sword_palettes = rom_vars.swordPalettesVar.get() | 
					
						
							|  |  |  |         guiargs.shield_palettes = rom_vars.shieldPalettesVar.get() | 
					
						
							|  |  |  |         guiargs.quickswap = bool(rom_vars.quickSwapVar.get()) | 
					
						
							|  |  |  |         guiargs.disablemusic = bool(rom_vars.disableMusicVar.get()) | 
					
						
							|  |  |  |         guiargs.reduceflashing = bool(rom_vars.disableFlashingVar.get()) | 
					
						
							|  |  |  |         guiargs.rom = romVar2.get() | 
					
						
							|  |  |  |         guiargs.baserom = romVar.get() | 
					
						
							|  |  |  |         guiargs.sprite = rom_vars.sprite | 
					
						
							| 
									
										
										
										
											2021-03-27 07:12:08 -07:00
										 |  |  |         if rom_vars.sprite_pool: | 
					
						
							|  |  |  |             guiargs.world = AdjusterWorld(rom_vars.sprite_pool) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |         try: | 
					
						
							|  |  |  |             guiargs, path = adjust(args=guiargs) | 
					
						
							| 
									
										
										
										
											2021-03-27 07:12:08 -07:00
										 |  |  |             if rom_vars.sprite_pool: | 
					
						
							|  |  |  |                 guiargs.sprite_pool = rom_vars.sprite_pool | 
					
						
							|  |  |  |                 delattr(guiargs, "world") | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |         except Exception as e: | 
					
						
							|  |  |  |             logging.exception(e) | 
					
						
							|  |  |  |             messagebox.showerror(title="Error while adjusting Rom", message=str(e)) | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2021-02-19 19:10:01 +01:00
										 |  |  |             messagebox.showinfo(title="Success", message=f"Rom patched successfully to {path}") | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |             from Utils import persistent_store | 
					
						
							| 
									
										
										
										
											2021-02-21 20:37:43 +01:00
										 |  |  |             from worlds.alttp.Rom import Sprite | 
					
						
							| 
									
										
										
										
											2021-02-19 19:08:11 +01:00
										 |  |  |             if isinstance(guiargs.sprite, Sprite): | 
					
						
							|  |  |  |                 guiargs.sprite = guiargs.sprite.name | 
					
						
							|  |  |  |             persistent_store("adjuster", "last_settings_3", guiargs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     adjustButton = Button(bottomFrame2, text='Adjust Rom', command=adjustRom) | 
					
						
							|  |  |  |     rom_options_frame.pack(side=TOP) | 
					
						
							|  |  |  |     adjustButton.pack(side=BOTTOM, padx=(5, 5)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bottomFrame2.pack(side=BOTTOM, pady=(5, 5)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     adjustWindow.mainloop() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 00:25:46 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  | def run_sprite_update(): | 
					
						
							|  |  |  |     import threading | 
					
						
							|  |  |  |     done = threading.Event() | 
					
						
							|  |  |  |     top = Tk() | 
					
						
							|  |  |  |     top.withdraw() | 
					
						
							|  |  |  |     BackgroundTaskProgress(top, update_sprites, "Updating Sprites", lambda succesful, resultmessage: done.set()) | 
					
						
							|  |  |  |     while not done.isSet(): | 
					
						
							|  |  |  |         top.update() | 
					
						
							|  |  |  |     print("Done updating sprites") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 00:25:46 -05:00
										 |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											2021-04-21 23:53:59 +02:00
										 |  |  |     main() |