diff --git a/source-code/data/amd-tools/.gitignore b/source-code/data/amd-tools/.gitignore new file mode 100644 index 0000000..f7823f9 --- /dev/null +++ b/source-code/data/amd-tools/.gitignore @@ -0,0 +1,3 @@ +venv/* +*.farc +*.vcdiff \ No newline at end of file diff --git a/source-code/data/amd-tools/ARB Patcher Source/gamesettings/divaaft.py b/source-code/data/amd-tools/AFT Shader Patcher/ARB Patcher/gamesettings/divaaft.py similarity index 100% rename from source-code/data/amd-tools/ARB Patcher Source/gamesettings/divaaft.py rename to source-code/data/amd-tools/AFT Shader Patcher/ARB Patcher/gamesettings/divaaft.py diff --git a/source-code/data/amd-tools/AFT Shader Patcher/ARB Patcher/gamesettings/divaaft_noskinning.py b/source-code/data/amd-tools/AFT Shader Patcher/ARB Patcher/gamesettings/divaaft_noskinning.py new file mode 100644 index 0000000..d038ac7 --- /dev/null +++ b/source-code/data/amd-tools/AFT Shader Patcher/ARB Patcher/gamesettings/divaaft_noskinning.py @@ -0,0 +1,74 @@ +# gane-specific settings for diva arcade future tone +GAME_NAME = "Project DIVA Arcade: Future Tone" + +from re import compile as recompile + +# some skinning can't be done due to using NV parameter buffers, so just disable it. +VP_SKINNING_REGEX = recompile(r"(BUFFER4[\s\S]*?)MOV (.*?).w, 1; SUBC _tmp1, vertex.attrib\[15\], (-1|255); (.*?) IF NE.y; (.*?) MAD \2.xyz, _tmp0, vertex.attrib\[1\].y, \2; (.*?) MAD (.*?).xyz, _tmp0, vertex.attrib\[1\].y, \7; (.*?) MAD (.*?).xyz, _tmp0, vertex.attrib\[1\].y, \9; IF NE.z; (.*?) MAD \2.xyz, _tmp0, vertex.attrib\[1\].z, \2; (.*?) MAD \7.xyz, _tmp0, vertex.attrib\[1\].z, \7; (.*?) MAD \9.xyz, _tmp0, vertex.attrib\[1\].z, \9; IF NE.w; (.*?) MAD \2.xyz, _tmp0, vertex.attrib\[1\].w, \2; (.*?) MAD \7.xyz, _tmp0, vertex.attrib\[1\].w, \7; (.*?) MAD \9.xyz, _tmp0, vertex.attrib\[1\].w, \9; (?:ENDIF; ENDIF; ENDIF;|.*:)") +VP_SKINNING_SUB = "\\1MOV \\2.w, 1; MOV \\2.xyz, vertex.position; MOV \\7, vertex.normal; MOV \\9, vertex.attrib[6];" + +VP_SKINNING_REGEX_2 = recompile(r"(BUFFER4[\s\S]*?)MOV (.*?).w, 1; SUBC _tmp1, vertex.attrib\[15\], (-1|255); (.*?) IF NE.y; (.*?) MAD \2.xyz, _tmp0, vertex.attrib\[1\].y, \2; (.*?) MAD (.*?).xyz, _tmp0, vertex.attrib\[1\].y, \7; IF NE.z; (.*?) MAD \2.xyz, _tmp0, vertex.attrib\[1\].z, \2; (.*?) MAD \7.xyz, _tmp0, vertex.attrib\[1\].z, \7; IF NE.w; (.*?) MAD \2.xyz, _tmp0, vertex.attrib\[1\].w, \2; (.*?) MAD \7.xyz, _tmp0, vertex.attrib\[1\].w, \7; (?:ENDIF; ENDIF; ENDIF;|.*:)") +VP_SKINNING_SUB_2 = "\\1MOV \\2.w, 1; MOV \\2.xyz, vertex.position; MOV \\7, vertex.normal;" + +VP_SKINNING_REGEX_3 = recompile(r"(BUFFER4[\s\S]*?)MOV (.*?).w, 1; SUBC _tmp1, vertex.attrib\[15\], (-1|255); (.*?) IF NE.y; (.*?) MAD \2.xyz, _tmp0, vertex.attrib\[1\].y, \2; IF NE.z; (.*?) MAD \2.xyz, _tmp0, vertex.attrib\[1\].z, \2; IF NE.w; (.*?) MAD \2.xyz, _tmp0, vertex.attrib\[1\].w, \2; (?:ENDIF; ENDIF; ENDIF;|.*:)") +VP_SKINNING_SUB_3 = "\\1MOV \\2.w, 1; MOV \\2.xyz, vertex.position;" + + +# some kind of effect (scrunching up or stretching?) in tights shaders starting with 11 that partially uses skinning of normals... let's just pretend it always results in 0 +TIGHTS_SKINNING_EFFECT_REGEX = recompile(r"(BUFFER4[\s\S]*?)SUBC .*?, vertex.attrib\[15\], .*?;\s*?SUBC1 tmp, vertex.attrib\[15\], .*?;[\s\S]*?XPD .*?, .*?, .*?;\s*?DP3_SAT (.*?), .*?, .*?;") +TIGHTS_SKINNING_EFFECT_SUB = "\\1MOV \\2, 0;" + + +# some skinning just needs some branching fixup for AMD BRA working different (needs a target per branch instruction apparently) +SKIN_BRA_REGEX = recompile(r"BRA skinning_(?:\S*)end (\(.*?\.y\))*?\s*?;") +SKIN_BRA_SUB = "BRA sk_end1 \\1;" +SKIN_BRA_REGEX_2 = recompile(r"BRA skinning_(?:\S*)end (\(.*?\.z\))*?\s*?;") +SKIN_BRA_SUB_2 = "BRA sk_end2 \\1;" +SKIN_BRA_REGEX_3 = recompile(r"BRA skinning_(?:\S*)end (\(.*?\.w\))*?\s*?;") +SKIN_BRA_SUB_3 = "BRA sk_end3 \\1;" + +SKIN_BRA_TGT_REGEX = recompile(r"skinning_(?:\S*)end:") +SKIN_BRA_TGT_SUB = "\nsk_end1:\nsk_end2:\nsk_end3:\n" + + +MATCH_FP_FNAME = recompile(r".*fp") +MATCH_VP_FNAME = recompile(r".*vp") +MATCH_ALL_FNAME = recompile(r".*") +MATCH_FONT_FNAME = recompile(r"font.*fp") +MATCH_TIGHTS_FNAME = recompile(r"tights.*vp") + +# fourth param: apply continuously until no more matches are found +fix_repls = [ + (MATCH_VP_FNAME, VP_SKINNING_REGEX, VP_SKINNING_SUB, False), + (MATCH_VP_FNAME, VP_SKINNING_REGEX_2, VP_SKINNING_SUB_2, False), + (MATCH_VP_FNAME, VP_SKINNING_REGEX_3, VP_SKINNING_SUB_3, False), + (MATCH_TIGHTS_FNAME, TIGHTS_SKINNING_EFFECT_REGEX, TIGHTS_SKINNING_EFFECT_SUB, False), + (MATCH_VP_FNAME, SKIN_BRA_REGEX, SKIN_BRA_SUB, False), + (MATCH_VP_FNAME, SKIN_BRA_REGEX_2, SKIN_BRA_SUB_2, False), + (MATCH_VP_FNAME, SKIN_BRA_REGEX_3, SKIN_BRA_SUB_3, False), + (MATCH_VP_FNAME, SKIN_BRA_TGT_REGEX, SKIN_BRA_TGT_SUB, False), +] + + +# use to open a differnt file instead of the original shader (eg. to replace with an easier-to-patch variant +def filename_filter(fname): + if fname == 'sss_filter.130.fp': + return 'sss_filter.120.fp' + elif fname == 'sss_filter.131.fp': + return 'sss_filter.121.fp' + else: + return fname + + +# use to tweak reasults after patching +def post_filter(fname, f_full): + f_full = f_full.replace('\nBUFFER4', '\n#BUFFER4') + + # fix tex sampler offsets + # diva has something we can use for pixel size (program.local[0]), but it isn't in fonts so they get an approximation instead + if MATCH_FONT_FNAME.match(fname): + f_full = f_full.replace('{ 0.00078, 0.0014 }; ADD tex_offset_coord', '0.00035; ADD tex_offset_coord') + else: + f_full = f_full.replace('{ 0.00078, 0.0014 }; ADD tex_offset_coord', 'program.local[0]; ADD tex_offset_coord') + + return f_full \ No newline at end of file diff --git a/source-code/data/amd-tools/ARB Patcher Source/main.py b/source-code/data/amd-tools/AFT Shader Patcher/ARB Patcher/main.py similarity index 100% rename from source-code/data/amd-tools/ARB Patcher Source/main.py rename to source-code/data/amd-tools/AFT Shader Patcher/ARB Patcher/main.py diff --git a/source-code/data/amd-tools/ARB Patcher Source/rules.py b/source-code/data/amd-tools/AFT Shader Patcher/ARB Patcher/rules.py similarity index 100% rename from source-code/data/amd-tools/ARB Patcher Source/rules.py rename to source-code/data/amd-tools/AFT Shader Patcher/ARB Patcher/rules.py diff --git a/source-code/data/amd-tools/AFT Shader Patcher/aft_shader_patcher.py b/source-code/data/amd-tools/AFT Shader Patcher/aft_shader_patcher.py new file mode 100644 index 0000000..a1eee1e --- /dev/null +++ b/source-code/data/amd-tools/AFT Shader Patcher/aft_shader_patcher.py @@ -0,0 +1,117 @@ +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') + +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 + #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')], ) diff --git a/source-code/data/amd-tools/AFT Shader Patcher/pyfarc.py b/source-code/data/amd-tools/AFT Shader Patcher/pyfarc.py new file mode 100644 index 0000000..7936c15 --- /dev/null +++ b/source-code/data/amd-tools/AFT Shader Patcher/pyfarc.py @@ -0,0 +1,252 @@ +""" +pyfarc reader and writer for farc archives +supports Farc and FarC only +""" + +from construct import Struct, Const, Int32ub, Int32sb, RepeatUntil, CString, Pointer, Bytes, Padding +from copy import deepcopy +import gzip + +_FArc_format = Struct( + "signature" / Const(b'FArc'), + "header_size" / Int32ub, # doesn't include signature or header_size + "alignment" / Int32sb, + "files" / RepeatUntil(lambda obj,lst,ctx: ctx._io.tell() - 7 > ctx.header_size, Struct( + "name" / CString("utf8"), + "pointer" / Int32ub, + "size" / Int32ub, + "data" / Pointer(lambda this: this.pointer, Bytes(lambda this: this.size)) + )), + #Padding(lambda this: this.alignment - (this._io.tell() % this.alignment) if this._io.tell() % this.alignment else 0) +) + +_FArC_format = Struct( + "signature" / Const(b'FArC'), + "header_size" / Int32ub, # doesn't include signature or header_size + "alignment" / Int32sb, + "files" / RepeatUntil(lambda obj,lst,ctx: ctx._io.tell() - 7 > ctx.header_size, Struct( + "name" / CString("utf8"), + "pointer" / Int32ub, + "compressed_size" / Int32ub, + "uncompressed_size" / Int32ub, + "data" / Pointer(lambda this: this.pointer, Bytes(lambda this: this.compressed_size)) + )), + #Padding(lambda this: this.alignment - (this._io.tell() % this.alignment) if this._io.tell() % this.alignment else 0) +) + +_farc_types = { + 'FArc': { + 'remarks': 'basic farc format', + 'struct': _FArc_format, + 'compression_support': False, + 'compression_forced': False, + 'fixed_header_size': 4, + 'files_header_fields_size': 8, + }, + 'FArC': { + 'remarks': 'farc with compression support', + 'struct': _FArC_format, + 'compression_support': True, + 'compression_forced': True, + 'fixed_header_size': 4, + 'files_header_fields_size': 12, + }, +} + +class UnsupportedFarcTypeException(Exception): + pass + +def check_farc_type(t): + """Checks if a farc type is supported and returns a remarks string. Raises UnsupportedFarcTypeException if not supported.""" + + if not t in _farc_types: + raise UnsupportedFarcTypeException("{} type not supported".format(t)) + + return _farc_types[t]['remarks'] + + +def _files_header_size_calc(files, farc_type): + """Sums the size of the files header section for the given files and farc_type data.""" + + size = 0 + for fname, info in files.items(): + size += len(fname) + 1 + size += farc_type['files_header_fields_size'] + return size + +def _prep_files(files, alignment, farc_type): + """Gets files ready for writing by compressing them and calculating pointers.""" + + def _compress_files(files, farc_type): + for fname, info in files.items(): + info['data_compressed'] = gzip.compress(info['data'], mtime=39) # set mtime for reproducible output + if (not farc_type['compression_forced']) and (len(info['data_compressed']) >= len(info['data'])): + info['data_compressed'] = info['data'] + + def _set_files_pointers(files, alignment, farc_type): + pos = 8 + farc_type['fixed_header_size'] + _files_header_size_calc(files, farc_type) + + for fname, info in files.items(): + if pos % alignment: pos += alignment - (pos % alignment) + info['pointer'] = pos + if 'data_compressed' in info: + pos += len(info['data_compressed']) + else: + pos += len(info['data']) + + if farc_type['compression_support']: + _compress_files(files, farc_type) + _set_files_pointers(files, alignment, farc_type) + +def to_bytes(data, alignment=1, no_copy=False): + """ + Converts a farc dictionary (formatted like the dictionary returned by from_bytes) to an in-memory bytes object containing farc data. + + Set no_copy to True for a speedup and memory usage reduction if you don't mind your input data being contaminated. + """ + + magic_str = data['farc_type'] + check_farc_type(magic_str) + farc_type = _farc_types[magic_str] + + if no_copy: + files = data['files'] + else: + files = deepcopy(data['files']) + _prep_files(files, alignment, farc_type) + + if farc_type['compression_support']: + return farc_type['struct'].build(dict( + header_size=farc_type['fixed_header_size'] + _files_header_size_calc(files, farc_type), + alignment=alignment, + files=[dict( + name=fname, + pointer=info['pointer'], + compressed_size=len(info['data_compressed']), + uncompressed_size=len(info['data']), + data=info['data_compressed'] + ) for fname, info in files.items()] + )) + else: + return farc_type['struct'].build(dict( + header_size=farc_type['fixed_header_size'] + _files_header_size_calc(files, farc_type), + alignment=alignment, + files=[dict( + name=fname, + pointer=info['pointer'], + size=len(info['data']), + data=info['data'] + ) for fname, info in files.items()] + )) + +def to_stream(data, stream, alignment=1, no_copy=False): + """ + Converts a farc dictionary (formatted like the dictionary returned by from_stream) to farc data and writes it to a stream. + + Set no_copy to True for a speedup and memory usage reduction if you don't mind your input data being contaminated. + """ + + magic_str = data['farc_type'] + check_farc_type(magic_str) + farc_type = _farc_types[magic_str] + + if no_copy: + files = data['files'] + else: + files = deepcopy(data['files']) + _prep_files(files, alignment, farc_type) + + if farc_type['compression_support']: + return farc_type['struct'].build_stream(dict( + header_size=farc_type['fixed_header_size'] + _files_header_size_calc(files, farc_type), + alignment=alignment, + files=[dict( + name=fname, + pointer=info['pointer'], + compressed_size=len(info['data_compressed']), + uncompressed_size=len(info['data']), + data=info['data_compressed'] + ) for fname, info in files.items()] + ), stream) + else: + return farc_type['struct'].build_stream(dict( + header_size=farc_type['fixed_header_size'] + _files_header_size_calc(files, farc_type), + alignment=alignment, + files=[dict( + name=fname, + pointer=info['pointer'], + size=len(info['data']), + data=info['data'] + ) for fname, info in files.items()] + ), stream) + + +def _parsed_to_dict(farcdata, farc_type): + """Converts the raw construct data to our standard dictionary format.""" + + files = {} + + if farc_type['compression_support']: + for f in farcdata['files']: + if farc_type['compression_forced'] or (f['uncompressed_size'] != f['compressed_size']): + data = gzip.decompress(f['data']) + else: + data = f['data'] + files[f['name']] = {'data': data} + else: + for f in farcdata['files']: + data = f['data'] + files[f['name']] = {'data': data} + + return {'farc_type': farcdata['signature'].decode('ascii'), 'files': files} + +def from_bytes(b): + """Converts farc data from bytes to a dictionary.""" + + magic_str = b[:4].decode('ascii') + check_farc_type(magic_str) + farc_type = _farc_types[magic_str] + + farcdata = farc_type['struct'].parse(b) + return _parsed_to_dict(farcdata, farc_type) + +def from_stream(s): + """Converts farc data from a stream to a dictionary.""" + + pos = s.tell() + magic_str = s.read(4).decode('ascii') + check_farc_type(magic_str) + farc_type = _farc_types[magic_str] + s.seek(pos) + + farcdata = farc_type['struct'].parse_stream(s) + return _parsed_to_dict(farcdata, farc_type) + + +#test_farc = {'farc_type': 'FArc', 'files': {'aaa': {'data': b'test1'}, 'bbb': {'data': b'test2'}, 'ccc': {'data': b'aaaaaaaaaaaaaaaaaaaaaaaa'}}} +test_farc = {'farc_type': 'FArC', 'files': {'aaa': {'data': b'test1'}, 'bbb': {'data': b'test2'}, 'ccc': {'data': b'aaaaaaaaaaaaaaaaaaaaaaaa'}}} +#print (test_farc) + +#test_bytes = to_bytes(test_farc, alignment=16) +#print (test_bytes) +#print (from_bytes(test_bytes)) + +#with open('test.farc', 'wb') as f: +# to_stream(test_farc, f, alignment=16) +#with open('test.farc', 'rb') as f: +# print (from_stream(f)) + +#with open('shader_amd.farc', 'rb') as f: +# shaderfarc = from_stream(f) +#with open('shader_amd_out.farc', 'wb') as f: +# to_stream(shaderfarc, f, alignment=16, no_copy=True) + +#with open('shader_amd_compressed.farc', 'rb') as f: +# shaderfarc = from_stream(f) +#with open('shader_amd_out_compressed.farc', 'wb') as f: +# to_stream(shaderfarc, f, alignment=1, no_copy=True) + +#with open('fontmap.farc', 'rb') as f: +# fontmapfarc = from_stream(f) +#with open('fontmap_out.farc', 'wb') as f: +# to_stream(fontmapfarc, f, alignment=1, no_copy=True) \ No newline at end of file diff --git a/source-code/data/amd-tools/AFT Shader Patcher/xdelta3.exe b/source-code/data/amd-tools/AFT Shader Patcher/xdelta3.exe new file mode 100644 index 0000000..f3532d4 Binary files /dev/null and b/source-code/data/amd-tools/AFT Shader Patcher/xdelta3.exe differ diff --git a/source-code/data/amd-tools/FarcPack.exe b/source-code/data/amd-tools/FarcPack.exe deleted file mode 100644 index fe90b45..0000000 Binary files a/source-code/data/amd-tools/FarcPack.exe and /dev/null differ diff --git a/source-code/data/amd-tools/MikuMikuLibrary.dll b/source-code/data/amd-tools/MikuMikuLibrary.dll deleted file mode 100644 index e331492..0000000 Binary files a/source-code/data/amd-tools/MikuMikuLibrary.dll and /dev/null differ diff --git a/source-code/data/amd-tools/README.txt b/source-code/data/amd-tools/README.txt index 615993a..2f7f9a3 100644 --- a/source-code/data/amd-tools/README.txt +++ b/source-code/data/amd-tools/README.txt @@ -1,34 +1,236 @@ PD Loader Tools for AMD Compatibility ===================================== -Use the files here to patch your shaders to work (with Novidia) on AMD GPUs. +The Novidia plugin and its included shader patch data will allow Project DIVA +Arcade: Future Tone to work on AMD GPUs. -Instructions: - 1. Copy amd-tools and plugins folders to your game directory. - 2. Run "patch shaders" from amd-tools. This may take several minutes. - **WARNING** This will overwrite shader_amd.farc from existing MAMD mdata! +Usage Instructions: + Simply copy the plugins folder to your game directory. -ARB Patcher was developed with a lot of help from Nezarn, without whom AMD -support would not be possible. +================================================================================ +AFT Shader Patcher can be used to attempt patching modded Nvidia-only shaders to +also work. +Patch Creation Instructions: + 1. Extract amd-tools. + 2. Copy your modified shader.farc into your extracted amd-tools folder. + 3. Run "patch shaders". This may take several minutes. + 4. Copy the "XXXXXXXX.vcdiff" file into your "plugins\Novidia Shaders" folder. + 5. Install the shader mod like you would normally using shader.farc. + 6. Novidia will automatically apply the generated patches. + * shader_patched.farc is an intermediate file and can be safely deleted. +================================================================================ -FarcPack is from MikuMikuLibrary, licensed under MIT license: +ARB Patcher, the tool used to make modifications to shaders, was developed with +a lot of help from Nezarn, without whom AMD support would not be possible. + +================================================================================ + +Novidia and AFT Shader Patcher use xdelta3, licensed under the Apache License +Version 2.0: - Copyright (c) 2020 Skyth + Xdelta version 3.0.12, Copyright (C) Joshua MacDonald + Xdelta version 3.1.1, Copyright (C) Joshua MacDonald - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ - - The above copyright notice and this permission notice shall be included in all + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + +Novidia uses Microsoft Detours, licensed under MIT License: + + # Copyright (c) Microsoft Corporation + + All rights reserved. + + # MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER @@ -37,7 +239,8 @@ FarcPack is from MikuMikuLibrary, licensed under MIT license: SOFTWARE. -ARB Patcher includes (parts of) Python 3.8, licensed under PSF License 2.0: +AFT Shader Patcher and ARB Patcher include (parts of) Python 3.8, licensed +under PSF License 2.0: 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and @@ -86,7 +289,7 @@ ARB Patcher includes (parts of) Python 3.8, licensed under PSF License 2.0: Agreement. -ARB Patcher is built using cx_Freeze, licensed under cx_Freeze license: +AFT Shader Patcher is built using cx_Freeze, licensed under cx_Freeze license: * Copyright © 2007-2020, Anthony Tuininga. * Copyright © 2001-2006, Computronix (Canada) Ltd., Edmonton, Alberta, Canada. @@ -133,4 +336,30 @@ ARB Patcher is built using cx_Freeze, licensed under cx_Freeze license: 8. By copying, installing or otherwise using cx_Freeze, Licensee agrees to be bound by the terms and conditions of this License Agreement. - Computronix® is a registered trademark of Computronix (Canada) Ltd. \ No newline at end of file + Computronix® is a registered trademark of Computronix (Canada) Ltd. + + +pyfarc (used by AFT Shader Patcher) uses construct, licensed under MIT License: + + Copyright (C) 2006-2020 + Arkadiusz Bulski (arek.bulski@gmail.com) + Tomer Filiba (tomerfiliba@gmail.com) + Corbin Simpson (MostAwesomeDude@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. \ No newline at end of file diff --git a/source-code/data/amd-tools/info.txt b/source-code/data/amd-tools/info.txt deleted file mode 100644 index 885e083..0000000 --- a/source-code/data/amd-tools/info.txt +++ /dev/null @@ -1,3 +0,0 @@ -#mdata_info -depend.length=0 -version=20161030 diff --git a/source-code/data/amd-tools/patch shaders py.bat b/source-code/data/amd-tools/patch shaders py.bat index 43b32d0..51a3980 100644 --- a/source-code/data/amd-tools/patch shaders py.bat +++ b/source-code/data/amd-tools/patch shaders py.bat @@ -1,10 +1 @@ -FarcPack ..\rom\shader.farc shader_unpacked -"ARB Patcher Source\main.py" -i shader_unpacked -o shader_patched -g divaaft -mkdir ..\mdata\MAMD -mkdir ..\mdata\MAMD\rom -copy info.txt ..\mdata\MAMD\ -FarcPack -c shader_patched ..\mdata\MAMD\rom\shader_amd.farc -del /Q shader_unpacked -rmdir shader_unpacked -del /Q shader_patched -rmdir shader_patched \ No newline at end of file +"AFT Shader Patcher\aft_shader_patcher.py" -i shader.farc -o shader_patched.farc --xdelta \ No newline at end of file diff --git a/source-code/data/amd-tools/patch shaders.bat b/source-code/data/amd-tools/patch shaders.bat index 7ad267c..562406f 100644 --- a/source-code/data/amd-tools/patch shaders.bat +++ b/source-code/data/amd-tools/patch shaders.bat @@ -1,10 +1 @@ -FarcPack ..\rom\shader.farc shader_unpacked -"ARB Patcher\main.exe" -i shader_unpacked -o shader_patched -g divaaft -mkdir ..\mdata\MAMD -mkdir ..\mdata\MAMD\rom -copy info.txt ..\mdata\MAMD\ -FarcPack -c shader_patched ..\mdata\MAMD\rom\shader_amd.farc -del /Q shader_unpacked -rmdir shader_unpacked -del /Q shader_patched -rmdir shader_patched \ No newline at end of file +"AFT Shader Patcher\aft_shader_patcher.exe" -i shader.farc -o shader_patched.farc --xdelta \ No newline at end of file