summaryrefslogtreecommitdiff
path: root/progress.py
diff options
context:
space:
mode:
authorCoderStig <79828759+CoderStig@users.noreply.github.com>2021-11-05 05:17:09 -0600
committerGitHub <noreply@github.com>2021-11-05 05:17:09 -0600
commit8ab4557b393073e8b544e8ceb834f5baddb465de (patch)
tree4e35f1b65eaa814845aab7c137e1cfd17520760c /progress.py
parent48f2c2fddec9601759fcd847268547a97dd85f5b (diff)
Split asm using autodecompiler (#49)
* Split asm using autodecompiler * Placed libultra bss and linked more C
Diffstat (limited to 'progress.py')
-rw-r--r--progress.py261
1 files changed, 261 insertions, 0 deletions
diff --git a/progress.py b/progress.py
new file mode 100644
index 000000000..c701a7f77
--- /dev/null
+++ b/progress.py
@@ -0,0 +1,261 @@
+#!/usr/bin/env python3
+
+import argparse
+import json
+import csv
+#import git
+import os
+import re
+
+parser = argparse.ArgumentParser(description="Computes current progress throughout the whole project.")
+parser.add_argument("format", nargs="?", default="text", choices=["text", "csv", "shield-json"])
+parser.add_argument("-m", "--matching", dest='matching', action='store_true',
+ help="Output matching progress instead of decompilation progress")
+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 []
+
+mainSegFiles2 = [
+ "asm/non_matchings/main", "asm/non_matchings/code_800029B0",
+ "asm/non_matchings/profiler", "asm/non_matchings/crash_screen",
+ "asm/non_matchings/code_80004740", "asm/non_matchings/staff_ghosts",
+ "asm/non_matchings/code_80005FD0", "asm/non_matchings/code_80005FD0",
+ "asm/non_matchings/code_8001C4D0", "asm/non_matchings/code_8001F980",
+ "asm/non_matchings/code_80027040", "asm/non_matchings/code_80027D00",
+ "asm/non_matchings/code_800393C0", "asm/non_matchings/code_8003DC40",
+ "asm/non_matchings/gbiMacro", "asm/non_matchings/code_80040E50",
+ "asm/non_matchings/code_800431B0", "asm/non_matchings/code_80057C60",
+ "asm/non_matchings/code_8006E9C0", "asm/non_matchings/code_80071F00",
+ "asm/non_matchings/code_80086E70", "asm/non_matchings/code_8008C1D0",
+ "asm/non_matchings/code_80091750", "asm/non_matchings/code_800AF9B0"
+ ]
+seg2Files2 = [
+ "asm/non_matchings/code_8028DF00", "asm/non_matchings/code_80290C20",
+ "asm/non_matchings/code_80296A50", "asm/non_matchings/code_802A3730",
+ "asm/non_matchings/memory", "asm/non_matchings/code_802B0210",
+ "asm/non_matchings/math_util"
+]
+seg3Files2 = [
+ "asm/non_matchings/code_80280000", "asm/non_matchings/code_80280650",
+ "asm/non_matchings/code_80281610", "asm/non_matchings/code_80281780",
+ "asm/non_matchings/code_80281C40", "asm/non_matchings/code_80281FA0"
+]
+audioFiles2 = [
+ "asm/non_matchings/audio"
+]
+
+def GetNonMatchingSize(path):
+ size = 0
+
+ if (path == "main"):
+ for file in mainSegFiles2:
+ size += getData(file)
+
+ elif (path == "seg2"):
+ for file in seg2Files2:
+ size += getData(file)
+
+ elif (path == "seg3"):
+ for file in seg3Files2:
+ size += getData(file)
+
+ elif (path == "os"):
+ size = getData("asm/os/func_800CE720.s")
+
+ elif (path == "audio"):
+ for file in audioFiles2:
+ size += getData(file)
+
+ else: size = getData("asm/non_matchings")
+
+
+ return size
+
+def getData(path):
+ size = 0
+
+
+ asmFiles = GetFiles(path, ".s")
+
+
+ for asmFilePath in asmFiles:
+ #if path == asmFilePath.startswith("audio"):
+ # continue
+ if asmFilePath not in nonMatchingFunctions:
+ asmLines = ReadAllLines(asmFilePath)
+
+ for asmLine in asmLines:
+ if (asmLine.startswith("/*")):
+ size += 4
+
+ return size
+
+
+
+mapFile = ReadAllLines("build/us/mk64.us.map")
+src = 0
+mainSeg = 0
+seg2 = 0
+seg3 = 0
+audio = 0
+libultra = 0
+
+mainSegFiles = [
+ "build/us/src/main", "build/us/src/code_800029B0",
+ "build/us/src/profiler", "build/us/src/crash_screen",
+ "build/us/src/code_80004740", "build/us/src/staff_ghosts",
+ "build/us/src/code_80005FD0", "build/us/src/code_80005FD0",
+ "build/us/src/code_8001C4D0", "build/us/src/code_8001F980",
+ "build/us/src/code_80027040", "build/us/src/code_80027D00",
+ "build/us/src/code_800393C0", "build/us/src/code_8003DC40",
+ "build/us/src/gbiMacro", "build/us/src/code_80040E50",
+ "build/us/src/code_800431B0", "build/us/src/code_80057C60",
+ "build/us/src/code_8006E9C0", "build/us/src/code_80071F00",
+ "build/us/src/code_80086E70", "build/us/src/code_8008C1D0",
+ "build/us/src/code_80091750", "build/us/src/code_800AF9B0"
+ ]
+seg2Files = [
+ "build/us/src/code_8028DF00", "build/us/src/code_80290C20",
+ "build/us/src/code_80296A50", "build/us/src/code_802A3730",
+ "build/us/src/memory", "build/us/src/code_802B0210",
+ "build/us/src/math_util"
+]
+seg3Files = [
+ "build/us/src/code_80280000", "build/us/src/code_80280650",
+ "build/us/src/code_80281610", "build/us/src/code_80281780",
+ "build/us/src/code_80281C40", "build/us/src/code_80281FA0"
+]
+segAudioFiles = [
+ "build/us/src/synthesis"
+]
+
+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/us/src")):
+ src += size
+
+ if (objFile.startswith(tuple(mainSegFiles))):
+ print(size)
+ mainSeg += size
+
+ if (objFile.startswith(tuple(seg2Files))):
+ seg2 += size
+
+ if (objFile.startswith(tuple(seg3Files))):
+ seg3 += size
+
+ if (objFile.startswith("build/us/src/os")):
+ libultra += size
+
+ if (objFile.startswith(tuple(segAudioFiles))):
+ audio += size
+
+nonMatchingASM = GetNonMatchingSize("asm/non_matchings")
+nonMatchingMain = GetNonMatchingSize("main")
+nonMatchingSeg2 = GetNonMatchingSize("seg2")
+nonMatchingSeg3 = GetNonMatchingSize("seg3")
+nonMatchingLibultra = GetNonMatchingSize("os")
+nonMatchingASMAudio = GetNonMatchingSize("audio")
+
+decompilable = src + audio + 448 # 448 = OS func_800CE720
+
+src -= nonMatchingASM
+print("main")
+print(mainSeg)
+print(nonMatchingMain)
+mainSeg -= nonMatchingMain
+
+seg2 -= nonMatchingSeg2
+seg3 -= nonMatchingSeg3
+audio -= nonMatchingASMAudio
+libultra -= nonMatchingLibultra
+
+
+mainSeg_size = 831024
+seg2_size = 174224
+seg3_size = 20032
+mk64Code_size = 1025280
+libultra_size = 53248 - 2112 # total - handwritten
+audio_size = 86912
+text_size = (mk64Code_size + libultra_size + audio_size) - decompilable
+
+srcPct = 100 * src / mk64Code_size
+libultraPct = 100 * libultra / libultra_size
+audioPct = 100 * audio / audio_size
+mainSegPct = 100 * mainSeg / mainSeg_size
+seg2Pct = 100 * seg2 / seg2_size
+seg3Pct = 100 * seg3 / seg3_size
+
+bytesPerHeartPiece = text_size / 80
+
+#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(code), str(codeSize), str(boot), str(bootSize), str(ovl), str(ovlSize), str(src), str(nonMatchingASM), str(len(nonMatchingFunctions))]
+# 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',
+# }))
+if args.format == 'text':
+ adjective = "decompiled" if not args.matching else "matched"
+
+ print(str(text_size) + " total bytes of decompilable code\n")
+ print(str(src) + " bytes " + adjective + " in game code " + str(srcPct) + "%\n")
+ print(str(audio) + "/" + str(audio_size) + " bytes " + adjective + " in audio " + str(audioPct) + "%\n")
+ print(str(libultra) + "/" + str(libultra_size) + " bytes " + adjective + " in libultra " + str(libultraPct) + "%\n")
+ print(str(mainSeg) + "/" + str(mainSeg_size) + " bytes " + adjective + " in mainSeg " + str(mainSegPct) + "%\n")
+ print(str(seg2) + "/" + str(seg2_size) + " bytes " + adjective + " in seg2 " + str(seg2Pct) + "%\n")
+ print(str(seg3) + "/" + str(seg3_size) + " bytes " + adjective + " in seg3 " + str(seg3Pct) + "%\n")
+ print("------------------------------------\n")
+
+ heartPieces = int(src / bytesPerHeartPiece)
+ rupees = int(((src % bytesPerHeartPiece) * 100) / bytesPerHeartPiece)
+
+ if (rupees > 0):
+ print("You have " + str(heartPieces) + "/80 GP Wins and " + str(rupees) + " bronze cup(s).\n")
+ else:
+ print("You have " + str(heartPieces) + "/80 GP Wins.\n")
+else:
+ print("Unknown format argument: " + args.format)