1 /*
2 * dcc.c -- An hcode compiler/decompiler for Hexen II by Eric Hobbs
3 * $Id: dcc.c 5787 2017-01-03 22:22:34Z sezero $
4 *
5 * Copyright (C) 1996-1997 Id Software, Inc.
6 * Copyright (C) 1997 Eric Hobbs <elhobbs@comcast.net>
7 * Copyright (C) 2005-2012 O.Sezer <sezero@users.sourceforge.net>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 *
18 * See the GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25
26 // HEADER FILES ------------------------------------------------------------
27
28 #include "q_stdinc.h"
29 #include "compiler.h"
30 #include "arch_def.h"
31 #include "cmdlib.h"
32 #include "util_io.h"
33 #include "qcc.h"
34 #include "dcc.h"
35 #include "q_endian.h"
36
37 // MACROS ------------------------------------------------------------------
38
39 #define MAX_DEC_FILES 512
40
41 // TYPES -------------------------------------------------------------------
42
43 struct flowinfo_t
44 {
45 int if_cnt;
46 int do_cnt;
47 };
48
49 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
50
51 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
52
53 /* IMPORTANT NOTE about functions taking a gofs_t argument: If you pass a
54 * dstatement_t->a, b or c (signed short) value to them and the function
55 * compares that value to a ddef_t->ofs value (unsigned short), then you
56 * must explicitly cast that dstatement_t->a, b or c to unsigned short.
57 * BackBuildReturnType() is an exception, because it compares its gofs_t
58 * argument to dstatement_t->a, b or c values, therefore you must not do
59 * that casting for that case.
60 */
61 static void Make_Immediate (gofs_t ofs, const char *s);
62 static char *Get_Immediate (gofs_t ofs);
63 static void Clear_Immediates (void);
64 static void PR_Indent (void);
65 static void PR_FunctionHeader (dfunction_t *df);
66 static void PR_Print (const char *s,...) FUNC_PRINTF(1,2);
67 static const char *PR_PrintGlobal (gofs_t ofs, def_t* typ);
68 static ddef_t *PR_GetField (const char *name, ddef_t*);
69 static int DEC_GetFunctionIdxByName (const char *name);
70 static void PR_LocalGlobals (void);
71 static int DEC_AlreadySeen (const char *fname);
72 static ddef_t *DEC_GetParameter (gofs_t ofs);
73 static const char *GetFieldFunctionHeader (const char *s_name);
74 static void DccStatement (dstatement_t *s);
75 static void AddProgramFlowInfo (dfunction_t *df);
76 static void PR_Locals (dfunction_t *df);
77 static const char * PR_ValueString (etype_t type, void *val);
78 static const char *DCC_ValueString (etype_t type, void *val);
79 /* same as PR_ValueString(), differing
80 * in float/vector print precision. */
81 static unsigned short GetReturnType (int func);
82 static unsigned short BackBuildReturnType (dfunction_t *df, dstatement_t *dsf, gofs_t ofs);
83 static unsigned short GetType (gofs_t ofs);
84 static unsigned short GetLastFunctionReturn (dfunction_t *df, dstatement_t *ds);
85
86 static void Init_Dcc (void);
87 static void DEC_ReadData (const char *srcfile);
88 static void Dcc_Functions (void);
89 static void FindBuiltinParameters (int func);
90 static void DccFunctionOP (unsigned short op);
91 static void PR_PrintFunction (const char *name);
92 static def_t *PR_DefForFieldOfs (gofs_t ofs);
93 static const char *PR_String (const char *string);
94
95 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
96
97 // PUBLIC DATA DEFINITIONS -------------------------------------------------
98
99 // PRIVATE DATA DEFINITIONS ------------------------------------------------
100
101 static const char *type_names[8] =
102 {
103 "void",
104 "string",
105 "float",
106 "vector",
107 "entity",
108 "ev_field",
109 "void()",
110 "ev_pointer"
111 };
112
113 static dprograms_t *progs;
114 static dfunction_t *pr_functions;
115 static ddef_t *pr_globaldefs;
116 static ddef_t *pr_fielddefs;
117 static dstatement_t *pr_statements;
118 static char *pr_strings;
119 static int progs_length;
120
121 static dfunction_t *cfunc;
122 static struct flowinfo_t *flowinfo;
123
124 static qboolean FILE_NUM_FOR_NAME;
125 static qboolean pr_dumpasm;
126 static qboolean printassign;
127 static int pr_infoonly;
128
129 static FILE *PR_FILE;
130 static char **func_headers;
131 static char **temp_val;
132
133 static int lindent;
134 static char **DEC_FilesSeen;
135 static int DEC_FileCtr;
136
137 /* avoid infinite recursion in GetFieldFunctionHeader() which has
138 * thankfully only one caller, PR_LocalGlobals(). this solution
139 * is naive, cheesy, [insert more here.. or find a better one...] */
140 #define GFFH_MAX_DEPTH 64
141 static int GFFH_depth = 0;
142
143 // CODE --------------------------------------------------------------------
144
PR_PrintStringAtOfs(gofs_t ofs,def_t * typ)145 static const char *PR_PrintStringAtOfs (gofs_t ofs, def_t* typ)
146 {
147 int i;
148 ddef_t *def = NULL;
149 ddef_t *d = NULL;
150
151 for (i = 0; i < progs->numglobaldefs; i++)
152 {
153 d = &pr_globaldefs[i];
154 if (d->ofs == ofs)
155 {
156 def = d;
157 break;
158 }
159 }
160
161 if (!def)
162 return Get_Immediate(ofs);
163
164 if (!strcmp(pr_strings + def->s_name, IMMEDIATE_NAME))
165 return DCC_ValueString ((etype_t)def->type, &pr_globals[ofs]);
166
167 if (typ)
168 {
169 // printf("type %s %d\n", pr_strings + def->s_name, typ->type->type);
170 if (typ->type->type == ev_float && d->type == ev_vector)
171 def = &pr_globaldefs[i + 1];
172 }
173 // printf("found %s\n", pr_strings + def->s_name);
174 return (pr_strings + def->s_name);
175 }
176
PR_PrintGlobal(gofs_t ofs,def_t * typ)177 static const char *PR_PrintGlobal (gofs_t ofs, def_t* typ)
178 {
179 int i;
180 ddef_t *def = NULL;
181 ddef_t *d = NULL;
182
183 for (i = 0; i < progs->numglobaldefs; i++)
184 {
185 d = &pr_globaldefs[i];
186 if (d->ofs == ofs)
187 {
188 def = d;
189 break;
190 }
191 }
192
193 if (!def)
194 return NULL;
195
196 if (!strcmp(pr_strings + def->s_name, IMMEDIATE_NAME))
197 return DCC_ValueString ((etype_t)def->type, &pr_globals[ofs]);
198
199 if (typ)
200 {
201 if (typ->type->type == ev_float && d->type == ev_vector)
202 def = &pr_globaldefs[i + 1];
203 }
204 return (pr_strings + def->s_name);
205 }
206
207
DccStatement(dstatement_t * s)208 static void DccStatement (dstatement_t *s)
209 {
210 static char dsline[2048], funcname[512];
211 const char *arg1, *arg2, *arg3;
212 char a1[1024], a2[1024], a3[1024];
213 int nargs, i, j;
214 dstatement_t *t, *k;
215 int doc, ifc;
216 unsigned short tom;
217 def_t *typ1 = NULL, *typ2 = NULL, *typ3 = NULL;
218 ddef_t *par;
219 int op_a, op_b;
220
221 a1[0] = a2[0] = a3[0] = dsline[0] = funcname[0] = '\0';
222
223 doc = flowinfo[s - pr_statements].do_cnt;
224 ifc = flowinfo[s - pr_statements].if_cnt;
225
226 /* use program flow information */
227 for (i = 0; i < ifc; i++)
228 {
229 PR_Print("\n");
230 lindent--;
231 PR_Indent();
232 PR_Print("}\n");
233 // printf("entered program flow\n");
234 }
235
236 for (i = 0; i < doc; i++)
237 {
238 PR_Indent();
239 PR_Print("do {\n\n");
240 lindent++;
241 }
242
243 typ1 = pr_opcodes[s->op].type_a;
244 typ2 = pr_opcodes[s->op].type_b;
245 typ3 = pr_opcodes[s->op].type_c;
246
247 if (pr_dumpasm)
248 {
249 arg1 = PR_PrintGlobal(s->a, typ1);
250 arg2 = PR_PrintGlobal(s->b, typ2);
251 arg3 = PR_PrintGlobal(s->c, typ3);
252 PR_Print("\n%s(%d): %s(%d) %s(%d) %s(%d):\n",
253 pr_opcodes[s->op].opname, s->op,
254 arg1, s->a, arg2, s->b, arg3, s->c);
255 }
256
257 arg1 = arg2 = arg3 = NULL;
258
259 if (s->op == OP_DONE)
260 {
261 lindent--;
262 PR_Indent();
263 PR_Print("};\n\n");
264 return;
265 }
266 else if (s->op == OP_STATE)
267 {
268 }
269 else if (s->op == OP_RETURN)
270 {
271 PR_Indent();
272 PR_Print("return ");
273
274 if (s->a)
275 {
276 arg1 = PR_PrintStringAtOfs(s->a, typ1);
277 PR_Print("( %s )", arg1);
278 }
279
280 PR_Print(";\n");
281 }
282 else if ((OP_MUL_F <= s->op && s->op <= OP_SUB_V) ||
283 (OP_EQ_F <= s->op && s->op <= OP_GT ) ||
284 (OP_AND <= s->op && s->op <= OP_BITOR))
285 {
286 arg1 = PR_PrintStringAtOfs(s->a, typ1);
287 if (arg1)
288 strcpy(a1, arg1);
289
290 arg2 = PR_PrintStringAtOfs(s->b, typ2);
291 if (arg2)
292 strcpy(a2, arg2);
293
294 arg3 = PR_PrintGlobal(s->c, typ3);
295 if (arg3)
296 {
297 PR_Indent();
298 PR_Print("%s = %s %s %s;\n", arg3, a1, pr_opcodes[s->op].name, a2);
299 }
300 else
301 {
302 sprintf(dsline, "(%s %s %s)", a1, pr_opcodes[s->op].name, a2);
303 Make_Immediate(s->c, dsline);
304 }
305 }
306 else if (OP_LOAD_F <= s->op && s->op <= OP_ADDRESS)
307 {
308 arg1 = PR_PrintStringAtOfs(s->a, typ1);
309 if (arg1)
310 strcpy(a1, arg1);
311
312 arg2 = PR_PrintStringAtOfs(s->b, typ2);
313 if (arg2)
314 strcpy(a2, arg2);
315
316 arg3 = PR_PrintGlobal(s->c, typ3);
317 if (arg3)
318 {
319 PR_Indent();
320 PR_Print("%s = %s.%s;\n", arg3, a1, a2);
321 }
322 else
323 {
324 sprintf(dsline, "%s.%s", a1, a2);
325 // printf("%s.%s making immediate at %d\n",a1,a2,s->c);
326 Make_Immediate(s->c, dsline);
327 }
328 }
329 else if ((OP_STORE_F <= s->op) && (s->op <= OP_STORE_FNC))
330 {
331 arg1 = PR_PrintStringAtOfs(s->a, typ1);
332 if (arg1)
333 strcpy(a1,arg1);
334
335 /*
336 par = DEC_GetParameter (s->a);
337 if (par && s->op == OP_STORE_F)
338 {
339 if (par->type == ev_vector)
340 strcat(a1, "_x");
341 }
342 */
343 arg3 = PR_PrintGlobal(s->b, typ2);
344 if (arg3)
345 {
346 PR_Indent();
347 PR_Print("%s = %s;\n", arg3, a1);
348 }
349 else
350 {
351 sprintf(dsline,"%s", a1);
352 Make_Immediate(s->b, dsline);
353 }
354 }
355 else if ((OP_STOREP_F <= s->op) && (s->op <= OP_STOREP_FNC))
356 {
357 arg1 = PR_PrintStringAtOfs(s->a, typ1);
358 if (arg1)
359 strcpy(a1, arg1);
360
361 par = DEC_GetParameter (s->a);
362 if (par && s->op == OP_STOREP_F)
363 {
364 if (par->type == ev_vector)
365 strcat(a1, "_x");
366 }
367
368 arg2 = PR_PrintStringAtOfs(s->b, typ2);
369
370 PR_Indent();
371 PR_Print("%s = %s;\n", arg2, a1);
372 }
373 else if ((OP_NOT_F <= s->op) && (s->op <= OP_NOT_FNC))
374 {
375 arg1 = PR_PrintStringAtOfs(s->a, typ1);
376 sprintf(dsline, "!%s", arg1);
377 Make_Immediate(s->c, dsline);
378 }
379 else if ((OP_CALL0 <= s->op) && (s->op <= OP_CALL8))
380 {
381 nargs = s->op - OP_CALL0;
382
383 arg1 = PR_PrintStringAtOfs(s->a, typ1);
384 if (arg1)
385 strcpy(a1, arg1);
386 // printf("fname: %s %s\n", a1, arg1);
387
388 arg2 = PR_PrintStringAtOfs(s->b, typ2);
389 if (arg2)
390 strcpy(a2, arg2);
391
392 arg3 = PR_PrintStringAtOfs(s->c, typ3);
393 sprintf(dsline, "%s (", a1);
394 sprintf(funcname, "%s", a1);
395 if (arg2)
396 {
397 strcat(dsline, " ");
398 strcat(dsline, a2);
399 i++;
400 }
401
402 if (arg3 && nargs > 1)
403 {
404 size_t len = strlen(arg3);
405 strcat(dsline, ", ");
406 strcat(dsline, arg3);
407 if (!strcmp(funcname, "WriteCoord") || !strcmp(funcname, "WriteAngle"))
408 {
409 if (len >= 2)
410 {
411 len -= 2;
412 if (strcmp(&arg3[len], "_x") &&
413 !(!strcmp(&arg3[len], "_y") ||
414 !strcmp(&arg3[len], "_z") ||
415 !strcmp(&arg3[len+1], ")")))
416 strcat(dsline, "_x");
417 }
418 }
419 }
420
421 for (i = 2; i < nargs; i++)
422 {
423 strcat(dsline, ", ");
424 arg2 = Get_Immediate(OFS_PARM0 + (i * 3));
425 if (!arg2)
426 continue;
427 strcat(dsline, arg2);
428 }
429
430 strcat(dsline, ")");
431 Make_Immediate(OFS_RETURN, dsline);
432 j = 1; /* print now */
433
434 for (i = 1; (s + i)->op; i++)
435 {
436 // printf ("\n%d\n", (s + i)->op);
437 if ((s + i)->op == OP_DONE)
438 break;
439
440 if ((s + i)->op >= OP_RAND0)
441 break;
442
443 if ((s + i)->a == OFS_RETURN ||
444 (s + i)->b == OFS_RETURN ||
445 (s + i)->c == OFS_RETURN)
446 {
447 j = 0;
448 // printf("ofs_return is used before another call %d %d %d\n",
449 // j, i, (s + i)->op);
450 break;
451 }
452
453 if (OP_CALL0 <= (s + i)->op && (s + i)->op <= OP_CALL8)
454 {
455 // if (i == 1)
456 // j = 0;
457 // printf("another call %d %d %d %d \n",
458 // j, i, (s + i)->a, (s + i)->b);
459 break;
460 }
461 }
462
463 if (j)
464 {
465 PR_Indent();
466 PR_Print("%s;\n", temp_val[OFS_RETURN]);
467 }
468 }
469 else if (s->op == OP_IF || s->op == OP_IFNOT)
470 {
471 arg1 = PR_PrintStringAtOfs(s->a, typ1);
472 if (arg1)
473 strcpy(a1, arg1);
474
475 if (s->op == OP_IFNOT)
476 {
477 op_b = (progs->version == PROG_VERSION_V6) ? (signed short)s->b : s->b;
478 if (op_b < 1)
479 COM_Error("Found a negative IFNOT jump.");
480
481 /* get instruction right before the target */
482 t = s + op_b - 1; /* */
483 tom = t->op;
484
485 if (tom != OP_GOTO)
486 {
487 /* pure if */
488 PR_Indent();
489 PR_Print("if ( %s ) {\n\n", a1);
490 lindent++;
491 }
492 else
493 {
494 op_a = (progs->version == PROG_VERSION_V6) ? (signed short)t->a : t->a;
495 if (op_a > 0)
496 {
497 /* ite */
498 PR_Indent();
499 PR_Print("if ( %s ) {\n\n", a1);
500 lindent++;
501 }
502 else
503 {
504 if (op_a + op_b > 1)
505 {
506 /* pure if */
507 PR_Indent();
508 PR_Print("if ( %s ) {\n\n", a1);
509 lindent++;
510 }
511 else
512 {
513 int dum = 1;
514 for (k = t + op_a; k < s; k++)
515 {
516 tom = k->op;
517 if (tom == OP_GOTO || tom == OP_IF || tom == OP_IFNOT)
518 dum = 0;
519 }
520
521 if (dum)
522 {
523 /* while */
524 PR_Indent();
525 PR_Print("while ( %s ) {\n\n", a1);
526 lindent++;
527 }
528 else
529 {
530 /* pure if */
531 PR_Indent();
532 PR_Print("if ( %s ) {\n\n", a1);
533 lindent++;
534 }
535 }
536 }
537 }
538 }
539 else
540 {
541 /* do ... while */
542 op_b = (progs->version == PROG_VERSION_V6) ? (signed short)s->b : s->b;
543 if (op_b < 0)
544 {
545 lindent--;
546 PR_Indent();
547 PR_Print("} while ( %s );\n", a1);
548 }
549 else
550 {
551 PR_Indent();
552 PR_Print("if ( !(%s) ) {\n\n", a1);
553 lindent++;
554 }
555 }
556 }
557 else if (s->op == OP_GOTO)
558 {
559 op_a = (progs->version == PROG_VERSION_V6) ? (signed short)s->a : s->a;
560 if (op_a > 0)
561 {
562 /* else */
563 lindent--;
564 PR_Indent();
565 PR_Print("} else {\n\n");
566 lindent++;
567 }
568 else
569 {
570 /* while */
571 PR_Print("\n");
572 lindent--;
573 PR_Indent();
574 PR_Print("}\n");
575 }
576 }
577 else if ((s->op >= OP_MULSTORE_F && s->op <= OP_SUBSTOREP_V) ||
578 (s->op >= OP_BITSET && s->op <= OP_BITCLRP))
579 {
580 arg1 = PR_PrintStringAtOfs(s->a, typ1);
581 if (arg1)
582 strcpy(a1, arg1);
583
584 arg2 = PR_PrintStringAtOfs(s->b, typ2);
585 if (arg2)
586 sprintf(dsline, "%s", arg2);
587
588 PR_Indent();
589 PR_Print("%s %s %s;\n", arg2, pr_opcodes[s->op].name, a1);
590
591 if (s->c)
592 Make_Immediate(s->c, dsline);
593 }
594 else if (s->op == OP_FETCH_GBL_F || s->op == OP_FETCH_GBL_V)
595 {
596 arg1 = PR_PrintStringAtOfs(s->a, typ1);
597 if (arg1)
598 strcpy(a1, arg1);
599
600 arg2 = PR_PrintStringAtOfs(s->b, typ2);
601 if (arg2)
602 strcpy(a2, arg2);
603
604 arg3 = PR_PrintStringAtOfs(s->c, typ3);
605 if (arg3)
606 {
607 PR_Indent();
608 PR_Print("%s = %s->%s;\n", arg3, a2, a1);
609 }
610 else
611 {
612 sprintf(dsline, "(%s->%s)", a1, a2);
613 Make_Immediate(s->c, dsline);
614 }
615 }
616 else if (s->op == OP_CSTATE)
617 {
618 arg1 = PR_PrintStringAtOfs(s->a, typ1);
619 if (arg1)
620 strcpy(a1, arg1);
621
622 arg2 = PR_PrintStringAtOfs(s->b, typ2);
623 PR_Indent();
624 PR_Print("AdvanceFrame( %s, %s);\n", a1, arg2);
625 }
626 else if (s->op == OP_THINKTIME)
627 {
628 arg1 = PR_PrintStringAtOfs(s->a, typ1);
629 if (arg1)
630 strcpy(a1, arg1);
631
632 arg2 = PR_PrintStringAtOfs(s->b, typ2);
633 PR_Indent();
634 PR_Print("AdvanceThinkTime(%s,%s);\n", a1, arg2);
635 }
636 else if (s->op == OP_RAND0)
637 {
638 sprintf(dsline,"random()");
639 Make_Immediate(OFS_RETURN, dsline);
640 }
641 else if (s->op == OP_RAND1)
642 {
643 arg1 = PR_PrintStringAtOfs(s->a, typ1);
644 if (arg1)
645 strcpy(a1, arg1);
646
647 sprintf(dsline, "random(%s)", a1);
648 Make_Immediate(OFS_RETURN, dsline);
649 }
650 else if (s->op == OP_RAND2)
651 {
652 arg1 = PR_PrintStringAtOfs(s->a, typ1);
653 if (arg1)
654 strcpy(a1, arg1);
655
656 arg2 = PR_PrintStringAtOfs(s->b, typ2);
657 sprintf(dsline, "random(%s,%s)", a1, arg2);
658 Make_Immediate(OFS_RETURN, dsline);
659 }
660 else if (s->op == OP_RANDV0)
661 {
662 sprintf(dsline,"random( )");
663 Make_Immediate(OFS_RETURN, dsline);
664 }
665 else if (s->op == OP_RANDV1)
666 {
667 arg1 = PR_PrintStringAtOfs(s->a, typ1);
668 if (arg1)
669 strcpy(a1, arg1);
670
671 sprintf(dsline, "random(%s)", a1);
672 Make_Immediate(OFS_RETURN, dsline);
673 }
674 else if (s->op == OP_RANDV2)
675 {
676 arg1 = PR_PrintStringAtOfs(s->a, typ1);
677 if (arg1)
678 strcpy(a1, arg1);
679
680 arg2 = PR_PrintStringAtOfs(s->b, typ2);
681 sprintf(dsline, "random(%s,%s)", a1, arg2);
682 Make_Immediate(OFS_RETURN, dsline);
683 }
684 else
685 {
686 PR_Print("\n/* ERROR: UNKNOWN COMMAND */\n OP: %d ", s->op);
687 arg1 = PR_PrintStringAtOfs(s->a, NULL);
688 arg2 = PR_PrintStringAtOfs(s->b, NULL);
689 arg3 = PR_PrintStringAtOfs(s->c, NULL);
690 if (progs->version == PROG_VERSION_V6)
691 {
692 PR_Print("a: %s(%d)", arg1, (signed short)s->a);
693 PR_Print(" b: %s(%d)", arg2, (signed short)s->b);
694 PR_Print(" c: %s(%d)\n", arg3, (signed short)s->c);
695 }
696 else /* PROG_VERSION_V7 */
697 {
698 PR_Print("a: %s(%d)", arg1, s->a);
699 PR_Print(" b: %s(%d)", arg2, s->b);
700 PR_Print(" c: %s(%d)\n", arg3, s->c);
701 }
702 }
703 }
704
Make_Immediate(gofs_t ofs,const char * s)705 static void Make_Immediate (gofs_t ofs, const char *s)
706 {
707 if (ofs >= progs->numglobals) /* happens with opcodes that DHCC doesn't know, i.e. switches. */
708 {
709 // printf ("%s: ofs %d is past numpr_globals %d (cfunc->parm_start: %d, cfunc->locals: %d)\n",
710 // __thisfunc__, ofs, progs->numglobals, cfunc->parm_start, cfunc->locals);
711 return;
712 }
713 if (temp_val[ofs])
714 free(temp_val[ofs]);
715 temp_val[ofs] = SafeStrdup(s);
716 }
717
Get_Immediate(gofs_t ofs)718 static char *Get_Immediate (gofs_t ofs)
719 {
720 if (ofs >= progs->numglobals) /* happens with opcodes that DHCC doesn't know, i.e. switches. */
721 {
722 // printf ("%s: ofs %d is past numpr_globals %d (cfunc->parm_start: %d, cfunc->locals: %d)\n",
723 // __thisfunc__, ofs, progs->numglobals, cfunc->parm_start, cfunc->locals);
724 return NULL;
725 }
726
727 return temp_val[ofs];
728 }
729
Clear_Immediates(void)730 static void Clear_Immediates (void)
731 {
732 int i;
733 for (i = 0; i < progs->numglobals; i++)
734 {
735 if (temp_val[i])
736 {
737 free(temp_val[i]);
738 temp_val[i] = NULL;
739 }
740 }
741 }
742
743
AddProgramFlowInfo(dfunction_t * df)744 static void AddProgramFlowInfo (dfunction_t *df)
745 {
746 dstatement_t *ds, *ts;
747 unsigned short dom, tom;
748 dstatement_t *k;
749 int op_a, op_b;
750
751 ds = pr_statements + df->first_statement;
752
753 while (1)
754 {
755 dom = ds->op;
756 if (!dom)
757 {
758 break;
759 }
760 else if (dom == OP_GOTO)
761 {
762 /* check for i-t-e */
763 op_a = (progs->version == PROG_VERSION_V6) ? (signed short)ds->a : ds->a;
764 if (op_a > 0)
765 {
766 ts = ds + op_a;
767 /* mark the end of a if/ite construct */
768 flowinfo[ts - pr_statements].if_cnt++;
769 }
770 }
771 else if (dom == OP_IFNOT)
772 {
773 /* check for pure if */
774 op_b = (progs->version == PROG_VERSION_V6) ? (signed short)ds->b : ds->b;
775 ts = ds + op_b; /* FIXME: ds->b < 0 possible? */
776 tom = (ts - 1)->op;
777
778 if (tom != OP_GOTO)
779 {
780 /* mark the end of a if/ite construct */
781 flowinfo[ts - pr_statements].if_cnt++;
782 }
783 else
784 {
785 op_a = (progs->version == PROG_VERSION_V6) ? (signed short)((ts - 1)->a) : (ts - 1)->a;
786 if (op_a < 0)
787 {
788 if (op_a + op_b > 1)
789 { /* pure if */
790 /* mark the end of a if/ite construct */
791 flowinfo[ts - pr_statements].if_cnt++;
792 }
793 else
794 {
795 int dum = 1;
796 for (k = (ts - 1) + op_a; k < ds; k++)
797 {
798 tom = k->op;
799 if (tom == OP_GOTO || tom == OP_IF || tom == OP_IFNOT)
800 dum = 0;
801 }
802 if (!dum)
803 { /* pure if */
804 /* mark the end of a if/ite construct */
805 flowinfo[ts - pr_statements].if_cnt++;
806 }
807 }
808 }
809 }
810 }
811 else if (dom == OP_IF)
812 {
813 op_b = (progs->version == PROG_VERSION_V6) ? (signed short)ds->b : ds->b;
814 ts = ds + op_b;
815 if (op_b < 0)
816 {
817 /* mark the start of a do construct */
818 flowinfo[ts - pr_statements].do_cnt++;
819 }
820 else
821 {
822 /* mark the end of a if/ite construct */
823 flowinfo[ts - pr_statements].if_cnt++;
824 }
825 }
826
827 ds++;
828 }
829 }
830
831
PR_Indent(void)832 static void PR_Indent (void)
833 {
834 int i;
835
836 if (lindent < 0)
837 lindent = 0;
838
839 for (i = 0; i < lindent; i++)
840 {
841 PR_Print(" ");
842 }
843 }
844
PR_Locals(dfunction_t * df)845 static void PR_Locals (dfunction_t *df)
846 {
847 int start, i, j, k;
848 ddef_t *par;
849
850 start = df->parm_start;
851 i = df->numparms;
852
853 for (j = k = 0; j < i; j++)
854 k += df->parm_size[j];
855
856 start += k;
857
858 for (j = start; j < df->parm_start + df->locals; j++)
859 {
860 PR_Indent();
861 par = DEC_GetParameter (j);
862 if (par)
863 {
864 if (par->type == ev_void || par->type == ev_void ||
865 par->type == ev_field || par->type == ev_function ||
866 par->type == ev_pointer)
867 {
868 continue;
869 }
870
871 if (!strcmp(IMMEDIATE_NAME, pr_strings + par->s_name))
872 continue;
873
874 PR_Print("local ");
875
876 switch (par->type)
877 {
878 case ev_string:
879 PR_Print("string");
880 break;
881 case ev_void:
882 PR_Print("void");
883 break;
884 case ev_float:
885 PR_Print("float");
886 break;
887 case ev_vector:
888 PR_Print("vector");
889 j += 2;
890 break;
891 case ev_entity:
892 PR_Print("entity");
893 break;
894 case ev_field:
895 PR_Print("ev_field");
896 break;
897 case ev_function:
898 PR_Print("void()");
899 break;
900 case ev_pointer:
901 PR_Print("ev_pointer");
902 break;
903 }
904
905 PR_Print(" %s", pr_strings + par->s_name);
906
907 if (par->type == ev_float || par->type == ev_vector)
908 PR_Print(" = %s", DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs]));
909
910 PR_Print(";\n");
911 }
912 }
913 }
914
915
PR_FunctionHeader(dfunction_t * df)916 static void PR_FunctionHeader (dfunction_t *df)
917 {
918 int j, start;
919 ddef_t *par;
920 char linetxt[512];
921 unsigned short t1;
922
923 if (func_headers[df - pr_functions]) /* already done */
924 return;
925
926 if (df->first_statement < 0)
927 { /* builtin */
928 FindBuiltinParameters(df - pr_functions);
929 return;
930 }
931
932 /* get return type */
933 linetxt[0] = '\0';
934 t1 = GetReturnType(df - pr_functions);
935
936 switch (t1)
937 {
938 case ev_string:
939 sprintf(linetxt, "string ");
940 break;
941 case ev_void:
942 sprintf(linetxt, "void ");
943 break;
944 case ev_float:
945 sprintf(linetxt, "float ");
946 break;
947 case ev_vector:
948 sprintf(linetxt, "vector ");
949 break;
950 case ev_entity:
951 sprintf(linetxt, "entity ");
952 break;
953 case ev_field:
954 sprintf(linetxt, "ev_field ");
955 break;
956 case ev_function:
957 sprintf(linetxt, "void() ");
958 break;
959 case ev_pointer:
960 sprintf(linetxt, "ev_pointer ");
961 break;
962 default:
963 sprintf(linetxt, "void ");
964 break;
965 }
966
967 /* print parameters */
968 strcat(linetxt, " (");
969
970 start = df->parm_start;
971
972 for (j = 0; j < df->numparms; j++)
973 {
974 par = DEC_GetParameter (start);
975
976 if (par)
977 {
978 switch (par->type)
979 {
980 case ev_string:
981 strcat(linetxt, "string ");
982 break;
983 case ev_void:
984 strcat(linetxt, "void ");
985 break;
986 case ev_float:
987 strcat(linetxt, "float ");
988 break;
989 case ev_vector:
990 strcat(linetxt, "vector ");
991 break;
992 case ev_entity:
993 strcat(linetxt, "entity ");
994 break;
995 case ev_field:
996 strcat(linetxt, "ev_field ");
997 break;
998 case ev_function:
999 strcat(linetxt, "void() ");
1000 break;
1001 case ev_pointer:
1002 strcat(linetxt, "ev_pointer ");
1003 break;
1004 }
1005
1006 strcat(linetxt, pr_strings + par->s_name);
1007 }
1008 else
1009 {
1010 sprintf(linetxt, "void unknown ");
1011 }
1012
1013 if (j < (df->numparms - 1))
1014 strcat(linetxt, ",");
1015
1016 start += df->parm_size[j];
1017 }
1018
1019 strcat(linetxt, ")");
1020 func_headers[df - pr_functions] = SafeStrdup(linetxt);
1021 }
1022
1023
PR_Print(const char * s,...)1024 static void PR_Print (const char *s,...)
1025 {
1026 va_list argptr;
1027
1028 va_start (argptr, s);
1029 vfprintf (PR_FILE, s, argptr);
1030 va_end (argptr);
1031 }
1032
GetReturnType(int func)1033 static unsigned short GetReturnType (int func)
1034 {
1035 int i, j;
1036 ddef_t *par = NULL;
1037 dstatement_t *ds, *di;
1038 dfunction_t *df;
1039 const char *arg1;
1040 unsigned short rtype[2] = {ev_void, ev_void};
1041 def_t *type1;
1042
1043 if (func == 0)
1044 return ev_void;
1045
1046 df = pr_functions + func;
1047 ds = pr_statements + df->first_statement;
1048
1049 if (df->first_statement < 0)
1050 {
1051 /* ??? */
1052 }
1053
1054 j = 0;
1055 while (1)
1056 {
1057 if (j > 1)
1058 break;
1059
1060 if (ds->op == OP_DONE)
1061 break;
1062
1063 if (ds->op == OP_RETURN)
1064 { /* find 2 different returns if possible just to be certain (ie: findtarget) */
1065 j++; /* we do come here with j == 1 already. put j > 1 checks below. */
1066 if (ds->a != 0)
1067 {
1068 if (ds->a == OFS_RETURN)
1069 {
1070 di = ds - 1;
1071 while ((di - pr_statements) >= df->first_statement)
1072 { /* that stupid equal, what a bitch */
1073 if (OP_CALL0 <= di->op && di->op <= OP_CALL8)
1074 {
1075 type1 = pr_opcodes[di->op].type_a;
1076 arg1 = PR_PrintStringAtOfs(di->a, type1);
1077 if (!arg1)
1078 COM_Error("function name not found!!!\n");
1079 i = DEC_GetFunctionIdxByName(arg1);
1080 if (i == 0)
1081 break;
1082 if (i != func)
1083 {
1084 if (j < 2)
1085 rtype[j] = GetReturnType(i);
1086 /* else: array out of bounds */
1087 break;
1088 }
1089 else
1090 {
1091 j--;
1092 break;
1093 }
1094 } /* end if call */
1095 else if (OP_RAND0 <= di->op && di->op <= OP_RAND2)
1096 {
1097 if (j < 2)
1098 rtype[j] = ev_float;
1099 /* else: array out of bounds */
1100 break;
1101 }
1102 else if (OP_RANDV0 <= di->op && di->op <= OP_RANDV2)
1103 {
1104 if (j < 2)
1105 rtype[j] = ev_vector;
1106 /* else: array out of bounds */
1107 break;
1108 }
1109
1110 di--;
1111 } /* end while ofs_return */
1112 }
1113 else
1114 {
1115 if (j > 1)
1116 break; /* array out of bounds */
1117 par = DEC_GetParameter (ds->a);
1118 if (par)
1119 {
1120 rtype[j] = par->type;
1121 }
1122 else
1123 {
1124 /* find the op where the reg was created,
1125 * it can tell what the val is */
1126 rtype[j] = pr_opcodes[ds->op].type_a->type->type;
1127 if (rtype[j] == ev_pointer)
1128 {
1129 rtype[j] = BackBuildReturnType(df, ds, ds->a);
1130 }
1131 }
1132 }
1133 }
1134 else
1135 {
1136 if (j > 1)
1137 break; /* array out of bounds */
1138 rtype[j] = ev_void;
1139 }
1140 }
1141
1142 ds++;
1143 }
1144
1145 if ((rtype[0] != rtype[1]) && (rtype[0] == ev_void))
1146 rtype[0] = rtype[1];
1147
1148 return rtype[0];
1149 }
1150
1151 #if 0 /* this is unused */
1152 static unsigned short OP_StoreValue (dstatement_t *ds)
1153 {
1154 switch (ds->op)
1155 {
1156 case OP_CALL0:
1157 case OP_CALL1:
1158 case OP_CALL2:
1159 case OP_CALL3:
1160 case OP_CALL4:
1161 case OP_CALL5:
1162 case OP_CALL6:
1163 case OP_CALL7:
1164 case OP_CALL8:
1165 return ev_function;
1166
1167 case OP_NOT_V:
1168 case OP_STORE_V:
1169 case OP_LOAD_V:
1170 case OP_NE_V:
1171 case OP_EQ_V:
1172 case OP_SUB_V:
1173 case OP_ADD_V:
1174 case OP_MUL_V:
1175 case OP_MUL_FV:
1176 case OP_MUL_VF:
1177 case OP_STOREP_V:
1178 return ev_vector;
1179
1180 case OP_NE_F:
1181 case OP_EQ_F:
1182 case OP_MUL_F:
1183 case OP_DIV_F:
1184 case OP_ADD_F:
1185 case OP_SUB_F:
1186 case OP_LE:
1187 case OP_GE:
1188 case OP_LT:
1189 case OP_GT:
1190 case OP_LOAD_F:
1191 case OP_STORE_F:
1192 case OP_NOT_F:
1193 case OP_STOREP_F:
1194 case OP_IF:
1195 case OP_IFNOT:
1196 case OP_STATE:
1197 case OP_AND:
1198 case OP_OR:
1199 case OP_BITAND:
1200 case OP_BITOR:
1201 return ev_float;
1202
1203 case OP_EQ_S:
1204 case OP_NE_S:
1205 case OP_LOAD_S:
1206 case OP_STORE_S:
1207 case OP_STOREP_S:
1208 case OP_NOT_S:
1209 return ev_string;
1210
1211 case OP_NE_E:
1212 case OP_EQ_E:
1213 case OP_LOAD_ENT:
1214 case OP_STORE_ENT:
1215 case OP_NOT_ENT:
1216 case OP_STOREP_ENT:
1217 return ev_entity;
1218
1219 case OP_EQ_FNC:
1220 case OP_NE_FNC:
1221 case OP_LOAD_FNC:
1222 case OP_STORE_FNC:
1223 case OP_STOREP_FNC:
1224 return ev_function;
1225
1226 case OP_LOAD_FLD:
1227 case OP_ADDRESS:
1228 case OP_STORE_FLD:
1229 case OP_STOREP_FLD:
1230 return ev_field;
1231
1232 case OP_RETURN:
1233 case OP_NOT_FNC:
1234 case OP_DONE:
1235 case OP_GOTO:
1236 return ev_void;
1237 }
1238
1239 return ev_void;
1240 }
1241 #endif /* end of unused */
1242
PR_GetField(const char * name,ddef_t * dd)1243 static ddef_t *PR_GetField (const char *name, ddef_t *dd)
1244 {
1245 int i;
1246 ddef_t *d;
1247
1248 for (i = 1; i < progs->numfielddefs; i++)
1249 {
1250 d = &pr_fielddefs[i];
1251 if (!strcmp(pr_strings + d->s_name, name))
1252 {
1253 // printf("%s %d %d\n", name, dd ? dd->ofs : 0, d ? d->ofs : 0);
1254 return d;
1255 }
1256 }
1257
1258 return NULL;
1259 }
1260
1261
PR_FieldIsUnique(ddef_t * dd)1262 static ddef_t *PR_FieldIsUnique (ddef_t *dd)
1263 {
1264 int i;
1265 ddef_t *d;
1266
1267 for (i = 1; i < progs->numfielddefs; i++)
1268 {
1269 d = &pr_fielddefs[i];
1270 if (d->ofs == dd->ofs)
1271 {
1272 if (d->type == ev_vector && dd - 1 == d)
1273 return dd;
1274 // printf("%s %d %d\n", dd ? pr_strings + dd->s_name : "null", dd ? dd->ofs : 0, d ? d->ofs : 0);
1275 return d;
1276 }
1277 }
1278
1279 return NULL;
1280 }
1281
1282
Dcc_Functions(void)1283 static void Dcc_Functions (void)
1284 {
1285 int i;
1286 dfunction_t *df;
1287 char fname[1024], *p;
1288 FILE *prgs;
1289
1290 prgs = fopen("progs.src","w");
1291 if (!prgs)
1292 COM_Error("unable to open progs.src!!!\n");
1293
1294 fprintf(prgs, "%s", "progs.dat\n\n");
1295
1296 for (i = 1; i < progs->numfunctions; i++)
1297 {
1298 df = pr_functions + i;
1299
1300 if (FILE_NUM_FOR_NAME)
1301 sprintf (fname, "%d.hc", df->s_file);
1302 else sprintf (fname, "%s", pr_strings + df->s_file);
1303 /* unixify the path, */
1304 p = fname;
1305 while (*p)
1306 {
1307 if (*p == '\\')
1308 *p = '/';
1309 ++p;
1310 }
1311 /* create parent directories, if any */
1312 CreatePath(fname);
1313
1314 if (! DEC_AlreadySeen(fname))
1315 {
1316 fprintf(prgs, "%s\n", fname);
1317 printf("decompiling %s\n", fname);
1318 }
1319
1320 PR_FILE = fopen(fname, "a+");
1321 if (PR_FILE == NULL)
1322 {
1323 PR_FILE = stdout;
1324 COM_Error("unable to open %s\n", fname);
1325 }
1326
1327 PR_PrintFunction(pr_strings + df->s_name);
1328 fclose(PR_FILE);
1329 PR_FILE = stdout;
1330 }
1331
1332 fclose(prgs);
1333 }
1334
1335
CalcArraySize(int j,int end)1336 static int CalcArraySize (int j, int end)
1337 {
1338 ddef_t *par;
1339
1340 if (j == end)
1341 return 0;
1342
1343 for (j++; j < end; j++)
1344 {
1345 par = DEC_GetParameter (j);
1346 if (par && strcmp(pr_strings + par->s_name, IMMEDIATE_NAME))
1347 {
1348 // printf("next is %s at %d\n", pr_strings + par->s_name, par->ofs);
1349 return par->ofs;
1350 }
1351 }
1352
1353 // printf("can not find next %d %d!!!!!!!!!!!!!!!!!!!!\n", j, end);
1354 return j;
1355 }
1356
1357
PR_InitValues(ddef_t * par,int size)1358 static void PR_InitValues (ddef_t *par, int size)
1359 {
1360 int j;
1361
1362 // printf("size %d\n", size);
1363
1364 if (size > 1)
1365 {
1366 PR_Print("{ %s,\n", DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs]));
1367 }
1368 else
1369 {
1370 PR_Print(" %s;\n", DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs]));
1371 return;
1372 }
1373
1374 lindent++;
1375
1376 for (j = 1; j < size; j++)
1377 {
1378 PR_Indent();
1379 if (j < size - 1)
1380 {
1381 if (! (j & 0x3))
1382 PR_Print(" %s,\n", DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs + (j*type_size[par->type])]));
1383 else PR_Print(" %s,", DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs + (j*type_size[par->type])]));
1384 }
1385 else
1386 {
1387 PR_Print(" %s", DCC_ValueString((etype_t)par->type, &pr_globals[par->ofs + (j*type_size[par->type])]));
1388 }
1389 }
1390
1391 PR_Print("};\n");
1392 lindent--;
1393 }
1394
1395
PR_LocalGlobals(void)1396 static void PR_LocalGlobals (void)
1397 {
1398 int i, j, ps, cnt = 0;
1399 int start, end, bsize;
1400 dfunction_t *df, *dfpred;
1401 ddef_t *par;
1402 // ddef_t *par2;
1403 ddef_t *ef;
1404 const char *arg2;
1405
1406 printf("finding declared globals:.");
1407
1408 df = cfunc;
1409 dfpred = df - 1;
1410
1411 for (j = 0, ps = 0; j < dfpred->numparms; j++)
1412 ps += dfpred->parm_size[j];
1413
1414 start = dfpred->parm_start + dfpred->locals + ps;
1415
1416 if (dfpred->first_statement < 0 && df->first_statement > 0)
1417 start -= 1;
1418
1419 if (start == 0)
1420 start = 1;
1421
1422 // printf("starting at %d ending at %d\n", start, end);
1423
1424 end = df->parm_start;
1425
1426 for (j = start; j < end; j++)
1427 {
1428 par = DEC_GetParameter (j);
1429 // par2 = DEC_GetParameter (j+1);
1430 if (! (j & 0xf))
1431 printf(".");
1432
1433 if (!par)
1434 cnt++;
1435
1436 if (par/* && strcmp(pr_strings + par->s_name, IMMEDIATE_NAME)*/)
1437 {
1438 // printf("cnt is %d\n", cnt);
1439 cnt = 0;
1440 bsize = CalcArraySize(j, end);
1441
1442 par->type &= ~DEF_SAVEGLOBAL;
1443
1444 // printf("%s type: %d ofs: %d par2: %d bsize: %d\n",
1445 // pr_strings + par->s_name, par->type,
1446 // par->ofs, par2 ? (par2->ofs-par->ofs) : -1,
1447 // bsize-par->ofs);
1448
1449 if (par->type == ev_function)
1450 {
1451 if (strcmp(pr_strings + par->s_name, IMMEDIATE_NAME) == 0)
1452 continue;
1453 if (strcmp(pr_strings + par->s_name, pr_strings + cfunc->s_name) == 0)
1454 continue;
1455 i = DEC_GetFunctionIdxByName(pr_strings + par->s_name);
1456 /* check for i == 0 here ???? */
1457 PR_FunctionHeader(pr_functions + i);
1458 PR_Print("%s%s;\n", func_headers[i],pr_strings + (pr_functions + i)->s_name);
1459 }
1460 else if (par->type != ev_pointer)
1461 {
1462 if (strcmp(pr_strings + par->s_name, IMMEDIATE_NAME) == 0)
1463 continue;
1464 if (par->type == ev_field)
1465 {
1466 ef = PR_GetField(pr_strings + par->s_name, par);
1467 if (!ef)
1468 COM_Error("Could not locate a field named \"%s\"", pr_strings + par->s_name);
1469 i = (ef->type & ~DEF_SAVEGLOBAL);
1470 if (i == ev_vector)
1471 j += 3;
1472 if (i == ev_function)
1473 {
1474 arg2 = GetFieldFunctionHeader(pr_strings + ef->s_name);
1475 GFFH_depth = 0;
1476 // printf("function .%s %s;\n", arg2, pr_strings + ef->s_name);
1477 PR_Print(".%s %s;\n", arg2, pr_strings + ef->s_name);
1478 }
1479 else
1480 {
1481 // printf("variable %d .%s %s;\n", i, type_names[i], pr_strings + ef->s_name);
1482 par = PR_FieldIsUnique(ef);
1483 if (par == ef)
1484 PR_Print(".%s %s;\n", type_names[i], pr_strings + ef->s_name);
1485 else
1486 PR_Print(".%s %s alias %s;\n", type_names[i], pr_strings + ef->s_name, pr_strings + par->s_name);
1487 }
1488 }
1489 else
1490 {
1491 bsize = (bsize - par->ofs) / type_size[par->type];
1492 if (!par->ofs || bsize - 1 < *(int *)&pr_globals[par->ofs - 1])
1493 {
1494 // printf("bsize %d %d\n", bsize, *(int *)&pr_globals[par->ofs - 1]);
1495 bsize = 1;
1496 }
1497 if (bsize != 1)
1498 {
1499 bsize = *(int *)&pr_globals[par->ofs - 1] + 1;
1500 }
1501 if (par->type == ev_vector)
1502 j += 2;
1503 if (par->type == ev_entity || par->type == ev_void)
1504 {
1505 if (!strcmp(pr_strings + par->s_name, "end_sys_fields"))
1506 printassign = true;
1507 PR_Print("%s %s;\n", type_names[par->type], pr_strings + par->s_name);
1508 }
1509 else
1510 {
1511 if (pr_dumpasm ||
1512 printassign ||
1513 !strcmp(pr_strings + par->s_name, "string_null"))
1514 {
1515 if (bsize < 2)
1516 PR_Print("%s %s = ", type_names[par->type], pr_strings + par->s_name);
1517 else
1518 PR_Print("%s %s [%d] = ", type_names[par->type], pr_strings + par->s_name, bsize);
1519 PR_InitValues(par, bsize);
1520 }
1521 else
1522 {
1523 PR_Print("%s %s;\n", type_names[par->type], pr_strings + par->s_name);
1524 }
1525 }
1526 }
1527 }
1528 }
1529 }
1530
1531 printf("\n");
1532 }
1533
1534
GetFieldFunctionHeader(const char * s_name)1535 static const char *GetFieldFunctionHeader (const char *s_name)
1536 {
1537 int i, j = 0;
1538 dstatement_t *d;
1539 // const char *arg1;
1540 const char *arg2, *arg3;
1541 def_t *typ;
1542
1543 if (++GFFH_depth > GFFH_MAX_DEPTH) /* see below */
1544 {
1545 // printf("\n%s: MAX_DEPTH reached for \"%s\", returning void ()\n",
1546 // __thisfunc__, s_name);
1547 return "void ()";
1548 }
1549
1550 for (i = 1; i < progs->numstatements; i++)
1551 {
1552 d = pr_statements + i;
1553
1554 if (d->op == OP_ADDRESS)
1555 {
1556 // typ = pr_opcodes[d->op].type_a;
1557 // arg1 = PR_PrintGlobal(d->a, typ);
1558 typ = pr_opcodes[d->op].type_b;
1559 arg2 = PR_PrintGlobal(d->b, typ);
1560
1561 if (arg2)
1562 {
1563 if (!strcmp(s_name, arg2))
1564 {
1565 if ((d + 1)->op == OP_STOREP_FNC)
1566 {
1567 d++;
1568 typ = pr_opcodes[d->op].type_a;
1569 arg3 = PR_PrintGlobal(d->a, typ);
1570 if (!arg3)
1571 continue;
1572 j = DEC_GetFunctionIdxByName(arg3);
1573 /* check for j == 0 here ???? */
1574 PR_FunctionHeader(pr_functions + j);
1575 if (strcmp("void ()", func_headers[j]))
1576 return func_headers[j];
1577 /* if void (), continue checking just to be certain (ie: th_pain) */
1578
1579 /* NOTE: When decompiling progs.dat of hcbots, this
1580 * results in an infinite recursion below by the function
1581 * calling itself with "think" and "th_stand" as the
1582 * arguments alternating between each succession,
1583 * hence the MAX_DEPTH check at the function's entrance.
1584 * I don't have a better solution so far.. - O.S. */
1585 }
1586
1587 if ((d + 1)->op == OP_LOAD_FNC && (d + 2)->op == OP_STOREP_FNC)
1588 {
1589 d++;
1590 // typ = pr_opcodes[d->op].type_a;
1591 // arg1 = PR_PrintGlobal(d->a, typ);
1592 typ = pr_opcodes[d->op].type_b;
1593 arg2 = PR_PrintGlobal(d->b, typ);
1594 if (!arg2)
1595 continue;
1596 if (strcmp(s_name, arg2))
1597 return GetFieldFunctionHeader(arg2);
1598 }
1599 }
1600 }
1601 }
1602 }
1603
1604 // printf ("returning found statement %5d %s %s\n", i, arg3, func_headers[j]);
1605
1606 if (j == 0)
1607 return "void ()";
1608
1609 return func_headers[j];
1610 }
1611
1612
FindBuiltinParameters(int func)1613 static void FindBuiltinParameters (int func)
1614 {
1615 int i, j;
1616 unsigned short type[9];
1617 dstatement_t *ds, *dsf = NULL;
1618 dfunction_t *df, *dft = NULL;
1619 const char *arg1;
1620 char sname[512], plist[512], parm[128];
1621
1622 if (func_headers[func])
1623 return;
1624
1625 df = pr_functions + func;
1626
1627 // printf("%s %d\n", pr_strings + df->s_name, df->numparms);
1628 printf("looking for builtin %s...: ", pr_strings + df->s_name);
1629
1630 for (i = 1; i < progs->numfunctions; i++)
1631 {
1632 if (! (i & 0xf))
1633 printf("."); /* let'em know its working, not hanging */
1634
1635 j = (pr_functions + i)->first_statement;
1636 if (j < 0)
1637 continue;
1638
1639 ds = pr_statements + j;
1640
1641 while (ds && ds->op)
1642 {
1643 if (ds->op >= OP_CALL0 && ds->op <= OP_CALL8)
1644 {
1645 arg1 = PR_PrintStringAtOfs(ds->a, 0);
1646
1647 if (arg1)
1648 {
1649 if (!strcmp(pr_strings + df->s_name, arg1))
1650 {
1651 dsf = ds;
1652 dft = pr_functions + i;
1653 printf("\nfound!!\ndetermining parameters\n");
1654 break;
1655 }
1656 }
1657 }
1658
1659 arg1 = NULL;
1660 ds++;
1661 // ds = pr_statements + (pr_functions + i)->first_statement + j;
1662 }
1663
1664 if (dsf)
1665 break;
1666 }
1667
1668 if (!dsf)
1669 {
1670 printf("NOT found!!\nsetting parameters to void\n");
1671 func_headers[func] = SafeStrdup("void ()");
1672 return;
1673 }
1674
1675 j = ((dsf->op - OP_CALL0));
1676 type[8] = ev_void;
1677
1678 for (ds = dsf + 1; ds && ds->op; ds++)
1679 {
1680 if ((ds->op >= OP_CALL0 && ds->op <= OP_CALL8) || ds->op >= OP_RAND0)
1681 break;
1682
1683 if (ds->a == OFS_RETURN)
1684 {
1685 // printf("%d %d %d %d 1 rt %d %d\n", ds->op, ds->a, ds->b, ds->c, pr_opcodes[ds->op].type_a->type->type, ev_pointer);
1686 if (ds->c)
1687 {
1688 type[8] = pr_opcodes[ds->op].type_c->type->type;
1689 if (type[8] == ev_pointer)
1690 type[8] = BackBuildReturnType(dft, ds, ds->c);
1691 }
1692 else
1693 {
1694 type[8] = pr_opcodes[ds->op].type_b->type->type;
1695 if (type[8] == ev_pointer)
1696 type[8] = BackBuildReturnType(dft, ds, ds->b);
1697 }
1698 break;
1699 }
1700
1701 if (ds->b == OFS_RETURN)
1702 {
1703 // printf("%d %d %d %d 2 rt %d\n", ds->op, ds->a, ds->b, ds->c, pr_opcodes[ds->op].type_b->type->type);
1704 type[8] = pr_opcodes[ds->op].type_b->type->type;
1705 if (type[8] == ev_pointer)
1706 type[8] = BackBuildReturnType(dft, ds, ds->b);
1707 break;
1708 }
1709
1710 if (ds->c == OFS_RETURN)
1711 {
1712 // printf("%d %d %d %d 3 rt %d\n", ds->op, ds->a, ds->b, ds->c, pr_opcodes[ds->op].type_c->type->type);
1713 type[8] = pr_opcodes[ds->op].type_c->type->type;
1714 if (type[8] == ev_pointer)
1715 type[8] = BackBuildReturnType(dft, ds, ds->c);
1716 break;
1717 }
1718 }
1719
1720 /* find name */
1721 memset (sname, 0, sizeof(sname));
1722 arg1 = PR_PrintStringAtOfs(dsf->a, 0);
1723 sprintf(sname, "%s", arg1);
1724
1725 /* look for first two parms */
1726 if (dsf->b == 1)
1727 type[0] = GetLastFunctionReturn(dft, dsf);
1728 else type[0] = GetType(dsf->b);
1729
1730 if (type[0] == ev_pointer)
1731 type[0] = BackBuildReturnType(dft, dsf, dsf->b);
1732
1733 if (dsf->c == 1)
1734 type[1] = GetLastFunctionReturn(dft, dsf);
1735 else type[1] = GetType(dsf->c);
1736
1737 printf("type b %d %d\n", type[0], (progs->version == PROG_VERSION_V6) ? (signed short)dsf->b : dsf->b);
1738 printf("type c %d %d\n", type[1], (progs->version == PROG_VERSION_V6) ? (signed short)dsf->c : dsf->c);
1739 if (type[1] == ev_pointer)
1740 type[1] = BackBuildReturnType(dft, dsf, dsf->c);
1741
1742 /* look in regs for rest of parms */
1743 i = 2;
1744
1745 while (i < j)
1746 {
1747 if (i > 8) /* just in case.. */
1748 COM_Error ("%s (%d): array out of bounds.", __thisfunc__, __LINE__);
1749 type[i] = ev_void;
1750 for (ds = dsf; ds - pr_statements >= dft->first_statement; ds--)
1751 {
1752 if (ds->a == ((3 * i) + 4))
1753 {
1754 // printf("a ");
1755 type[i] = GetType(ds->a);
1756 if (type[i] == ev_pointer)
1757 type[i] = BackBuildReturnType(dft, ds, ds->a);
1758 break;
1759 }
1760
1761 if (ds->b == ((3 * i) + 4))
1762 {
1763 // printf("b ");
1764 if (pr_opcodes[ds->op].right_associative)
1765 {
1766 type[i] = GetType(ds->a);
1767 if (type[i] == ev_pointer || type[i] == ev_field)
1768 type[i] = BackBuildReturnType(dft, ds, ds->a);
1769 }
1770 else
1771 {
1772 type[i] = GetType(ds->c);
1773 if (type[i] == ev_pointer || type[i] == ev_field)
1774 type[i] = BackBuildReturnType(dft, ds, ds->c);
1775 }
1776 break;
1777 }
1778
1779 if (ds->c == ((3 * i) + 4))
1780 {
1781 // printf("c ");
1782 type[i] = GetType(ds->a);
1783 if (type[i] == ev_pointer)
1784 type[i] = BackBuildReturnType(dft, ds, ds->c);
1785 break;
1786 }
1787 }
1788
1789 // printf("type %i: op: %d a:%d b: %d c: %d rt: %d\n", i, ds->op, ds->a, ds->b, ds->c, type[i]);
1790 i++;
1791 }
1792
1793 /* print results to string */
1794 memset (plist, 0, sizeof(plist));
1795 if (type[8] & DEF_SAVEGLOBAL)
1796 {
1797 sprintf(plist,".");
1798 type[8] &= ~DEF_SAVEGLOBAL;
1799 }
1800
1801 switch (type[8])
1802 {
1803 case ev_string:
1804 strcat(plist, "string ");
1805 break;
1806 case ev_void:
1807 strcat(plist, "void ");
1808 break;
1809 case ev_float:
1810 strcat(plist, "float ");
1811 break;
1812 case ev_vector:
1813 strcat(plist, "vector ");
1814 break;
1815 case ev_entity:
1816 strcat(plist, "entity ");
1817 break;
1818 case ev_field:
1819 strcat(plist, "ev_field ");
1820 break;
1821 case ev_function:
1822 strcat(plist, "void() ");
1823 break;
1824 case ev_pointer:
1825 strcat(plist, "ev_pointer ");
1826 break;
1827 default:
1828 strcat(plist, "unknown ");
1829 break;
1830 }
1831
1832 strcat(plist, "(");
1833 if (df->numparms < 0)
1834 {
1835 strcat(plist, "...");
1836 }
1837 else
1838 {
1839 for (i = 0; i < j; i++)
1840 {
1841 if (type[i] & DEF_SAVEGLOBAL)
1842 {
1843 strcat(plist, ".");
1844 type[i] &= ~DEF_SAVEGLOBAL;
1845 }
1846
1847 switch (type[i])
1848 {
1849 case ev_string:
1850 strcat(plist, "string ");
1851 break;
1852 case ev_void:
1853 strcat(plist, "void ");
1854 break;
1855 case ev_float:
1856 strcat(plist, "float ");
1857 break;
1858 case ev_vector:
1859 strcat(plist, "vector ");
1860 break;
1861 case ev_entity:
1862 strcat(plist, "entity ");
1863 break;
1864 case ev_field:
1865 strcat(plist, "ev_field ");
1866 break;
1867 case ev_function:
1868 strcat(plist, "void() ");
1869 break;
1870 case ev_pointer:
1871 strcat(plist, "ev_pointer ");
1872 break;
1873 default:
1874 sprintf(parm, "unknown%d",type[i]);
1875 strcat(plist, parm);
1876 break;
1877 }
1878
1879 sprintf(parm, "%c", 'a'+i);
1880 strcat(plist, parm);
1881
1882 if (i < j - 1)
1883 strcat(plist, ", ");
1884 }
1885 }
1886
1887 strcat(plist, ")");
1888 func_headers[func] = SafeStrdup(plist);
1889 printf("%s%s\nin %s in file %s\n", plist, sname, pr_strings + dft->s_name, pr_strings + dft->s_file);
1890 }
1891
1892
BackBuildReturnType(dfunction_t * df,dstatement_t * dsf,gofs_t ofs)1893 static unsigned short BackBuildReturnType (dfunction_t *df,dstatement_t *dsf, gofs_t ofs)
1894 {
1895 dstatement_t *ds;
1896 unsigned short rtype = ev_void;
1897 ddef_t *par;
1898
1899 // printf("backbuilding...\n");
1900
1901 for (ds = dsf - 1; ds - pr_statements >= df->first_statement; ds--)
1902 {
1903 if (ds->a == ofs)
1904 {
1905 rtype = pr_opcodes[ds->op].type_a->type->type;
1906 par = DEC_GetParameter (ds->b);
1907 if (par)
1908 {
1909 // printf("ds->b type: %d\n", par->type);
1910 rtype = par->type;
1911 }
1912 break;
1913 }
1914
1915 if (ds->b == ofs)
1916 {
1917 rtype = pr_opcodes[ds->op].type_b->type->type;
1918 par = DEC_GetParameter (ds->a);
1919 if (par)
1920 {
1921 // printf("ds->a type: %d\n", par->type);
1922 rtype = par->type;
1923 }
1924 break;
1925 }
1926
1927 if (ds->c == ofs)
1928 {
1929 rtype = pr_opcodes[ds->op].type_c->type->type;
1930 // rtype = GetType(ds->b);
1931 break;
1932 }
1933 }
1934
1935 return rtype;
1936 }
1937
1938
GetType(gofs_t ofs)1939 static unsigned short GetType (gofs_t ofs)
1940 {
1941 ddef_t *par;
1942 unsigned short rtype;
1943 ddef_t *ef;
1944
1945 rtype = ev_pointer;
1946 par = DEC_GetParameter (ofs);
1947
1948 if (par)
1949 {
1950 par->type &= ~DEF_SAVEGLOBAL;
1951
1952 if (par->type == ev_field)
1953 {
1954 ef = PR_GetField(pr_strings + par->s_name, par);
1955 if (!ef)
1956 COM_Error("Could not locate a field named \"%s\"", pr_strings + par->s_name);
1957 rtype = (ef->type | DEF_SAVEGLOBAL);
1958 }
1959 else
1960 {
1961 rtype = par->type;
1962 }
1963 }
1964
1965 return rtype;
1966 }
1967
1968
DccFunctionOP(unsigned short op)1969 static void DccFunctionOP (unsigned short op)
1970 {
1971 int i, j = 0;
1972 dfunction_t *df;
1973 dstatement_t *ds;
1974
1975 for (i = 1; i < progs->numfunctions; i++)
1976 {
1977 df = pr_functions + i;
1978
1979 if (df->first_statement < 0)
1980 continue;
1981
1982 for (ds = &pr_statements[df->first_statement]; ds && ds->op; ds++)
1983 {
1984 if (ds->op == op && j++)
1985 {
1986 PR_PrintFunction(pr_strings + df->s_name);
1987 return;
1988 }
1989 }
1990 }
1991 }
1992
1993
1994 /*
1995 ===============
1996 DEC_ConvertV6Defs, DEC_ConvertV6Stmts -- Pa3PyX
1997
1998 Convert ddef_v6_t and dstatement_v6_t arrays into _v7 format
1999 with byte swapping.
2000 ===============
2001 */
DEC_ConvertV6Defs(ddef_v6_t * v6defs,int numdefs)2002 static ddef_v7_t *DEC_ConvertV6Defs (ddef_v6_t *v6defs, int numdefs)
2003 {
2004 int i;
2005 ddef_v7_t *v7defs, *v7ptr;
2006 ddef_v6_t *v6ptr;
2007
2008 v7defs = (ddef_v7_t *) SafeMalloc(sizeof(ddef_v7_t) * numdefs);
2009 for (i = 0, v6ptr = v6defs, v7ptr = v7defs; i < numdefs; i++, v6ptr++, v7ptr++)
2010 {
2011 v7ptr->type = LittleShort(v6ptr->type);
2012 v7ptr->ofs = (unsigned short)LittleShort(v6ptr->ofs);
2013 v7ptr->s_name = LittleLong(v6ptr->s_name);
2014 }
2015
2016 return v7defs;
2017 }
2018
DEC_ConvertV6Stmts(dstatement_v6_t * v6stmts,int numstmts)2019 static dstatement_v7_t *DEC_ConvertV6Stmts (dstatement_v6_t *v6stmts, int numstmts)
2020 {
2021 int i;
2022 dstatement_v7_t *v7stmts, *v7ptr;
2023 dstatement_v6_t *v6ptr;
2024
2025 v7stmts = (dstatement_v7_t *) SafeMalloc(sizeof(dstatement_v7_t) * numstmts);
2026 for (i = 0, v6ptr = v6stmts, v7ptr = v7stmts; i < numstmts; i++, v6ptr++, v7ptr++)
2027 {
2028 v7ptr->op = LittleShort(v6ptr->op);
2029 v7ptr->a = (unsigned short)LittleShort(v6ptr->a);
2030 v7ptr->b = (unsigned short)LittleShort(v6ptr->b);
2031 v7ptr->c = (unsigned short)LittleShort(v6ptr->c);
2032 }
2033
2034 return v7stmts;
2035 }
2036
DEC_ReadData(const char * srcfile)2037 static void DEC_ReadData (const char *srcfile)
2038 {
2039 void *p;
2040 int i;
2041
2042 progs_length = LoadFile (srcfile, &p);
2043 progs = (dprograms_t *) p;
2044
2045 /* byte swap the header */
2046 for (i = 0; i < (int) sizeof(*progs) / 4; i++)
2047 ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] );
2048
2049 printf ("read data from %s:\n", srcfile);
2050 printf ("%10i bytes, version %i, crc: %i\n", progs_length, progs->version, progs->crc);
2051 printf ("%10i strofs\n", progs->numstrings);
2052 printf ("%10i numstatements\n", progs->numstatements);
2053 printf ("%10i numfunctions\n", progs->numfunctions);
2054 printf ("%10i numglobaldefs\n", progs->numglobaldefs);
2055 printf ("%10i numfielddefs\n", progs->numfielddefs);
2056 printf ("%10i numpr_globals\n", progs->numglobals);
2057 printf ("----------------------------------------\n");
2058
2059 if (pr_infoonly != 0)
2060 return;
2061
2062 switch (progs->version)
2063 {
2064 case PROG_VERSION_V6:
2065 case PROG_VERSION_V7:
2066 break;
2067 default:
2068 COM_Error("%s is of unsupported version (%d, should be %d or %d)",
2069 srcfile, progs->version, PROG_VERSION_V6, PROG_VERSION_V7);
2070 break;
2071 }
2072
2073 pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions);
2074 pr_globals = (float *)((byte *)progs + progs->ofs_globals);
2075 pr_strings = (char *)progs + progs->ofs_strings;
2076
2077 if (progs->version == PROG_VERSION_V6)
2078 {
2079 pr_globaldefs = DEC_ConvertV6Defs ((ddef_v6_t *)((byte *)progs + progs->ofs_globaldefs), progs->numglobaldefs);
2080 pr_fielddefs = DEC_ConvertV6Defs ((ddef_v6_t *)((byte *)progs + progs->ofs_fielddefs), progs->numfielddefs);
2081 pr_statements = DEC_ConvertV6Stmts((dstatement_v6_t *)((byte *)progs + progs->ofs_statements), progs->numstatements);
2082 }
2083 else
2084 {
2085 pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs);
2086 pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs);
2087 pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements);
2088 }
2089
2090 /* byte swap the lumps */
2091 for (i = 0; i < progs->numfunctions; i++)
2092 {
2093 pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement);
2094 pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start);
2095 pr_functions[i].s_name = LittleLong (pr_functions[i].s_name);
2096 pr_functions[i].s_file = LittleLong (pr_functions[i].s_file);
2097 pr_functions[i].numparms = LittleLong (pr_functions[i].numparms);
2098 pr_functions[i].locals = LittleLong (pr_functions[i].locals);
2099 }
2100
2101 if (progs->version == PROG_VERSION_V7)
2102 {
2103 for (i = 0; i < progs->numstatements; i++)
2104 {
2105 pr_statements[i].op = LittleShort(pr_statements[i].op);
2106 pr_statements[i].a = LittleLong(pr_statements[i].a);
2107 pr_statements[i].b = LittleLong(pr_statements[i].b);
2108 pr_statements[i].c = LittleLong(pr_statements[i].c);
2109 }
2110
2111 for (i = 0; i < progs->numglobaldefs; i++)
2112 {
2113 pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type);
2114 pr_globaldefs[i].ofs = LittleLong (pr_globaldefs[i].ofs);
2115 pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name);
2116 }
2117
2118 for (i = 0; i < progs->numfielddefs; i++)
2119 {
2120 pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type);
2121 pr_fielddefs[i].ofs = LittleLong (pr_fielddefs[i].ofs);
2122 pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name);
2123 }
2124 }
2125
2126 for (i = 0; i < progs->numglobals; i++)
2127 ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]);
2128 }
2129
2130
Init_Dcc(void)2131 static void Init_Dcc (void)
2132 {
2133 int i;
2134
2135 def_ret.ofs = OFS_RETURN;
2136 for (i = 0; i < MAX_PARMS; i++)
2137 def_parms[i].ofs = OFS_PARM0 + 3*i;
2138
2139 if (CheckParm("-fix")) /* fix mangled names */
2140 FILE_NUM_FOR_NAME = true;
2141 else FILE_NUM_FOR_NAME = false;
2142
2143 if (CheckParm("-dump"))
2144 pr_dumpasm = true;
2145 else pr_dumpasm = false;
2146
2147 PR_FILE = stdout;
2148 cfunc = NULL;
2149 printassign = false;
2150
2151 DEC_FileCtr = 0;
2152
2153 func_headers = (char **) SafeMalloc (progs->numfunctions * sizeof(char *));
2154 temp_val = (char **) SafeMalloc (progs->numglobals * sizeof(char *));
2155 DEC_FilesSeen = (char **) SafeMalloc (MAX_DEC_FILES * sizeof(char *));
2156 flowinfo = (struct flowinfo_t *) SafeMalloc (progs->numstatements * sizeof(struct flowinfo_t));
2157 }
2158
2159
DEC_GetFunctionIdxByName(const char * name)2160 static int DEC_GetFunctionIdxByName (const char *name)
2161 {
2162 int i;
2163
2164 for (i = 1; i < progs->numfunctions; i++)
2165 {
2166 if (!strcmp (name, pr_strings + pr_functions[i].s_name))
2167 return i;
2168 }
2169
2170 return 0;
2171 }
2172
2173
DEC_GetParameter(gofs_t ofs)2174 static ddef_t *DEC_GetParameter (gofs_t ofs)
2175 {
2176 int i;
2177 ddef_t *def;
2178
2179 def = NULL;
2180
2181 for (i = 0; i < progs->numglobaldefs; i++)
2182 {
2183 def = &pr_globaldefs[i];
2184 if (def->ofs == ofs)
2185 return def;
2186 }
2187
2188 return NULL;
2189 }
2190
2191
DEC_AlreadySeen(const char * fname)2192 static int DEC_AlreadySeen (const char *fname)
2193 {
2194 int i;
2195 char *new1;
2196
2197 for (i = 0; i < DEC_FileCtr; i++)
2198 {
2199 if (!strcmp(fname, DEC_FilesSeen[i]))
2200 return 1;
2201 }
2202
2203 if (DEC_FileCtr >= MAX_DEC_FILES - 1)
2204 COM_Error("%s: too many source files.", __thisfunc__);
2205
2206 new1 = SafeStrdup(fname);
2207 DEC_FilesSeen[DEC_FileCtr++] = new1;
2208
2209 return 0;
2210 }
2211
2212
2213 #if 0 /* not used */
2214 static void FixFunctionNames (void)
2215 {
2216 int i, j;
2217 dfunction_t *d;
2218 char s[128], *c;
2219
2220 for (i = 1; i < progs->numfunctions; i++)
2221 {
2222 d = &pr_functions[i];
2223 // printf ("%s : %s : %i %i (", pr_strings + d->s_file, pr_strings + d->s_name, d->first_statement, d->parm_start);
2224 s[0] = '\0';
2225 j = strlen(pr_strings + d->s_file) + 1;
2226 sprintf (s, "%d.hc", d->s_file);
2227 c = pr_strings;
2228 c += d->s_file;
2229 sprintf (c, "%s", s);
2230 }
2231 }
2232 #endif /* end of unused */
2233
2234
PR_String(const char * string)2235 static const char *PR_String (const char *string)
2236 {
2237 static char buf[80];
2238 char *s;
2239
2240 s = buf;
2241 *s++ = '"';
2242 while (string && *string)
2243 {
2244 if (s == buf + sizeof(buf) - 2)
2245 break;
2246 if (*string == '\n')
2247 {
2248 *s++ = '\\';
2249 *s++ = 'n';
2250 }
2251 else if (*string == '"')
2252 {
2253 *s++ = '\\';
2254 *s++ = '"';
2255 }
2256 else
2257 *s++ = *string;
2258 string++;
2259 if (s - buf > 60)
2260 {
2261 *s++ = '.';
2262 *s++ = '.';
2263 *s++ = '.';
2264 break;
2265 }
2266 }
2267 *s++ = '"';
2268 *s++ = 0;
2269 return buf;
2270 }
2271
PR_DefForFieldOfs(gofs_t ofs)2272 static def_t *PR_DefForFieldOfs (gofs_t ofs)
2273 {
2274 def_t *d;
2275
2276 for (d = pr.def_head.next; d; d = d->next)
2277 {
2278 if (d->type->type != ev_field)
2279 continue;
2280 if (((int *)pr_globals)[d->ofs] == ofs)
2281 return d;
2282 }
2283 COM_Error ("%s: couldn't find %i", __thisfunc__, ofs);
2284 return NULL;
2285 }
2286
PR_ValueString(etype_t type,void * val)2287 static const char *PR_ValueString (etype_t type, void *val)
2288 {
2289 static char line[256];
2290 def_t *def;
2291 dfunction_t *f;
2292
2293 switch (type)
2294 {
2295 case ev_string:
2296 sprintf (line, "%s", PR_String(pr_strings + *(int *)val));
2297 break;
2298 case ev_entity:
2299 sprintf (line, "entity %i", *(int *)val);
2300 break;
2301 case ev_function:
2302 f = pr_functions + *(int *)val;
2303 if (!f)
2304 sprintf (line, "undefined function");
2305 else
2306 sprintf (line, "%s()", pr_strings + f->s_name);
2307 break;
2308 case ev_field:
2309 def = PR_DefForFieldOfs ( *(int *)val );
2310 sprintf (line, ".%s", def->name);
2311 break;
2312 case ev_void:
2313 sprintf (line, "void");
2314 break;
2315 case ev_float:
2316 sprintf (line, "%5.1f", *(float *)val);
2317 break;
2318 case ev_vector:
2319 sprintf (line, "'%5.1f %5.1f %5.1f'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
2320 break;
2321 case ev_pointer:
2322 sprintf (line, "pointer");
2323 break;
2324 default:
2325 sprintf (line, "bad type %i", type);
2326 break;
2327 }
2328
2329 return line;
2330 }
2331
DCC_ValueString(etype_t type,void * val)2332 static const char *DCC_ValueString (etype_t type, void *val)
2333 {
2334 static char vsline[256];
2335 def_t *def;
2336 dfunction_t *f;
2337
2338 switch (type)
2339 {
2340 case ev_string:
2341 sprintf (vsline, "%s", PR_String(pr_strings + *(int *)val));
2342 break;
2343 case ev_entity:
2344 sprintf (vsline, "entity %i", *(int *)val);
2345 break;
2346 case ev_function:
2347 f = pr_functions + *(int *)val;
2348 if (!f)
2349 sprintf (vsline, "undefined function");
2350 else sprintf (vsline, "%s()", pr_strings + f->s_name);
2351 break;
2352 case ev_field:
2353 def = PR_DefForFieldOfs (*(int *)val);
2354 sprintf (vsline, ".%s", def->name);
2355 break;
2356 case ev_void:
2357 sprintf (vsline, "void");
2358 break;
2359 case ev_float:
2360 sprintf (vsline, "%.5f", *(float *)val);
2361 break;
2362 case ev_vector:
2363 sprintf (vsline, "'%.5f %.5f %.5f'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
2364 break;
2365 case ev_pointer:
2366 sprintf (vsline, "pointer");
2367 break;
2368 default:
2369 sprintf (vsline, "bad type %i", type);
2370 break;
2371 }
2372
2373 return vsline;
2374 }
2375
2376
PR_PrintFunction(const char * name)2377 static void PR_PrintFunction (const char *name)
2378 {
2379 int i;
2380 dstatement_t *ds;
2381 dfunction_t *df;
2382 const char *arg1, *arg2;
2383 def_t *typ1, *typ2;
2384
2385 for (i = 0; i < progs->numfunctions; i++)
2386 {
2387 if (!strcmp (name, pr_strings + pr_functions[i].s_name))
2388 break;
2389 }
2390
2391 if (i == progs->numfunctions)
2392 COM_Error ("No function names \"%s\"", name);
2393
2394 df = pr_functions + i;
2395 cfunc = df;
2396 printf("Statements for %s:\n", name);
2397 ds = pr_statements + df->first_statement;
2398 Clear_Immediates();
2399 PR_LocalGlobals();
2400 PR_FunctionHeader(df);
2401
2402 if (df->first_statement < 0)
2403 {
2404 PR_Print("\n%s%s = #%d;\n", func_headers[df - pr_functions], pr_strings + df->s_name, -df->first_statement);
2405 return;
2406 }
2407
2408 PR_Print("\n%s%s = ", func_headers[df - pr_functions], pr_strings + df->s_name);
2409
2410 if (ds->op == OP_STATE)
2411 {
2412 typ1 = pr_opcodes[ds->op].type_a;
2413 typ2 = pr_opcodes[ds->op].type_b;
2414 arg1 = PR_ValueString(typ1->type->type, &pr_globals[ds->a]);
2415 arg2 = PR_PrintStringAtOfs(ds->b, typ2);
2416 PR_Print(" [%s, %s]", arg1, arg2);
2417 }
2418
2419 PR_Print(" {\n");
2420 AddProgramFlowInfo(df);
2421 PR_Locals(df);
2422 lindent = 1;
2423
2424 while (1)
2425 {
2426 DccStatement(ds);
2427 if (!ds->op)
2428 break;
2429 ds++;
2430 }
2431 }
2432
2433
GetLastFunctionReturn(dfunction_t * df,dstatement_t * ds)2434 static unsigned short GetLastFunctionReturn (dfunction_t *df, dstatement_t *ds)
2435 {
2436 dstatement_t *di;
2437 int i;
2438 const char *arg1;
2439 def_t *type1;
2440
2441 printf("looking for last return type\n");
2442
2443 di = ds - 1;
2444
2445 while ((di - pr_statements) >= df->first_statement)
2446 { /* that stupid equal, what a bitch */
2447 printf(" op %d a: %d b: %d c: %d\n", di->op, di->a, di->b, di->c);
2448
2449 if (OP_CALL0 <= di->op && di->op <= OP_CALL8)
2450 {
2451 type1 = pr_opcodes[di->op].type_a;
2452 arg1 = PR_PrintStringAtOfs(di->a, type1);
2453 if (!arg1)
2454 COM_Error("function name not found!!!\n");
2455
2456 i = DEC_GetFunctionIdxByName(arg1);
2457 if (i == 0)
2458 break;
2459
2460 if (i != (df - pr_functions))
2461 {
2462 i = GetReturnType(i);
2463 printf("%s %d is found\n", arg1, i);
2464 return i;
2465 }
2466 else
2467 {
2468 break;
2469 }
2470 } /* end if call */
2471 else if (OP_RAND0 <= di->op && di->op <= OP_RAND2)
2472 {
2473 return ev_float;
2474 }
2475 else if (OP_RANDV0 <= di->op && di->op <= OP_RANDV2)
2476 {
2477 return ev_vector;
2478 }
2479
2480 di--;
2481 } /* end while ofs_return */
2482
2483 return ev_void;
2484 }
2485
PrintGlobaldefs(void)2486 static void PrintGlobaldefs (void)
2487 {
2488 int i;
2489 ddef_t *d;
2490
2491 for (i = 0; i < progs->numglobaldefs; i++)
2492 {
2493 d = &pr_globaldefs[i];
2494 printf ("%5i : (%i) %s\n", d->ofs, d->type, pr_strings + d->s_name);
2495 }
2496 }
2497
PrintPRGlobals(void)2498 static void PrintPRGlobals (void)
2499 {
2500 int i;
2501
2502 for (i = 0; i < progs->numglobals; i++)
2503 {
2504 printf ("%5i %5.5f %5d\n", i, pr_globals[i], ((int *)pr_globals)[i]);
2505 }
2506 }
2507
PrintStatements(void)2508 static void PrintStatements (void)
2509 {
2510 int i;
2511 dstatement_t *ds;
2512
2513 for (i = 0; i < progs->numstatements; i++)
2514 {
2515 ds = pr_statements + i;
2516 printf ("%5d op: %2d a: %5d b: %5d c: %5d\n", i, ds->op, ds->a, ds->b, ds->c);
2517 }
2518 }
2519
PrintStrings(void)2520 static void PrintStrings (void)
2521 {
2522 int i, l;
2523 const char *s;
2524
2525 for (i = 0; i < progs->numstrings; i += l)
2526 {
2527 s = pr_strings + i;
2528 l = strlen(s) + 1;
2529 printf ("%5i : ", i);
2530 for ( ; *s; ++s)
2531 {
2532 if (*s == '\n')
2533 {
2534 putchar ('\\');
2535 putchar ('n');
2536 }
2537 else
2538 putchar (*s);
2539 }
2540 printf ("\n");
2541 }
2542 }
2543
PrintFunctions(void)2544 static void PrintFunctions (void)
2545 {
2546 int i, j;
2547 dfunction_t *d;
2548
2549 for (i = 0; i < progs->numfunctions; i++)
2550 {
2551 d = &pr_functions[i];
2552 printf ("%s : %s : %i %i (", pr_strings + d->s_file, pr_strings + d->s_name, d->first_statement, d->parm_start);
2553 for (j = 0; j < d->numparms; j++)
2554 printf ("%i ", d->parm_size[j]);
2555 printf (")\n");
2556 }
2557 }
2558
PrintFields(void)2559 static void PrintFields (void)
2560 {
2561 int i;
2562 ddef_t *d;
2563
2564 for (i = 0; i < progs->numfielddefs; i++)
2565 {
2566 d = &pr_fielddefs[i];
2567 printf ("%5i %5i : (%i) %s\n", i, d->ofs, d->type, pr_strings + d->s_name);
2568 }
2569 }
2570
Dcc_main(int argc,char ** argv)2571 int Dcc_main (int argc, char **argv)
2572 {
2573 int p;
2574 double start, stop;
2575
2576 start = COM_GetTime ();
2577
2578 pr_infoonly = CheckParm("-info");
2579
2580 p = CheckParm("-name");
2581 if (p == 0)
2582 DEC_ReadData ("progs.dat");
2583 else
2584 {
2585 if (p >= argc - 1)
2586 COM_Error ("No input filename specified with -name");
2587 DEC_ReadData (argv[p + 1]);
2588 }
2589
2590 if (pr_infoonly != 0)
2591 return 0;
2592
2593 /* don't need Init_Dcc () for the following info stuff */
2594 if (CheckParm("-fields") != 0)
2595 {
2596 printf("\nFIELDS =========================\n");
2597 PrintFields ();
2598 return 0;
2599 }
2600 if (CheckParm("-functions") != 0)
2601 {
2602 printf("\nFUNCTIONS ======================\n");
2603 PrintFunctions ();
2604 return 0;
2605 }
2606 if (CheckParm("-globaldefs") != 0)
2607 {
2608 printf("\nGLOBALDEFS =====================\n");
2609 PrintGlobaldefs();
2610 return 0;
2611 }
2612 if (CheckParm("-prglobals") != 0)
2613 {
2614 printf("\nPR_GLOBALS =====================\n");
2615 PrintPRGlobals ();
2616 return 0;
2617 }
2618 if (CheckParm("-statements") != 0)
2619 {
2620 printf("\nSTATEMENTS =====================\n");
2621 PrintStatements();
2622 return 0;
2623 }
2624 if (CheckParm("-strings") != 0)
2625 {
2626 printf("\nSTRINGS ========================\n");
2627 PrintStrings ();
2628 return 0;
2629 }
2630
2631 Init_Dcc ();
2632
2633 p = CheckParm("-bbb");
2634 if (p != 0)
2635 {
2636 /*
2637 i= -999;
2638 for (p = 0; p < progs->numstatements; ++p)
2639 {
2640 if ((pr_statements + p)->op > i)
2641 i = (pr_statements + p)->op;
2642 }
2643 printf("largest op %d\n", i);
2644 */
2645 FindBuiltinParameters(1);
2646 return 0;
2647 }
2648
2649 p = CheckParm("-ddd");
2650 if (p != 0)
2651 {
2652 for (++p; p < argc; ++p)
2653 {
2654 if (argv[p][0] == '-')
2655 break;
2656 DccFunctionOP (atoi(argv[p]));
2657 }
2658 return 0;
2659 }
2660
2661 p = CheckParm("-asm");
2662 if (p != 0)
2663 {
2664 for (++p; p < argc; ++p)
2665 {
2666 if (argv[p][0] == '-')
2667 break;
2668 PR_PrintFunction(argv[p]);
2669 }
2670 }
2671 else
2672 {
2673 Dcc_Functions ();
2674 stop = COM_GetTime ();
2675 printf("\n%d seconds elapsed.\n", (int)(stop - start));
2676 }
2677
2678 return 0;
2679 }
2680
2681