From 2c4c4fab4b52f62f3a393dc95f9f79a1eaeb0c51 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Wed, 18 Sep 2024 23:05:43 -0600 Subject: [PATCH] Add progress categories --- configure.py | 59 +++++++++++++++++++++++---------- tools/project.py | 86 +++++++++++++++++++++++------------------------- 2 files changed, 83 insertions(+), 62 deletions(-) diff --git a/configure.py b/configure.py index 444d0c07..7aded54b 100755 --- a/configure.py +++ b/configure.py @@ -15,8 +15,15 @@ import argparse import sys from pathlib import Path -from typing import Any, Dict, List -from tools.project import * + +from tools.project import ( + Object, + ProgressCategory, + ProjectConfig, + calculate_progress, + generate_build, + is_windows, +) # Game versions DEFAULT_VERSION = 0 @@ -125,7 +132,6 @@ config.dtk_path = args.dtk config.objdiff_path = args.objdiff config.binutils_path = args.binutils config.compilers_path = args.compilers -config.debug = args.debug config.generate_map = args.map config.non_matching = args.non_matching config.sjiswrap_path = args.sjiswrap @@ -157,14 +163,10 @@ config.ldflags = [ "-fp hardware", "-nodefaults", ] - -config.progress_all = False -config.progress_modules = False -config.progress_use_fancy = True -config.progress_code_fancy_frac = 1499 -config.progress_code_fancy_item = "Energy" -config.progress_data_fancy_frac = 250 -config.progress_data_fancy_item = "Missiles" +if args.debug: + config.ldflags.append("-g") +if args.map: + config.ldflags.append("-mapunused") config.build_rels = False @@ -198,7 +200,7 @@ cflags_base = [ ] # Debug flags -if config.debug: +if args.debug: cflags_base.extend(["-sym on", "-DDEBUG=1"]) else: cflags_base.append("-DNDEBUG=1") @@ -277,20 +279,22 @@ config.linker_version = "GC/1.3.2" # Helper function for Dolphin libraries def DolphinLib(lib_name, objects): return { - "lib": lib_name + "D" if config.debug else "", + "lib": lib_name + "D" if args.debug else "", "mw_version": "GC/1.2.5n", "cflags": cflags_base, "host": False, + "progress_category": "sdk", "objects": objects, } -def RetroLib(lib_name, objects): +def RetroLib(lib_name, progress_category, objects): return { - "lib": lib_name + "CW" + "D" if config.debug else "", + "lib": lib_name + "CW" + "D" if args.debug else "", "mw_version": "GC/1.3.2", "cflags": cflags_retro, "host": False, + "progress_category": progress_category, "objects": objects, } @@ -308,6 +312,7 @@ def MusyX(objects, mw_version="GC/1.3.2", debug=False, major=2, minor=0, patch=0 f"-DMUSY_VERSION_MINOR={minor}", f"-DMUSY_VERSION_PATCH={patch}", ], + "progress_category": "third_party", "objects": objects, } @@ -319,6 +324,7 @@ def Rel(lib_name, objects): "mw_version": "GC/1.3.2", "cflags": cflags_rel, "host": True, + "progress_category": "third_party", "objects": objects, } @@ -340,6 +346,7 @@ config.libs = [ ), RetroLib( "MetroidPrime", + "game", [ Object(NonMatching, "MetroidPrime/main.cpp"), Object(NonMatching, "MetroidPrime/IRenderer.cpp"), @@ -723,6 +730,7 @@ config.libs = [ ), RetroLib( "WorldFormat", + "core", [ Object(NonMatching, "WorldFormat/CAreaOctTree_Tests.cpp"), Object(Matching, "WorldFormat/CCollisionSurface.cpp"), @@ -740,6 +748,7 @@ config.libs = [ ), RetroLib( "Weapons", + "core", [ Object(NonMatching, "Weapons/CProjectileWeapon.cpp"), Object(NonMatching, "Weapons/CProjectileWeaponDataFactory.cpp"), @@ -753,12 +762,14 @@ config.libs = [ ), RetroLib( "MetaRender", + "core", [ Object(NonMatching, "MetaRender/CCubeRenderer.cpp"), ], ), RetroLib( "GuiSys", + "core", [ Object(Matching, "GuiSys/CAuiMain.cpp"), Object(NonMatching, "GuiSys/CAuiMeter.cpp"), @@ -783,6 +794,7 @@ config.libs = [ ), RetroLib( "Collision", + "core", [ Object(NonMatching, "Collision/CCollidableAABox.cpp"), Object(Matching, "Collision/CCollidableCollisionSurface.cpp"), @@ -799,6 +811,7 @@ config.libs = [ ), RetroLib( "Kyoto1", + "core", [ Object(Matching, "Kyoto/Basics/CBasics.cpp"), Object(Matching, "Kyoto/Basics/CStopwatch.cpp"), @@ -958,6 +971,7 @@ config.libs = [ "mw_version": "GC/1.3.2", "cflags": cflags_runtime, "host": False, + "progress_category": "third_party", "objects": [ Object(Matching, "Kyoto/zlib/adler32.c"), Object(Matching, "Kyoto/zlib/deflate.c"), @@ -974,6 +988,7 @@ config.libs = [ # TODO: Merge this with zlib and Kyoto1 RetroLib( "Kyoto2", + "core", [ Object(Matching, "Kyoto/CARAMManager.cpp"), Object(NonMatching, "Kyoto/Math/CFrustumPlanes.cpp"), @@ -1155,6 +1170,7 @@ config.libs = [ "mw_version": "GC/1.3.2", "cflags": cflags_runtime, "host": False, + "progress_category": "sdk", "objects": [ Object(Matching, "Runtime/__mem.c"), Object(Matching, "Runtime/__va_arg.c"), @@ -1343,10 +1359,19 @@ config.libs = [ # Optional extra categories for progress tracking config.progress_categories = [ - # ProgressCategory("game", "Game Code"), - # ProgressCategory("sdk", "SDK Code"), + ProgressCategory("game", "Game"), + ProgressCategory("core", "Core Engine (Kyoto)"), + ProgressCategory("sdk", "SDK"), + ProgressCategory("third_party", "Third Party"), ] +config.progress_all = False config.progress_each_module = args.verbose +config.progress_modules = False +config.progress_use_fancy = True +config.progress_code_fancy_frac = 1499 +config.progress_code_fancy_item = "Energy" +config.progress_data_fancy_frac = 250 +config.progress_data_fancy_item = "Missiles" if args.mode == "configure": # Write build.ninja and objdiff.json diff --git a/tools/project.py b/tools/project.py index 639f5a13..d085c3b4 100644 --- a/tools/project.py +++ b/tools/project.py @@ -131,7 +131,6 @@ class ProjectConfig: self.build_rels: bool = True # Build REL files self.check_sha_path: Optional[Path] = None # Path to version.sha1 self.config_path: Optional[Path] = None # Path to config.yml - self.debug: bool = False # Build with debug info self.generate_map: bool = False # Generate map file(s) self.asflags: Optional[List[str]] = None # Assembler flags self.ldflags: Optional[List[str]] = None # Linker flags @@ -214,11 +213,13 @@ CHAIN = "cmd /c " if is_windows() else "" EXE = ".exe" if is_windows() else "" -def make_flags_str(cflags: Union[str, List[str]]) -> str: - if isinstance(cflags, list): - return " ".join(cflags) +def make_flags_str(flags: Optional[Union[str, List[str]]]) -> str: + if flags is None: + return "" + elif isinstance(flags, list): + return " ".join(flags) else: - return cflags + return flags # Load decomp-toolkit generated config.json @@ -235,14 +236,14 @@ def load_build_config( build_config: Dict[str, Any] = json.load(f) config_version = build_config.get("version") if config_version is None: - # Invalid config.json + print("Invalid config.json, regenerating...") f.close() os.remove(build_config_path) return None dtk_version = str(config.dtk_tag)[1:] # Strip v if versiontuple(config_version) < versiontuple(dtk_version): - # Outdated config.json + print("Outdated config.json, regenerating...") f.close() os.remove(build_config_path) return None @@ -283,12 +284,7 @@ def generate_build_ninja( # Variables ### n.comment("Variables") - ldflags = " ".join(config.ldflags or []) - if config.generate_map: - ldflags += " -mapunused" - if config.debug: - ldflags += " -g" - n.variable("ldflags", ldflags) + n.variable("ldflags", make_flags_str(config.ldflags)) if config.linker_version is None: sys.exit("ProjectConfig.linker_version missing") n.variable("mw_version", Path(config.linker_version)) @@ -1194,7 +1190,6 @@ def generate_objdiff_config( } # decomp.me compiler name mapping - # Commented out versions have not been added to decomp.me yet COMPILER_MAP = { "GC/1.0": "mwcc_233_144", "GC/1.1": "mwcc_233_159", @@ -1371,16 +1366,11 @@ def calculate_progress(config: ProjectConfig) -> None: def __init__(self, name: str) -> None: self.name: str = name self.code_total: int = 0 - self.code_fancy_frac: int = config.progress_code_fancy_frac - self.code_fancy_item: str = config.progress_code_fancy_item self.code_progress: int = 0 self.data_total: int = 0 - self.data_fancy_frac: int = config.progress_data_fancy_frac - self.data_fancy_item: str = config.progress_data_fancy_item self.data_progress: int = 0 - self.objects_progress: int = 0 - self.objects_total: int = 0 self.objects: Set[Object] = set() + self.objects_progress: int = 0 def add(self, build_obj: Dict[str, Any]) -> None: self.code_total += build_obj["code_size"] @@ -1390,7 +1380,6 @@ def calculate_progress(config: ProjectConfig) -> None: include_object = build_obj["name"] not in self.objects if include_object: self.objects.add(build_obj["name"]) - self.objects_total += 1 if build_obj["autogenerated"]: # Skip autogenerated objects @@ -1406,9 +1395,13 @@ def calculate_progress(config: ProjectConfig) -> None: self.objects_progress += 1 def code_frac(self) -> float: + if self.code_total == 0: + return 1.0 return self.code_progress / self.code_total def data_frac(self) -> float: + if self.data_total == 0: + return 1.0 return self.data_progress / self.data_total progress_units: Dict[str, ProgressUnit] = {} @@ -1461,44 +1454,47 @@ def calculate_progress(config: ProjectConfig) -> None: # Print human-readable progress print("Progress:") - def print_category(unit: Optional[ProgressUnit]) -> None: - if unit is None: + for unit in progress_units.values(): + if len(unit.objects) == 0: + continue + + code_frac = unit.code_frac() + data_frac = unit.data_frac() + print( + f" {unit.name}: {code_frac:.2%} code, {data_frac:.2%} data ({unit.objects_progress} / {len(unit.objects)} files)" + ) + print(f" Code: {unit.code_progress} / {unit.code_total} bytes") + print(f" Data: {unit.data_progress} / {unit.data_total} bytes") + + if config.progress_use_fancy: + unit = progress_units.get("all") or progress_units.get("dol") + if unit is None or len(unit.objects) == 0: return code_frac = unit.code_frac() data_frac = unit.data_frac() print( - f" {unit.name}: {code_frac:.2%} code, {data_frac:.2%} data ({unit.objects_progress} / {unit.objects_total} files)" - ) - print(f" Code: {unit.code_progress} / {unit.code_total} bytes") - print(f" Data: {unit.data_progress} / {unit.data_total} bytes") - if config.progress_use_fancy: - print( - "\nYou have {} out of {} {} and {} out of {} {}.".format( - math.floor(code_frac * unit.code_fancy_frac), - unit.code_fancy_frac, - unit.code_fancy_item, - math.floor(data_frac * unit.data_fancy_frac), - unit.data_fancy_frac, - unit.data_fancy_item, - ) + "\nYou have {} out of {} {} and {} out of {} {}.".format( + math.floor(code_frac * config.progress_code_fancy_frac), + config.progress_code_fancy_frac, + config.progress_code_fancy_item, + math.floor(data_frac * config.progress_data_fancy_frac), + config.progress_data_fancy_frac, + config.progress_data_fancy_item, ) - - for progress in progress_units.values(): - print_category(progress) + ) # Generate and write progress.json progress_json: Dict[str, Any] = {} - - def add_category(category: str, unit: ProgressUnit) -> None: - progress_json[category] = { + for id, unit in progress_units.items(): + if len(unit.objects) == 0: + continue + progress_json[id] = { "code": unit.code_progress, "code/total": unit.code_total, "data": unit.data_progress, "data/total": unit.data_total, } - for id, progress in progress_units.items(): - add_category(id, progress) with open(out_path / "progress.json", "w", encoding="utf-8") as w: json.dump(progress_json, w, indent=4)