Files
gamestabled a87ddae432 Attempt to pull GLOBAL_ASMs for actor functions into their correct source files (#17)
* pull known Actor functions GLOBAL_ASMs into their cpp files

* attempt to pull unidentified actor functions GLOBAL_ASMs into their corresponding source files by scanning the call-graph
2026-09-04 15:43:43 -04:00

111 lines
3.6 KiB
Python

import argparse
import json
import git
from pathlib import Path
import math
parser = argparse.ArgumentParser(description="Computes current progress throughout the whole project.")
parser.add_argument("format", nargs="?", default="text", choices=["text", "csv", "shield-json"])
args = parser.parse_args()
def ReadAllLines(fileName: Path) -> list[str]:
with open(fileName) as f:
return f.readlines()
def GetFiles(path: Path, ext) -> list[Path]:
files: list[Path] = list()
for (dirpath, _, filenames) in path.walk():
for file in filenames:
if Path(file).suffix == ext:
files.append(dirpath / file)
return files
def GetSizeOfASMSourceFile(asmSrc: Path) -> int:
size: int = 0
asmLines: list[str] = ReadAllLines(asmSrc)
for asmLine in asmLines:
if asmLine.startswith("\t"):
asmLineStripped = asmLine.strip()
if not (asmLineStripped.startswith("AREA") or
asmLineStripped.startswith("EXPORT") or
asmLineStripped.startswith("END") or
asmLineStripped.startswith("DCD") or
asmLineStripped.startswith("DCB")):
size += 4
elif asmLineStripped.startswith("DCD "):
size += 4
elif asmLineStripped.startswith("DCB "):
size += len(asmLineStripped.split(','))
size = 4 * math.ceil(size / 4.0)
return size
def GetAllNonMatchingASMFunctionSourceFiles(nonmatchFiles: list[Path]) -> list[Path]:
nonmatchASMFunctionSourceFiles: list[Path] = list()
for nonmatchFile in nonmatchFiles:
with open(nonmatchFile, 'r') as nonmatch:
nonmatchLines: list[str] = nonmatch.readlines()
for line in nonmatchLines:
if line.startswith("\tGET") and line.count("disassembly\\asm") > 0:
nonmatchASMFunctionSourceFiles.append(Path(line.split(' ')[-1].strip()))
return nonmatchASMFunctionSourceFiles
def GetTotalNonMatchSize() -> int:
nonmatchFiles: list[Path] = GetFiles(Path("build/nonmatch"), ".s")
nonMatchingASMFunctionSourceFiles: list[Path] = GetAllNonMatchingASMFunctionSourceFiles(nonmatchFiles)
size: int = 0
for nonMatchFunction in nonMatchingASMFunctionSourceFiles:
size += GetSizeOfASMSourceFile(nonMatchFunction)
return size
nonMatchingASMSize: int = GetTotalNonMatchSize()
totalSize: int = 0x3C97B8
srcSize: int = totalSize - nonMatchingASMSize
srcPct: float = 100.0 * srcSize / totalSize
bytesPerHeartPiece: float = totalSize / 80.0
if args.format == 'csv':
version = 1
git_object = git.Repo().head.object
timestamp = str(git_object.committed_date)
git_hash = git_object.hexsha
csv_list = [str(version), timestamp, git_hash, str(srcSize), str(nonMatchingASMSize)]
print(",".join(csv_list))
elif args.format == 'shield-json':
# https://shields.io/endpoint
print(json.dumps({
"schemaVersion": 1,
"label": "progress",
"message": f"{srcPct:.3g}%",
"color": 'yellow',
}))
elif args.format == 'text':
print(f"{totalSize} total bytes of decompilable code\n")
print(f"{srcSize} bytes decompiled in src {srcPct}%\n")
print("------------------------------------\n")
heartPieces = int(srcSize / bytesPerHeartPiece)
rupees = int(((srcSize % bytesPerHeartPiece) * 100) / bytesPerHeartPiece)
if (rupees > 0):
print(f"You have {heartPieces}/80 heart pieces and {rupees} rupee{"s" if rupees != 1 else ""}.\n")
else:
print(f"You have {heartPieces}/80 heart pieces.\n")
else:
print(f"Unknown format argument: {args.format}")