mirror of
https://gitlab.com/dk64_decomp/dk64.git
synced 2024-11-27 01:00:34 +00:00
87 lines
3.5 KiB
Python
87 lines
3.5 KiB
Python
import argparse
|
|
import os
|
|
import re
|
|
import sys
|
|
import subprocess
|
|
import glob
|
|
|
|
def get_functions(elffile, section, ending=None):
|
|
try:
|
|
result = subprocess.run(['objdump', '-x', elffile], stdout=subprocess.PIPE)
|
|
nm_lines = result.stdout.decode().split("\n")
|
|
except:
|
|
sys.stderr.write(f"Error: Could not run objdump on {elffile} - make sure that the project is built")
|
|
sys.exit(1)
|
|
|
|
functions = {}
|
|
|
|
for line in nm_lines:
|
|
if f"g F {section}" in line or "g F *ABS* " in line:
|
|
components = line.split()
|
|
size = int(components[4], 16)
|
|
name = components[5]
|
|
functions[name] = {"function": name, "length": size}
|
|
|
|
return functions
|
|
|
|
def generate_csv(functions, nonmatching_funcs, version, section):
|
|
ret = []
|
|
ret.append("version,section,function,length,matching")
|
|
for func in functions:
|
|
length = functions[func]["length"]
|
|
if length > 0:
|
|
matching = "no" if func in nonmatching_funcs else "yes"
|
|
ret.append(f"{version},{section},{func},{length},{matching}")
|
|
return "\n".join(ret)
|
|
|
|
def get_nonmatching_funcs(basedir, subcode):
|
|
grepstr = r'#pragma GLOBAL_ASM\(.*/\K.*(?=\.s)'
|
|
if subcode:
|
|
try:
|
|
funcs = set(subprocess.check_output(['grep', '-ohPR', grepstr, basedir + '/src/' + subcode]).decode('ascii').split())
|
|
except subprocess.CalledProcessError as grepexc:
|
|
if grepexc.returncode != 1:
|
|
raise grepexc
|
|
funcs = set()
|
|
else:
|
|
args = ['grep', '-ohPs', '-d', 'skip', grepstr]
|
|
args.extend(glob.glob(basedir + '/src/*'))
|
|
try:
|
|
funcs = set(subprocess.check_output(args).decode('ascii').split())
|
|
except subprocess.CalledProcessError as grepexc:
|
|
if grepexc.returncode != 1:
|
|
raise grepexc
|
|
funcs = set()
|
|
try:
|
|
funcs = funcs.union(set(subprocess.check_output(['grep', '-ohPR', grepstr, basedir + '/src/done']).decode('ascii').split()))
|
|
except subprocess.CalledProcessError as grepexc:
|
|
if grepexc.returncode != 1:
|
|
raise grepexc
|
|
return funcs
|
|
|
|
|
|
def main(basedir, elffile, section, ending, version, subcode):
|
|
functions = get_functions(elffile, section, ending)
|
|
section_name = section.split("_")[-1] # .code_game -> game
|
|
nonmatching_funcs = get_nonmatching_funcs(basedir, subcode)
|
|
csv = generate_csv(functions, nonmatching_funcs, version, section_name)
|
|
print(csv)
|
|
|
|
if __name__ == '__main__':
|
|
parser = argparse.ArgumentParser(description='Create progress csv based on map file',
|
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
parser.add_argument('basedir', type=str,
|
|
help="base directory (containing src/)")
|
|
parser.add_argument('elffile', type=str,
|
|
help=".elf file to be read")
|
|
parser.add_argument('section', type=str,
|
|
help=".text section of the map")
|
|
parser.add_argument('--ending', type=str,
|
|
help="section name that marks the end of 'section'")
|
|
parser.add_argument('--version', type=str, default='us',
|
|
help="ROM version, us, eu, debug, ects")
|
|
parser.add_argument('--subcode', type=str, default=None,
|
|
help="Subcode for section to get progress of")
|
|
args = parser.parse_args()
|
|
|
|
main(args.basedir, args.elffile, args.section, args.ending, args.version, args.subcode) |