diff --git a/Quake/pr_edict.c b/Quake/pr_edict.c index f59f6f51..97eb514e 100644 --- a/Quake/pr_edict.c +++ b/Quake/pr_edict.c @@ -313,7 +313,7 @@ Returns a string describing *data in a type specific manner */ static const char *PR_ValueString (int type, eval_t *val) { - static char line[512]; + static char line[4096]; ddef_t *def; dfunction_t *f; @@ -415,9 +415,9 @@ padded to 20 field width */ const char *PR_GlobalString (int ofs) { - static char line[512]; + static char line[4096]; const char *s; - int i; + size_t i; ddef_t *def; void *val; @@ -434,15 +434,16 @@ const char *PR_GlobalString (int ofs) i = strlen(line); for ( ; i < 20; i++) strcat (line, " "); - strcat (line, " "); + if (i < Q_COUNTOF(line) - 1) + strcat (line, " "); return line; } const char *PR_GlobalStringNoContents (int ofs) { - static char line[512]; - int i; + static char line[4096]; + size_t i; ddef_t *def; def = ED_GlobalAtOfs(ofs); @@ -454,7 +455,8 @@ const char *PR_GlobalStringNoContents (int ofs) i = strlen(line); for ( ; i < 20; i++) strcat (line, " "); - strcat (line, " "); + if (i < Q_COUNTOF(line) - 1) + strcat (line, " "); return line; } @@ -1336,6 +1338,10 @@ void PR_Init (void) Cmd_AddCommand ("edicts", ED_PrintEdicts); Cmd_AddCommand ("edictcount", ED_Count); Cmd_AddCommand ("profile", PR_Profile_f); + + void PR_Disassemble_f (void); + Cmd_AddCommand ("disassemble", PR_Disassemble_f); + Cvar_RegisterVariable (&nomonsters); Cvar_RegisterVariable (&gamecfg); Cvar_RegisterVariable (&scratch1); diff --git a/Quake/pr_exec.c b/Quake/pr_exec.c index 55efd7e7..d3cba798 100644 --- a/Quake/pr_exec.c +++ b/Quake/pr_exec.c @@ -651,3 +651,135 @@ void PR_ExecuteProgram (func_t fnum) #undef OPA #undef OPB #undef OPC + + +static ddef_t* PR_GetDefinition(int offset) +{ + ddef_t* globaldefs = (ddef_t*)((byte*)progs + progs->ofs_globaldefs); + + for (int i = 0; i < progs->numglobaldefs; ++i) + { + ddef_t* defition = &globaldefs[i]; + + if (defition->ofs == offset) + return defition; + } + + return NULL; +} + +static const char* PR_TypeToString(const ddef_t* defition) +{ + switch (defition->type) + { + case ev_void: return "void"; break; + case ev_string: return "string"; break; + case ev_float: return "float"; break; + case ev_vector: return "vector"; break; + case ev_entity: return "entity"; break; + case ev_field: return "field"; break; + case ev_function: return "function"; break; + case ev_pointer: return "pointer"; break; + default: return "???"; break; + } +} + +static void PR_DisassembleFunction(const dfunction_t* func) +{ + int first_statement = func->first_statement; + + if (first_statement > 0) + { + const char* rettype = "void"; + + for (int i = first_statement, ie = progs->numstatements; i < ie; ++i) + { + dstatement_t* statement = &pr_statements[i]; + + if (statement->op == OP_RETURN) + { + ddef_t* def = PR_GetDefinition(statement->a); + rettype = def ? PR_TypeToString(def) : "???"; // TODO: ??? + break; + } + else if (statement->op == OP_DONE) + break; + } + + Con_SafePrintf("%s ", rettype); + } + + const char* name = PR_GetString(func->s_name); + Con_SafePrintf("%s(", name); + + if (first_statement > 0) + { + for (int ib = func->parm_start, ie = ib + func->numparms, i = ib; i < ie; ++i) + { + ddef_t* def = PR_GetDefinition(i); + Con_SafePrintf("%s%s %s", i == ib ? "" : ", ", PR_TypeToString(def), PR_GetString(def->s_name)); + } + } + else + Con_SafePrintf("<%i parameters>", func->numparms); // TODO: ??? + + Con_SafePrintf("): // %s\n", PR_GetString(func->s_file)); + + if (first_statement > 0) + { + for (int i = first_statement, ie = progs->numstatements; i < ie; ++i) + { + dstatement_t* statement = &pr_statements[i]; + PR_PrintStatement(statement); + + if (statement->op == OP_DONE) + break; + } + } + else + Con_SafePrintf("\n"); +} + +void PR_Disassemble_f(void) +{ + if (!progs) + return; + + if (Cmd_Argc() < 2) + { + Con_SafePrintf("disassemble "); + return; + } + + int numfuncs = progs->numfunctions; + const char* name = Cmd_Argv(1); + + if (strcmp(name, "*") == 0) + { + for (int i = 1; i < numfuncs; ++i) + { + PR_DisassembleFunction(&pr_functions[i]); + Con_SafePrintf("\n"); + } + } + else + { + qboolean found = false; + + for (int i = 1; i < numfuncs; ++i) + { + dfunction_t* func = &pr_functions[i]; + + if (strcmp(PR_GetString(func->s_name), name) == 0) + { + PR_DisassembleFunction(func); + + found = true; + break; + } + } + + if (!found) + Con_SafePrintf("ERROR: Could not find function \"%s\"\n", name); + } +}