]> git.xonotic.org Git - voretournament/voretournament.git/blob - misc/source/fteqcc-src/qcdecomp.c
Get VoreTournament code to compile with gmqcc. To be compiled with the same parameter...
[voretournament/voretournament.git] / misc / source / fteqcc-src / qcdecomp.c
1 #ifndef MINIMAL
2
3 #include "progsint.h"
4 #include "setjmp.h"
5
6 #define MAX_PARMS       8
7
8 // I put the following here to resolve "undefined reference to `__imp__vsnprintf'" with MinGW64 ~ Moodles
9 #ifdef _WIN32
10         #if (_MSC_VER >= 1400)
11                 //with MSVC 8, use MS extensions
12                 #define snprintf linuxlike_snprintf_vc8
13                 int VARGS linuxlike_snprintf_vc8(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
14                 #define vsnprintf(a, b, c, d) vsnprintf_s(a, b, _TRUNCATE, c, d)
15         #else
16                 //msvc crap
17                 #define snprintf linuxlike_snprintf
18                 int VARGS linuxlike_snprintf(char *buffer, int size, const char *format, ...) LIKEPRINTF(3);
19                 #define vsnprintf linuxlike_vsnprintf
20                 int VARGS linuxlike_vsnprintf(char *buffer, int size, const char *format, va_list argptr);
21         #endif
22 #endif
23
24 typedef struct QCC_type_s
25 {
26         etype_t                 type;
27
28         struct QCC_type_s       *next;
29 // function types are more complex
30         struct QCC_type_s       *aux_type;      // return type or field type
31         int                             num_parms;      // -1 = variable args
32 //      struct QCC_type_s       *parm_types[MAX_PARMS]; // only [num_parms] allocated
33
34         int ofs;        //inside a structure.
35         int size;
36         char *name;
37
38 } QCC_type_t;
39
40
41 extern QCC_type_t       *qcc_typeinfo;
42 extern int numtypeinfos;
43 extern int maxtypeinfos;
44 extern QCC_type_t       *type_void;// = {ev_void/*, &def_void*/};
45 extern QCC_type_t       *type_string;// = {ev_string/*, &def_string*/};
46 extern QCC_type_t       *type_float;// = {ev_float/*, &def_float*/};
47 extern QCC_type_t       *type_vector;// = {ev_vector/*, &def_vector*/};
48 extern QCC_type_t       *type_entity;// = {ev_entity/*, &def_entity*/};
49 extern QCC_type_t       *type_field;// = {ev_field/*, &def_field*/};
50 extern QCC_type_t       *type_function;// = {ev_function/*, &def_function*/,NULL,&type_void};
51 // type_function is a void() function used for state defs
52 extern QCC_type_t       *type_pointer;// = {ev_pointer/*, &def_pointer*/};
53 extern QCC_type_t       *type_integer;// = {ev_integer/*, &def_integer*/};
54 extern QCC_type_t       *type_floatpointer;
55 extern QCC_type_t       *type_intpointer;
56
57 extern QCC_type_t       *type_floatfield;// = {ev_field/*, &def_field*/, NULL, &type_float};
58 QCC_type_t *QCC_PR_NewType (char *name, int basictype, pbool typedefed);
59
60
61 jmp_buf decompilestatementfailure;
62
63 #if 0
64 pbool Decompile(progfuncs_t *progfuncs, char *fname)
65 {
66         return false;
67 }
68 #else
69
70 QCC_type_t **ofstype;
71 qbyte *ofsflags;
72
73 int SafeOpenWrite (char *filename, int maxsize);
74 void SafeWrite(int hand, void *buf, long count);
75 int SafeSeek(int hand, int ofs, int mode);
76 void SafeClose(int hand);
77 void VARGS writes(int hand, char *msg, ...)
78 {
79         va_list va;
80         char buf[4192];
81
82         va_start(va, msg);
83         Q_vsnprintf (buf,sizeof(buf)-1, msg, va);
84         va_end(va);
85
86         SafeWrite(hand, buf, strlen(buf));
87 };
88
89 char *PR_UglyValueString (etype_t type, eval_t *val);
90 ddef16_t *ED_GlobalAtOfs16 (progfuncs_t *progfuncs, int ofs);
91 char *VarAtOfs(progfuncs_t *progfuncs, int ofs)
92 {
93         static char buf [4192];
94         ddef16_t *def;
95         int typen;
96
97         if (ofsflags[ofs]&8)
98                 def = ED_GlobalAtOfs16(progfuncs, ofs);
99         else
100                 def = NULL;
101         if (!def)
102         {
103                 if (ofsflags[ofs]&3)
104                 {
105                         if (ofstype[ofs])
106                                 sprintf(buf, "_v_%s_%i", ofstype[ofs]->name, ofs);
107                         else
108                                 sprintf(buf, "_v_%i", ofs);
109                 }
110                 else
111                 {
112                         if (ofstype[ofs])
113                         {
114                                 typen = ofstype[ofs]->type;
115                                 goto evaluateimmediate;
116                         }
117                         else
118                                 sprintf(buf, "_c_%i", ofs);
119                 }
120                 return buf;
121         }
122         if (!def->s_name[progfuncs->stringtable] || !strcmp(progfuncs->stringtable+def->s_name, "IMMEDIATE"))
123         {
124                 if (current_progstate->types)
125                         typen = current_progstate->types[def->type & ~DEF_SHARED].type;
126                 else
127                         typen = def->type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
128
129 evaluateimmediate:
130 //              return PR_UglyValueString(def->type, (eval_t *)&current_progstate->globals[def->ofs]);
131                 switch(typen)
132                 {
133                 case ev_float:
134                         sprintf(buf, "%f", G_FLOAT(ofs));
135                         return buf;
136                 case ev_vector:
137                         sprintf(buf, "\'%f %f %f\'", G_FLOAT(ofs), G_FLOAT(ofs+1), G_FLOAT(ofs+2));
138                         return buf;
139                 case ev_string:
140                         {
141                                 char *s, *s2;
142                                 s = buf;
143                                 *s++ = '\"';
144                                 s2 = pr_strings+G_INT(ofs);
145
146
147                                 if (s2)
148                                 while(*s2)
149                                 {
150                                         if (*s2 == '\n')
151                                         {
152                                                 *s++ = '\\';
153                                                 *s++ = 'n';
154                                                 s2++;
155                                         }
156                                         else if (*s2 == '\"')
157                                         {
158                                                 *s++ = '\\';
159                                                 *s++ = '\"';
160                                                 s2++;
161                                         }
162                                         else if (*s2 == '\t')
163                                         {
164                                                 *s++ = '\\';
165                                                 *s++ = 't';
166                                                 s2++;
167                                         }
168                                         else
169                                                 *s++=*s2++;
170                                 }
171                                 *s++ = '\"';
172                                 *s++ = '\0';
173                         }
174                         return buf;
175                 case ev_pointer:
176                         sprintf(buf, "_c_pointer_%i", ofs);
177                         return buf;
178                 default:
179                         sprintf(buf, "_c_%i", ofs);
180                         return buf;
181                 }
182         }
183         return def->s_name+progfuncs->stringtable;
184 }
185
186
187 int file;
188
189 int ImmediateReadLater(progfuncs_t *progfuncs, progstate_t *progs, unsigned int ofs, int firstst)
190 {
191         dstatement16_t *st;
192         if (ofsflags[ofs] & 8)
193                 return false;   //this is a global/local/pramater, not a temp
194         if (!(ofsflags[ofs] & 3))
195                 return false;   //this is a constant.
196         for (st = &((dstatement16_t*)progs->statements)[firstst]; ; st++,firstst++)
197         {       //if written, return false, if read, return true.
198                 if (st->op >= OP_CALL0 && st->op <= OP_CALL8)
199                 {
200                         if (ofs == OFS_RETURN)
201                                 return false;
202                         if (ofs < OFS_PARM0 + 3*((unsigned int)st->op - OP_CALL0))
203                                 return true;
204                 }
205                 else if (pr_opcodes[st->op].associative == ASSOC_RIGHT)
206                 {
207                         if (ofs == st->b)
208                                 return false;
209                         if (ofs == st->a)
210                                 return true;
211                 }
212                 else
213                 {
214                         if (st->a == ofs)
215                                 return true;
216                         if (st->b == ofs)
217                                 return true;
218                         if (st->c == ofs)
219                                 return false;
220                 }
221
222                 if (st->op == OP_DONE || st->op == OP_RETURN)   //we missed our chance. (return/done ends any code coherancy).
223                         return false;
224         }
225         return false;
226 }
227 int ProductReadLater(progfuncs_t *progfuncs, progstate_t *progs, int stnum)
228 {
229         dstatement16_t *st;
230         st = &((dstatement16_t*)progs->statements)[stnum];
231         if (pr_opcodes[st->op].priority == -1)
232         {
233                 if (st->op >= OP_CALL0 && st->op <= OP_CALL7)
234                         return ImmediateReadLater(progfuncs, progs, OFS_RETURN, stnum+1);
235                 return false;//these don't have products...
236         }
237
238         if (pr_opcodes[st->op].associative == ASSOC_RIGHT)
239                 return ImmediateReadLater(progfuncs, progs, st->b, stnum+1);
240         else
241                 return ImmediateReadLater(progfuncs, progs, st->c, stnum+1);
242 }
243
244 void WriteStatementProducingOfs(progfuncs_t *progfuncs, progstate_t *progs, int lastnum, int firstpossible, int ofs)    //recursive, works backwards
245 {
246         int i;
247         dstatement16_t *st;
248         ddef16_t *def;
249         if (ofs == 0)
250                 longjmp(decompilestatementfailure, 1);
251         for (; lastnum >= firstpossible; lastnum--)
252         {
253                 st = &((dstatement16_t*)progs->statements)[lastnum];
254                 if (st->op >= OP_CALL0 && st->op < OP_CALL7)
255                 {
256                         if (ofs != OFS_RETURN)
257                                 continue;
258                         WriteStatementProducingOfs(progfuncs, progs, lastnum-1, firstpossible, st->a);
259                         writes(file, "(");
260                         for (i = 0; i < st->op - OP_CALL0; i++)
261                         {
262                                 WriteStatementProducingOfs(progfuncs, progs, lastnum-1, firstpossible, OFS_PARM0 + i*3);
263                                 if (i != st->op - OP_CALL0-1)
264                                         writes(file, ", ");
265                         }
266                         writes(file, ")");
267                         return;
268                 }
269                 else if (pr_opcodes[st->op].associative == ASSOC_RIGHT)
270                 {
271                         if (st->b != ofs)
272                                 continue;
273                         if (!ImmediateReadLater(progfuncs, progs, st->b, lastnum+1))
274                         {
275                                 writes(file, "(");
276                                 WriteStatementProducingOfs(progfuncs, progs, lastnum-1, firstpossible, st->b);
277                                 writes(file, " ");
278                                 writes(file, pr_opcodes[st->op].name);
279                                 writes(file, " ");
280                                 WriteStatementProducingOfs(progfuncs, progs, lastnum-1, firstpossible, st->a);
281                                 writes(file, ")");
282                                 return;
283                         }
284                         WriteStatementProducingOfs(progfuncs, progs, lastnum-1, firstpossible, st->a);
285                         return;
286                 }
287                 else
288                 {
289                         if (st->c != ofs)
290                                 continue;
291
292                         if (!ImmediateReadLater(progfuncs, progs, st->c, lastnum+1))
293                         {
294                                 WriteStatementProducingOfs(progfuncs, progs, lastnum-1, firstpossible, st->c);
295                                 writes(file, " = ");
296                         }
297                         writes(file, "(");
298                         WriteStatementProducingOfs(progfuncs, progs, lastnum-1, firstpossible, st->a);
299
300                         if (!strcmp(pr_opcodes[st->op].name, "."))
301                                 writes(file, pr_opcodes[st->op].name);  //extra spaces around .s are ugly.
302                         else
303                         {
304                                 writes(file, " ");
305                                 writes(file, pr_opcodes[st->op].name);
306                                 writes(file, " ");
307                         }
308                         WriteStatementProducingOfs(progfuncs, progs, lastnum-1, firstpossible, st->b);
309                         writes(file, ")");
310                         return;
311                 }
312         }
313
314         def = ED_GlobalAtOfs16(progfuncs, ofs);
315         if (def)
316         {
317                 if (!strcmp(def->s_name+progfuncs->stringtable, "IMMEDIATE"))
318                         writes(file, "%s", VarAtOfs(progfuncs, ofs));
319                 else
320                         writes(file, "%s", progfuncs->stringtable+def->s_name);
321         }
322         else
323                 writes(file, "%s", VarAtOfs(progfuncs, ofs));
324 //              longjmp(decompilestatementfailure, 1);
325 }
326
327 int WriteStatement(progfuncs_t *progfuncs, progstate_t *progs, int stnum, int firstpossible)
328 {
329         int count, skip;
330         dstatement16_t *st;
331         st = &((dstatement16_t*)progs->statements)[stnum];
332         switch(st->op)
333         {
334         case OP_IFNOT_I:
335                 count = (signed short)st->b;
336                 writes(file, "if (");
337                 WriteStatementProducingOfs(progfuncs, progs, stnum, firstpossible, st->a);
338                 writes(file, ")\r\n");
339                 writes(file, "{\r\n");
340                 firstpossible = stnum+1;
341                 count--;
342                 stnum++;
343                 while(count)
344                 {
345                         if (ProductReadLater(progfuncs, progs, stnum))
346                         {
347                                 count--;
348                                 stnum++;
349                                 continue;
350                         }
351                         skip = WriteStatement(progfuncs, progs, stnum, firstpossible);
352                         count-=skip;
353                         stnum+=skip;
354                 }
355                 writes(file, "}\r\n");
356                 st = &((dstatement16_t*)progs->statements)[stnum];
357                 if (st->op == OP_GOTO)
358                 {
359                         count = (signed short)st->b;
360                         count--;
361                         stnum++;
362
363                         writes(file, "else\r\n");
364                         writes(file, "{\r\n");
365                         while(count)
366                         {
367                                 if (ProductReadLater(progfuncs, progs, stnum))
368                                 {
369                                         count--;
370                                         stnum++;
371                                         continue;
372                                 }
373                                 skip = WriteStatement(progfuncs, progs, stnum, firstpossible);
374                                 count-=skip;
375                                 stnum+=skip;
376                         }
377                         writes(file, "}\r\n");
378                 }
379                 break;
380         case OP_IF_I:
381                 longjmp(decompilestatementfailure, 1);
382                 break;
383         case OP_GOTO:
384                 longjmp(decompilestatementfailure, 1);
385                 break;
386         case OP_RETURN:
387         case OP_DONE:
388                 if (st->a)
389                         WriteStatementProducingOfs(progfuncs, progs, stnum-1, firstpossible, st->a);
390                 break;
391         case OP_CALL0:
392         case OP_CALL1:
393         case OP_CALL2:
394         case OP_CALL3:
395         case OP_CALL4:
396         case OP_CALL5:
397         case OP_CALL6:
398         case OP_CALL7:
399                 WriteStatementProducingOfs(progfuncs, progs, stnum, firstpossible, OFS_RETURN);
400                 writes(file, ";\r\n");
401                 break;
402         default:
403                 if (pr_opcodes[st->op].associative == ASSOC_RIGHT)
404                         WriteStatementProducingOfs(progfuncs, progs, stnum, firstpossible, st->b);
405                 else
406                         WriteStatementProducingOfs(progfuncs, progs, stnum, firstpossible, st->c);
407                 writes(file, ";\r\n");
408                 break;
409         }
410
411         return 1;
412 }
413
414 void WriteAsmStatements(progfuncs_t *progfuncs, progstate_t *progs, int num, int f, char *functionname)
415 {
416         int stn = progs->functions[num].first_statement;
417         QCC_opcode_t *op;
418         dstatement16_t *st = NULL;
419         eval_t *v;
420
421         ddef16_t *def;
422         int ofs,i;
423
424         int fileofs;
425
426         if (!functionname && stn<0)
427         {
428                 //we wrote this one...
429                 return;
430         }
431
432         if (stn>=0)
433         {
434                 for (stn = progs->functions[num].first_statement; stn < (signed int)pr_progs->numstatements; stn++)
435                 {
436                         st = &((dstatement16_t*)progs->statements)[stn];
437                         if (st->op == OP_DONE || st->op == OP_RETURN)
438                         {
439                                 if (!st->a)
440                                         writes(f, "void(");
441                                 else if (ofstype[st->a])
442                                 {
443                                         writes(f, "%s", ofstype[st->a]->name);
444                                         writes(f, "(");
445                                 }
446                                 else
447                                         writes(f, "function(");
448                                 break;
449                         }
450                 }
451                 st=NULL;
452                 stn = progs->functions[num].first_statement;
453         }
454         else
455                 writes(f, "function(");
456         for (ofs = progs->functions[num].parm_start, i = 0; i < progs->functions[num].numparms; i++, ofs+=progs->functions[num].parm_size[i])
457         {
458                 ofsflags[ofs] |= 4;
459
460                 def = ED_GlobalAtOfs16(progfuncs, ofs);
461                 if (def && stn>=0)
462                 {
463                         if (st)
464                                 writes(f, ", ");
465                         st = (void *)0xffff;
466
467                         if (!def->s_name[progfuncs->stringtable])
468                         {
469                                 char mem[64];
470                                 sprintf(mem, "_p_%i", def->ofs);
471                                 def->s_name = (char*)malloc(strlen(mem)+1)-progfuncs->stringtable;
472                                 strcpy(def->s_name+progfuncs->stringtable, mem);
473                         }
474
475                         if (current_progstate->types)
476                                 writes(f, "%s %s", current_progstate->types[def->type&~(DEF_SHARED|DEF_SAVEGLOBAL)].name, def->s_name);
477                         else
478                                 switch(def->type&~(DEF_SHARED|DEF_SAVEGLOBAL))
479                                 {
480                                 case ev_string:
481                                         writes(f, "%s %s", "string", progfuncs->stringtable+def->s_name);
482                                         break;
483                                 case ev_float:
484                                         writes(f, "%s %s", "float", progfuncs->stringtable+def->s_name);
485                                         break;
486                                 case ev_entity:
487                                         writes(f, "%s %s", "entity", progfuncs->stringtable+def->s_name);
488                                         break;
489                                 case ev_vector:
490                                         writes(f, "%s %s", "vector", progfuncs->stringtable+def->s_name);
491                                         break;
492                                 default:
493                                         writes(f, "%s %s", "randomtype", progfuncs->stringtable+def->s_name);
494                                         break;
495                                 }
496                 }
497         }
498         for (ofs = progs->functions[num].parm_start+progs->functions[num].numparms, i = progs->functions[num].numparms; i < progs->functions[num].locals; i++, ofs+=1)
499                 ofsflags[ofs] |= 4;
500
501         if (!progfuncs->stringtable[progs->functions[num].s_name])
502         {
503                 char mem[64];
504                 if (!functionname)
505                 {
506                         sprintf(mem, "_bi_%i", num);
507                         progs->functions[num].s_name = (char*)malloc(strlen(mem)+1)-progfuncs->stringtable;
508                         strcpy(progs->functions[num].s_name+progfuncs->stringtable, mem);
509                 }
510                 else
511                 {
512                         progs->functions[num].s_name = (char*)malloc(strlen(functionname)+1)-progfuncs->stringtable;
513                         strcpy(progs->functions[num].s_name+progfuncs->stringtable, functionname);
514                 }
515         }
516
517         writes(f, ") %s", progfuncs->stringtable+progs->functions[num].s_name);
518
519         if (stn < 0)
520         {
521                 stn*=-1;
522                 writes(f, " = #%i;\r\n", stn);
523 /*
524                 for (ofs = progs->functions[num].parm_start, i = 0; i < progs->functions[num].numparms; i++, ofs+=progs->functions[num].parm_size[i])
525                 {
526                         def = ED_GlobalAtOfs16(progfuncs, ofs);
527                         if (def)
528                         {
529                                 def->ofs = 0xffff;
530
531                                 if (progs->types)
532                                 {
533                                         if (progs->types[def->type & ~(DEF_SHARED|DEF_SAVEGLOBAL)].type == ev_vector)
534                                         {
535                                                 def = ED_GlobalAtOfs16(progfuncs, ofs);
536                                                 def->ofs = 0xffff;
537                                                 def = ED_GlobalAtOfs16(progfuncs, ofs+1);
538                                                 def->ofs = 0xffff;
539                                                 def = ED_GlobalAtOfs16(progfuncs, ofs+2);
540                                                 def->ofs = 0xffff;
541                                         }
542                                 }
543                                 else if ((def->type & (~(DEF_SHARED|DEF_SAVEGLOBAL))) == ev_vector)
544                                 {
545                                         def = ED_GlobalAtOfs16(progfuncs, ofs);
546                                         def->ofs = 0xffff;
547                                         def = ED_GlobalAtOfs16(progfuncs, ofs+1);
548                                         def->ofs = 0xffff;
549                                         def = ED_GlobalAtOfs16(progfuncs, ofs+2);
550                                         def->ofs = 0xffff;
551                                 }
552                         }
553                 }
554                 */
555                 return;
556         }
557
558         if (functionname)       //parsing defs
559         {
560                 writes(f, ";\r\n");
561                 return;
562         }
563
564         fileofs = SafeSeek(f, 0, SEEK_CUR);
565         if (setjmp(decompilestatementfailure))
566         {
567                 writes(f, "*/\r\n");
568         //      SafeSeek(f, fileofs, SEEK_SET);
569                 writes(f, " = asm {\r\n");
570
571                 stn = progs->functions[num].first_statement;
572                 for (ofs = progs->functions[num].parm_start+progs->functions[num].numparms, i = progs->functions[num].numparms; i < progs->functions[num].locals; i++, ofs+=1)
573                 {
574                         def = ED_GlobalAtOfs16(progfuncs, ofs);
575                         if (def)
576                         {
577                                 v = (eval_t *)&((int *)progs->globals)[def->ofs];
578                                 if (current_progstate->types)
579                                         writes(f, "\tlocal %s %s;\r\n", current_progstate->types[def->type&~(DEF_SHARED|DEF_SAVEGLOBAL)].name, def->s_name);
580                                 else
581                                 {
582                                         if (!progfuncs->stringtable[def->s_name])
583                                         {
584                                                 char mem[64];
585                                                 sprintf(mem, "_l_%i", def->ofs);
586                                                 def->s_name = (char*)malloc(strlen(mem)+1)-progfuncs->stringtable;
587                                                 strcpy(def->s_name+progfuncs->stringtable, mem);
588                                         }
589
590                                         switch(def->type&~(DEF_SHARED|DEF_SAVEGLOBAL))
591                                         {
592                                         case ev_string:
593                                                 writes(f, "\tlocal %s %s;\r\n", "string", progfuncs->stringtable+def->s_name);
594                                                 break;
595                                         case ev_float:
596                                                 writes(f, "\tlocal %s %s;\r\n", "float", progfuncs->stringtable+def->s_name);
597                                                 break;
598                                         case ev_entity:
599                                                 writes(f, "\tlocal %s %s;\r\n", "entity", progfuncs->stringtable+def->s_name);
600                                                 break;
601                                         case ev_vector:
602                                                 if (v->_vector[0] || v->_vector[1] || v->_vector[2])
603                                                         writes(f, "\tlocal vector %s = '%f %f %f';\r\n", progfuncs->stringtable+def->s_name, v->_vector[0], v->_vector[1], v->_vector[2]);
604                                                 else
605                                                         writes(f, "\tlocal %s %s;\r\n", "vector", progfuncs->stringtable+def->s_name);
606                                                 ofs+=2; //skip floats;
607                                                 break;
608                                         default:
609                                                 writes(f, "\tlocal %s %s;\r\n", "randomtype", progfuncs->stringtable+def->s_name);
610                                                 break;
611                                         }
612                                 }
613                         }
614                 }
615
616                 while(1)
617                 {
618                         st = &((dstatement16_t*)progs->statements)[stn];
619                         if (!st->op)    //end of function statement!
620                                 break;
621                         op = &pr_opcodes[st->op];
622                         writes(f, "\t%s", op->opname);
623
624                         if (op->priority==-1&&op->associative==ASSOC_RIGHT)     //last param is a goto
625                         {
626                                 if (op->type_b == &type_void)
627                                 {
628                                         if (st->a)
629                                                 writes(f, " %i", (signed short)st->a);
630                                 }
631                                 else if (op->type_c == &type_void)
632                                 {
633                                         if (st->a)
634                                                 writes(f, " %s", VarAtOfs(progfuncs, st->a));
635                                         if (st->b)
636                                                 writes(f, " %i", (signed short)st->b);
637                                 }
638                                 else
639                                 {
640                                         if (st->a)
641                                                 writes(f, " %s", VarAtOfs(progfuncs, st->a));
642                                         if (st->b)
643                                                 writes(f, " %s", VarAtOfs(progfuncs, st->b));
644                                         if (st->c)      //rightness means it uses a as c
645                                                 writes(f, " %i", (signed short)st->c);
646                                 }
647                         }
648                         else
649                         {
650                                 if (st->a)
651                                 {
652                                         if (op->type_a == NULL)
653                                                 writes(f, " %i", (signed short)st->a);
654                                         else
655                                                 writes(f, " %s", VarAtOfs(progfuncs, st->a));
656                                 }
657                                 if (st->b)
658                                 {
659                                         if (op->type_b == NULL)
660                                                 writes(f, " %i", (signed short)st->b);
661                                         else
662                                                 writes(f, " %s", VarAtOfs(progfuncs, st->b));
663                                 }
664                                 if (st->c && op->associative != ASSOC_RIGHT)    //rightness means it uses a as c
665                                 {
666                                         if (op->type_c == NULL)
667                                                 writes(f, " %i", (signed short)st->c);
668                                         else
669                                                 writes(f, " %s", VarAtOfs(progfuncs, st->c));
670                                 }
671                         }
672
673                         writes(f, ";\r\n");
674
675                         stn++;
676                 }
677         }
678         else
679         {
680                 if (!strcmp(progfuncs->stringtable+progs->functions[num].s_name, "SUB_Remove"))
681                         file = 0;
682                 file = f;
683
684                 writes(f, "/*\r\n");
685
686                 writes(f, " =\r\n{\r\n");
687
688                 for (ofs = progs->functions[num].parm_start+progs->functions[num].numparms, i = progs->functions[num].numparms; i < progs->functions[num].locals; i++, ofs+=1)
689                 {
690                         def = ED_GlobalAtOfs16(progfuncs, ofs);
691                         if (def)
692                         {
693                                 v = (eval_t *)&((int *)progs->globals)[def->ofs];
694                                 if (current_progstate->types)
695                                         writes(f, "\tlocal %s %s;\r\n", current_progstate->types[def->type&~(DEF_SHARED|DEF_SAVEGLOBAL)].name, def->s_name);
696                                 else
697                                 {
698                                         if (!def->s_name[progfuncs->stringtable])
699                                         {
700                                                 char mem[64];
701                                                 sprintf(mem, "_l_%i", def->ofs);
702                                                 def->s_name = (char*)malloc(strlen(mem)+1)-progfuncs->stringtable;
703                                                 strcpy(def->s_name+progfuncs->stringtable, mem);
704                                         }
705
706                                         switch(def->type&~(DEF_SHARED|DEF_SAVEGLOBAL))
707                                         {
708                                         case ev_string:
709                                                 writes(f, "\tlocal %s %s;\r\n", "string", progfuncs->stringtable+def->s_name);
710                                                 break;
711                                         case ev_float:
712                                                 writes(f, "\tlocal %s %s;\r\n", "float", progfuncs->stringtable+def->s_name);
713                                                 break;
714                                         case ev_entity:
715                                                 writes(f, "\tlocal %s %s;\r\n", "entity", progfuncs->stringtable+def->s_name);
716                                                 break;
717                                         case ev_vector:
718                                                 if (v->_vector[0] || v->_vector[1] || v->_vector[2])
719                                                         writes(f, "\tlocal vector %s = '%f %f %f';\r\n", progfuncs->stringtable+def->s_name, v->_vector[0], v->_vector[1], v->_vector[2]);
720                                                 else
721                                                         writes(f, "\tlocal %s %s;\r\n", "vector",progfuncs->stringtable+def->s_name);
722                                                 ofs+=2; //skip floats;
723                                                 break;
724                                         default:
725                                                 writes(f, "\tlocal %s %s;\r\n", "randomtype", progfuncs->stringtable+def->s_name);
726                                                 break;
727                                         }
728                                 }
729                         }
730                 }
731
732
733                 for (stn = progs->functions[num].first_statement; stn < (signed int)pr_progs->numstatements; stn++)
734                 {
735                         if (ProductReadLater(progfuncs, progs, stn))
736                                 continue;
737
738                         st = &((dstatement16_t*)progs->statements)[stn];
739                         if (!st->op)
740                                 break;
741                         WriteStatement(progfuncs, progs, stn, progs->functions[num].first_statement);
742                 }
743
744                 longjmp(decompilestatementfailure, 1);
745         }
746         writes(f, "};\r\n");
747 }
748
749 void FigureOutTypes(progfuncs_t *progfuncs)
750 {
751         ddef16_t                *def;
752         QCC_opcode_t *op;
753         unsigned int i,p;
754         dstatement16_t *st;
755
756         int parmofs[8];
757
758         ofstype         = realloc(ofstype,              sizeof(*ofstype)*65535);
759         ofsflags        = realloc(ofsflags,     sizeof(*ofsflags)*65535);
760
761         maxtypeinfos=256;
762         qcc_typeinfo = (void *)realloc(qcc_typeinfo, sizeof(QCC_type_t)*maxtypeinfos);
763         numtypeinfos = 0;
764
765         memset(ofstype,         0, sizeof(*ofstype)*65535);
766         memset(ofsflags,        0, sizeof(*ofsflags)*65535);
767
768         type_void = QCC_PR_NewType("void", ev_void, true);
769         type_string = QCC_PR_NewType("string", ev_string, true);
770         type_float = QCC_PR_NewType("float", ev_float, true);
771         type_vector = QCC_PR_NewType("vector", ev_vector, true);
772         type_entity = QCC_PR_NewType("entity", ev_entity, true);
773         type_field = QCC_PR_NewType("field", ev_field, false);
774         type_function = QCC_PR_NewType("function", ev_function, false);
775         type_pointer = QCC_PR_NewType("pointer", ev_pointer, false);
776         type_integer = QCC_PR_NewType("integer", ev_integer, true);
777
778 //      type_variant = QCC_PR_NewType("__variant", ev_variant);
779
780         type_floatfield = QCC_PR_NewType("fieldfloat", ev_field, false);
781         type_floatfield->aux_type = type_float;
782         type_pointer->aux_type = QCC_PR_NewType("pointeraux", ev_float, false);
783
784         type_function->aux_type = type_void;
785
786         for (i = 0,st = pr_statements16; i < pr_progs->numstatements; i++,st++)
787         {
788                 op = &pr_opcodes[st->op];
789                 if (st->op >= OP_CALL1 && st->op <= OP_CALL8)
790                 {
791                         for (p = 0; p < (unsigned int)st->op-OP_CALL0; p++)
792                         {
793                                 ofstype[parmofs[p]] = ofstype[OFS_PARM0+p*3];
794                         }
795                 }
796                 else if (op->associative == ASSOC_RIGHT)
797                 {       //assignment
798                         ofsflags[st->b] |= 1;
799                         if (st->b >= OFS_PARM0 && st->b < RESERVED_OFS)
800                                 parmofs[(st->b-OFS_PARM0)/3] = st->a;
801
802 //                      if (st->op != OP_STORE_F || st->b>RESERVED_OFS) //optimising compilers fix the OP_STORE_V, it's the storef that becomes meaningless (this is the only time that we need this sort of info anyway)
803                         {
804                                 if (op->type_c && op->type_c != &type_void)
805                                         ofstype[st->a] = *op->type_c;
806                                 if (op->type_b && op->type_b != &type_void)
807                                         ofstype[st->b] = *op->type_b;
808                         }
809                 }
810                 else if (op->type_c)
811                 {
812                         ofsflags[st->c] |= 2;
813
814                         if (st->c >= OFS_PARM0 && st->b < RESERVED_OFS) //too complicated
815                                 parmofs[(st->b-OFS_PARM0)/3] = 0;
816
817 //                      if (st->op != OP_STORE_F || st->b>RESERVED_OFS) //optimising compilers fix the OP_STORE_V, it's the storef that becomes meaningless (this is the only time that we need this sort of info anyway)
818                         {
819                                 if (op->type_a && op->type_a != &type_void)
820                                         ofstype[st->a] = *op->type_a;
821                                 if (op->type_b && op->type_b != &type_void)
822                                         ofstype[st->b] = *op->type_b;
823                                 if (op->type_c && op->type_c != &type_void)
824                                         ofstype[st->c] = *op->type_c;
825                         }
826                 }
827         }
828
829
830         for (i=0 ; i<pr_progs->numglobaldefs ; i++)
831         {
832                 def = &pr_globaldefs16[i];
833                 ofsflags[def->ofs] |= 8;
834                 switch(def->type)
835                 {
836                 case ev_float:
837                         ofstype[def->ofs] = type_float;
838                         break;
839                 case ev_string:
840                         ofstype[def->ofs] = type_string;
841                         break;
842                 case ev_vector:
843                         ofstype[def->ofs] = type_vector;
844                         break;
845                 default:
846                         break;
847                 }
848         }
849 }
850
851 pbool Decompile(progfuncs_t *progfuncs, char *fname)
852 {
853         extern progfuncs_t *qccprogfuncs;
854         unsigned int i;
855         unsigned int fld=0;
856         eval_t *v;
857 //      char *filename;
858         int f, type;
859
860         progstate_t progs, *op;
861
862         qccprogfuncs = progfuncs;
863         op=current_progstate;
864
865         if (!PR_ReallyLoadProgs(progfuncs, fname, -1, &progs, false))
866         {
867                 return false;
868         }
869
870         f=SafeOpenWrite("qcdtest/defs.qc", 1024*512);
871
872         writes(f, "//Decompiled code can contain little type info.\r\n#define NOWARNINGS\r\n");
873
874         FigureOutTypes(progfuncs);
875
876         for (i = 1; i < progs.progs->numglobaldefs; i++)
877         {
878                 if (!strcmp(progfuncs->stringtable+pr_globaldefs16[i].s_name, "IMMEDIATE"))
879                         continue;
880
881                 if (ofsflags[pr_globaldefs16[i].ofs] & 4)
882                         continue;       //this is a local.
883
884                 if (current_progstate->types)
885                         type = progs.types[pr_globaldefs16[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL)].type;
886                 else
887                         type = pr_globaldefs16[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
888                 v = (eval_t *)&((int *)progs.globals)[pr_globaldefs16[i].ofs];
889
890                 if (!progfuncs->stringtable[pr_globaldefs16[i].s_name])
891                 {
892                         char mem[64];
893                         if (ofsflags[pr_globaldefs16[i].ofs] & 3)
894                         {
895                                 ofsflags[pr_globaldefs16[i].ofs] &= ~8;
896                                 continue;       //this is a constant...
897                         }
898
899                         sprintf(mem, "_g_%i", pr_globaldefs16[i].ofs);
900                         pr_globaldefs16[i].s_name = (char*)malloc(strlen(mem)+1)-progfuncs->stringtable;
901                         strcpy(pr_globaldefs16[i].s_name+progfuncs->stringtable, mem);
902                 }
903
904                 switch(type)
905                 {
906                 case ev_void:
907                         writes(f, "void %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
908                         break;
909                 case ev_string:
910                         if (v->string && *(pr_strings+v->_int))
911                                 writes(f, "string %s = \"%s\";\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name, pr_strings+v->_int);
912                         else
913                                 writes(f, "string %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
914                         break;
915                 case ev_float:
916                         if (v->_float)
917                                 writes(f, "float %s = %f;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name, v->_float);
918                         else
919                                 writes(f, "float %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
920                         break;
921                 case ev_vector:
922                         if (v->_vector[0] || v->_vector[1] || v->_vector[2])
923                                 writes(f, "vector %s = '%f %f %f';\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name, v->_vector[0], v->_vector[1], v->_vector[2]);
924                         else
925                                 writes(f, "vector %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
926                         i+=3;//skip the floats
927                         break;
928                 case ev_entity:
929                         writes(f, "entity %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
930                         break;
931                 case ev_field:
932 //wierd
933                         fld++;
934                         if (!v->_int)
935                                 writes(f, "var ");
936                         switch(pr_fielddefs16[fld].type)
937                         {
938                         case ev_string:
939                                 writes(f, ".string %s;", progfuncs->stringtable+pr_globaldefs16[i].s_name);
940                                 break;
941
942                         case ev_float:
943                                 writes(f, ".float %s;", progfuncs->stringtable+pr_globaldefs16[i].s_name);
944                                 break;
945
946                         case ev_vector:
947                                 writes(f, ".float %s;", progfuncs->stringtable+pr_globaldefs16[i].s_name);
948                                 break;
949
950                         case ev_entity:
951                                 writes(f, ".float %s;", progfuncs->stringtable+pr_globaldefs16[i].s_name);
952                                 break;
953
954                         case ev_function:
955                                 writes(f, ".void() %s;", progfuncs->stringtable+pr_globaldefs16[i].s_name);
956                                 break;
957
958                         default:
959                                 writes(f, "field %s;", progfuncs->stringtable+pr_globaldefs16[i].s_name);
960                                 break;
961                         }
962                         if (v->_int)
963                                 writes(f, "/* %i */", v->_int);
964                         writes(f, "\r\n");
965                         break;
966
967                 case ev_function:
968 //wierd
969                         WriteAsmStatements(progfuncs, &progs, ((int *)progs.globals)[pr_globaldefs16[i].ofs], f, pr_globaldefs16[i].s_name+progfuncs->stringtable);
970                         break;
971
972                 case ev_pointer:
973                         writes(f, "pointer %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
974                         break;
975                 case ev_integer:
976                         writes(f, "integer %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
977                         break;
978
979                 case ev_union:
980                         writes(f, "union %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
981                         break;
982                 case ev_struct:
983                         writes(f, "struct %s;\r\n", progfuncs->stringtable+pr_globaldefs16[i].s_name);
984                         break;
985                 default:
986                         break;
987
988                 }
989         }
990
991         for (i = 0; i < progs.progs->numfunctions; i++)
992         {
993                 WriteAsmStatements(progfuncs, &progs, i, f, NULL);
994         }
995
996         SafeClose(f);
997
998         current_progstate=op;
999
1000         return true;
1001 }
1002 #endif
1003
1004 #endif