#!/usr/bin/env python3 import argparse import json import csv import os import re parser = argparse.ArgumentParser(description="Computes current progress throughout the whole project.") parser.add_argument("format", nargs="?", default="text", choices=["text", "verbose", "totalBadge", "gameBadge", "mainBadge", "endingBadge", "racingBadge", "audioBadge", "osBadge", "bytesToDecompile", "globalAsmFuncs", "m2cFuncs", "nonmatchingFuncs"]) args = parser.parse_args() NON_MATCHING_PATTERN = r"#ifdef\s+NON_MATCHING.*?#pragma\s+GLOBAL_ASM\s*\(\s*\"(.*?)\"\s*\).*?#endif" MIPS_TO_C_FUNC_COUNT_PATTERN = r"#ifdef\s+MIPS_TO_C.*?GLOBAL_ASM\s*\(\s*\"(.*?)\"\s*\).*?#endif" NON_MATCHING_FUNC_COUNT_PATTERN = r"#ifdef\s+NON_MATCHING.*?GLOBAL_ASM\s*\(\s*\"(.*?)\"\s*\).*?#endif" GLOBAL_ASM_FUNC_COUNT_PATTERN = r"GLOBAL_ASM\s*\(\s*\"(.*?)\"\s*\)." 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 CountMipsToCFunctions(files): functions = [] for file in files: with open(file) as f: functions += re.findall(MIPS_TO_C_FUNC_COUNT_PATTERN, f.read(), re.DOTALL) return functions def CountNonMatchingFunctions(files): functions = [] for file in files: with open(file) as f: functions += re.findall(NON_MATCHING_FUNC_COUNT_PATTERN, f.read(), re.DOTALL) return functions def CountGlobalAsmFunctions(files): functions = [] for file in files: with open(file) as f: functions += re.findall(GLOBAL_ASM_FUNC_COUNT_PATTERN, f.read(), re.DOTALL) return functions C_FUNCTION_PATERN_REGEX = r'^(? total_length: position = total_length line = charfill * total_length line = list(line) line[position] = charbase return "".join(line) def check_table_cond(cond, total, table): if total > cond: sym = " (V)" elif total == cond: sym = " (~)" else: sym = " (X)" return str(table[cond]) + str(sym) mkCups = [ "Mushroom Cup", "Flower Cup", "Star Cup", "Special Cup", ] mkCourses = [ "Luigi Raceway", "Moo Moo Farm", "Koopa Troopa Beach", "Kalimari Desert", "Toad's Turnpike", "Frappe Snowland", "Choco Mountain", "Mario Raceway", "Wario Stadium", "Sherbet Land", "Royal Raceway", "Bowser's Castle", "D.K.'s Jungle Parkway", "Yoshi Valley", "Banshee Boardwalk", "Rainbow Road", ] if args.format == 'totalBadge': print(str(round(srcPct, 2))+"%") elif args.format == 'gameBadge': print(str(round(gamePct, 2))+"%") elif args.format == 'mainBadge': print(str(round(segMainPct, 2))+"%") elif args.format == 'endingBadge': print(str(round(segEndingPct, 2))+"%") elif args.format == 'racingBadge': print(str(round(segRacingPct, 2))+"%") elif args.format == 'audioBadge': print(str(round(audioPct, 2))+"%") elif args.format == 'osBadge': print(str(round(libultraPct, 2))+"%") elif args.format == 'bytesToDecompile': print(str(remaining_size)+" of "+str(total_code_size)+"\n") elif args.format == 'globalAsmFuncs': print(str(TotalGlobalAsmFunctions)) elif args.format == 'm2cFuncs': print(str(TotalMipsToCFunctions)) elif args.format == 'nonmatchingFuncs': print(str(TotalNonMatchingFunctions)) elif args.format == 'text': bytesPerTotalLaps = total_code_size // 47 srcDivNear = find_closest_divisible(src, 49) lapTotalCounts = int(srcDivNear / bytesPerTotalLaps) curLapProgress = int(((srcDivNear % bytesPerTotalLaps) * 66) / (bytesPerTotalLaps)) curLapCount = int((lapTotalCounts % 3) + 1) curCourseCount = int(lapTotalCounts / 3) curCupCount = int((lapTotalCounts / 12) % 12) print(str(center_text("", 67, "="))) print(str(center_text(" All Cups (Decompilation) ", 67))) print(str(center_text(" " + str(round(srcPct, 2))+"% Complete ", 67, "-"))) print(str(center_text(" # Decompiled functions: " + str(TotalCFunctions) + " ", 67))) print(str(center_text(" # GLOBAL_ASM remaining: " + str(TotalGlobalAsmFunctions) + " ", 67))) print(str(center_text(" # NON_MATCHING remaining: " + str(TotalNonMatchingFunctions) + " ", 67))) print(str(center_text(" # MIPS_TO_C remaining: " + str(TotalMipsToCFunctions) + " ", 67))) print(str(center_text(" Game Status ", 67, "-"))) if TotalGlobalAsmFunctions > 0: print(str(center_text(check_table_cond(0, curCupCount, mkCups) + " - " + check_table_cond(1, curCupCount, mkCups), 67))) print(str(center_text(check_table_cond(2, curCupCount, mkCups) + " - " + check_table_cond(3, curCupCount, mkCups), 67))) print(str(center_text(" Lap Progress Bar and Race Status", 67, "-"))) print(str(move_character_from_bar(curLapProgress, 67, "O", "-"))) print(str(center_text("We are in " + str(get_string_from_table(curCupCount, mkCups)) + " racing at " + str(get_string_from_table(curCourseCount, mkCourses)) + " (Lap " + str(curLapCount) + "/3)", 67))) else: print(str(center_text("Mushroom Cup (V) - Flower Cup (V)", 67))) print(str(center_text("Star Cup (V) - Special Cup (V)", 67))) print(str(center_text("We finished All Cups! We got all 4 Gold Cups!", 67))) print(str(center_text("", 67, "="))) elif args.format == 'verbose': print("Total decompilable bytes remaining: "+str(remaining_size)+" out of "+str(total_code_size)+"\n") print(str(src) + "/" + str(total_code_size) + " bytes " + "decompiled" + " in total code " + str(srcPct) + "%\n") print(str(TotalCFunctions) + " decompiled functions - " +str(TotalGlobalAsmFunctions)+" GLOBAL_ASM functions remaining."+"\n") print(str(TotalNonMatchingFunctions)+" NON_MATCHING functions - " + str(TotalMipsToCFunctions) + " MIPS_TO_C functions." +"\n") print("------------------------------------\n") print(str(segMain) + "/" + str(seg_main_size) + " bytes " + "decompiled" + " in segMain " + str(segMainPct) + "%\n") print(str(segEnding) + "/" + str(seg_ending_size) + " bytes " + "decompiled" + " in segEnding " + str(segEndingPct) + "%\n") print(str(segRacing) + "/" + str(seg_racing_size) + " bytes " + "decompiled" + " in segRacing " + str(segRacingPct) + "%\n") print(str(game) + "/" + str(game_code_size) + " bytes " + "decompiled" + " in game code " + str(gamePct) + "%\n") print("------------------------------------\n") print(str(audio) + "/" + str(audio_size) + " bytes " + "decompiled" + " in audio " + str(audioPct) + "%\n") print(str(libultra) + "/" + str(libultra_size) + " bytes " + "decompiled" + " in libultra " + str(libultraPct) + "%\n") else: print("Unknown format argument: " + args.format)