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