116 lines
3.5 KiB
Python
116 lines
3.5 KiB
Python
import os
|
|
import sys
|
|
import hashlib
|
|
|
|
from asar import init as asar_init, close as asar_close, patch as asar_patch, geterrors as asar_errors, getprints as asar_prints, getwarnings as asar_warnings
|
|
|
|
JAP10HASH = '03a63945398191337e896e5771f77173'
|
|
|
|
try:
|
|
from yaml import CLoader as Loader
|
|
except ImportError:
|
|
from yaml import Loader
|
|
|
|
|
|
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]
|
|
|
|
|
|
def is_bundled():
|
|
return getattr(sys, 'frozen', False)
|
|
|
|
|
|
def local_path(path):
|
|
if local_path.cached_path:
|
|
return os.path.join(local_path.cached_path, path)
|
|
|
|
elif is_bundled():
|
|
if hasattr(sys, "_MEIPASS"):
|
|
# we are running in a PyInstaller bundle
|
|
local_path.cached_path = sys._MEIPASS # pylint: disable=protected-access,no-member
|
|
else:
|
|
# cx_Freeze
|
|
local_path.cached_path = os.path.dirname(os.path.abspath(sys.argv[0]))
|
|
else:
|
|
# we are running in a normal Python environment
|
|
import __main__
|
|
local_path.cached_path = os.path.dirname(os.path.abspath(__main__.__file__))
|
|
|
|
return os.path.join(local_path.cached_path, path)
|
|
|
|
|
|
local_path.cached_path = None
|
|
|
|
|
|
def make_new_base2current(old_rom_data, new_rom_data):
|
|
from collections import OrderedDict
|
|
import json
|
|
# extend to 2 mb
|
|
old_rom_data.extend(bytearray([0x00]) * (2097152 - len(old_rom_data)))
|
|
|
|
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('../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()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
asar_init()
|
|
print("Asar DLL initialized")
|
|
|
|
print("Opening Base rom")
|
|
with open('../alttp.sfc', 'rb') as stream:
|
|
old_rom_data = bytearray(stream.read())
|
|
|
|
if len(old_rom_data) % 0x400 == 0x200:
|
|
old_rom_data = old_rom_data[0x200:]
|
|
|
|
basemd5 = hashlib.md5()
|
|
basemd5.update(old_rom_data)
|
|
if JAP10HASH != basemd5.hexdigest():
|
|
raise Exception("Base rom is not 'Zelda no Densetsu - Kamigami no Triforce (J) (V1.0)'")
|
|
|
|
print("Patching Base Rom")
|
|
result, new_rom_data = asar_patch(os.path.abspath('LTTP_RND_GeneralBugfixes.asm'), old_rom_data)
|
|
|
|
if result:
|
|
with open('../working.sfc', 'wb') as stream:
|
|
stream.write(new_rom_data)
|
|
print("Success\n")
|
|
print(make_new_base2current(old_rom_data, new_rom_data))
|
|
prints = asar_prints()
|
|
for p in prints:
|
|
print(p)
|
|
else:
|
|
errors = asar_errors()
|
|
print("\nErrors: " + str(len(errors)))
|
|
for error in errors:
|
|
print (error)
|
|
warnings = asar_warnings()
|
|
print("\nWarnings: " + str(len(warnings)))
|
|
for w in warnings:
|
|
print(w)
|
|
|
|
asar_close()
|
|
except:
|
|
import traceback
|
|
traceback.print_exc()
|
|
|