diff options
| author | Aetias <aetias@outlook.com> | 2025-02-04 21:30:00 +0100 |
|---|---|---|
| committer | Aetias <aetias@outlook.com> | 2025-02-04 21:30:00 +0100 |
| commit | c380ac51a48d17348b1cdcbb615ce22be22f409e (patch) | |
| tree | 6713ed5a1cd172f665e52ea0f995fc905ca3db2d /tools | |
| parent | 8cda3ca2d7f5fe424cc1a649baec2ff992368e62 (diff) | |
| parent | 3f7197110627adbbe7ff1f69db1f5a15f9b6c598 (diff) | |
Merge remote-tracking branch 'zeldaret/main' into decomp-PlayerControl
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/configure.py | 45 | ||||
| -rwxr-xr-x | tools/m2ctx.py | 7 | ||||
| -rw-r--r-- | tools/mangle.py | 30 | ||||
| -rw-r--r-- | tools/setup.py | 4 | ||||
| -rw-r--r-- | tools/sha1.py | 29 | ||||
| -rw-r--r-- | tools/transform_dep.py | 84 |
6 files changed, 175 insertions, 24 deletions
diff --git a/tools/configure.py b/tools/configure.py index b1416e0f..26f7e86e 100644 --- a/tools/configure.py +++ b/tools/configure.py @@ -27,7 +27,7 @@ CC_FLAGS = " ".join([ "-proc arm946e", # Target processor "-gccext,on", # Enable GCC extensions "-fp soft", # Compute float operations in software - "-inline on,noauto", # Inline only functions marked with 'inline' + "-inline noauto", # Inline only functions marked with 'inline' "-lang=c++", # Set language to C++ "-Cpp_exceptions off", # Disable C++ exceptions "-RTTI off", # Disable runtime type information @@ -82,7 +82,7 @@ CC_INCLUDES = " ".join(f"-i {include}" for include in includes) EXE = "" WINE = "" system = platform.system() -if system == "Windows" or system.startswith("MSYS") or system.startswith("MINGW"): +if system == "Windows": system = "windows" EXE = ".exe" elif system == "Linux": @@ -129,9 +129,17 @@ def main(): ) n.newline() + # -MMD excludes all includes instead of just system includes for some reason, so use -MD instead. + mwcc_cmd = f'{WINE} "{mwcc_path}/mwccarm.exe" {CC_FLAGS} {CC_INCLUDES} $cc_flags -d $game_version -MD -c $in -o $basedir' + mwcc_implicit = [] + if system != "windows": + transform_dep = "tools/transform_dep.py" + mwcc_cmd += f" && $python {transform_dep} $basefile.d $basefile.d" + mwcc_implicit.append(transform_dep) n.rule( name="mwcc", - command=f'{WINE} "{mwcc_path}/mwccarm.exe" {CC_FLAGS} {CC_INCLUDES} $cc_flags -d $game_version $in -o $out' + command=mwcc_cmd, + depfile="$basefile.d", ) n.newline() @@ -171,12 +179,18 @@ def main(): ) n.newline() + n.rule( + name="sha1", + command=f"{PYTHON} tools/sha1.py $in -c $sha1_file" + ) + n.newline() + game_build = build_path / game_version game_extract = extract_path / game_version add_extract_build(n, game_extract, game_version) add_delink_and_lcf_builds(n, game_config, game_build, game_extract) - add_mwcc_builds(n, game_version, game_build) + add_mwcc_builds(n, game_version, game_build, mwcc_implicit) add_mwld_and_rom_builds(n, game_build, game_config, game_version) @@ -241,21 +255,34 @@ def add_mwld_and_rom_builds(n: ninja_syntax.Writer, game_build: Path, game_confi ) n.newline() + n.build( + inputs=rom_file, + rule="sha1", + variables={ + "sha1_file": str(Path(rom_file).with_suffix(".sha1")) + }, + outputs="sha1", + ) + n.newline() + -def add_mwcc_builds(n: ninja_syntax.Writer, game_version: str, game_build: Path): +def add_mwcc_builds(n: ninja_syntax.Writer, game_version: str, game_build: Path, mwcc_implicit: list[Path]): for source_file in get_c_cpp_files([src_path, libs_path]): - output_file = str(game_build / source_file.with_suffix(".o")) + src_obj_path = game_build / source_file cc_flags = [] if is_cpp(source_file): cc_flags.append("-lang=c++") elif is_c(source_file): cc_flags.append("-lang=c") n.build( inputs=str(source_file), rule="mwcc", - outputs=output_file, + outputs=str(src_obj_path.with_suffix(".o")), variables={ "game_version": game_version, - "cc_flags": " ".join(cc_flags) - } + "cc_flags": " ".join(cc_flags), + "basedir": os.path.dirname(src_obj_path), + "basefile": str(src_obj_path.with_suffix("")), + }, + implicit=mwcc_implicit, ) n.newline() diff --git a/tools/m2ctx.py b/tools/m2ctx.py index dc43f326..f2275e33 100755 --- a/tools/m2ctx.py +++ b/tools/m2ctx.py @@ -21,7 +21,8 @@ CXX_FLAGS = [ '-nostdinc', '-Iinclude', '-Ilibs/c/include', - '-Ilibs/cpp/include' + '-Ilibs/cpp/include', + '-Ilibs/nds/include' ] script_dir = Path(os.path.dirname(os.path.realpath(__file__))) @@ -37,8 +38,8 @@ COMMENT_REGEX = r'\/\/.*$|\/\*(?:.|\r|\n)+?\*\/' with open(args.file, 'r') as f: contents = f.read() -contents = re.sub(COMMENT_REGEX, '', contents, 0, re.MULTILINE) -includes = re.findall(INCLUDE_REGEX, contents, re.MULTILINE) +contents = re.sub(COMMENT_REGEX, '', contents, count=0, flags=re.MULTILINE) +includes = re.findall(INCLUDE_REGEX, contents, flags=re.MULTILINE) _, suffix = os.path.splitext(args.file) diff --git a/tools/mangle.py b/tools/mangle.py index 68d2aeb3..0d173788 100644 --- a/tools/mangle.py +++ b/tools/mangle.py @@ -15,6 +15,7 @@ include_dir = root_dir / 'include' libs_dir = root_dir / 'libs' libc_include_dir = libs_dir / 'c' / 'include' libcpp_include_dir = libs_dir / 'cpp' / 'include' +libnds_include_dir = libs_dir / 'nds' / 'include' if platform.system() == 'Windows': cc = [str(cc_path)] else: cc = ['wine', str(cc_path)] @@ -27,7 +28,7 @@ cc.extend([ '-proc', 'arm946e', '-gccext,on', '-fp', 'soft', - '-inline', 'on,noauto', + '-inline', 'noauto', '-Cpp_exceptions', 'off', '-RTTI', 'off', '-interworking', @@ -38,6 +39,7 @@ cc.extend([ '-i', include_dir, '-i', libc_include_dir, '-i', libcpp_include_dir, + '-i', libnds_include_dir, args.file ]) @@ -52,19 +54,27 @@ output = output.decode() # print(output) mangled_funcs: list[str] = re.findall(r'.text +([^\$ ]\S+)', output) -mangled_data: list[str] = re.findall(r'(?:.data|.bss) +([^\. ]\S+)', output) +init_funcs: list[str] = re.findall(r'.init +([^\$ ]\S+)', output) +mangled_data: list[str] = re.findall(r'.data +([^\. ]\S+)', output) +mangled_bss: list[str] = re.findall(r'.bss +([^\. ]\S+)', output) if len(mangled_funcs) > 0: - print('Functions:') - print() + print('.text:\n') for func in mangled_funcs: print(func) - print() - print() + print('\n') +if len(init_funcs) > 0: + print('.init:\n') + for func in init_funcs: + print(func) + print('\n') if len(mangled_data) > 0: - print('Data:') - print() + print('.data:\n') for data in mangled_data: print(data) - print() - print() + print('\n') +if len(mangled_bss) > 0: + print('.bss:\n') + for bss in mangled_bss: + print(bss) + print('\n') diff --git a/tools/setup.py b/tools/setup.py index 44d146f7..bc322e1d 100644 --- a/tools/setup.py +++ b/tools/setup.py @@ -4,7 +4,7 @@ import io from pathlib import Path import platform -DSD_VERSION = 'v0.2.3' +DSD_VERSION = 'v0.4.0' tools_path = Path(__file__).parent @@ -13,7 +13,7 @@ root_path = tools_path.parent EXE = "" system = platform.system() -if system == "Windows" or system.startswith("MSYS") or system.startswith("MINGW"): +if system == "Windows": system = "windows" EXE = ".exe" elif system == "Linux": diff --git a/tools/sha1.py b/tools/sha1.py new file mode 100644 index 00000000..8cd6edd8 --- /dev/null +++ b/tools/sha1.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +from pathlib import Path +import argparse +import hashlib +import sys + +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + +parser = argparse.ArgumentParser(description="Computes and verifies a SHA1 checksum") +parser.add_argument('file', help="Input file to verify") +parser.add_argument('-c', type=str, dest='checksum_file', required=False, help='Checksum file') +args = parser.parse_args() + +file_path = Path(args.file) +checksum_path = Path(args.checksum_file) + +with checksum_path.open('r') as file: + target_sha1, _ = file.readline().split(' ', 1) + +with file_path.open('rb') as file: + file_sha1 = hashlib.sha1(file.read()).hexdigest() + +if target_sha1 != file_sha1: + eprint(f"{file_path}: FAILED") + exit(1) +else: + eprint(f"{file_path}: OK") diff --git a/tools/transform_dep.py b/tools/transform_dep.py new file mode 100644 index 00000000..124de04b --- /dev/null +++ b/tools/transform_dep.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 + +### +# Transforms .d files, converting Windows paths to Unix paths. +# Allows usage of the mwcc -MMD flag on platforms other than Windows. +# +# Usage: +# python3 tools/transform_dep.py build/src/file.d build/src/file.d +# +# If changes are made, please submit a PR to +# https://github.com/encounter/dtk-template +### + +import argparse +import os +from platform import uname + +wineprefix = os.path.join(os.environ["HOME"], ".wine") +if "WINEPREFIX" in os.environ: + wineprefix = os.environ["WINEPREFIX"] +winedevices = os.path.join(wineprefix, "dosdevices") + + +def in_wsl() -> bool: + return "microsoft-standard" in uname().release + + +def import_d_file(in_file: str) -> str: + out_text = "" + + with open(in_file) as file: + for idx, line in enumerate(file): + if idx == 0: + if line.endswith(" \\\n"): + out_text += line[:-3].replace("\\", "/") + " \\\n" + else: + out_text += line.replace("\\", "/") + else: + suffix = "" + if line.endswith(" \\\n"): + suffix = " \\" + path = line.lstrip()[:-3] + else: + path = line.strip() + # lowercase drive letter + path = path[0].lower() + path[1:] + if path[0] == "z": + # shortcut for z: + path = path[2:].replace("\\", "/") + elif in_wsl(): + path = path[0:1] + path[2:] + path = os.path.join("/mnt", path.replace("\\", "/")) + else: + # use $WINEPREFIX/dosdevices to resolve path + path = os.path.realpath( + os.path.join(winedevices, path.replace("\\", "/")) + ) + out_text += "\t" + path + suffix + "\n" + + return out_text + + +def main() -> None: + parser = argparse.ArgumentParser( + description="""Transform a .d file from Wine paths to normal paths""" + ) + parser.add_argument( + "d_file", + help="""Dependency file in""", + ) + parser.add_argument( + "d_file_out", + help="""Dependency file out""", + ) + args = parser.parse_args() + + output = import_d_file(args.d_file) + + with open(args.d_file_out, "w", encoding="UTF-8") as f: + f.write(output) + + +if __name__ == "__main__": + main() |
