diff options
Diffstat (limited to 'tools/progress.py')
-rw-r--r-- | tools/progress.py | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/tools/progress.py b/tools/progress.py new file mode 100644 index 0000000..b1e1160 --- /dev/null +++ b/tools/progress.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python3# +import subprocess +import math +import argparse + +# TODO - +# -- reportINCROMs -- + # add in percentage +# -- reportUnnamedSymbols -- + +# global vals +banks = 0x40 + +def main(): + parser = argparse.ArgumentParser(description='Progress checker for poketcg') + parser.add_argument('-i', '--incrom', action='store_true', help="Turns on incrom report") + parser.add_argument('-d', '--directory', default=".", help="Override incrom search directory. Ignores if incrom report is off") + parser.add_argument('-s', '--symfile', default=None, type=argparse.FileType('r'), help="Turns on Unnamed Symbol report using given sym file") + parser.add_argument('-f', '--function_source', action='store_true', help='Shows a breakdown of what bank each unnamed function comes from. Ignores if symfile report is off') + parser.add_argument('-o', '--other_unnamed', action='store_true', help='Shows all other unnamed symbols and a count of how many there are. Ignores if symfile report is off') + parser.add_argument('--list_funcs', nargs="+", default=None, help="Lists every unnamed function in the given banks. WILL BE LONG. ignores if symfile report is off") + + args = parser.parse_args() + + if args.incrom: + reportINCROMs(args.directory) + print("\n") + + if args.symfile != None: + # parse the list command + listBankSet = set([]) + if args.list_funcs != None: + listBankSet = parseBankList(args.list_funcs) + reportUnnamedSymbols(args.symfile,listBankSet, args.function_source, args.other_unnamed) + +def reportINCROMs(incromDir): + grepProc = subprocess.Popen(['grep', '-r', 'INCROM', incromDir], stdout=subprocess.PIPE) + targetLines = grepProc.communicate()[0].decode().split('\n') + incromBytes = [0]*banks + incromByteTotal = 0 + for line in targetLines: + line = line.lower() # ignore case + + # ignore the actual definition of the macro + if 'macro' in line: + continue + + # ignore anything in tools + if '/tools/' in line: + continue + + # ignore binary files in case swp's exist + if 'binary file' in line: + continue + + # find the last two hex location values + splitLine = line.split("$") + + # not sure what the line is, but it's not working so skip + if len(splitLine) < 3: + continue + + incEnd = int(splitLine[-1],16) + incStart = int(splitLine[-2].split(",",1)[0],16) + incBank = math.floor(incStart / 0x4000) + diff = incEnd - incStart + incromBytes[incBank] += diff + incromByteTotal += diff + print("Total: " + str(incromByteTotal) + " bytes") + print("Made up of the following: ") + for i in range(0,banks): + if incromBytes[i] == 0: + continue + + bankName= "bank" + format(i,"02x") + ": " + if i == 0: + bankName = "home: " + bytesString = str(incromBytes[i]) + formattingStrings = " "*(8-len(bytesString)) + print(bankName + bytesString + formattingStrings + "bytes") + + +# reads sym files and looks for instances of tcgdisasm's automatic symbols +def reportUnnamedSymbols(symfile, listBankSet, showFunctionBanks, showOtherUnnamed): + data = symfile.read().split("\n") + + # format [ [ "type" : number ], ... ] + typeCounts = [] + + # to cut back on for loops I'll manually list the super common ones, such as Func + funcCounts = [0]*banks + funcCount = 1 + branchCount = 0 + wramCount = 0 + sramCount = 0 + hramCount = 0 + + labelTotal = 0 + localLabelTotal = 0 + unnamedLocalLabelTotal = 0 + unnamedLabelTotal = 0 + + # expecting all lines to be formated as `bank:addr name` + for line in data: + + splitline = line.split(":") + + # line not formatted as expected + if len(splitline) < 2: + continue + + # at this point it's probably some form of label + if "." in line: + localLabelTotal += 1 + else: + labelTotal += 1 + + bank = int(splitline[0], 16) + splitline = splitline[1].split(" ") + + # line not formatted as expected + if len(splitline) < 2: + continue + + localAddr = int(splitline[0], 16) + name = splitline[1] + + globalAddr = bank*0x4000 + localAddr + if bank > 0: + globalAddr -= 0x4000 + + globalAddrString = format(globalAddr,"04x") + if name.endswith(globalAddrString): + + # don't pay as much attention to local labels + if "." in line: + unnamedLocalLabelTotal += 1 + continue + else: + unnamedLabelTotal += 1 + + labelType = name[0:len(globalAddrString)*-1] + + # take care of the common ones before looping + if labelType == "Func_": + if bank in listBankSet: + print("bank " + format(bank,'02x') + ":" + name) + funcCounts[bank] += 1 + funcCount += 1 + continue + elif labelType == "Branch_": + branchCount += 1 + continue + elif labelType == "w": + wramCount += 1 + continue + elif labelType in ["s0","s1","s2","s3"]: # all that are listed in sram.asm + sramCount += 1 + continue + elif labelType == "h": + hramCount += 1 + continue + + foundType = False + for tc in typeCounts: + if tc[0] == labelType: + tc[1] += 1 + foundType = True + + if not foundType: + typeCounts.append([labelType,1]) + + + # there are so many that I did them manually, but they're a misc type + typeCounts.append(["Branch_", branchCount]) + + # do some sorting. + typeCounts = sorted(typeCounts, key = lambda x: x[1], reverse = True) + + namedLabelTotal = labelTotal - unnamedLabelTotal + namedLabelPercent = round((namedLabelTotal / labelTotal)*100, 3) + namedLocalLabelTotal = localLabelTotal - unnamedLocalLabelTotal + namedLocalLabelPercent = round((namedLocalLabelTotal / localLabelTotal)*100, 3) + + print("Named Labels: " + str(namedLabelTotal) + "/" + str(labelTotal) + " (" + str(namedLabelPercent) + "%)") + print("Named Local Labels: " + str(namedLocalLabelTotal) + "/" + str(localLabelTotal) + " (" + str(namedLocalLabelPercent) + "%)") + print() + print("func count: " + str(funcCount)) + if showFunctionBanks: + for i in range(0,banks): + if funcCounts[i] == 0: + continue + bank = "bank" + format(i,"02x") + ":" + if i == 0: + bank = "home: " + print("\t" + bank + " " + str(funcCounts[i])) + + print("wram count: " + str(wramCount)) + print("sram count: " + str(sramCount)) + print("hram count: " + str(hramCount)) + if showOtherUnnamed: + print() + print("Additional types:") + + for tc in typeCounts: + spaces = " " * (30 - len(tc[0])) + if tc[1] == 1: + print(tc[0]) + continue + print(tc[0] + spaces + "x" + format(tc[1],"02")) + +def parseBankList(strList): + retSet = set([]) + for bankName in strList: + if bankName == "home": + retSet.add(0) + elif bankName.startswith("bank"): + retSet.add(int(bankName[4:],16)) + else: + retSet.add(int(bankName,0)) + return retSet + + +if __name__ == '__main__': + main() |