mirror of
https://github.com/zeldaret/botw
synced 2026-05-23 15:01:35 -04:00
2204f46b0b
The intention was to catch functional regressions in non-matching functions but this doesn't actually work well because referenced code and data may have moved after a function was dumped, in which case the reference checker is unable to verify that function calls and data references are still correct. Considering this increases the amount of complexity in the checker and makes the workflow more complicated for contributors, let's just drop this mechanism. It isn't worth it. Putting binary files in the repo is also pretty meh.
102 lines
3.7 KiB
Python
Executable File
102 lines
3.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import argparse
|
|
from collections import defaultdict
|
|
from colorama import Back, Fore, Style
|
|
from util import utils
|
|
from util.utils import FunctionStatus
|
|
import typing as tp
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--csv", "-c", action="store_true",
|
|
help="Print a CSV line rather than a human-readable progress report")
|
|
parser.add_argument("--print-nm", "-n", action="store_true",
|
|
help="Print non-matching functions with major issues")
|
|
parser.add_argument("--print-eq", "-e", action="store_true",
|
|
help="Print non-matching functions with minor issues")
|
|
parser.add_argument("--print-ok", "-m", action="store_true",
|
|
help="Print matching functions")
|
|
args = parser.parse_args()
|
|
|
|
code_size_total = 0
|
|
num_total = 0
|
|
code_size: tp.DefaultDict[FunctionStatus, int] = defaultdict(int)
|
|
counts: tp.DefaultDict[FunctionStatus, int] = defaultdict(int)
|
|
|
|
for info in utils.get_functions():
|
|
code_size_total += info.size
|
|
num_total += 1
|
|
|
|
if not info.decomp_name:
|
|
continue
|
|
|
|
counts[info.status] += 1
|
|
code_size[info.status] += info.size
|
|
|
|
if not args.csv:
|
|
if info.status == FunctionStatus.NonMatching:
|
|
if args.print_nm:
|
|
print(f"{Fore.RED}NM{Fore.RESET} {utils.format_symbol_name(info.decomp_name)}")
|
|
elif info.status == FunctionStatus.Equivalent:
|
|
if args.print_eq:
|
|
print(f"{Fore.YELLOW}EQ{Fore.RESET} {utils.format_symbol_name(info.decomp_name)}")
|
|
elif info.status == FunctionStatus.Matching:
|
|
if args.print_ok:
|
|
print(f"{Fore.GREEN}OK{Fore.RESET} {utils.format_symbol_name(info.decomp_name)}")
|
|
elif info.status == FunctionStatus.Wip:
|
|
print(
|
|
f"{Back.RED}{Style.BRIGHT}{Fore.WHITE} WIP {Style.RESET_ALL} {utils.format_symbol_name(info.decomp_name)}{Style.RESET_ALL}")
|
|
|
|
|
|
def format_progress(label: str, num: int, size: int):
|
|
percentage = round(100 * num / num_total, 3)
|
|
size_percentage = round(100 * size / code_size_total, 3)
|
|
return f"{num:>7d} {label}{Fore.RESET} ({percentage}% | size: {size_percentage}%)"
|
|
|
|
|
|
def format_progress_for_status(label: str, status: FunctionStatus):
|
|
return format_progress(label, counts[status], code_size[status])
|
|
|
|
|
|
if args.csv:
|
|
import git
|
|
|
|
version = 1
|
|
git_object = git.Repo().head.object
|
|
timestamp = str(git_object.committed_date)
|
|
git_hash = git_object.hexsha
|
|
|
|
fields = [
|
|
str(version),
|
|
timestamp,
|
|
git_hash,
|
|
|
|
str(num_total),
|
|
str(code_size_total),
|
|
|
|
str(counts[FunctionStatus.Matching]),
|
|
str(code_size[FunctionStatus.Matching]),
|
|
|
|
str(counts[FunctionStatus.Equivalent]),
|
|
str(code_size[FunctionStatus.Equivalent]),
|
|
|
|
str(counts[FunctionStatus.NonMatching]),
|
|
str(code_size[FunctionStatus.NonMatching]),
|
|
]
|
|
print(",".join(fields))
|
|
|
|
else:
|
|
print()
|
|
|
|
print(f"{num_total:>7d} functions (size: ~{code_size_total} bytes)")
|
|
|
|
count_decompiled = counts[FunctionStatus.Matching] + counts[FunctionStatus.Equivalent] + counts[
|
|
FunctionStatus.NonMatching]
|
|
code_size_decompiled = code_size[FunctionStatus.Matching] + code_size[FunctionStatus.Equivalent] + code_size[
|
|
FunctionStatus.NonMatching]
|
|
|
|
print(format_progress(f"{Fore.CYAN}decompiled", count_decompiled, code_size_decompiled))
|
|
print(format_progress_for_status(f"{Fore.GREEN}matching", FunctionStatus.Matching))
|
|
print(format_progress_for_status(f"{Fore.YELLOW}non-matching (minor issues)", FunctionStatus.Equivalent))
|
|
print(format_progress_for_status(f"{Fore.RED}non-matching (major issues)", FunctionStatus.NonMatching))
|
|
print()
|