2017-11-28 14:36:32 +00:00
|
|
|
import os
|
2019-12-09 18:27:56 +00:00
|
|
|
import re
|
2017-12-17 05:25:46 +00:00
|
|
|
import subprocess
|
2017-11-28 14:36:32 +00:00
|
|
|
import sys
|
|
|
|
|
2018-02-17 23:38:54 +00:00
|
|
|
def int16_as_bytes(value):
|
|
|
|
value = value & 0xFFFF
|
|
|
|
return [value & 0xFF, (value >> 8) & 0xFF]
|
|
|
|
|
|
|
|
def int32_as_bytes(value):
|
|
|
|
value = value & 0xFFFFFFFF
|
|
|
|
return [value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF, (value >> 24) & 0xFF]
|
|
|
|
|
2018-09-23 02:51:54 +00:00
|
|
|
def pc_to_snes(value):
|
|
|
|
return ((value<<1) & 0x7F0000)|(value & 0x7FFF)|0x8000
|
|
|
|
|
|
|
|
def snes_to_pc(value):
|
|
|
|
return ((value & 0x7F0000)>>1)|(value & 0x7FFF)
|
|
|
|
|
2020-01-14 09:42:27 +00:00
|
|
|
def parse_player_names(names, players, teams):
|
|
|
|
names = [n for n in re.split(r'[, ]', names) if n]
|
|
|
|
ret = []
|
|
|
|
while names or len(ret) < teams:
|
|
|
|
team = [n[:16] for n in names[:players]]
|
|
|
|
while len(team) != players:
|
|
|
|
team.append(f"Player {len(team) + 1}")
|
|
|
|
ret.append(team)
|
|
|
|
|
|
|
|
names = names[players:]
|
|
|
|
return ret
|
|
|
|
|
2017-11-28 14:36:32 +00:00
|
|
|
def is_bundled():
|
|
|
|
return getattr(sys, 'frozen', False)
|
|
|
|
|
|
|
|
def local_path(path):
|
|
|
|
if local_path.cached_path is not None:
|
|
|
|
return os.path.join(local_path.cached_path, path)
|
|
|
|
|
2020-02-02 21:36:55 +00:00
|
|
|
if is_bundled() and hasattr(sys, "_MEIPASS"):
|
|
|
|
# we are running in a PyInstaller bundle
|
2017-12-17 05:25:46 +00:00
|
|
|
local_path.cached_path = sys._MEIPASS # pylint: disable=protected-access,no-member
|
2020-02-02 21:36:55 +00:00
|
|
|
elif is_bundled():
|
|
|
|
#probably cxFreeze
|
|
|
|
local_path.cached_path = os.path.dirname(sys.argv[0])
|
2017-11-28 14:36:32 +00:00
|
|
|
else:
|
|
|
|
# we are running in a normal Python environment
|
|
|
|
local_path.cached_path = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
return os.path.join(local_path.cached_path, path)
|
|
|
|
|
|
|
|
local_path.cached_path = None
|
|
|
|
|
|
|
|
def output_path(path):
|
|
|
|
if output_path.cached_path is not None:
|
|
|
|
return os.path.join(output_path.cached_path, path)
|
|
|
|
|
|
|
|
if not is_bundled():
|
|
|
|
output_path.cached_path = '.'
|
|
|
|
return os.path.join(output_path.cached_path, path)
|
|
|
|
else:
|
|
|
|
# has been packaged, so cannot use CWD for output.
|
|
|
|
if sys.platform == 'win32':
|
|
|
|
#windows
|
|
|
|
import ctypes.wintypes
|
|
|
|
CSIDL_PERSONAL = 5 # My Documents
|
|
|
|
SHGFP_TYPE_CURRENT = 0 # Get current, not default value
|
|
|
|
|
|
|
|
buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH)
|
|
|
|
ctypes.windll.shell32.SHGetFolderPathW(None, CSIDL_PERSONAL, None, SHGFP_TYPE_CURRENT, buf)
|
|
|
|
|
|
|
|
documents = buf.value
|
|
|
|
|
|
|
|
elif sys.platform == 'darwin':
|
2017-12-17 05:25:46 +00:00
|
|
|
from AppKit import NSSearchPathForDirectoriesInDomains # pylint: disable=import-error
|
2017-11-28 14:36:32 +00:00
|
|
|
# http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Functions/Reference/reference.html#//apple_ref/c/func/NSSearchPathForDirectoriesInDomains
|
|
|
|
NSDocumentDirectory = 9
|
|
|
|
NSUserDomainMask = 1
|
|
|
|
# True for expanding the tilde into a fully qualified path
|
|
|
|
documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, True)[0]
|
|
|
|
else:
|
|
|
|
raise NotImplementedError('Not supported yet')
|
|
|
|
|
|
|
|
output_path.cached_path = os.path.join(documents, 'ALttPEntranceRandomizer')
|
|
|
|
if not os.path.exists(output_path.cached_path):
|
|
|
|
os.mkdir(output_path.cached_path)
|
|
|
|
return os.path.join(output_path.cached_path, path)
|
|
|
|
|
|
|
|
output_path.cached_path = None
|
|
|
|
|
|
|
|
def open_file(filename):
|
|
|
|
if sys.platform == 'win32':
|
|
|
|
os.startfile(filename)
|
|
|
|
else:
|
2017-12-17 05:25:46 +00:00
|
|
|
open_command = 'open' if sys.platform == 'darwin' else 'xdg-open'
|
2017-11-28 14:36:32 +00:00
|
|
|
subprocess.call([open_command, filename])
|
2017-12-02 14:21:04 +00:00
|
|
|
|
|
|
|
def close_console():
|
|
|
|
if sys.platform == 'win32':
|
|
|
|
#windows
|
|
|
|
import ctypes.wintypes
|
|
|
|
try:
|
|
|
|
ctypes.windll.kernel32.FreeConsole()
|
2017-12-17 05:25:46 +00:00
|
|
|
except Exception:
|
2017-12-02 14:21:04 +00:00
|
|
|
pass
|
2018-01-01 19:42:23 +00:00
|
|
|
|
|
|
|
def make_new_base2current(old_rom='Zelda no Densetsu - Kamigami no Triforce (Japan).sfc', new_rom='working.sfc'):
|
|
|
|
from collections import OrderedDict
|
|
|
|
import json
|
|
|
|
import hashlib
|
|
|
|
with open(old_rom, 'rb') as stream:
|
|
|
|
old_rom_data = bytearray(stream.read())
|
|
|
|
with open(new_rom, 'rb') as stream:
|
|
|
|
new_rom_data = bytearray(stream.read())
|
|
|
|
# extend to 2 mb
|
2020-01-22 16:50:00 +00:00
|
|
|
old_rom_data.extend(bytearray([0x00]) * (2097152 - len(old_rom_data)))
|
2018-01-01 19:42:23 +00:00
|
|
|
|
|
|
|
out_data = OrderedDict()
|
|
|
|
for idx, old in enumerate(old_rom_data):
|
|
|
|
new = new_rom_data[idx]
|
|
|
|
if old != new:
|
|
|
|
out_data[idx] = [int(new)]
|
|
|
|
for offset in reversed(list(out_data.keys())):
|
|
|
|
if offset - 1 in out_data:
|
|
|
|
out_data[offset-1].extend(out_data.pop(offset))
|
|
|
|
with open('data/base2current.json', 'wt') as outfile:
|
|
|
|
json.dump([{key:value} for key, value in out_data.items()], outfile, separators=(",", ":"))
|
|
|
|
|
|
|
|
basemd5 = hashlib.md5()
|
|
|
|
basemd5.update(new_rom_data)
|
|
|
|
return "New Rom Hash: " + basemd5.hexdigest()
|
2020-02-09 04:28:48 +00:00
|
|
|
|
|
|
|
from yaml import load
|
|
|
|
import functools
|
|
|
|
|
|
|
|
try: from yaml import CLoader as Loader
|
|
|
|
except ImportError: from yaml import Loader
|
|
|
|
|
|
|
|
parse_yaml = functools.partial(load, Loader=Loader)
|