1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2024-11-14 05:19:36 +00:00
oot/progress.py
Ethan Roseman e3dc47efe7
Progress reporting through Jenkins (#164)
* Progress reporting through Jenkins

* Update progress.py

Co-authored-by: Roman971 <32455037+Roman971@users.noreply.github.com>

Co-authored-by: Roman971 <32455037+Roman971@users.noreply.github.com>
2020-05-26 16:36:30 -04:00

144 lines
4.5 KiB
Python
Executable file

#!/usr/bin/env python3
import argparse
import json
import os
import re
import time
parser = argparse.ArgumentParser(description="Computes current progress throughout the whole project.")
parser.add_argument("-m", "--matching", dest='matching', action='store_true',
help="Output matching progress instead of decompilation progress")
parser.add_argument("-j", "--json", dest="json", action="store_true",
help="Output results as a json file at build/progress.json")
args = parser.parse_args()
NON_MATCHING_PATTERN = r"#ifdef\s+NON_MATCHING.*?#pragma\s+GLOBAL_ASM\s*\(\s*\"(.*?)\"\s*\).*?#endif"
def GetNonMatchingFunctions(files):
functions = []
for file in files:
with open(file) as f:
functions += re.findall(NON_MATCHING_PATTERN, f.read(), re.DOTALL)
return functions
def ReadAllLines(fileName):
lineList = list()
with open(fileName) as f:
lineList = f.readlines()
return lineList
def GetFiles(path, ext):
files = []
for r, d, f in os.walk(path):
for file in f:
if file.endswith(ext):
files.append(os.path.join(r, file))
return files
nonMatchingFunctions = GetNonMatchingFunctions(GetFiles("src", ".c")) if not args.matching else []
def GetNonMatchingSize(path):
size = 0
asmFiles = GetFiles(path, ".s")
for asmFilePath in asmFiles:
if asmFilePath not in nonMatchingFunctions:
asmLines = ReadAllLines(asmFilePath)
for asmLine in asmLines:
if (asmLine.startswith("/*")):
size += 4
return size
mapFile = ReadAllLines("build/z64.map")
src = 0
code = 0
boot = 0
ovl = 0
asm = 0
for line in mapFile:
lineSplit = list(filter(None, line.split(" ")))
if (len(lineSplit) == 4 and lineSplit[0].startswith(".")):
section = lineSplit[0]
size = int(lineSplit[2], 16)
objFile = lineSplit[3]
if (section == ".text"):
if (objFile.startswith("build/src")):
src += size
elif (objFile.startswith("build/asm")):
asm += size
if (objFile.startswith("build/src/code") or objFile.startswith("build/src/libultra_code")):
code += size
elif (objFile.startswith("build/src/boot") or objFile.startswith("build/src/libultra_boot")):
boot += size
elif (objFile.startswith("build/src/overlays")):
ovl += size
nonMatchingASM = GetNonMatchingSize("asm/non_matchings")
nonMatchingASMBoot = GetNonMatchingSize("asm/non_matchings/boot")
nonMatchingASMCode = GetNonMatchingSize("asm/non_matchings/code") + GetNonMatchingSize("asm/non_matchings/libultra_code")
nonMatchingASMOvl = GetNonMatchingSize("asm/non_matchings/overlays")
src -= nonMatchingASM
code -= nonMatchingASMCode
boot -= nonMatchingASMBoot
ovl -= nonMatchingASMOvl
asm += nonMatchingASM
bootSize = 30704 # decompilable code only
codeSize = 1004128 # .text section except rsp bins (1.00mb)
ovlSize = 2812000 # .text sections
handwritten = 5840 # boot only
asm -= handwritten
total = src + asm
srcPct = 100 * src / total
asmPct = 100 * asm / total
codePct = 100 * code / codeSize
bootPct = 100 * boot / bootSize
ovlPct = 100 * ovl / ovlSize
compiled_bytes = total
bytesPerHeartPiece = compiled_bytes / 80
if args.json:
timestamp = str(time.time())
json_dict = {"reports":{}}
json_dict["reports"][timestamp] = {
"total_percent": srcPct,
"boot_percent": bootPct,
"code_percent": codePct,
"overlay_percent": ovlPct
}
with open("build/progress.json", "w", newline="\n") as f:
json.dump(json_dict, f)
else:
adjective = "decompiled" if not args.matching else "matched"
print(str(total) + " total bytes of decompilable code\n")
print(str(src) + " bytes " + adjective + " in src " + str(srcPct) + "%\n")
print(str(boot) + "/" + str(bootSize) + " bytes " + adjective + " in boot " + str(bootPct) + "%\n")
print(str(code) + "/" + str(codeSize) + " bytes " + adjective + " in code " + str(codePct) + "%\n")
print(str(ovl) + "/" + str(ovlSize) + " bytes " + adjective + " in overlays " + str(ovlPct) + "%\n")
print("------------------------------------\n")
heartPieces = int(src / bytesPerHeartPiece)
rupees = int(((src % bytesPerHeartPiece) * 100) / bytesPerHeartPiece)
if (rupees > 0):
print("You have " + str(heartPieces) + "/80 heart pieces and " + str(rupees) + " rupee(s).\n")
else:
print("You have " + str(heartPieces) + "/80 heart pieces.\n")