122 lines
4.4 KiB
Python
122 lines
4.4 KiB
Python
import sys
|
|
from os import chdir, makedirs, get_terminal_size
|
|
from os.path import join as joinpath, splitext, isfile, exists, dirname, abspath
|
|
import pyfarc
|
|
import importlib, importlib.util
|
|
|
|
if getattr(sys, 'frozen', False):
|
|
datadir = dirname(sys.executable)
|
|
else:
|
|
datadir = dirname(__file__)
|
|
|
|
arbpatcher_dir = joinpath(datadir, 'ARB Patcher')
|
|
arbpatcher_gamesettings_dir = joinpath(arbpatcher_dir, 'gamesettings')
|
|
|
|
sys.path = [arbpatcher_dir] + sys.path
|
|
import main as ArbPatcher
|
|
sys.path = sys.path[1:]
|
|
|
|
game_settings_spec = importlib.util.spec_from_file_location('divaaft', joinpath(arbpatcher_gamesettings_dir, 'divaaft.py'))
|
|
game_settings_module = importlib.util.module_from_spec(game_settings_spec)
|
|
game_settings_spec.loader.exec_module(game_settings_module)
|
|
|
|
|
|
# not bothering to check for main here because it's just a glue script anyway
|
|
def get_args():
|
|
import argparse
|
|
parser = argparse.ArgumentParser(description='AFT Shader Patcher: Patches Nvidia-only ARB shaders from PDAFT to work on AMD. Patching techniques from Nezarn; implementation by somewhatlurker.')
|
|
parser.add_argument('-i', '--in_farc', default='shader.farc', help='input shader farc file (default: "shader.farc")')
|
|
parser.add_argument('-o', '--out_farc', default='shader_patched.farc', help='output shader farc file (default: "shader_patched.farc")')
|
|
parser.add_argument('-c', '--compress', action='store_true', help='force use of farc compression (this mey produce larger vcdiff files)')
|
|
parser.add_argument('-x', '--xdelta', action='store_true', help='generate a vcdiff patch file')
|
|
|
|
return parser.parse_args()
|
|
|
|
args = get_args()
|
|
|
|
print("AFT Shader Patcher")
|
|
print("==================")
|
|
print("Patching techniques from Nezarn; implementation by somewhatlurker")
|
|
print("=================================================================")
|
|
print("Input file: '{}'".format(args.in_farc))
|
|
print("Output file: '{}'".format(args.out_farc))
|
|
|
|
if not exists(args.in_farc):
|
|
print ("'{}' does not exist. Aborting".format(args.in_farc))
|
|
sys.exit()
|
|
elif not isfile(args.in_farc):
|
|
print ("'{}' is not a file. Aborting".format(args.in_farc))
|
|
sys.exit()
|
|
|
|
if exists(args.out_farc):
|
|
if not isfile(args.out_farc):
|
|
print ("'{}' already exists but is a directory. Aborting".format(args.out_farc))
|
|
sys.exit()
|
|
|
|
|
|
with open(args.in_farc, 'rb') as f:
|
|
farcdata = pyfarc.from_stream(f)
|
|
if args.xdelta:
|
|
f.seek(0)
|
|
from binascii import crc32
|
|
in_farc_crc_str = '{:08x}'.format(crc32(f.read()))
|
|
|
|
proc_count = 0
|
|
|
|
last_status_len = 0
|
|
|
|
for fname in farcdata['files']:
|
|
proc_count += 1
|
|
progress_val = proc_count / len(farcdata['files'])
|
|
progress_cnt_X = int(progress_val * 20)
|
|
|
|
status_str = '\r[{e:{s1}<{n1}}{e:{s2}<{n2}}]'.format(e='', s1='X', s2='-', n1=progress_cnt_X, n2=20-progress_cnt_X)
|
|
status_str += ' {:.2%}'.format(progress_val)
|
|
status_str += ' ' + fname
|
|
|
|
try:
|
|
terminal_width = get_terminal_size()[0]
|
|
except:
|
|
terminal_width = 120
|
|
|
|
if len(status_str) > terminal_width:
|
|
status_str = status_str[:terminal_width-3] + '...'
|
|
|
|
# fix characters left on screen from a previous longer line
|
|
# (without cursor staying off to the side)
|
|
this_status_len = len(status_str)
|
|
if this_status_len < last_status_len:
|
|
status_str = '{: <{l}}'.format(status_str, l=last_status_len)
|
|
last_status_len = this_status_len
|
|
|
|
print (status_str, end='')
|
|
|
|
if game_settings_module and game_settings_module.filename_filter:
|
|
openname = game_settings_module.filename_filter(fname)
|
|
else:
|
|
openname = fname
|
|
|
|
f_lines = farcdata['files'][openname]['data'].decode('utf-8').splitlines(keepends=True)
|
|
|
|
f_full = ArbPatcher.patch_shader(fname, f_lines, game_settings_module, True)
|
|
|
|
farcdata['files'][fname]['data'] = f_full.encode('utf-8')
|
|
|
|
print('')
|
|
|
|
if args.compress:
|
|
farcdata['farc_type'] = 'FArC'
|
|
|
|
with open(args.out_farc, 'wb') as f:
|
|
pyfarc.to_stream(farcdata, f, no_copy=True)
|
|
|
|
if args.xdelta:
|
|
import subprocess
|
|
|
|
# make paths absolute before running this (actually not needed)
|
|
#args.in_farc = abspath(args.in_farc)
|
|
#args.out_farc = abspath(args.out_farc)
|
|
|
|
subprocess.run([joinpath(datadir, 'xdelta3.exe'), '-e', '-f', '-S', 'none', '-s', args.in_farc, args.out_farc, joinpath(dirname(args.out_farc), in_farc_crc_str + '.vcdiff')], )
|
|
print ("Generated '{}.vcdiff'".format(in_farc_crc_str))
|