Prototype spitter

This commit is contained in:
krystalgamer 2024-08-03 18:29:10 +02:00
parent 317bf759ca
commit c544354bda
5 changed files with 3762 additions and 1 deletions

4
dest.sh Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
name=$1::~$1
git commit -am "$name"

View File

@ -0,0 +1,89 @@
import os
import idc
import json
from idautils import Segments, Functions
from ida_kernwin import ask_file
from collections import defaultdict
import idaapi
import json
def function_name_generator():
for segment in Segments():
for funcea in Functions(segment, idc.get_segm_end(idc.INF_LONG_DN)):
#func_name = idc.get_func_name(funcea)
func_name = idaapi.get_ea_name(funcea, idaapi.GN_SHORT|idaapi.GN_DEMANGLED)
yield (funcea, func_name, idc.find_func_end(funcea)-funcea)
def main():
path = ask_file(1, "*.json", "Output functions and names")
if path is None:
print('Cancelled')
return
with open(path, 'w') as fp:
functions = function_name_generator()
functions = filter(lambda x: x[1].startswith('sub_') is False, functions)
functions = list(functions)
functions.sort(reverse=True, key= lambda x: x[0])
total_counter = 0
counter = 0
size = 0
current_file = None
file_to_funcs = defaultdict(lambda: dict())
for _, name, func_size in functions:
if name.startswith('.__sinit'):
if current_file is not None:
print(f'{current_file} has {counter} functions ({size} bytes)')
counter = 0
size = 0
current_file = '_'.join(name.replace('.__sinit_', '').split('_')[:-1])
continue
if current_file is not None:
counter += 1
size += func_size
total_counter += 1
file_to_funcs[current_file][name] = func_size
if counter > 0:
print(f'{current_file} has {counter} functions ({size} bytes)')
print(total_counter)
json.dump(file_to_funcs, fp, indent=2)
'''
old_names = None
if os.path.exists(path):
with open(path, "r") as fp:
old_names = json.load(fp)['functions']
if old_names is not None:
for k,v in old_names.items():
old_name = v['name']
new_name = new_names[k]['name']
if old_name != new_name:
print(f'{old_name} has been replaced with {new_name}')
with open(path, 'w') as fp:
json.dump({'functions': new_names}, fp)
'''
print('Done')
if __name__ == '__main__':
main()

109
tools/prototype_spitter.py Normal file
View File

@ -0,0 +1,109 @@
import sys
import json
def get_func_type(name):
func_type = 'void '
if '~' in name:
func_type = ''
if '::' in name:
i = name.index('::')
class_name = name[:i]
second_part = name[i+2:]
second_part = second_part[:second_part.index('(')]
if class_name == second_part:
func_type = ''
return func_type
def generate_header(name):
func_type = get_func_type(name)
print(f'EXPORT {func_type}{name};')
def generate_body(name, size):
tag = '// @SMALLTODO'
if size > 900:
tag = '// @BIGTODO'
if size > 450:
tag = '// @MEDIUMTODO'
func_type = get_func_type(name)
print(f'''
{tag}
{func_type}{name}
{{
printf("{name}");
}}''')
def set_widthed_type(entry):
entry = entry.replace('(int)', '(i32)').replace(',int)', ',i32)').replace('(int,', '(i32,').replace(',int,',',i32,')
entry = entry.replace('(uchar)', '(u8)').replace(',uchar)', ',u8)').replace('(uchar,', '(u8,').replace(',uchar,',',u8,')
entry = entry.replace('&', '*')
entry = entry.replace('((', '(').replace('))',')')
return entry
def does_func_exist(entry, base):
name = entry[:entry.index('(')].strip()
res = name in base
'''
if res:
print(f'Will remove {entry} {name}')
'''
return res
def main():
prototype_def = None
entry = sys.argv[2]
base_file = None
with open(sys.argv[1], 'r') as fp:
prototype_def = json.load(fp)
with open(sys.argv[3], 'r') as fp:
base_file = fp.read()
if entry not in prototype_def:
print(f'{entry} not part of prototypes')
return 1
functions = list(prototype_def[entry].items())
functions.sort(key=lambda x: x[0])
functions = map(lambda x: (set_widthed_type(x[0]), x[1]), functions)
functions = map(lambda x: (set_widthed_type(x[0]), x[1]), functions)
functions = map(lambda x: (set_widthed_type(x[0]), x[1]), functions)
functions = filter(lambda x: does_func_exist(x[0], base_file) == False, functions)
functions = list(functions)
class_prefix = None
for name, _ in functions:
if '::' not in name:
if class_prefix is not None:
print('')
class_prefix = None
else:
current_prefix = name[:name.index('::')]
if class_prefix != current_prefix:
print('')
class_prefix = current_prefix
generate_header(name)
'''
for name, size in functions:
generate_body(name, size)
'''
return 0
if __name__ == '__main__':
sys.exit(main())

3559
tools/prototypes.json Normal file

File diff suppressed because it is too large Load Diff

2
web.h
View File

@ -97,7 +97,7 @@ class CSwinger : public CBody
};
class CSplat : public CQuadBit {
public:
public:
};
class CTrapWebEffect : public CNonRenderedBit