Add progress categories

This commit is contained in:
Luke Street 2024-09-18 23:05:43 -06:00
parent da7e0244bc
commit 2c4c4fab4b
2 changed files with 83 additions and 62 deletions

View File

@ -15,8 +15,15 @@
import argparse import argparse
import sys import sys
from pathlib import Path 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 # Game versions
DEFAULT_VERSION = 0 DEFAULT_VERSION = 0
@ -125,7 +132,6 @@ config.dtk_path = args.dtk
config.objdiff_path = args.objdiff config.objdiff_path = args.objdiff
config.binutils_path = args.binutils config.binutils_path = args.binutils
config.compilers_path = args.compilers config.compilers_path = args.compilers
config.debug = args.debug
config.generate_map = args.map config.generate_map = args.map
config.non_matching = args.non_matching config.non_matching = args.non_matching
config.sjiswrap_path = args.sjiswrap config.sjiswrap_path = args.sjiswrap
@ -157,14 +163,10 @@ config.ldflags = [
"-fp hardware", "-fp hardware",
"-nodefaults", "-nodefaults",
] ]
if args.debug:
config.progress_all = False config.ldflags.append("-g")
config.progress_modules = False if args.map:
config.progress_use_fancy = True config.ldflags.append("-mapunused")
config.progress_code_fancy_frac = 1499
config.progress_code_fancy_item = "Energy"
config.progress_data_fancy_frac = 250
config.progress_data_fancy_item = "Missiles"
config.build_rels = False config.build_rels = False
@ -198,7 +200,7 @@ cflags_base = [
] ]
# Debug flags # Debug flags
if config.debug: if args.debug:
cflags_base.extend(["-sym on", "-DDEBUG=1"]) cflags_base.extend(["-sym on", "-DDEBUG=1"])
else: else:
cflags_base.append("-DNDEBUG=1") cflags_base.append("-DNDEBUG=1")
@ -277,20 +279,22 @@ config.linker_version = "GC/1.3.2"
# Helper function for Dolphin libraries # Helper function for Dolphin libraries
def DolphinLib(lib_name, objects): def DolphinLib(lib_name, objects):
return { return {
"lib": lib_name + "D" if config.debug else "", "lib": lib_name + "D" if args.debug else "",
"mw_version": "GC/1.2.5n", "mw_version": "GC/1.2.5n",
"cflags": cflags_base, "cflags": cflags_base,
"host": False, "host": False,
"progress_category": "sdk",
"objects": objects, "objects": objects,
} }
def RetroLib(lib_name, objects): def RetroLib(lib_name, progress_category, objects):
return { 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", "mw_version": "GC/1.3.2",
"cflags": cflags_retro, "cflags": cflags_retro,
"host": False, "host": False,
"progress_category": progress_category,
"objects": objects, "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_MINOR={minor}",
f"-DMUSY_VERSION_PATCH={patch}", f"-DMUSY_VERSION_PATCH={patch}",
], ],
"progress_category": "third_party",
"objects": objects, "objects": objects,
} }
@ -319,6 +324,7 @@ def Rel(lib_name, objects):
"mw_version": "GC/1.3.2", "mw_version": "GC/1.3.2",
"cflags": cflags_rel, "cflags": cflags_rel,
"host": True, "host": True,
"progress_category": "third_party",
"objects": objects, "objects": objects,
} }
@ -340,6 +346,7 @@ config.libs = [
), ),
RetroLib( RetroLib(
"MetroidPrime", "MetroidPrime",
"game",
[ [
Object(NonMatching, "MetroidPrime/main.cpp"), Object(NonMatching, "MetroidPrime/main.cpp"),
Object(NonMatching, "MetroidPrime/IRenderer.cpp"), Object(NonMatching, "MetroidPrime/IRenderer.cpp"),
@ -723,6 +730,7 @@ config.libs = [
), ),
RetroLib( RetroLib(
"WorldFormat", "WorldFormat",
"core",
[ [
Object(NonMatching, "WorldFormat/CAreaOctTree_Tests.cpp"), Object(NonMatching, "WorldFormat/CAreaOctTree_Tests.cpp"),
Object(Matching, "WorldFormat/CCollisionSurface.cpp"), Object(Matching, "WorldFormat/CCollisionSurface.cpp"),
@ -740,6 +748,7 @@ config.libs = [
), ),
RetroLib( RetroLib(
"Weapons", "Weapons",
"core",
[ [
Object(NonMatching, "Weapons/CProjectileWeapon.cpp"), Object(NonMatching, "Weapons/CProjectileWeapon.cpp"),
Object(NonMatching, "Weapons/CProjectileWeaponDataFactory.cpp"), Object(NonMatching, "Weapons/CProjectileWeaponDataFactory.cpp"),
@ -753,12 +762,14 @@ config.libs = [
), ),
RetroLib( RetroLib(
"MetaRender", "MetaRender",
"core",
[ [
Object(NonMatching, "MetaRender/CCubeRenderer.cpp"), Object(NonMatching, "MetaRender/CCubeRenderer.cpp"),
], ],
), ),
RetroLib( RetroLib(
"GuiSys", "GuiSys",
"core",
[ [
Object(Matching, "GuiSys/CAuiMain.cpp"), Object(Matching, "GuiSys/CAuiMain.cpp"),
Object(NonMatching, "GuiSys/CAuiMeter.cpp"), Object(NonMatching, "GuiSys/CAuiMeter.cpp"),
@ -783,6 +794,7 @@ config.libs = [
), ),
RetroLib( RetroLib(
"Collision", "Collision",
"core",
[ [
Object(NonMatching, "Collision/CCollidableAABox.cpp"), Object(NonMatching, "Collision/CCollidableAABox.cpp"),
Object(Matching, "Collision/CCollidableCollisionSurface.cpp"), Object(Matching, "Collision/CCollidableCollisionSurface.cpp"),
@ -799,6 +811,7 @@ config.libs = [
), ),
RetroLib( RetroLib(
"Kyoto1", "Kyoto1",
"core",
[ [
Object(Matching, "Kyoto/Basics/CBasics.cpp"), Object(Matching, "Kyoto/Basics/CBasics.cpp"),
Object(Matching, "Kyoto/Basics/CStopwatch.cpp"), Object(Matching, "Kyoto/Basics/CStopwatch.cpp"),
@ -958,6 +971,7 @@ config.libs = [
"mw_version": "GC/1.3.2", "mw_version": "GC/1.3.2",
"cflags": cflags_runtime, "cflags": cflags_runtime,
"host": False, "host": False,
"progress_category": "third_party",
"objects": [ "objects": [
Object(Matching, "Kyoto/zlib/adler32.c"), Object(Matching, "Kyoto/zlib/adler32.c"),
Object(Matching, "Kyoto/zlib/deflate.c"), Object(Matching, "Kyoto/zlib/deflate.c"),
@ -974,6 +988,7 @@ config.libs = [
# TODO: Merge this with zlib and Kyoto1 # TODO: Merge this with zlib and Kyoto1
RetroLib( RetroLib(
"Kyoto2", "Kyoto2",
"core",
[ [
Object(Matching, "Kyoto/CARAMManager.cpp"), Object(Matching, "Kyoto/CARAMManager.cpp"),
Object(NonMatching, "Kyoto/Math/CFrustumPlanes.cpp"), Object(NonMatching, "Kyoto/Math/CFrustumPlanes.cpp"),
@ -1155,6 +1170,7 @@ config.libs = [
"mw_version": "GC/1.3.2", "mw_version": "GC/1.3.2",
"cflags": cflags_runtime, "cflags": cflags_runtime,
"host": False, "host": False,
"progress_category": "sdk",
"objects": [ "objects": [
Object(Matching, "Runtime/__mem.c"), Object(Matching, "Runtime/__mem.c"),
Object(Matching, "Runtime/__va_arg.c"), Object(Matching, "Runtime/__va_arg.c"),
@ -1343,10 +1359,19 @@ config.libs = [
# Optional extra categories for progress tracking # Optional extra categories for progress tracking
config.progress_categories = [ config.progress_categories = [
# ProgressCategory("game", "Game Code"), ProgressCategory("game", "Game"),
# ProgressCategory("sdk", "SDK Code"), 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_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": if args.mode == "configure":
# Write build.ninja and objdiff.json # Write build.ninja and objdiff.json

View File

@ -131,7 +131,6 @@ class ProjectConfig:
self.build_rels: bool = True # Build REL files self.build_rels: bool = True # Build REL files
self.check_sha_path: Optional[Path] = None # Path to version.sha1 self.check_sha_path: Optional[Path] = None # Path to version.sha1
self.config_path: Optional[Path] = None # Path to config.yml 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.generate_map: bool = False # Generate map file(s)
self.asflags: Optional[List[str]] = None # Assembler flags self.asflags: Optional[List[str]] = None # Assembler flags
self.ldflags: Optional[List[str]] = None # Linker 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 "" EXE = ".exe" if is_windows() else ""
def make_flags_str(cflags: Union[str, List[str]]) -> str: def make_flags_str(flags: Optional[Union[str, List[str]]]) -> str:
if isinstance(cflags, list): if flags is None:
return " ".join(cflags) return ""
elif isinstance(flags, list):
return " ".join(flags)
else: else:
return cflags return flags
# Load decomp-toolkit generated config.json # Load decomp-toolkit generated config.json
@ -235,14 +236,14 @@ def load_build_config(
build_config: Dict[str, Any] = json.load(f) build_config: Dict[str, Any] = json.load(f)
config_version = build_config.get("version") config_version = build_config.get("version")
if config_version is None: if config_version is None:
# Invalid config.json print("Invalid config.json, regenerating...")
f.close() f.close()
os.remove(build_config_path) os.remove(build_config_path)
return None return None
dtk_version = str(config.dtk_tag)[1:] # Strip v dtk_version = str(config.dtk_tag)[1:] # Strip v
if versiontuple(config_version) < versiontuple(dtk_version): if versiontuple(config_version) < versiontuple(dtk_version):
# Outdated config.json print("Outdated config.json, regenerating...")
f.close() f.close()
os.remove(build_config_path) os.remove(build_config_path)
return None return None
@ -283,12 +284,7 @@ def generate_build_ninja(
# Variables # Variables
### ###
n.comment("Variables") n.comment("Variables")
ldflags = " ".join(config.ldflags or []) n.variable("ldflags", make_flags_str(config.ldflags))
if config.generate_map:
ldflags += " -mapunused"
if config.debug:
ldflags += " -g"
n.variable("ldflags", ldflags)
if config.linker_version is None: if config.linker_version is None:
sys.exit("ProjectConfig.linker_version missing") sys.exit("ProjectConfig.linker_version missing")
n.variable("mw_version", Path(config.linker_version)) n.variable("mw_version", Path(config.linker_version))
@ -1194,7 +1190,6 @@ def generate_objdiff_config(
} }
# decomp.me compiler name mapping # decomp.me compiler name mapping
# Commented out versions have not been added to decomp.me yet
COMPILER_MAP = { COMPILER_MAP = {
"GC/1.0": "mwcc_233_144", "GC/1.0": "mwcc_233_144",
"GC/1.1": "mwcc_233_159", "GC/1.1": "mwcc_233_159",
@ -1371,16 +1366,11 @@ def calculate_progress(config: ProjectConfig) -> None:
def __init__(self, name: str) -> None: def __init__(self, name: str) -> None:
self.name: str = name self.name: str = name
self.code_total: int = 0 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.code_progress: int = 0
self.data_total: 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.data_progress: int = 0
self.objects_progress: int = 0
self.objects_total: int = 0
self.objects: Set[Object] = set() self.objects: Set[Object] = set()
self.objects_progress: int = 0
def add(self, build_obj: Dict[str, Any]) -> None: def add(self, build_obj: Dict[str, Any]) -> None:
self.code_total += build_obj["code_size"] 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 include_object = build_obj["name"] not in self.objects
if include_object: if include_object:
self.objects.add(build_obj["name"]) self.objects.add(build_obj["name"])
self.objects_total += 1
if build_obj["autogenerated"]: if build_obj["autogenerated"]:
# Skip autogenerated objects # Skip autogenerated objects
@ -1406,9 +1395,13 @@ def calculate_progress(config: ProjectConfig) -> None:
self.objects_progress += 1 self.objects_progress += 1
def code_frac(self) -> float: def code_frac(self) -> float:
if self.code_total == 0:
return 1.0
return self.code_progress / self.code_total return self.code_progress / self.code_total
def data_frac(self) -> float: def data_frac(self) -> float:
if self.data_total == 0:
return 1.0
return self.data_progress / self.data_total return self.data_progress / self.data_total
progress_units: Dict[str, ProgressUnit] = {} progress_units: Dict[str, ProgressUnit] = {}
@ -1461,44 +1454,47 @@ def calculate_progress(config: ProjectConfig) -> None:
# Print human-readable progress # Print human-readable progress
print("Progress:") print("Progress:")
def print_category(unit: Optional[ProgressUnit]) -> None: for unit in progress_units.values():
if unit is None: 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 return
code_frac = unit.code_frac() code_frac = unit.code_frac()
data_frac = unit.data_frac() data_frac = unit.data_frac()
print( print(
f" {unit.name}: {code_frac:.2%} code, {data_frac:.2%} data ({unit.objects_progress} / {unit.objects_total} files)" "\nYou have {} out of {} {} and {} out of {} {}.".format(
) math.floor(code_frac * config.progress_code_fancy_frac),
print(f" Code: {unit.code_progress} / {unit.code_total} bytes") config.progress_code_fancy_frac,
print(f" Data: {unit.data_progress} / {unit.data_total} bytes") config.progress_code_fancy_item,
if config.progress_use_fancy: math.floor(data_frac * config.progress_data_fancy_frac),
print( config.progress_data_fancy_frac,
"\nYou have {} out of {} {} and {} out of {} {}.".format( config.progress_data_fancy_item,
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,
)
) )
)
for progress in progress_units.values():
print_category(progress)
# Generate and write progress.json # Generate and write progress.json
progress_json: Dict[str, Any] = {} progress_json: Dict[str, Any] = {}
for id, unit in progress_units.items():
def add_category(category: str, unit: ProgressUnit) -> None: if len(unit.objects) == 0:
progress_json[category] = { continue
progress_json[id] = {
"code": unit.code_progress, "code": unit.code_progress,
"code/total": unit.code_total, "code/total": unit.code_total,
"data": unit.data_progress, "data": unit.data_progress,
"data/total": unit.data_total, "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: with open(out_path / "progress.json", "w", encoding="utf-8") as w:
json.dump(progress_json, w, indent=4) json.dump(progress_json, w, indent=4)