#!/usr/bin/env python3 """Join the DBCServer RMI -> procedure map with procedure parameters. Inputs (derived, regenerable): decomp/DBCServer_Release_x64/rmi_to_proc.tsv RMI -> cmd -> procedures decomp/schema//routines.tsv procedure parameters Output: decomp/DBCServer_Release_x64/procs_used.tsv one row per (procedure, parameter) for every procedure reachable from an RMI; db = database that holds it (NOT_IN_SCHEMA if called but absent). Run from the repo root: python3 decomp/scripts/gen_dbc_tables.py """ import csv, os ROOT = os.getcwd() OUT = os.path.join(ROOT, 'decomp/DBCServer_Release_x64/procs_used.tsv') DBS = ['RustyHearts_Account', 'RustyHearts_Auth', 'RustyHearts', 'RustyHearts_Log'] def rows(path): with open(path, newline='') as f: return list(csv.reader(f, delimiter='\t')) procs = {} # lower name -> (name, db, [(param, type, maxlen, out)]) for db in DBS: for r in rows(f'{ROOT}/decomp/schema/{db}/routines.tsv')[1:]: if len(r) < 7 or r[0] != 'SQL_STORED_PROCEDURE': continue p = procs.setdefault(r[1].lower(), (r[1], db, [])) if r[2] != 'NULL': p[2].append((r[3], r[4], r[5], r[6])) rmi = rows(f'{ROOT}/decomp/DBCServer_Release_x64/rmi_to_proc.tsv') hdr = rmi[0] callers = {} for r in (dict(zip(hdr, x)) for x in rmi[1:]): for p in filter(None, r['procs'].split(',')): callers.setdefault(p.lower(), (p, []))[1].append(r['rmi_name']) out = [['proc', 'db', 'rmis', 'param_no', 'param', 'sql_type', 'max_length', 'is_output']] for key, (name, rmis) in sorted(callers.items()): pname, db, params = procs.get(key, (name, 'NOT_IN_SCHEMA', [])) if not params: out.append([pname, db, ','.join(rmis), '', '', '', '', '']) for i, (n, t, m, o) in enumerate(params, 1): out.append([pname, db, ','.join(rmis), str(i), n, t, m, o]) with open(OUT, 'w', newline='') as f: csv.writer(f, delimiter='\t', lineterminator='\n').writerows(out) print(f'{len(callers)} procedures -> {OUT}')