2004-08-23 01:38:21 +00:00
# ifndef MINIMAL
# include "progsint.h"
# include "setjmp.h"
# define MAX_PARMS 8
2010-12-08 14:42:05 +00:00
// I put the following here to resolve "undefined reference to `__imp__vsnprintf'" with MinGW64 ~ Moodles
# ifdef _WIN32
# if (_MSC_VER >= 1400)
//with MSVC 8, use MS extensions
# define snprintf linuxlike_snprintf_vc8
int VARGS linuxlike_snprintf_vc8 ( char * buffer , int size , const char * format , . . . ) LIKEPRINTF ( 3 ) ;
# define vsnprintf(a, b, c, d) vsnprintf_s(a, b, _TRUNCATE, c, d)
# else
//msvc crap
# define snprintf linuxlike_snprintf
int VARGS linuxlike_snprintf ( char * buffer , int size , const char * format , . . . ) LIKEPRINTF ( 3 ) ;
# define vsnprintf linuxlike_vsnprintf
int VARGS linuxlike_vsnprintf ( char * buffer , int size , const char * format , va_list argptr ) ;
# endif
# endif
2004-08-23 01:38:21 +00:00
typedef struct QCC_type_s
{
etype_t type ;
struct QCC_type_s * next ;
// function types are more complex
struct QCC_type_s * aux_type ; // return type or field type
int num_parms ; // -1 = variable args
2010-12-08 14:42:05 +00:00
// struct QCC_type_s *parm_types[MAX_PARMS]; // only [num_parms] allocated
2004-08-23 01:38:21 +00:00
int ofs ; //inside a structure.
int size ;
char * name ;
} QCC_type_t ;
extern QCC_type_t * qcc_typeinfo ;
extern int numtypeinfos ;
extern int maxtypeinfos ;
extern QCC_type_t * type_void ; // = {ev_void/*, &def_void*/};
extern QCC_type_t * type_string ; // = {ev_string/*, &def_string*/};
extern QCC_type_t * type_float ; // = {ev_float/*, &def_float*/};
extern QCC_type_t * type_vector ; // = {ev_vector/*, &def_vector*/};
extern QCC_type_t * type_entity ; // = {ev_entity/*, &def_entity*/};
extern QCC_type_t * type_field ; // = {ev_field/*, &def_field*/};
extern QCC_type_t * type_function ; // = {ev_function/*, &def_function*/,NULL,&type_void};
// type_function is a void() function used for state defs
extern QCC_type_t * type_pointer ; // = {ev_pointer/*, &def_pointer*/};
extern QCC_type_t * type_integer ; // = {ev_integer/*, &def_integer*/};
extern QCC_type_t * type_floatfield ; // = {ev_field/*, &def_field*/, NULL, &type_float};
QCC_type_t * QCC_PR_NewType ( char * name , int basictype ) ;
jmp_buf decompilestatementfailure ;
2005-09-08 22:52:46 +00:00
#if 0
2005-05-15 18:49:04 +00:00
pbool Decompile ( progfuncs_t * progfuncs , char * fname )
2004-08-23 01:38:21 +00:00
{
return false ;
}
# else
QCC_type_t * * ofstype ;
qbyte * ofsflags ;
int SafeOpenWrite ( char * filename , int maxsize ) ;
void SafeWrite ( int hand , void * buf , long count ) ;
int SafeSeek ( int hand , int ofs , int mode ) ;
void SafeClose ( int hand ) ;
void VARGS writes ( int hand , char * msg , . . . )
{
va_list va ;
char buf [ 4192 ] ;
va_start ( va , msg ) ;
Q_vsnprintf ( buf , sizeof ( buf ) - 1 , msg , va ) ;
va_end ( va ) ;
SafeWrite ( hand , buf , strlen ( buf ) ) ;
} ;
char * PR_UglyValueString ( etype_t type , eval_t * val ) ;
ddef16_t * ED_GlobalAtOfs16 ( progfuncs_t * progfuncs , int ofs ) ;
char * VarAtOfs ( progfuncs_t * progfuncs , int ofs )
{
static char buf [ 4192 ] ;
ddef16_t * def ;
int typen ;
if ( ofsflags [ ofs ] & 8 )
def = ED_GlobalAtOfs16 ( progfuncs , ofs ) ;
else
def = NULL ;
if ( ! def )
{
if ( ofsflags [ ofs ] & 3 )
{
if ( ofstype [ ofs ] )
sprintf ( buf , " _v_%s_%i " , ofstype [ ofs ] - > name , ofs ) ;
else
sprintf ( buf , " _v_%i " , ofs ) ;
}
else
{
if ( ofstype [ ofs ] )
{
typen = ofstype [ ofs ] - > type ;
goto evaluateimmediate ;
}
else
sprintf ( buf , " _c_%i " , ofs ) ;
}
return buf ;
}
2005-09-08 22:52:46 +00:00
if ( ! def - > s_name [ progfuncs - > stringtable ] | | ! strcmp ( progfuncs - > stringtable + def - > s_name , " IMMEDIATE " ) )
2004-08-23 01:38:21 +00:00
{
if ( current_progstate - > types )
typen = current_progstate - > types [ def - > type & ~ DEF_SHARED ] . type ;
else
typen = def - > type & ~ ( DEF_SHARED | DEF_SAVEGLOBAL ) ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
evaluateimmediate :
// return PR_UglyValueString(def->type, (eval_t *)¤t_progstate->globals[def->ofs]);
switch ( typen )
{
case ev_float :
sprintf ( buf , " %f " , G_FLOAT ( ofs ) ) ;
return buf ;
case ev_vector :
sprintf ( buf , " \' %f %f %f \' " , G_FLOAT ( ofs ) , G_FLOAT ( ofs + 1 ) , G_FLOAT ( ofs + 2 ) ) ;
return buf ;
case ev_string :
{
char * s , * s2 ;
s = buf ;
* s + + = ' \" ' ;
s2 = pr_strings + G_INT ( ofs ) ;
if ( s2 )
while ( * s2 )
{
if ( * s2 = = ' \n ' )
{
* s + + = ' \\ ' ;
* s + + = ' n ' ;
s2 + + ;
}
else if ( * s2 = = ' \" ' )
{
* s + + = ' \\ ' ;
* s + + = ' \" ' ;
s2 + + ;
}
else if ( * s2 = = ' \t ' )
{
* s + + = ' \\ ' ;
* s + + = ' t ' ;
s2 + + ;
}
else
* s + + = * s2 + + ;
}
* s + + = ' \" ' ;
* s + + = ' \0 ' ;
}
return buf ;
case ev_pointer :
sprintf ( buf , " _c_pointer_%i " , ofs ) ;
return buf ;
default :
sprintf ( buf , " _c_%i " , ofs ) ;
return buf ;
}
}
2005-09-08 22:52:46 +00:00
return def - > s_name + progfuncs - > stringtable ;
2004-08-23 01:38:21 +00:00
}
int file ;
int ImmediateReadLater ( progfuncs_t * progfuncs , progstate_t * progs , unsigned int ofs , int firstst )
{
dstatement16_t * st ;
if ( ofsflags [ ofs ] & 8 )
return false ; //this is a global/local/pramater, not a temp
2010-12-08 14:42:05 +00:00
if ( ! ( ofsflags [ ofs ] & 3 ) )
2004-08-23 01:38:21 +00:00
return false ; //this is a constant.
for ( st = & ( ( dstatement16_t * ) progs - > statements ) [ firstst ] ; ; st + + , firstst + + )
{ //if written, return false, if read, return true.
if ( st - > op > = OP_CALL0 & & st - > op < = OP_CALL8 )
{
if ( ofs = = OFS_RETURN )
return false ;
if ( ofs < OFS_PARM0 + 3 * ( ( unsigned int ) st - > op - OP_CALL0 ) )
return true ;
}
else if ( pr_opcodes [ st - > op ] . associative = = ASSOC_RIGHT )
{
if ( ofs = = st - > b )
return false ;
if ( ofs = = st - > a )
return true ;
}
else
{
if ( st - > a = = ofs )
return true ;
if ( st - > b = = ofs )
return true ;
if ( st - > c = = ofs )
return false ;
}
if ( st - > op = = OP_DONE | | st - > op = = OP_RETURN ) //we missed our chance. (return/done ends any code coherancy).
return false ;
}
return false ;
}
int ProductReadLater ( progfuncs_t * progfuncs , progstate_t * progs , int stnum )
{
dstatement16_t * st ;
st = & ( ( dstatement16_t * ) progs - > statements ) [ stnum ] ;
if ( pr_opcodes [ st - > op ] . priority = = - 1 )
{
if ( st - > op > = OP_CALL0 & & st - > op < = OP_CALL7 )
return ImmediateReadLater ( progfuncs , progs , OFS_RETURN , stnum + 1 ) ;
return false ; //these don't have products...
}
if ( pr_opcodes [ st - > op ] . associative = = ASSOC_RIGHT )
return ImmediateReadLater ( progfuncs , progs , st - > b , stnum + 1 ) ;
else
return ImmediateReadLater ( progfuncs , progs , st - > c , stnum + 1 ) ;
}
void WriteStatementProducingOfs ( progfuncs_t * progfuncs , progstate_t * progs , int lastnum , int firstpossible , int ofs ) //recursive, works backwards
{
int i ;
dstatement16_t * st ;
ddef16_t * def ;
if ( ofs = = 0 )
longjmp ( decompilestatementfailure , 1 ) ;
for ( ; lastnum > = firstpossible ; lastnum - - )
{
st = & ( ( dstatement16_t * ) progs - > statements ) [ lastnum ] ;
if ( st - > op > = OP_CALL0 & & st - > op < OP_CALL7 )
{
if ( ofs ! = OFS_RETURN )
continue ;
WriteStatementProducingOfs ( progfuncs , progs , lastnum - 1 , firstpossible , st - > a ) ;
writes ( file , " ( " ) ;
for ( i = 0 ; i < st - > op - OP_CALL0 ; i + + )
{
WriteStatementProducingOfs ( progfuncs , progs , lastnum - 1 , firstpossible , OFS_PARM0 + i * 3 ) ;
if ( i ! = st - > op - OP_CALL0 - 1 )
writes ( file , " , " ) ;
}
writes ( file , " ) " ) ;
return ;
}
else if ( pr_opcodes [ st - > op ] . associative = = ASSOC_RIGHT )
{
if ( st - > b ! = ofs )
continue ;
if ( ! ImmediateReadLater ( progfuncs , progs , st - > b , lastnum + 1 ) )
{
writes ( file , " ( " ) ;
WriteStatementProducingOfs ( progfuncs , progs , lastnum - 1 , firstpossible , st - > b ) ;
writes ( file , " " ) ;
writes ( file , pr_opcodes [ st - > op ] . name ) ;
writes ( file , " " ) ;
WriteStatementProducingOfs ( progfuncs , progs , lastnum - 1 , firstpossible , st - > a ) ;
writes ( file , " ) " ) ;
return ;
}
WriteStatementProducingOfs ( progfuncs , progs , lastnum - 1 , firstpossible , st - > a ) ;
return ;
}
else
{
if ( st - > c ! = ofs )
continue ;
if ( ! ImmediateReadLater ( progfuncs , progs , st - > c , lastnum + 1 ) )
{
WriteStatementProducingOfs ( progfuncs , progs , lastnum - 1 , firstpossible , st - > c ) ;
writes ( file , " = " ) ;
}
writes ( file , " ( " ) ;
WriteStatementProducingOfs ( progfuncs , progs , lastnum - 1 , firstpossible , st - > a ) ;
if ( ! strcmp ( pr_opcodes [ st - > op ] . name , " . " ) )
writes ( file , pr_opcodes [ st - > op ] . name ) ; //extra spaces around .s are ugly.
else
{
writes ( file , " " ) ;
writes ( file , pr_opcodes [ st - > op ] . name ) ;
writes ( file , " " ) ;
}
WriteStatementProducingOfs ( progfuncs , progs , lastnum - 1 , firstpossible , st - > b ) ;
writes ( file , " ) " ) ;
return ;
}
}
def = ED_GlobalAtOfs16 ( progfuncs , ofs ) ;
if ( def )
{
2005-09-08 22:52:46 +00:00
if ( ! strcmp ( def - > s_name + progfuncs - > stringtable , " IMMEDIATE " ) )
2004-08-23 01:38:21 +00:00
writes ( file , " %s " , VarAtOfs ( progfuncs , ofs ) ) ;
else
2005-09-08 22:52:46 +00:00
writes ( file , " %s " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
}
else
writes ( file , " %s " , VarAtOfs ( progfuncs , ofs ) ) ;
// longjmp(decompilestatementfailure, 1);
}
int WriteStatement ( progfuncs_t * progfuncs , progstate_t * progs , int stnum , int firstpossible )
{
int count , skip ;
dstatement16_t * st ;
st = & ( ( dstatement16_t * ) progs - > statements ) [ stnum ] ;
switch ( st - > op )
{
2011-07-08 18:59:48 +00:00
case OP_IFNOT_I :
2004-08-23 01:38:21 +00:00
count = ( signed short ) st - > b ;
writes ( file , " if ( " ) ;
WriteStatementProducingOfs ( progfuncs , progs , stnum , firstpossible , st - > a ) ;
writes ( file , " ) \r \n " ) ;
writes ( file , " { \r \n " ) ;
firstpossible = stnum + 1 ;
count - - ;
stnum + + ;
while ( count )
{
if ( ProductReadLater ( progfuncs , progs , stnum ) )
{
count - - ;
stnum + + ;
continue ;
}
skip = WriteStatement ( progfuncs , progs , stnum , firstpossible ) ;
count - = skip ;
stnum + = skip ;
}
writes ( file , " } \r \n " ) ;
st = & ( ( dstatement16_t * ) progs - > statements ) [ stnum ] ;
if ( st - > op = = OP_GOTO )
{
count = ( signed short ) st - > b ;
count - - ;
stnum + + ;
writes ( file , " else \r \n " ) ;
writes ( file , " { \r \n " ) ;
while ( count )
{
if ( ProductReadLater ( progfuncs , progs , stnum ) )
{
count - - ;
stnum + + ;
continue ;
}
skip = WriteStatement ( progfuncs , progs , stnum , firstpossible ) ;
count - = skip ;
stnum + = skip ;
}
writes ( file , " } \r \n " ) ;
}
break ;
2011-07-08 18:59:48 +00:00
case OP_IF_I :
2004-08-23 01:38:21 +00:00
longjmp ( decompilestatementfailure , 1 ) ;
break ;
case OP_GOTO :
longjmp ( decompilestatementfailure , 1 ) ;
break ;
case OP_RETURN :
case OP_DONE :
if ( st - > a )
WriteStatementProducingOfs ( progfuncs , progs , stnum - 1 , firstpossible , st - > a ) ;
break ;
case OP_CALL0 :
case OP_CALL1 :
case OP_CALL2 :
case OP_CALL3 :
case OP_CALL4 :
case OP_CALL5 :
case OP_CALL6 :
case OP_CALL7 :
WriteStatementProducingOfs ( progfuncs , progs , stnum , firstpossible , OFS_RETURN ) ;
writes ( file , " ; \r \n " ) ;
break ;
default :
if ( pr_opcodes [ st - > op ] . associative = = ASSOC_RIGHT )
WriteStatementProducingOfs ( progfuncs , progs , stnum , firstpossible , st - > b ) ;
else
WriteStatementProducingOfs ( progfuncs , progs , stnum , firstpossible , st - > c ) ;
writes ( file , " ; \r \n " ) ;
break ;
}
return 1 ;
}
void WriteAsmStatements ( progfuncs_t * progfuncs , progstate_t * progs , int num , int f , char * functionname )
{
int stn = progs - > functions [ num ] . first_statement ;
QCC_opcode_t * op ;
dstatement16_t * st = NULL ;
eval_t * v ;
ddef16_t * def ;
int ofs , i ;
int fileofs ;
if ( ! functionname & & stn < 0 )
{
//we wrote this one...
return ;
}
if ( stn > = 0 )
{
for ( stn = progs - > functions [ num ] . first_statement ; stn < ( signed int ) pr_progs - > numstatements ; stn + + )
{
st = & ( ( dstatement16_t * ) progs - > statements ) [ stn ] ;
if ( st - > op = = OP_DONE | | st - > op = = OP_RETURN )
{
if ( ! st - > a )
writes ( f , " void( " ) ;
else if ( ofstype [ st - > a ] )
{
writes ( f , " %s " , ofstype [ st - > a ] - > name ) ;
writes ( f , " ( " ) ;
}
else
writes ( f , " function( " ) ;
break ;
}
}
st = NULL ;
stn = progs - > functions [ num ] . first_statement ;
}
else
writes ( f , " function( " ) ;
for ( ofs = progs - > functions [ num ] . parm_start , i = 0 ; i < progs - > functions [ num ] . numparms ; i + + , ofs + = progs - > functions [ num ] . parm_size [ i ] )
{
ofsflags [ ofs ] | = 4 ;
def = ED_GlobalAtOfs16 ( progfuncs , ofs ) ;
if ( def & & stn > = 0 )
{
if ( st )
writes ( f , " , " ) ;
st = ( void * ) 0xffff ;
2005-09-08 22:52:46 +00:00
if ( ! def - > s_name [ progfuncs - > stringtable ] )
2004-08-23 01:38:21 +00:00
{
char mem [ 64 ] ;
sprintf ( mem , " _p_%i " , def - > ofs ) ;
2005-09-08 22:52:46 +00:00
def - > s_name = ( char * ) malloc ( strlen ( mem ) + 1 ) - progfuncs - > stringtable ;
strcpy ( def - > s_name + progfuncs - > stringtable , mem ) ;
2004-08-23 01:38:21 +00:00
}
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
if ( current_progstate - > types )
writes ( f , " %s %s " , current_progstate - > types [ def - > type & ~ ( DEF_SHARED | DEF_SAVEGLOBAL ) ] . name , def - > s_name ) ;
else
switch ( def - > type & ~ ( DEF_SHARED | DEF_SAVEGLOBAL ) )
{
case ev_string :
2005-09-08 22:52:46 +00:00
writes ( f , " %s %s " , " string " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_float :
2005-09-08 22:52:46 +00:00
writes ( f , " %s %s " , " float " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_entity :
2005-09-08 22:52:46 +00:00
writes ( f , " %s %s " , " entity " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_vector :
2005-09-08 22:52:46 +00:00
writes ( f , " %s %s " , " vector " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
2010-12-08 14:42:05 +00:00
default :
2005-09-08 22:52:46 +00:00
writes ( f , " %s %s " , " randomtype " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
}
}
}
for ( ofs = progs - > functions [ num ] . parm_start + progs - > functions [ num ] . numparms , i = progs - > functions [ num ] . numparms ; i < progs - > functions [ num ] . locals ; i + + , ofs + = 1 )
ofsflags [ ofs ] | = 4 ;
2005-09-08 22:52:46 +00:00
if ( ! progfuncs - > stringtable [ progs - > functions [ num ] . s_name ] )
2004-08-23 01:38:21 +00:00
{
char mem [ 64 ] ;
if ( ! functionname )
{
sprintf ( mem , " _bi_%i " , num ) ;
2005-09-08 22:52:46 +00:00
progs - > functions [ num ] . s_name = ( char * ) malloc ( strlen ( mem ) + 1 ) - progfuncs - > stringtable ;
strcpy ( progs - > functions [ num ] . s_name + progfuncs - > stringtable , mem ) ;
2004-08-23 01:38:21 +00:00
}
else
{
2005-09-08 22:52:46 +00:00
progs - > functions [ num ] . s_name = ( char * ) malloc ( strlen ( functionname ) + 1 ) - progfuncs - > stringtable ;
strcpy ( progs - > functions [ num ] . s_name + progfuncs - > stringtable , functionname ) ;
2004-08-23 01:38:21 +00:00
}
}
2005-09-08 22:52:46 +00:00
writes ( f , " ) %s " , progfuncs - > stringtable + progs - > functions [ num ] . s_name ) ;
2004-08-23 01:38:21 +00:00
if ( stn < 0 )
{
stn * = - 1 ;
writes ( f , " = #%i; \r \n " , stn ) ;
/*
for ( ofs = progs - > functions [ num ] . parm_start , i = 0 ; i < progs - > functions [ num ] . numparms ; i + + , ofs + = progs - > functions [ num ] . parm_size [ i ] )
{
def = ED_GlobalAtOfs16 ( progfuncs , ofs ) ;
if ( def )
{
def - > ofs = 0xffff ;
if ( progs - > types )
{
if ( progs - > types [ def - > type & ~ ( DEF_SHARED | DEF_SAVEGLOBAL ) ] . type = = ev_vector )
{
def = ED_GlobalAtOfs16 ( progfuncs , ofs ) ;
def - > ofs = 0xffff ;
def = ED_GlobalAtOfs16 ( progfuncs , ofs + 1 ) ;
def - > ofs = 0xffff ;
def = ED_GlobalAtOfs16 ( progfuncs , ofs + 2 ) ;
def - > ofs = 0xffff ;
}
}
else if ( ( def - > type & ( ~ ( DEF_SHARED | DEF_SAVEGLOBAL ) ) ) = = ev_vector )
{
def = ED_GlobalAtOfs16 ( progfuncs , ofs ) ;
def - > ofs = 0xffff ;
def = ED_GlobalAtOfs16 ( progfuncs , ofs + 1 ) ;
def - > ofs = 0xffff ;
def = ED_GlobalAtOfs16 ( progfuncs , ofs + 2 ) ;
def - > ofs = 0xffff ;
}
}
}
*/
return ;
}
if ( functionname ) //parsing defs
{
writes ( f , " ; \r \n " ) ;
return ;
}
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
fileofs = SafeSeek ( f , 0 , SEEK_CUR ) ;
if ( setjmp ( decompilestatementfailure ) )
{
writes ( f , " */ \r \n " ) ;
// SafeSeek(f, fileofs, SEEK_SET);
writes ( f , " = asm { \r \n " ) ;
stn = progs - > functions [ num ] . first_statement ;
for ( ofs = progs - > functions [ num ] . parm_start + progs - > functions [ num ] . numparms , i = progs - > functions [ num ] . numparms ; i < progs - > functions [ num ] . locals ; i + + , ofs + = 1 )
{
def = ED_GlobalAtOfs16 ( progfuncs , ofs ) ;
if ( def )
2010-12-08 14:42:05 +00:00
{
2004-08-23 01:38:21 +00:00
v = ( eval_t * ) & ( ( int * ) progs - > globals ) [ def - > ofs ] ;
if ( current_progstate - > types )
writes ( f , " \t local %s %s; \r \n " , current_progstate - > types [ def - > type & ~ ( DEF_SHARED | DEF_SAVEGLOBAL ) ] . name , def - > s_name ) ;
else
{
2005-09-08 22:52:46 +00:00
if ( ! progfuncs - > stringtable [ def - > s_name ] )
2004-08-23 01:38:21 +00:00
{
char mem [ 64 ] ;
sprintf ( mem , " _l_%i " , def - > ofs ) ;
2005-09-08 22:52:46 +00:00
def - > s_name = ( char * ) malloc ( strlen ( mem ) + 1 ) - progfuncs - > stringtable ;
strcpy ( def - > s_name + progfuncs - > stringtable , mem ) ;
2004-08-23 01:38:21 +00:00
}
switch ( def - > type & ~ ( DEF_SHARED | DEF_SAVEGLOBAL ) )
{
case ev_string :
2005-09-08 22:52:46 +00:00
writes ( f , " \t local %s %s; \r \n " , " string " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_float :
2005-09-08 22:52:46 +00:00
writes ( f , " \t local %s %s; \r \n " , " float " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_entity :
2005-09-08 22:52:46 +00:00
writes ( f , " \t local %s %s; \r \n " , " entity " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_vector :
2005-11-29 13:30:20 +00:00
if ( v - > _vector [ 0 ] | | v - > _vector [ 1 ] | | v - > _vector [ 2 ] )
writes ( f , " \t local vector %s = '%f %f %f'; \r \n " , progfuncs - > stringtable + def - > s_name , v - > _vector [ 0 ] , v - > _vector [ 1 ] , v - > _vector [ 2 ] ) ;
2010-12-08 14:42:05 +00:00
else
2005-09-08 22:52:46 +00:00
writes ( f , " \t local %s %s; \r \n " , " vector " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
ofs + = 2 ; //skip floats;
break ;
2010-12-08 14:42:05 +00:00
default :
2005-09-08 22:52:46 +00:00
writes ( f , " \t local %s %s; \r \n " , " randomtype " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
}
}
}
}
while ( 1 )
{
st = & ( ( dstatement16_t * ) progs - > statements ) [ stn ] ;
if ( ! st - > op ) //end of function statement!
break ;
2010-12-08 14:42:05 +00:00
op = & pr_opcodes [ st - > op ] ;
2004-08-23 01:38:21 +00:00
writes ( f , " \t %s " , op - > opname ) ;
if ( op - > priority = = - 1 & & op - > associative = = ASSOC_RIGHT ) //last param is a goto
{
if ( op - > type_b = = & type_void )
{
if ( st - > a )
writes ( f , " %i " , ( signed short ) st - > a ) ;
}
else if ( op - > type_c = = & type_void )
{
if ( st - > a )
writes ( f , " %s " , VarAtOfs ( progfuncs , st - > a ) ) ;
if ( st - > b )
writes ( f , " %i " , ( signed short ) st - > b ) ;
}
else
{
if ( st - > a )
writes ( f , " %s " , VarAtOfs ( progfuncs , st - > a ) ) ;
if ( st - > b )
writes ( f , " %s " , VarAtOfs ( progfuncs , st - > b ) ) ;
if ( st - > c ) //rightness means it uses a as c
writes ( f , " %i " , ( signed short ) st - > c ) ;
}
}
else
{
if ( st - > a )
{
if ( op - > type_a = = NULL )
writes ( f , " %i " , ( signed short ) st - > a ) ;
else
writes ( f , " %s " , VarAtOfs ( progfuncs , st - > a ) ) ;
}
if ( st - > b )
{
if ( op - > type_b = = NULL )
writes ( f , " %i " , ( signed short ) st - > b ) ;
else
writes ( f , " %s " , VarAtOfs ( progfuncs , st - > b ) ) ;
}
if ( st - > c & & op - > associative ! = ASSOC_RIGHT ) //rightness means it uses a as c
{
if ( op - > type_c = = NULL )
writes ( f , " %i " , ( signed short ) st - > c ) ;
else
writes ( f , " %s " , VarAtOfs ( progfuncs , st - > c ) ) ;
}
}
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
writes ( f , " ; \r \n " ) ;
stn + + ;
}
}
else
{
2005-09-08 22:52:46 +00:00
if ( ! strcmp ( progfuncs - > stringtable + progs - > functions [ num ] . s_name , " SUB_Remove " ) )
2004-08-23 01:38:21 +00:00
file = 0 ;
file = f ;
writes ( f , " /* \r \n " ) ;
writes ( f , " = \r \n { \r \n " ) ;
for ( ofs = progs - > functions [ num ] . parm_start + progs - > functions [ num ] . numparms , i = progs - > functions [ num ] . numparms ; i < progs - > functions [ num ] . locals ; i + + , ofs + = 1 )
{
def = ED_GlobalAtOfs16 ( progfuncs , ofs ) ;
if ( def )
2010-12-08 14:42:05 +00:00
{
2004-08-23 01:38:21 +00:00
v = ( eval_t * ) & ( ( int * ) progs - > globals ) [ def - > ofs ] ;
if ( current_progstate - > types )
writes ( f , " \t local %s %s; \r \n " , current_progstate - > types [ def - > type & ~ ( DEF_SHARED | DEF_SAVEGLOBAL ) ] . name , def - > s_name ) ;
else
{
2005-09-08 22:52:46 +00:00
if ( ! def - > s_name [ progfuncs - > stringtable ] )
2004-08-23 01:38:21 +00:00
{
char mem [ 64 ] ;
sprintf ( mem , " _l_%i " , def - > ofs ) ;
2005-09-08 22:52:46 +00:00
def - > s_name = ( char * ) malloc ( strlen ( mem ) + 1 ) - progfuncs - > stringtable ;
strcpy ( def - > s_name + progfuncs - > stringtable , mem ) ;
2004-08-23 01:38:21 +00:00
}
switch ( def - > type & ~ ( DEF_SHARED | DEF_SAVEGLOBAL ) )
{
case ev_string :
2005-09-08 22:52:46 +00:00
writes ( f , " \t local %s %s; \r \n " , " string " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_float :
2005-09-08 22:52:46 +00:00
writes ( f , " \t local %s %s; \r \n " , " float " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_entity :
2005-09-08 22:52:46 +00:00
writes ( f , " \t local %s %s; \r \n " , " entity " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_vector :
2005-11-29 13:30:20 +00:00
if ( v - > _vector [ 0 ] | | v - > _vector [ 1 ] | | v - > _vector [ 2 ] )
2011-07-06 01:01:13 +00:00
writes ( f , " \t local vector %s = '%f %f %f'; \r \n " , progfuncs - > stringtable + def - > s_name , v - > _vector [ 0 ] , v - > _vector [ 1 ] , v - > _vector [ 2 ] ) ;
2010-12-08 14:42:05 +00:00
else
2005-09-08 22:52:46 +00:00
writes ( f , " \t local %s %s; \r \n " , " vector " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
ofs + = 2 ; //skip floats;
break ;
2010-12-08 14:42:05 +00:00
default :
2005-09-08 22:52:46 +00:00
writes ( f , " \t local %s %s; \r \n " , " randomtype " , progfuncs - > stringtable + def - > s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
}
}
}
}
for ( stn = progs - > functions [ num ] . first_statement ; stn < ( signed int ) pr_progs - > numstatements ; stn + + )
{
if ( ProductReadLater ( progfuncs , progs , stn ) )
continue ;
st = & ( ( dstatement16_t * ) progs - > statements ) [ stn ] ;
if ( ! st - > op )
break ;
WriteStatement ( progfuncs , progs , stn , progs - > functions [ num ] . first_statement ) ;
}
longjmp ( decompilestatementfailure , 1 ) ;
}
writes ( f , " }; \r \n " ) ;
}
void FigureOutTypes ( progfuncs_t * progfuncs )
{
ddef16_t * def ;
QCC_opcode_t * op ;
unsigned int i , p ;
dstatement16_t * st ;
int parmofs [ 8 ] ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
ofstype = realloc ( ofstype , sizeof ( * ofstype ) * 65535 ) ;
ofsflags = realloc ( ofsflags , sizeof ( * ofsflags ) * 65535 ) ;
maxtypeinfos = 256 ;
qcc_typeinfo = ( void * ) realloc ( qcc_typeinfo , sizeof ( QCC_type_t ) * maxtypeinfos ) ;
numtypeinfos = 0 ;
memset ( ofstype , 0 , sizeof ( * ofstype ) * 65535 ) ;
memset ( ofsflags , 0 , sizeof ( * ofsflags ) * 65535 ) ;
type_void = QCC_PR_NewType ( " void " , ev_void ) ;
type_string = QCC_PR_NewType ( " string " , ev_string ) ;
type_float = QCC_PR_NewType ( " float " , ev_float ) ;
type_vector = QCC_PR_NewType ( " vector " , ev_vector ) ;
type_entity = QCC_PR_NewType ( " entity " , ev_entity ) ;
2010-12-08 14:42:05 +00:00
type_field = QCC_PR_NewType ( " field " , ev_field ) ;
2004-08-23 01:38:21 +00:00
type_function = QCC_PR_NewType ( " function " , ev_function ) ;
2010-12-08 14:42:05 +00:00
type_pointer = QCC_PR_NewType ( " pointer " , ev_pointer ) ;
2004-08-23 01:38:21 +00:00
type_integer = QCC_PR_NewType ( " integer " , ev_integer ) ;
2005-02-28 07:16:19 +00:00
// type_variant = QCC_PR_NewType("__variant", ev_variant);
2004-08-23 01:38:21 +00:00
type_floatfield = QCC_PR_NewType ( " fieldfloat " , ev_field ) ;
type_floatfield - > aux_type = type_float ;
type_pointer - > aux_type = QCC_PR_NewType ( " pointeraux " , ev_float ) ;
type_function - > aux_type = type_void ;
for ( i = 0 , st = pr_statements16 ; i < pr_progs - > numstatements ; i + + , st + + )
{
op = & pr_opcodes [ st - > op ] ;
if ( st - > op > = OP_CALL1 & & st - > op < = OP_CALL8 )
{
for ( p = 0 ; p < ( unsigned int ) st - > op - OP_CALL0 ; p + + )
{
ofstype [ parmofs [ p ] ] = ofstype [ OFS_PARM0 + p * 3 ] ;
}
}
else if ( op - > associative = = ASSOC_RIGHT )
{ //assignment
ofsflags [ st - > b ] | = 1 ;
if ( st - > b > = OFS_PARM0 & & st - > b < RESERVED_OFS )
parmofs [ ( st - > b - OFS_PARM0 ) / 3 ] = st - > a ;
// 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)
{
if ( op - > type_c & & op - > type_c ! = & type_void )
ofstype [ st - > a ] = * op - > type_c ;
if ( op - > type_b & & op - > type_b ! = & type_void )
ofstype [ st - > b ] = * op - > type_b ;
}
}
else if ( op - > type_c )
{
ofsflags [ st - > c ] | = 2 ;
if ( st - > c > = OFS_PARM0 & & st - > b < RESERVED_OFS ) //too complicated
parmofs [ ( st - > b - OFS_PARM0 ) / 3 ] = 0 ;
// 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)
{
if ( op - > type_a & & op - > type_a ! = & type_void )
ofstype [ st - > a ] = * op - > type_a ;
if ( op - > type_b & & op - > type_b ! = & type_void )
ofstype [ st - > b ] = * op - > type_b ;
if ( op - > type_c & & op - > type_c ! = & type_void )
ofstype [ st - > c ] = * op - > type_c ;
}
}
}
for ( i = 0 ; i < pr_progs - > numglobaldefs ; i + + )
{
def = & pr_globaldefs16 [ i ] ;
ofsflags [ def - > ofs ] | = 8 ;
switch ( def - > type )
{
case ev_float :
ofstype [ def - > ofs ] = type_float ;
break ;
case ev_string :
ofstype [ def - > ofs ] = type_string ;
break ;
case ev_vector :
ofstype [ def - > ofs ] = type_vector ;
break ;
default :
break ;
}
}
}
pbool Decompile ( progfuncs_t * progfuncs , char * fname )
{
extern progfuncs_t * qccprogfuncs ;
unsigned int i ;
unsigned int fld = 0 ;
eval_t * v ;
// char *filename;
int f , type ;
progstate_t progs , * op ;
qccprogfuncs = progfuncs ;
op = current_progstate ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
if ( ! PR_ReallyLoadProgs ( progfuncs , fname , - 1 , & progs , false ) )
{
return false ;
}
f = SafeOpenWrite ( " qcdtest/defs.qc " , 1024 * 512 ) ;
writes ( f , " //Decompiled code can contain little type info. \r \n #define NOWARNINGS \r \n " ) ;
FigureOutTypes ( progfuncs ) ;
for ( i = 1 ; i < progs . progs - > numglobaldefs ; i + + )
{
2005-09-08 22:52:46 +00:00
if ( ! strcmp ( progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name , " IMMEDIATE " ) )
2004-08-23 01:38:21 +00:00
continue ;
if ( ofsflags [ pr_globaldefs16 [ i ] . ofs ] & 4 )
continue ; //this is a local.
if ( current_progstate - > types )
type = progs . types [ pr_globaldefs16 [ i ] . type & ~ ( DEF_SHARED | DEF_SAVEGLOBAL ) ] . type ;
else
type = pr_globaldefs16 [ i ] . type & ~ ( DEF_SHARED | DEF_SAVEGLOBAL ) ;
v = ( eval_t * ) & ( ( int * ) progs . globals ) [ pr_globaldefs16 [ i ] . ofs ] ;
2005-09-08 22:52:46 +00:00
if ( ! progfuncs - > stringtable [ pr_globaldefs16 [ i ] . s_name ] )
2004-08-23 01:38:21 +00:00
{
char mem [ 64 ] ;
if ( ofsflags [ pr_globaldefs16 [ i ] . ofs ] & 3 )
{
ofsflags [ pr_globaldefs16 [ i ] . ofs ] & = ~ 8 ;
continue ; //this is a constant...
}
sprintf ( mem , " _g_%i " , pr_globaldefs16 [ i ] . ofs ) ;
2005-09-08 22:52:46 +00:00
pr_globaldefs16 [ i ] . s_name = ( char * ) malloc ( strlen ( mem ) + 1 ) - progfuncs - > stringtable ;
strcpy ( pr_globaldefs16 [ i ] . s_name + progfuncs - > stringtable , mem ) ;
2004-08-23 01:38:21 +00:00
}
switch ( type )
{
case ev_void :
2005-09-08 22:52:46 +00:00
writes ( f , " void %s; \r \n " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_string :
if ( v - > string & & * ( pr_strings + v - > _int ) )
2005-09-08 22:52:46 +00:00
writes ( f , " string %s = \" %s \" ; \r \n " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name , pr_strings + v - > _int ) ;
2004-08-23 01:38:21 +00:00
else
2011-02-27 15:01:56 +00:00
writes ( f , " string %s; \r \n " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_float :
if ( v - > _float )
2005-09-08 22:52:46 +00:00
writes ( f , " float %s = %f; \r \n " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name , v - > _float ) ;
2004-08-23 01:38:21 +00:00
else
2005-09-08 22:52:46 +00:00
writes ( f , " float %s; \r \n " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_vector :
2005-11-29 13:30:20 +00:00
if ( v - > _vector [ 0 ] | | v - > _vector [ 1 ] | | v - > _vector [ 2 ] )
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 ] ) ;
2004-08-23 01:38:21 +00:00
else
2005-09-08 22:52:46 +00:00
writes ( f , " vector %s; \r \n " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
i + = 3 ; //skip the floats
break ;
case ev_entity :
2005-09-08 22:52:46 +00:00
writes ( f , " entity %s; \r \n " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_field :
//wierd
fld + + ;
2005-09-08 22:52:46 +00:00
if ( ! v - > _int )
writes ( f , " var " ) ;
2004-08-23 01:38:21 +00:00
switch ( pr_fielddefs16 [ fld ] . type )
{
case ev_string :
2005-09-08 22:52:46 +00:00
writes ( f , " .string %s; " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_float :
2005-09-08 22:52:46 +00:00
writes ( f , " .float %s; " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_vector :
2005-09-08 22:52:46 +00:00
writes ( f , " .float %s; " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_entity :
2005-09-08 22:52:46 +00:00
writes ( f , " .float %s; " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_function :
2005-09-08 22:52:46 +00:00
writes ( f , " .void() %s; " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
default :
2005-09-08 22:52:46 +00:00
writes ( f , " field %s; " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
}
2005-09-08 22:52:46 +00:00
if ( v - > _int )
writes ( f , " /* %i */ " , v - > _int ) ;
writes ( f , " \r \n " ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_function :
2010-12-08 14:42:05 +00:00
//wierd
2005-05-15 18:49:04 +00:00
WriteAsmStatements ( progfuncs , & progs , ( ( int * ) progs . globals ) [ pr_globaldefs16 [ i ] . ofs ] , f , pr_globaldefs16 [ i ] . s_name + progfuncs - > stringtable ) ;
2004-08-23 01:38:21 +00:00
break ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
case ev_pointer :
2005-09-08 22:52:46 +00:00
writes ( f , " pointer %s; \r \n " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_integer :
2005-09-08 22:52:46 +00:00
writes ( f , " integer %s; \r \n " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_union :
2005-09-08 22:52:46 +00:00
writes ( f , " union %s; \r \n " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
case ev_struct :
2005-09-08 22:52:46 +00:00
writes ( f , " struct %s; \r \n " , progfuncs - > stringtable + pr_globaldefs16 [ i ] . s_name ) ;
2004-08-23 01:38:21 +00:00
break ;
2010-12-08 14:42:05 +00:00
default :
2004-08-23 01:38:21 +00:00
break ;
2010-12-08 14:42:05 +00:00
2004-08-23 01:38:21 +00:00
}
}
for ( i = 0 ; i < progs . progs - > numfunctions ; i + + )
{
WriteAsmStatements ( progfuncs , & progs , i , f , NULL ) ;
}
SafeClose ( f ) ;
current_progstate = op ;
return true ;
}
# endif
2004-09-20 23:25:38 +00:00
# endif