1 
2 #include "qcc.h"
3 #include "decomp.h"
4 
5 #include <stdio.h>
6 
7 extern opcode_t pr_opcodes [];
8 
9 
10 FILE *Decompileofile;
11 FILE *Decompileprogssrc;
12 FILE *Decompileprofile;
13 char *DecompileFilesSeen[1024];
14 int DecompileFileCtr = 0;
15 char *DecompileProfiles[MAX_FUNCTIONS];
16 
17 char *type_names[8] =
18 {
19     "void",
20     "string",
21     "float",
22     "vector",
23     "entity",
24     "ev_field",
25     "void()",
26     "ev_pointer"
27 };
28 
temp_type(unsigned short temp,dstatement_t * start,dfunction_t * df)29 char *temp_type (unsigned short temp, dstatement_t *start, dfunction_t *df)
30 {
31 	int i;
32 	dstatement_t *stat;
33 	stat = start - 1;
34 	// determine the type of a temp
35 
36     while(stat > statements)
37 	{
38 		if (temp == stat->a)
39 			return type_names[pr_opcodes[stat->op].type_a->type->type];
40 		else if (temp == stat->b)
41 			return type_names[pr_opcodes[stat->op].type_b->type->type];
42 		else if (temp == stat->c)
43 			return type_names[pr_opcodes[stat->op].type_c->type->type];
44 		stat--;
45     }
46 
47 	// method 2
48 	// find a call to this function
49 	for (i = 0; i < numstatements; i++)
50 	{
51 		stat = &statements[i];
52 
53 		if (stat->op >= OP2_CALL0 && stat->op <= OP2_CALL8 && ((eval_t *)&pr_globals[stat->a])->function == df - functions)
54 		{
55 			for(i++; i < numstatements; i++)
56 			{
57 				stat = &statements[i];
58 				if (OFS_RETURN == stat->a && pr_opcodes[stat->op].type_a->type->type != ev_void)
59 					return type_names[pr_opcodes[stat->op].type_a->type->type];
60 				else if (OFS_RETURN == stat->b && pr_opcodes[stat->op].type_b->type->type != ev_void)
61 					return type_names[pr_opcodes[stat->op].type_b->type->type];
62 				else if (stat->op == OP2_DONE)
63 					break;
64 				else if (stat->op >= OP2_CALL0 && stat->op <= OP2_CALL8 && stat->a != df - functions)
65 					break;
66 			}
67 		}
68 	}
69 
70 	printf("Warning: Could not determine return type for %s\n", df->s_name + strings);
71 
72     return "float";
73 
74 }
75 
IsConstant(ddef_t * def)76 boolean IsConstant(ddef_t *def)
77 {
78 
79     int i;
80 	dstatement_t *d;
81 
82 	if (def->type & DEF_SAVEGLOBGAL)
83 		return false;
84 
85     for (i = 1; i < numstatements; i++)
86 	{
87 		d = &statements[i];
88 		if (d->b == def->ofs)
89 		{
90 			if (pr_opcodes[d->op].right_associative)
91 			{
92 				if (d->op - OP2_STORE_F < 6)
93 				{
94 					return false;
95 				}
96 			}
97 		}
98     }
99 	return true;
100 }
101 
type_name(ddef_t * def)102 char *type_name (ddef_t *def)
103 {
104 	ddef_t *j;
105 
106 	static char fname [1024];
107 
108 	switch(def->type)
109 	{
110 	case ev_field:
111 	case ev_pointer:
112 		j = GetField(def->s_name + strings);
113 		if (j)
114 			return va(".%s",type_names[j->type]);
115 		else
116 			return type_names[def->type];
117 	case ev_void:
118 	case ev_string:
119 	case ev_entity:
120 	case ev_vector:
121 	case ev_float:
122 		return type_names[def->type];
123 	case ev_function:
124 		return "void()";
125 	default:
126 		return "float";
127 	}
128 };
129 extern float pr_globals[MAX_REGS];
130 extern int numpr_globals;
131 
132 extern char strings[MAX_STRINGS];
133 extern int strofs;
134 
135 extern dstatement_t statements[MAX_STATEMENTS];
136 extern int numstatements;
137 extern int statement_linenums[MAX_STATEMENTS];
138 
139 extern dfunction_t functions[MAX_FUNCTIONS];
140 extern int numfunctions;
141 
142 extern ddef_t globals[MAX_GLOBALS];
143 extern int numglobaldefs;
144 
145 extern ddef_t fields[MAX_FIELDS];
146 extern int numfielddefs;
147 
148 int maindecstatus = 6;
149 
150 #define FILELISTSIZE 62
151 
152 
153 
154 /*
155 ===============
156 PR_String
157 
158 Returns a string suitable for printing (no newlines, max 60 chars length)
159 ===============
160 */
PR_String(char * string)161 char *PR_String (char *string)
162 {
163 	static char buf[80];
164 	char	*s;
165 
166 	s = buf;
167 	*s++ = '"';
168 	while (string && *string)
169 	{
170 		if (s == buf + sizeof(buf) - 2)
171 			break;
172 		if (*string == '\n')
173 		{
174 			*s++ = '\\';
175 			*s++ = 'n';
176 		}
177 		else if (*string == '"')
178 		{
179 			*s++ = '\\';
180 			*s++ = '"';
181 		}
182 		else
183 			*s++ = *string;
184 		string++;
185 		if (s - buf > 60)
186 		{
187 			*s++ = '.';
188 			*s++ = '.';
189 			*s++ = '.';
190 			break;
191 		}
192 	}
193 	*s++ = '"';
194 	*s++ = 0;
195 	return buf;
196 }
197 /*
198 ============
199 PR_ValueString
200 
201 Returns a string describing *data in a type specific manner
202 =============
203 */
204 
205 
PR_ValueString(etype_t type,void * val)206 char *PR_ValueString (etype_t type, void *val)
207 {
208 	static char	line[256];
209 
210 	dfunction_t	*f;
211 
212 	switch (type)
213 	{
214 	case ev_string:
215 		sprintf (line, "%s", PR_String(strings + *(int *)val));
216 		break;
217 	case ev_entity:
218 		sprintf (line, "entity %i", *(int *)val);
219 		break;
220 	case ev_function:
221 		f = functions + *(int *)val;
222 		if (!f)
223 			sprintf (line, "undefined function");
224 		else
225 			sprintf (line, "%s()", strings + f->s_name);
226 		break;
227 	/*
228 	case ev_field:
229 		def = PR_DefForFieldOfs ( *(int *)val );
230 		sprintf (line, ".%s", def->name);
231 		break;
232 	*/
233 	case ev_void:
234 		sprintf (line, "void");
235 		break;
236 	case ev_float:
237 		{
238 			unsigned int high = *(unsigned int*)val & 0xff000000;
239 			if (high == 0xff000000 || !high)
240 				sprintf (line, "%%%d", *(int*)val);
241 			else
242 				sprintf (line, "%5.1f", *(float *)val);
243 		}
244 		break;
245 	case ev_vector:
246 		sprintf (line, "'%5.1f %5.1f %5.1f'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
247 		break;
248 	case ev_pointer:
249 		sprintf (line, "pointer");
250 		break;
251 	default:
252 		sprintf (line, "bad type %i", type);
253 		break;
254 	}
255 
256 	return line;
257 }
258 
259 
260 static char *filenames[] =
261 {
262 	"makevectors",		"defs.qc",
263 	"button_wait",		"buttons.qc",
264 	"anglemod",		"ai.qc",
265 	"boss_face",		"boss.qc",
266 	"info_intermission",	"client.qc",
267 	"CanDamage",	"combat.qc",
268 	"demon1_stand1",	"demon.qc",
269 	"dog_bite",		"dog.qc",
270 	"door_blocked",		"doors.qc",
271 	"Laser_Touch",		"enforcer.qc",
272 	"knight_attack",			"fight.qc",
273 	"f_stand1",	"fish.qc",
274 	"hknight_shot",	"hknight.qc",
275 	"SUB_regen",		"items.qc",
276 	"knight_stand1",	"knight.qc",
277 	"info_null",		"misc.qc",
278 	"monster_use",		"monsters.qc",
279 	"OgreGrenadeExplode",	"ogre.qc",
280 	"old_idle1",			"oldone.qc",
281 	"plat_spawn_inside_trigger", "plats.qc",
282 	"player_stand1",		"player.qc",
283 	"shal_stand",	"shalrath.qc",
284 	"sham_stand1",		"shambler.qc",
285 	"army_stand1",		"soldier.qc",
286 	"SUB_Null",			"subs.qc",
287 	"tbaby_stand1",		"tarbaby.qc",
288 	"trigger_reactivate",	"triggers.qc",
289 	"W_Precache",			"weapons.qc",
290 	"LaunchMissile",	"wizard.qc",
291 	"main",		"world.qc",
292 	"zombie_stand1",	"zombie.qc"
293 };
294 
295 static char *builtins[] =
296 {
297 
298     NULL,
299     "void (vector ang)",
300     "void (entity e, vector o)",
301     "void (entity e, string m)",
302     "void (entity e, vector min, vector max)",
303     NULL,
304     "void ()",
305     "float ()",
306     "void (entity e, float chan, string samp, float vol, float atten)",
307     "vector (vector v)",
308     "void (string e)",
309     "void (string e)",
310     "float (vector v)",
311     "float (vector v)",
312     "entity ()",
313     "void (entity e)",
314     "void (vector v1, vector v2, float nomonsters, entity forent)",
315     "entity ()",
316     "entity (entity start, .string fld, string match)",
317     "string (string s)",
318     "string (string s)",
319     "void (entity client, string s)",
320     "entity (vector org, float rad)",
321     "void (string s)",
322     "void (entity client, string s)",
323     "void (string s)",
324     "string (float f)",
325     "string (vector v)",
326     "void ()",
327     "void ()",
328     "void ()",
329     "void (entity e)",
330     "float (float yaw, float dist)",
331     NULL,
332     "float (float yaw, float dist)",
333     "void (float style, string value)",
334     "float (float v)",
335     "float (float v)",
336     "float (float v)",
337     NULL,
338     "float (entity e)",
339     "float (vector v)",
340     NULL,
341     "float (float f)",
342     "vector (entity e, float speed)",
343     "float (string s)",
344     "void (string s)",
345     "entity (entity e)",
346     "void (vector o, vector d, float color, float count)",
347     "void ()",
348     NULL,
349     "vector (vector v)",
350     "void (float to, float f)",
351     "void (float to, float f)",
352     "void (float to, float f)",
353     "void (float to, float f)",
354     "void (float to, float f)",
355     "void (float to, float f)",
356     "void (float to, string s)",
357     "void (float to, entity s)",
358     NULL,
359     NULL,
360     NULL,
361     NULL,
362     NULL,
363     NULL,
364     NULL,
365     "void (float step)",
366     "string (string s)",
367     "void (entity e)",
368     "void (string s)",
369     NULL,
370     "void (string var, string val)",
371     "void (entity client, string s, ...)",
372     "void (vector pos, string samp, float vol, float atten)",
373     "string (string s)",
374     "string (string s)",
375     "string (string s)",
376     "void (entity e)",
377 	"void(entity killer, entity killee)",
378 	"string(entity e, string key)",
379 	"float(string s)",
380 	"void(vector where, float set)"
381 
382 };
383 
384 char *DecompileValueString(etype_t type, void *val);
385 ddef_t *DecompileGetParameter(gofs_t ofs);
386 char *DecompilePrintParameter(ddef_t * def);
387 
DecompileReadData(char * srcfile)388 void DecompileReadData(char *srcfile)
389 {
390     dprograms_t progs;
391     int h, i;
392 	void *p;
393 	char name[1024];
394 
395     h = SafeOpenRead(srcfile);
396     SafeRead(h, &progs, sizeof(progs));
397 
398     lseek(h, progs.ofs_strings, SEEK_SET);
399     strofs = progs.numstrings;
400     SafeRead(h, strings, strofs);
401 
402     lseek(h, progs.ofs_statements, SEEK_SET);
403     numstatements = progs.numstatements;
404     SafeRead(h, statements, numstatements * sizeof(dstatement_t));
405 
406     lseek(h, progs.ofs_functions, SEEK_SET);
407     numfunctions = progs.numfunctions;
408     SafeRead(h, functions, numfunctions * sizeof(dfunction_t));
409 
410     lseek(h, progs.ofs_globaldefs, SEEK_SET);
411     numglobaldefs = progs.numglobaldefs;
412     SafeRead(h, globals, numglobaldefs * sizeof(ddef_t));
413 
414     lseek(h, progs.ofs_fielddefs, SEEK_SET);
415     numfielddefs = progs.numfielddefs;
416     SafeRead(h, fields, numfielddefs * sizeof(ddef_t));
417 
418     lseek(h, progs.ofs_globals, SEEK_SET);
419     numpr_globals = progs.numglobals;
420     SafeRead(h, pr_globals, numpr_globals * 4);
421 	printf("Decompiling...\n");
422 	printf("Read Data from %s:\n", srcfile);
423 	printf("Total Size is %6i\n", (int)lseek(h, 0, SEEK_END));
424 	printf("Version Code is %i\n", progs.version);
425 	printf("CRC is %i\n", progs.crc);
426 	printf("%6i strofs\n", strofs);
427 	printf("%6i numstatements\n", numstatements);
428 	printf("%6i numfunctions\n", numfunctions);
429 	printf("%6i numglobaldefs\n", numglobaldefs);
430 	printf("%6i numfielddefs\n", numfielddefs);
431 	printf("%6i numpr_globals\n", numpr_globals);
432 	printf("----------------------\n");
433 
434 // fix up the functions
435     for (i = 1; i < numfunctions; i++)
436 	{
437 			if (strlen(functions[i].s_name + strings) <= 0)
438 			{
439 				sprintf(name, "function%i", i);
440 				name[strlen(name)] = 0;
441 				p = malloc(strlen(name + 1));
442 				strcpy(p, name);
443 				functions[i].s_name = (char *)p - strings;
444 			}
445 	}
446 }
447 
448 int
DecompileGetFunctionIdxByName(char * name)449 DecompileGetFunctionIdxByName(char *name)
450 {
451 
452     int i;
453 
454     for (i = 1; i < numfunctions; i++)
455 		if (!strcmp(name, strings + functions[i].s_name))
456 		{
457 			break;
458 		}
459     return i;
460 }
461 
462 int
DecompileAlreadySeen(char * fname)463 DecompileAlreadySeen(char *fname)
464 {
465 
466     int i;
467     char *knew;
468 
469     if (DecompileFileCtr > 1000)
470 	{
471 		printf("Fatal Error - too many source files.\n");
472 		exit(1);
473 	}
474 
475     for (i = 0; i < DecompileFileCtr; i++)
476 	{
477 		if (!strcmp(fname, DecompileFilesSeen[i]))
478 		    return 1;
479     }
480 
481     knew = (char *)malloc(strlen(fname) + 1);
482     strcpy(knew, fname);
483     DecompileFilesSeen[DecompileFileCtr] = knew;
484     DecompileFileCtr++;
485 
486 
487 
488     return 0;
489 }
490 
491 void
DecompileCalcProfiles(void)492 DecompileCalcProfiles(void)
493 {
494 
495     int i, j, ps;
496     char *knew;
497     static char fname[512];
498     static char line[512];
499     dfunction_t *df;
500     dstatement_t *ds, *rds;
501     ddef_t *par;
502     unsigned short dom;
503 
504     for (i = 1; i < numfunctions; i++)
505 	{
506 
507 		df = functions + i;
508 		fname[0] = '\0';
509 		line[0] = '\0';
510 		DecompileProfiles[i] = NULL;
511 
512 		if (df->first_statement <= 0)
513 		{
514 			if ((df->first_statement > -82) && builtins[-df->first_statement])
515 				sprintf(fname, "%s %s", builtins[-df->first_statement], strings + functions[i].s_name);
516 			else
517 			{
518 				sprintf(fname, "void () %s", strings + functions[i].s_name, strings + functions[i].s_name);
519 				printf("Warning: unknown builtin %s\n", strings + functions[i].s_name);
520 			}
521 		}
522 		else
523 		{
524 
525 			ds = statements + df->first_statement;
526 			rds = NULL;
527 
528 			/*
529 			 * find a return statement, to determine the result type
530 			 */
531 
532 			while (1)
533 			{
534 				dom = (ds->op) % 100;
535 				if (!dom)
536 					break;
537 				if (dom == OP2_RETURN)
538 				{
539 					if (ds->a != 0)
540 					{
541 						if (DecompileGetParameter(ds->a))
542 						{
543 							rds = ds;
544 							break;
545 						}
546 					}
547 					if (rds == NULL)
548 						rds = ds;
549 
550 				}
551 				ds++;
552 			}
553 
554 			/*
555 			 * print the return type
556 			 */
557 
558 			if ((rds != NULL) && (rds->a != 0))
559 			{
560 				par = DecompileGetParameter(rds->a);
561 
562 				if (par)
563 				{
564 					sprintf(fname, "%s ", type_name(par));
565 				}
566 				else
567 				{
568 					sprintf(fname, "%s ", temp_type(rds->a, rds, df));
569 				}
570 			}
571 			else
572 			{
573 				sprintf(fname, "void ");
574 			}
575 			strcat(fname, "(");
576 
577 			/*
578 			 * determine overall parameter size
579 			 */
580 
581 			for (j = 0, ps = 0; j < df->numparms; j++)
582 			ps += df->parm_size[j];
583 
584 			if (ps > 0)
585 			{
586 				for (j = df->parm_start; j < (df->parm_start) + ps; j++)
587 				{
588 					line[0] = '\0';
589 					par = DecompileGetParameter(j);
590 
591 					if (!par)
592 					{
593 						//Error("Error - No parameter names with offset %i.", j);
594 						printf("No parameter names with offset %i\n", j);
595 						if (j < (df->parm_start) + ps - 1)
596 							sprintf(line, "float par%i, ", j - df->parm_start);
597 						else
598 							sprintf(line, "float par%i", j - df->parm_start);
599 					}
600 					else
601 					{
602 						if (par->type == ev_vector)
603 							j += 2;
604 						if (j < (df->parm_start) + ps - 1)
605 						{
606 							sprintf(line, "%s, ", DecompilePrintParameter(par));
607 						}
608 						else
609 						{
610 							sprintf(line, "%s", DecompilePrintParameter(par));
611 						}
612 					}
613 					strcat(fname, line);
614 				}
615 			}
616 			strcat(fname, ") ");
617 			line[0] = '\0';
618 			sprintf(line, strings + functions[i].s_name);
619 			strcat(fname, line);
620 
621 		}
622 
623 		if (i >= MAX_FUNCTIONS)
624 		{
625 		   printf("Fatal Error - too many functions.\n");
626 			exit(1);
627 		}
628 		knew = (char *)malloc(strlen(fname) + 1);
629 		strcpy(knew, fname);
630 		DecompileProfiles[i] = knew;
631     }
632 
633 }
634 
DecompileGlobal(gofs_t ofs,def_t * req_t)635 char *DecompileGlobal(gofs_t ofs, def_t * req_t)
636 {
637     int i;
638     ddef_t *def;
639     static char line[256];
640     char *res;
641     char found = 0;
642 
643     line[0] = '\0';
644 
645     def = NULL;
646 
647     for (i = 0; i < numglobaldefs; i++)
648 	{
649 		def = &globals[i];
650 
651 		if (def->ofs == ofs)
652 		{
653 	/*
654 			printf("DecompileGlobal - Found %i at %i.\n", ofs, (int)def);
655 	*/
656 			found = 1;
657 			break;
658 		}
659 	}
660 
661 	if (found)
662 	{
663 
664 		if (!strcmp(strings + def->s_name, "IMMEDIATE"))
665 			sprintf(line, "%s", DecompileValueString((etype_t)(def->type), &pr_globals[def->ofs]));
666 		else
667 		{
668 
669 			sprintf(line, "%s", strings + def->s_name);
670 			if (def->type == ev_vector && req_t == &def_float)
671 				strcat(line, "_x");
672 
673 		}
674 		res = (char *)malloc(strlen(line) + 1);
675 		strcpy(res, line);
676 
677 		return res;
678     }
679     return NULL;
680 }
681 
682 gofs_t
DecompileScaleIndex(dfunction_t * df,gofs_t ofs)683 DecompileScaleIndex(dfunction_t *df, gofs_t ofs)
684 {
685     gofs_t nofs = 0;
686 
687     if (ofs > RESERVED_OFS)
688 	nofs = ofs - df->parm_start + RESERVED_OFS;
689     else
690 	nofs = ofs;
691 
692     return nofs;
693 }
694 
695 #define MAX_NO_LOCAL_IMMEDIATES 4096 /* dln: increased, not enough! */
696 
DecompileImmediate(dfunction_t * df,gofs_t ofs,int fun,char * knew)697 char *DecompileImmediate(dfunction_t *df, gofs_t ofs, int fun, char *knew)
698 {
699     int i;
700     char *res;
701     static char *IMMEDIATES[MAX_NO_LOCAL_IMMEDIATES];
702     gofs_t nofs;
703 
704     // free 'em all
705 
706     if (fun == 0)
707 	{
708 
709 		//printf("DecompileImmediate - Initializing function environment.\n");
710 
711 
712 		for (i = 0; i < MAX_NO_LOCAL_IMMEDIATES; i++)
713 		{
714 			if (IMMEDIATES[i])
715 			{
716 				free(IMMEDIATES[i]);
717 				IMMEDIATES[i] = NULL;
718 			}
719 		}
720 		return NULL;
721     }
722     nofs = DecompileScaleIndex(df, ofs);
723   //  printf("DecompileImmediate - Index scale: %i -> %i.\n", ofs, nofs);
724 
725 
726     // check consistency
727 
728     if ((nofs <= 0) || (nofs > MAX_NO_LOCAL_IMMEDIATES - 1))
729 	{
730 		printf("Fatal Error - Index (%i) out of bounds.\n", nofs);
731 		exit(1);
732 	}
733 
734     // insert at nofs
735 
736     if (fun == 1)
737 	{
738 
739 		if (IMMEDIATES[nofs])
740 			free(IMMEDIATES[nofs]);
741 
742 		IMMEDIATES[nofs] = (char *)malloc(strlen(knew) + 1);
743 		strcpy(IMMEDIATES[nofs], knew);
744 
745 //		printf("DecompileImmediate - Putting \"%s\" at index %i.\n", knew, nofs);
746 
747     }
748     // get from nofs
749 
750     else if (fun == 2)
751 	{
752 
753 		if (IMMEDIATES[nofs])
754 		{
755 
756 		//	printf("DecompileImmediate - Reading \"%s\" at index %i.\n", IMMEDIATES[nofs], nofs);
757 
758 			res = (char *)malloc(strlen(IMMEDIATES[nofs]) + 1);
759 			strcpy(res, IMMEDIATES[nofs]);
760 
761 			return res;
762 		}
763 		else
764 		{
765 			printf("Fatal Error - %i not defined.\n", nofs);
766 			exit(1);
767 		}
768     }
769     return NULL;
770 }
771 
DecompileGet(dfunction_t * df,gofs_t ofs,def_t * req_t)772 char *DecompileGet(dfunction_t *df, gofs_t ofs, def_t *req_t)
773 {
774     char *farg1;
775 	farg1 = NULL;
776 
777     farg1 = DecompileGlobal(ofs, req_t);
778 
779     if (farg1 == NULL)
780 		farg1 = DecompileImmediate(df, ofs, 2, NULL);
781 
782 /*
783     if (arg1)
784 	printf("DecompileGet - found \"%s\".\n", farg1);
785 */
786 
787     return farg1;
788 }
789 
790 void DecompilePrintStatement(dstatement_t *s);
791 
DecompileIndent(int c)792 void DecompileIndent(int c)
793 {
794     int i;
795 
796     if (c < 0)
797 		c = 0;
798 
799     for (i = 0; i < c; i++)
800 	{
801 		fprintf(Decompileofile, "\t");
802     }
803 }
804 
DecompileDecompileStatement(dfunction_t * df,dstatement_t * s,int * indent)805 void DecompileDecompileStatement(dfunction_t * df, dstatement_t * s, int *indent)
806 {
807     static char line[512];
808     static char fnam[512];
809     char *arg1, *arg2, *arg3;
810     int nargs, i, j;
811     dstatement_t *t;
812     unsigned short dom, doc, ifc, tom;
813     def_t *typ1, *typ2, *typ3;
814 	ddef_t *par;
815     dstatement_t *k;
816     int dum;
817 
818 
819     arg1 = arg2 = arg3 = NULL;
820 
821     line[0] = '\0';
822     fnam[0] = '\0';
823 
824     dom = s->op;
825 
826     doc = dom / 10000;
827     ifc = (dom % 10000) / 100;
828 
829     // use program flow information
830 
831     for (i = 0; i < ifc; i++)
832 	{
833 		(*indent)--;
834 		DecompileIndent(*indent);
835 		fprintf(Decompileofile, "}\n");//FrikaC style modification
836     }
837     for (i = 0; i < doc; i++)
838 	{
839 		DecompileIndent(*indent);
840 		fprintf(Decompileofile, "do\n");
841 		DecompileIndent(*indent);
842 		fprintf(Decompileofile, "{\n");
843 		(*indent)++;
844     }
845 
846     /*
847      * remove all program flow information
848      */
849     s->op %= 100;
850     typ1 = pr_opcodes[s->op].type_a;
851     typ2 = pr_opcodes[s->op].type_b;
852     typ3 = pr_opcodes[s->op].type_c;
853 
854     /*
855      * printf("DecompileDecompileStatement - decompiling %i (%i):\n",(int)(s - statements),dom);
856      * DecompilePrintStatement (s);
857      */
858     /*
859      * states are handled at top level
860      */
861 	if (s->op == OP2_DONE)
862 	{
863 
864 	}
865     else if (s->op == OP2_STATE)
866 	{
867 
868 		par = DecompileGetParameter(s->a);
869 		if (!par)
870 		{
871 		    printf("Error - Can't determine frame number.\n");
872 			exit(1);
873 		}
874 		arg2 = DecompileGet(df, s->b, NULL);
875 		if (!arg2)
876 		{
877 		   printf("Error - No state parameter with offset %i.\n", s->b);
878 			exit(1);
879 		}
880 		DecompileIndent(*indent);
881 		fprintf(Decompileofile, "state [ %s, %s ];\n", DecompileValueString((etype_t)(par->type), &pr_globals[par->ofs]), arg2);
882 
883 	//	free(arg2);
884     }
885 	else if (s->op == OP2_RETURN)
886 	{
887 		DecompileIndent(*indent);
888 		fprintf(Decompileofile, "return");
889 
890 		if (s->a)
891 		{
892 			fprintf(Decompileofile, " ");
893 			arg1 = DecompileGet(df, s->a, typ1);
894 			fprintf(Decompileofile, "(%s)", arg1);
895 		}
896 		fprintf(Decompileofile, ";\n");
897 
898     }
899 	else if ((OP2_MUL_F <= s->op && s->op <= OP2_SUB_V) ||
900 		(OP2_EQ_F <= s->op && s->op <= OP2_GT) ||
901 		(OP2_AND <= s->op && s->op <= OP2_BITOR))
902 	{
903 
904 		arg1 = DecompileGet(df, s->a, typ1);
905 		arg2 = DecompileGet(df, s->b, typ2);
906 		arg3 = DecompileGlobal(s->c, typ3);
907 
908 		if (arg3)
909 		{
910 			DecompileIndent(*indent);
911 			fprintf(Decompileofile, "%s = %s %s %s;\n", arg3, arg1, pr_opcodes[s->op].name, arg2);
912 		}
913 		else
914 		{
915 			sprintf(line, "(%s %s %s)", arg1, pr_opcodes[s->op].name, arg2);
916 			DecompileImmediate(df, s->c, 1, line);
917 		}
918 
919     }
920 	else if (OP2_LOAD_F <= s->op && s->op <= OP2_ADDRESS)
921 	{
922 
923 // RIGHT HERE
924 
925 	arg1 = DecompileGet(df, s->a, typ1);
926 	arg2 = DecompileGet(df, s->b, typ2);
927 	arg3 = DecompileGlobal(s->c, typ3);
928 
929 	if (arg3) {
930 	    DecompileIndent(*indent);
931 	    fprintf(Decompileofile, "%s = %s.%s;\n", arg3, arg1, arg2);
932 	} else {
933 	    sprintf(line, "%s.%s", arg1, arg2);
934 	    DecompileImmediate(df, s->c, 1, line);
935 	}
936     } else if (OP2_STORE_F <= s->op && s->op <= OP2_STORE_FNC) {
937 
938 	arg1 = DecompileGet(df, s->a, typ1);
939 	arg3 = DecompileGlobal(s->b, typ2);
940 
941 	if (arg3) {
942 	    DecompileIndent(*indent);
943 	    fprintf(Decompileofile, "%s = %s;\n", arg3, arg1);
944 	} else {
945 	    sprintf(line, "%s", arg1);
946 	    DecompileImmediate(df, s->b, 1, line);
947 	}
948 
949     } else if (OP2_STOREP_F <= s->op && s->op <= OP2_STOREP_FNC) {
950 
951 	arg1 = DecompileGet(df, s->a, typ2);
952 	arg2 = DecompileGet(df, s->b, typ2);
953 
954 	DecompileIndent(*indent);
955 	fprintf(Decompileofile, "%s = %s;\n", arg2, arg1);
956 
957     } else if (OP2_NOT_F <= s->op && s->op <= OP2_NOT_FNC) {
958 
959 	arg1 = DecompileGet(df, s->a, typ1);
960 	sprintf(line, "!%s", arg1);
961 	DecompileImmediate(df, s->c, 1, line);
962 
963     }
964 	else if (OP2_CALL0 <= s->op && s->op <= OP2_CALL8)
965 	{
966 
967 	nargs = s->op - OP2_CALL0;
968 
969 	arg1 = DecompileGet(df, s->a, NULL);
970 	sprintf(line, "%s (", arg1);
971 	sprintf(fnam, "%s", arg1);
972 
973 	for (i = 0; i < nargs; i++)
974 	{
975 
976 	    typ1 = NULL;
977 
978 	    j = 4 + 3 * i;
979 
980 	    if (arg1)
981 		free(arg1);
982 
983 	    arg1 = DecompileGet(df, j, typ1);
984 	    strcat(line, arg1);
985 
986 #ifndef DONT_USE_DIRTY_TRICKS
987 	    if (!strcmp(fnam, "WriteCoord"))
988 		if (!strcmp(arg1, "org") || !strcmp(arg1, "trace_endpos") || !strcmp(arg1, "p1") || !strcmp(arg1, "p2") || !strcmp(arg1, "o"))
989 		    strcat(line, "_x");
990 #endif
991 
992 	    if (i < nargs - 1)
993 		strcat(line, ", ");//frikqcc modified
994 	}
995 
996 	strcat(line, ")");
997 	DecompileImmediate(df, 1, 1, line);
998 
999 	/*
1000 	 * if ( ( ( (s+1)->a != 1) && ( (s+1)->b != 1) &&
1001 	 * ( (s+2)->a != 1) && ( (s+2)->b != 1) ) ||
1002 	 * ( ((s+1)->op) % 100 == OP2_CALL0 ) ) {
1003 	 * DecompileIndent(*indent);
1004 	 * fprintf(Decompileofile,"%s;\n",line);
1005 	 * }
1006 	 */
1007 
1008 	if ((((s + 1)->a != 1) && ((s + 1)->b != 1) &&
1009 		((s + 2)->a != 1) && ((s + 2)->b != 1)) ||
1010 	    ((((s + 1)->op) % 100 == OP2_CALL0) && ((((s + 2)->a != 1)) || ((s + 2)->b != 1)))) {
1011 	    DecompileIndent(*indent);
1012 	    fprintf(Decompileofile, "%s;\n", line);
1013 	}
1014     } else if (s->op == OP2_IF || s->op == OP2_IFNOT) {
1015 
1016 	arg1 = DecompileGet(df, s->a, NULL);
1017 	arg2 = DecompileGlobal(s->a, NULL);
1018 
1019 	if (s->op == OP2_IFNOT)
1020 	{
1021 
1022 	    if (s->b < 1)
1023 		{
1024 			printf("Found a negative IFNOT jump.\n");
1025 			exit(1);
1026 		}
1027 
1028 	    /*
1029 	     * get instruction right before the target
1030 	     */
1031 	    t = s + s->b - 1;
1032 	    tom = t->op % 100;
1033 
1034 	    if (tom != OP2_GOTO) {
1035 
1036 		/*
1037 		 * pure if
1038 		 */
1039 		DecompileIndent(*indent);
1040 		fprintf(Decompileofile, "if (%s)\n", arg1);//FrikaC modified
1041 		DecompileIndent(*indent);
1042 		fprintf(Decompileofile, "{\n");
1043 
1044 		(*indent)++;
1045 
1046 	    } else {
1047 
1048 		if (t->a > 0) {
1049 		    /*
1050 		     * ite
1051 		     */
1052 
1053 		    DecompileIndent(*indent);
1054 		    fprintf(Decompileofile, "if (%s)\n", arg1);//FrikaC modified
1055 			DecompileIndent(*indent);
1056 			fprintf(Decompileofile, "{\n");
1057 
1058 			(*indent)++;
1059 
1060 		} else {
1061 
1062 
1063 		    if ((t->a + s->b) > 1) {
1064 			/*
1065 			 * pure if
1066 			 */
1067 
1068 			DecompileIndent(*indent);
1069 		    fprintf(Decompileofile, "if (%s)\n", arg1);//FrikaC modified
1070 			DecompileIndent(*indent);
1071 			fprintf(Decompileofile, "{\n");
1072 			(*indent)++;
1073 		    } else {
1074 
1075 			dum = 1;
1076 			for (k = t + (t->a); k < s; k++) {
1077 			    tom = k->op % 100;
1078 			    if (tom == OP2_GOTO || tom == OP2_IF || tom == OP2_IFNOT)
1079 				dum = 0;
1080 			}
1081 			if (dum)
1082 			{
1083 
1084 			    DecompileIndent(*indent);
1085 			    fprintf(Decompileofile, "while (%s)\n", arg1);
1086 				DecompileIndent(*indent); //FrikaC
1087 				fprintf(Decompileofile, "{\n");
1088 			    (*indent)++;
1089 			} else {
1090 
1091 			    DecompileIndent(*indent);
1092 
1093 
1094 				fprintf(Decompileofile, "if (%s)\n", arg1);//FrikaC modified
1095 				DecompileIndent(*indent);
1096 				fprintf(Decompileofile, "{\n");
1097 			    (*indent)++;
1098 			}
1099 		    }
1100 		}
1101 	    }
1102 
1103 	}
1104 	else
1105 	{
1106 	    /*
1107 	     * do ... while
1108 	     */
1109 
1110 	    (*indent)--;
1111 	    fprintf(Decompileofile, "\n");
1112 	    DecompileIndent(*indent);
1113 	    fprintf(Decompileofile, "} while (%s);\n", arg1);
1114 
1115 	}
1116 
1117     }
1118 	else if (s->op == OP2_GOTO)
1119 	{
1120 
1121 		if (s->a > 0)
1122 		{
1123 			/*
1124 			 * else
1125 			 */
1126 			(*indent)--;
1127 			DecompileIndent(*indent);
1128 			fprintf(Decompileofile, "}\n");
1129 			DecompileIndent(*indent);
1130 			fprintf(Decompileofile, "else\n");
1131 			DecompileIndent(*indent);
1132 			fprintf(Decompileofile, "{\n");
1133 			(*indent)++;
1134 
1135 		}
1136 		else
1137 		{
1138 			/*
1139 			 * while
1140 			 */
1141 			(*indent)--;
1142 
1143 			DecompileIndent(*indent);
1144 			fprintf(Decompileofile, "}\n");
1145 
1146 		}
1147 
1148     }
1149 	else
1150 	{
1151 		if (s->op <= OP2_BITOR)
1152 			printf("Warnint: Unknown usage of OP_%s", pr_opcodes[s->op].opname);
1153 		else
1154 			printf("Warning: Unknown command\n");
1155 
1156     }
1157 
1158 
1159 //    printf("DecompileDecompileStatement - Current line is \"%s\"\n", line);
1160 
1161 
1162     if (arg1)
1163 		free(arg1);
1164     if (arg2)
1165 		free(arg2);
1166     if (arg3)
1167 		free(arg3);
1168 
1169     return;
1170 }
1171 
DecompileDecompileFunction(dfunction_t * df)1172 void DecompileDecompileFunction(dfunction_t * df)
1173 {
1174     dstatement_t *ds;
1175     int indent;
1176 
1177     // Initialize
1178 
1179     DecompileImmediate(df, 0, 0, NULL);
1180 
1181     indent = 1;
1182 
1183     ds = statements + df->first_statement;
1184 	if(ds->op == OP2_STATE)
1185 		ds++;
1186     while (1)
1187 	{
1188 
1189 		DecompileDecompileStatement(df, ds, &indent);
1190 		if (!ds->op)
1191 			break;
1192 		ds++;
1193     }
1194 
1195     if (indent != 1)
1196 	{
1197 		printf("Warning: Indentation structure corrupt\n");
1198 
1199 	}
1200 }
1201 
DecompileString(char * string)1202 char *DecompileString(char *string)
1203 {
1204     static char buf[255];
1205     char *s;
1206     int c = 1;
1207 
1208     s = buf;
1209     *s++ = '"';
1210     while (string && *string)
1211 	{
1212 		if (c == sizeof(buf) - 2)
1213 			break;
1214 		if (*string == '\n')
1215 		{
1216 			*s++ = '\\';
1217 			*s++ = 'n';
1218 			c++;
1219 		}
1220 		else if (*string == '"')
1221 		{
1222 			*s++ = '\\';
1223 			*s++ = '"';
1224 			c++;
1225 		}
1226 		else
1227 		{
1228 			*s++ = *string;
1229 			c++;
1230 		}
1231 		string++;
1232 		if (c > (int)(sizeof(buf) - 10))
1233 		{
1234 			*s++ = '.';
1235 			*s++ = '.';
1236 			*s++ = '.';
1237 			c += 3;
1238 			break;
1239 		}
1240     }
1241     *s++ = '"';
1242     *s++ = 0;
1243     return buf;
1244 }
1245 
DecompileValueString(etype_t type,void * val)1246 char *DecompileValueString(etype_t type, void *val)
1247 {
1248     static char line[1024];
1249 
1250     line[0] = '\0';
1251 
1252     switch (type)
1253 	{
1254 		case ev_string:
1255 			sprintf(line, "%s", DecompileString(strings + *(int *)val));
1256 			break;
1257 		case ev_void:
1258 			sprintf(line, "void");
1259 			break;
1260 		case ev_float:
1261 			if (*(float *)val > 999999 || *(float *)val < -999999) // ugh
1262 				sprintf(line, "%.f", *(float *)val);
1263 			else if ((*(float *)val < 0.001) && (*(float *)val > 0))
1264 				sprintf(line, "%.6f", *(float *)val);
1265 			else
1266 				sprintf(line, "%g", *(float *)val);
1267 			break;
1268 		case ev_vector:
1269 			sprintf(line, "'%g %g %g'", ((float *)val)[0], ((float *)val)[1], ((float *)val)[2]);
1270 			break;
1271 		default:
1272 			sprintf(line, "bad type %i", type);
1273 			break;
1274 	}
1275 
1276 	return line;
1277 }
1278 
DecompilePrintParameter(ddef_t * def)1279 char *DecompilePrintParameter(ddef_t * def)
1280 {
1281     static char line[128];
1282 
1283     line[0] = '0';
1284 
1285     if (!strcmp(strings + def->s_name, "IMMEDIATE"))
1286 	{
1287 		sprintf(line, "%s", DecompileValueString((etype_t)(def->type), &pr_globals[def->ofs]));
1288     }
1289 	else
1290 	{
1291 		sprintf(line, "%s %s", type_name(def), strings + def->s_name);
1292 	}
1293     return line;
1294 }
1295 
GetField(char * name)1296 ddef_t *GetField(char *name)
1297 {
1298     int i;
1299     ddef_t *d;
1300 
1301     for (i = 1; i < numfielddefs; i++)
1302 	{
1303 		d = &fields[i];
1304 
1305 		if (!strcmp(strings + d->s_name, name))
1306 		    return d;
1307     }
1308     return NULL;
1309 }
DecompileGetParameter(gofs_t ofs)1310 ddef_t *DecompileGetParameter(gofs_t ofs)
1311 {
1312     int i;
1313     ddef_t *def;
1314 
1315     def = NULL;
1316 
1317     for (i = 0; i < numglobaldefs; i++)
1318 	{
1319 		def = &globals[i];
1320 
1321 		if (def->ofs == ofs)
1322 		{
1323 			return def;
1324 		}
1325     }
1326 
1327     return NULL;
1328 }
1329 
DecompileFunction(char * name)1330 void DecompileFunction(char *name)
1331 {
1332     int i, findex, ps;
1333     dstatement_t *ds, *ts;
1334     dfunction_t *df;
1335     ddef_t *par;
1336     char *arg2;
1337     unsigned short dom, tom;
1338     int j, start, end;
1339     dfunction_t *dfpred;
1340     ddef_t *ef;
1341     static char line[256];
1342     dstatement_t *k;
1343     int dum;
1344 
1345 
1346     for (i = 1; i < numfunctions; i++)
1347 		if (!strcmp(name, strings + functions[i].s_name))
1348 			break;
1349     if (i == numfunctions)
1350 	{
1351 		printf("Fatal Error: No function named \"%s\"\n", name);
1352 		exit(1);
1353 	}
1354     df = functions + i;
1355 
1356     findex = i;
1357 
1358     // Check ''local globals''
1359 
1360     dfpred = df - 1;
1361 
1362     for (j = 0, ps = 0; j < dfpred->numparms; j++)
1363 		ps += dfpred->parm_size[j];
1364 
1365     start = dfpred->parm_start + dfpred->locals + ps;
1366 
1367     if (dfpred->first_statement < 0 && df->first_statement > 0)
1368 		start -= 1;
1369 
1370     if (start == 0)
1371 		start = 1;
1372 
1373     end = df->parm_start;
1374 
1375     for (j = start; j < end; j++)
1376 	{
1377 
1378 		par = DecompileGetParameter(j);
1379 
1380 		if (par)
1381 		{
1382 			if (par->type & (1 << 15))
1383 				par->type -= (1 << 15);
1384 
1385 			if (par->type == ev_function)
1386 			{
1387 
1388 				if (strcmp(strings + par->s_name, "IMMEDIATE"))
1389 					if (strcmp(strings + par->s_name, name))
1390 					{
1391 						fprintf(Decompileofile, "%s;\n", DecompileProfiles[DecompileGetFunctionIdxByName(strings + par->s_name)]);
1392 					}
1393 			}
1394 			else if (par->type != ev_pointer)
1395 				if (strcmp(strings + par->s_name, "IMMEDIATE"))
1396 				{
1397 
1398 					if (par->type == ev_field)
1399 					{
1400 
1401 						ef = GetField(strings + par->s_name);
1402 
1403 						if (!ef)
1404 						{
1405 							printf("Fatal Error: Could not locate a field named \"%s\"\n", strings + par->s_name);
1406 							exit(1);
1407 						}
1408 						if (ef->type == ev_vector)
1409 							j += 3;
1410 
1411 	#ifndef DONT_USE_DIRTY_TRICKS
1412 						if ((ef->type == ev_function) && !strcmp(strings + ef->s_name, "th_pain"))
1413 						{
1414 							fprintf(Decompileofile, ".void(entity attacker, float damage) th_pain;\n");
1415 						}
1416 						else
1417 	#endif
1418 
1419 							fprintf(Decompileofile, ".%s %s;\n", type_name(ef), strings + ef->s_name);
1420 
1421 					}
1422 					else
1423 					{
1424 
1425 						if (par->type == ev_vector)
1426 							j += 2;
1427 
1428 						if (par->type == ev_entity || par->type == ev_void)
1429 						{
1430 
1431 							fprintf(Decompileofile, "%s %s;\n", type_name(par), strings + par->s_name);
1432 
1433 						}
1434 						else
1435 						{
1436 
1437 							line[0] = '\0';
1438 							sprintf(line, "%s", DecompileValueString((etype_t)(par->type), &pr_globals[par->ofs]));
1439 
1440 							if (IsConstant(par))
1441 							{
1442 								fprintf(Decompileofile, "%s %s    = %s;\n", type_name(par), strings + par->s_name, line);
1443 							}
1444 							else
1445 							{
1446 								if (pr_globals[par->ofs] != 0)
1447 									fprintf(Decompileofile, "%s %s /* = %s */;\n", type_name(par), strings + par->s_name, line);
1448 								else
1449 									fprintf(Decompileofile, "%s %s;\n", type_name(par), strings + par->s_name, line);
1450 							}
1451 						}
1452 					}
1453 				}
1454 			}
1455 		}
1456 		/*
1457 		 * Check ''local globals''
1458 		 */
1459 
1460 		if (df->first_statement <= 0)
1461 		{
1462 
1463 			fprintf(Decompileofile, "%s", DecompileProfiles[findex]);
1464 			fprintf(Decompileofile, " = #%i; \n", -df->first_statement);
1465 
1466 			return;
1467 		}
1468 		ds = statements + df->first_statement;
1469 
1470 		while (1)
1471 		{
1472 
1473 			dom = (ds->op) % 100;
1474 
1475 			if (!dom)
1476 				break;
1477 			else if (dom == OP2_GOTO)
1478 			{
1479 				// check for i-t-e
1480 				if (ds->a > 0)
1481 				{
1482 					ts = ds + ds->a;
1483 					ts->op += 100;	// mark the end of a if/ite construct
1484 				}
1485 			}
1486 			else if (dom == OP2_IFNOT)
1487 			{
1488 				// check for pure if
1489 
1490 				ts = ds + ds->b;
1491 				tom = (ts - 1)->op % 100;
1492 
1493 				if (tom != OP2_GOTO)
1494 					ts->op += 100;	// mark the end of a if/ite construct
1495 			else if ((ts - 1)->a < 0)
1496 			{
1497 
1498 		/*
1499 				arg2 = DecompileGlobal(ds->a, NULL);
1500 
1501 				if (!((((ts - 1)->a + ds->b) == 0) ||
1502 					((arg2 != NULL) && (((ts - 1)->a + ds->b) == 1))))
1503 					(ts - 1)->op += 100;
1504 
1505 				if (arg2)
1506 					free(arg2);
1507 		*/
1508 
1509 				if (((ts - 1)->a + ds->b) > 1)
1510 				{
1511 					// pure if
1512 					ts->op += 100;	// mark the end of a if/ite construct
1513 				}
1514 				else
1515 				{
1516 
1517 					dum = 1;
1518 					for (k = (ts - 1) + ((ts - 1)->a); k < ds; k++)
1519 					{
1520 						tom = k->op % 100;
1521 						if (tom == OP2_GOTO || tom == OP2_IF || tom == OP2_IFNOT)
1522 							dum = 0;
1523 					}
1524 					if (!dum)
1525 					{
1526 						// pure if
1527 						ts->op += 100;	// mark the end of a if/ite construct
1528 					}
1529 				}
1530 			}
1531 		}
1532 		else if (dom == OP2_IF)
1533 		{
1534 			ts = ds + ds->b;
1535 			ts->op += 10000;	// mark the start of a do construct
1536 
1537 		}
1538 		ds++;
1539 	}
1540 
1541     /*
1542      * print the prototype
1543      */
1544     fprintf(Decompileofile, "\n%s", DecompileProfiles[findex]);
1545 
1546     // handle state functions
1547 
1548     ds = statements + df->first_statement;
1549 
1550     if (ds->op == OP2_STATE)
1551 	{
1552 
1553 		par = DecompileGetParameter(ds->a);
1554 		if (!par)
1555 		{
1556 		    printf("Fatal Error - Can't determine frame number.");
1557 			exit(1);
1558 		}
1559 
1560 		arg2 = DecompileGet(df, ds->b, NULL);
1561 		if (!arg2)
1562 		{
1563 		    printf("Fatal Error - No state parameter with offset %i.", ds->b);
1564 			exit(1);
1565 		}
1566 
1567 		fprintf(Decompileofile, " = [ %s, %s ]", DecompileValueString((etype_t)(par->type), &pr_globals[par->ofs]), arg2);
1568 
1569 		free(arg2);
1570 
1571     }
1572 	else
1573 	{
1574 		fprintf(Decompileofile, " =");
1575     }
1576     fprintf(Decompileofile, "\n{\n");
1577 
1578 /*
1579     fprintf(Decompileprofile, "%s", DecompileProfiles[findex]);
1580     fprintf(Decompileprofile, ") %s;\n", name);
1581 */
1582 
1583     /*
1584      * calculate the parameter size
1585      */
1586 
1587     for (j = 0, ps = 0; j < df->numparms; j++)
1588 	ps += df->parm_size[j];
1589 
1590     /*
1591      * print the locals
1592      */
1593 
1594     if (df->locals > 0) {
1595 
1596 	if ((df->parm_start) + df->locals - 1 >= (df->parm_start) + ps)
1597 	{
1598 
1599 	    for (i = df->parm_start + ps; i < (df->parm_start) + df->locals; i++)
1600 		{
1601 
1602 			par = DecompileGetParameter(i);
1603 
1604 			if (!par)
1605 			{
1606 				// temps
1607 				continue;
1608 			}
1609 			else
1610 			{
1611 				if (!strcmp(strings + par->s_name, "IMMEDIATE"))
1612 					continue; // immediates don't belong
1613 				if (par->type == ev_function)
1614 				{
1615 					printf("Warning Fields and functions must be global\n");
1616 				}
1617 				else
1618 					fprintf(Decompileofile, "\tlocal %s;\n", DecompilePrintParameter(par));
1619 				if (par->type == ev_vector)
1620 					i += 2;
1621 			}
1622 	    }
1623 
1624 	    fprintf(Decompileofile, "\n");
1625 
1626 		}
1627     }
1628     /*
1629      * do the hard work
1630      */
1631 
1632     DecompileDecompileFunction(df);
1633 
1634     fprintf(Decompileofile, "};\n");
1635 }
1636 extern boolean safedecomp;
1637 int fake_name;
1638 char synth_name[1024]; // fake name part2
1639 
TrySynthName(char * first)1640 boolean TrySynthName(char *first)
1641 {
1642 	int i;
1643 
1644 	// try to figure out the filename
1645 	// based on the first function in the file
1646 	for (i=0; i < FILELISTSIZE; i+=2)
1647 	{
1648 		if (!strcmp(filenames[i], first))
1649 		{
1650 			sprintf(synth_name, filenames[i + 1]);
1651 			return true;
1652 		}
1653 	}
1654 	return false;
1655 }
1656 
DecompileDecompileFunctions(void)1657 void DecompileDecompileFunctions(void)
1658 {
1659     int i;
1660 	unsigned int o;
1661     dfunction_t *d;
1662 	boolean bogusname;
1663     FILE *f;
1664     char fname[512];
1665 
1666     DecompileCalcProfiles();
1667 
1668     Decompileprogssrc = fopen("progs.src", "w");
1669     if (!Decompileprogssrc)
1670 	{
1671 		printf("Fatal Error - Could not open \"progs.src\" for output.\n");
1672 		exit(1);
1673 	}
1674 
1675     fprintf(Decompileprogssrc, "./progs.dat\n\n");
1676 /*
1677     Decompileprofile = fopen("!profile.qc", "w");
1678     if (!Decompileprofile)
1679 		Error("DecompileDecompileFunctions - Could not open \"!profile.qc\" for output.");
1680     fprintf(Decompileprogssrc, "!profile.qc\n");
1681 */
1682 
1683     for (i = 1; i < numfunctions; i++)
1684 	{
1685 		d = &functions[i];
1686 
1687 		fname[0] = '\0';
1688 		if (d->s_file <= strofs && d->s_file >= 0)
1689 			sprintf(fname, "%s", strings + d->s_file);
1690 		// FrikaC -- not sure if this is cool or what?
1691 		bogusname = false;
1692 		if (strlen(fname) <= 0)
1693 				bogusname = true;
1694 		else for (o = 0; o < strlen(fname); o++)
1695 		{
1696 			if ((fname[o] < 'a' || fname[o] > 'z') &&
1697 			  (fname[o] < '0' || fname[o] > '9') &&
1698 			  (fname[o] <'A' || fname[o] > 'Z') &&
1699 			  (fname[o] != '.' && fname[o] != '!' && fname[o] != '_'))
1700 			{
1701 				if (fname[o] == '/')
1702 					fname[o] = '.';
1703 				else if (fname[o] == '\\')
1704 					fname[o] = '.';
1705 				else
1706 				{
1707 						bogusname = true;
1708 						break;
1709 				}
1710 			}
1711 		}
1712 
1713 		if (bogusname)
1714 		{
1715 			if (!DecompileAlreadySeen(fname))
1716 			{
1717 				synth_name[0] = 0;
1718 				if(!TrySynthName(va("%s", strings + d->s_name)))
1719 							fake_name++;
1720 			}
1721 			if (synth_name[0])
1722 				sprintf(fname, synth_name);
1723 			else
1724 				sprintf(fname, "frik%i.qc", fake_name);
1725 		}
1726 
1727 
1728 
1729 		if (!DecompileAlreadySeen(fname))
1730 		{
1731 			printf("decompiling %s...\n", fname);
1732 			fprintf(Decompileprogssrc, "%s\n", fname);
1733 			f = fopen(fname, "w");
1734 		}
1735 		else
1736 			f = fopen(fname, "a+");
1737 		if (!f)
1738 		{
1739 			printf("Fatal Error - Could not open \"%s\" for output.\n", fname);
1740 			exit(1);
1741 		}
1742 		Decompileofile = f;
1743 		DecompileFunction(strings + d->s_name);
1744 
1745 		if (fclose(f))
1746 		{
1747 			printf("Fatal Error - Could not close \"%s\" properly.\n", fname);
1748 			exit(1);
1749 		}
1750 
1751 	}
1752 	if (fclose(Decompileprogssrc))
1753 	{
1754 		printf("Fatal Error - Could not close \"progs.src\" properly.\n");
1755 		exit(1);
1756 	}
1757 }
1758 
DecompileProgsDat(char * name)1759 void DecompileProgsDat(char *name)
1760 {
1761     DecompileReadData(name);
1762     DecompileDecompileFunctions();
1763 
1764 }
1765 
DecompileGlobalStringNoContents(gofs_t ofs)1766 char *DecompileGlobalStringNoContents(gofs_t ofs)
1767 {
1768     int i;
1769     ddef_t *def;
1770     static char line[128];
1771 
1772     line[0] = '0';
1773     sprintf(line, "%i(???)", ofs);
1774 
1775     for (i = 0; i < numglobaldefs; i++)
1776 	{
1777 		def = &globals[i];
1778 
1779 		if (def->ofs == ofs)
1780 		{
1781 			line[0] = '0';
1782 			sprintf(line, "%i(%s)", def->ofs, strings + def->s_name);
1783 			break;
1784 		}
1785     }
1786 
1787     i = strlen(line);
1788     for (; i < 16; i++)
1789 		strcat(line, " ");
1790     strcat(line, " ");
1791 
1792     return line;
1793 }
1794 
DecompileGlobalString(gofs_t ofs)1795 char *DecompileGlobalString(gofs_t ofs)
1796 {
1797     char *s;
1798     int i;
1799     ddef_t *def;
1800     static char line[128];
1801 
1802     line[0] = '0';
1803     sprintf(line, "%i(???)", ofs);
1804 
1805     for (i = 0; i < numglobaldefs; i++)
1806 	{
1807 		def = &globals[i];
1808 
1809 		if (def->ofs == ofs)
1810 		{
1811 
1812 			line[0] = '0';
1813 			if (!strcmp(strings + def->s_name, "IMMEDIATE"))
1814 			{
1815 				s = PR_ValueString((etype_t)(def->type), &pr_globals[ofs]);
1816 				sprintf(line, "%i(%s)", def->ofs, s);
1817 			}
1818 			else
1819 				sprintf(line, "%i(%s)", def->ofs, strings + def->s_name);
1820 		}
1821     }
1822 
1823     i = strlen(line);
1824     for (; i < 16; i++)
1825 		strcat(line, " ");
1826     strcat(line, " ");
1827 
1828     return line;
1829 }
1830 
DecompilePrintStatement(dstatement_t * s)1831 void DecompilePrintStatement(dstatement_t * s)
1832 {
1833     int i;
1834 
1835     printf("%4i : %s ", (int)(s - statements), pr_opcodes[s->op].opname);
1836     i = strlen(pr_opcodes[s->op].opname);
1837     for (; i < 10; i++)
1838 		printf(" ");
1839 
1840     if (s->op == OP2_IF || s->op == OP2_IFNOT)
1841 		printf("%sbranch %i", DecompileGlobalString(s->a), s->b);
1842     else if (s->op == OP2_GOTO)
1843 	{
1844 		printf("branch %i", s->a);
1845     }
1846 	else if ((unsigned)(s->op - OP2_STORE_F) < 6)
1847 	{
1848 		printf("%s", DecompileGlobalString(s->a));
1849 		printf("%s", DecompileGlobalStringNoContents(s->b));
1850     }
1851 	else
1852 	{
1853 		if (s->a)
1854 			printf("%s", DecompileGlobalString(s->a));
1855 		if (s->b)
1856 			printf("%s", DecompileGlobalString(s->b));
1857 		if (s->c)
1858 			printf("%s", DecompileGlobalStringNoContents(s->c));
1859 	}
1860     printf("\n");
1861 }
1862 
DecompilePrintFunction(char * name)1863 void DecompilePrintFunction(char *name)
1864 {
1865     int i;
1866     dstatement_t *ds;
1867     dfunction_t *df;
1868 
1869     for (i = 0; i < numfunctions; i++)
1870 		if (!strcmp(name, strings + functions[i].s_name))
1871 			break;
1872     if (i == numfunctions)
1873 	{
1874 		printf("Fatal Error: No function names \"%s\"\n", name);
1875 		exit(1);
1876 	}
1877     df = functions + i;
1878 
1879     printf("Statements for %s:\n", name);
1880     ds = statements + df->first_statement;
1881     while (1)
1882 	{
1883 		DecompilePrintStatement(ds);
1884 
1885 		if (!ds->op)
1886 			break;
1887 		ds++;
1888     }
1889 }
1890 
1891