19 Jul 2008

This commit is contained in:
g-cont 2008-07-19 00:00:00 +04:00 committed by Alibek Omarov
parent 8adcced8b8
commit 9759bb3d12
23 changed files with 1046 additions and 148 deletions

View File

@ -39,7 +39,7 @@ void CL_ScreenshotGetName( int lastnum, char *filename )
if(lastnum < 0 || lastnum > 9999)
{
// bound
com.sprintf( filename, "scrshots/%s/shot9999.dds", cl.configstrings[CS_NAME] );
com.sprintf( filename, "scrshots/%s/shot9999.tga", cl.configstrings[CS_NAME] );
return;
}
@ -51,7 +51,7 @@ void CL_ScreenshotGetName( int lastnum, char *filename )
lastnum -= c * 10;
d = lastnum;
com.sprintf( filename, "scrshots/%s/shot%i%i%i%i.dds", cl.configstrings[CS_NAME], a, b, c, d );
com.sprintf( filename, "scrshots/%s/shot%i%i%i%i.tga", cl.configstrings[CS_NAME], a, b, c, d );
}
/*
@ -96,7 +96,7 @@ void CL_LevelShot_f( void )
char checkname[MAX_OSPATH];
// check for exist
com.sprintf( checkname, "gfx/background/%s.dds", cl.configstrings[CS_NAME] );
com.sprintf( checkname, "gfx/background/%s.tga", cl.configstrings[CS_NAME] );
if(!FS_FileExists( checkname )) re->ScrShot( checkname, true );
else Msg("levelshot for this map already created\nFirst remove old image if you wants do it again\n" );
}

View File

@ -90,4 +90,6 @@ static fields_t cl_reqfields[] =
{16, 2, "flags"}
};
#define PROG_CRC_CLIENT 9488
#endif//CL_EDICT_H

View File

@ -738,6 +738,7 @@ void UI_Init( void )
prog->init_cmd = VM_Cmd_Init;
prog->reset_cmd = VM_Cmd_Reset;
prog->error_cmd = VM_Error;
prog->filecrc = PROG_CRC_UIMENU;
PRVM_LoadProgs( GI->uimenu_prog, 0, NULL, UI_NUM_REQFIELDS, ui_reqfields );
*prog->time = cls.realtime * 0.001f;

View File

@ -609,6 +609,7 @@ void CL_InitClientProgs( void )
prog->free_edict = CL_FreeEdict;
prog->count_edicts = CL_CountEdicts;
prog->load_edict = CL_LoadEdict;
prog->filecrc = PROG_CRC_CLIENT;
// using default builtins
prog->init_cmd = VM_Cmd_Init;

View File

@ -108,4 +108,6 @@ static fields_t ui_reqfields[] =
{93, 2, "find2"}
};
#define PROG_CRC_UIMENU 2460
#endif//UI_EDICT_H

View File

@ -294,4 +294,6 @@ static fields_t sv_reqfields[] =
{264, 1, "oldmodel"}
};
#define PROG_CRC_SERVER 1320
#endif//SV_EDICT_H

View File

@ -2463,7 +2463,8 @@ void SV_InitServerProgs( void )
prog->free_edict = SV_FreeEdict;
prog->count_edicts = SV_CountEdicts;
prog->load_edict = SV_LoadEdict;
prog->filecrc = PROG_CRC_SERVER;
// using default builtins
prog->init_cmd = VM_Cmd_Init;
prog->reset_cmd = VM_Cmd_Reset;

View File

@ -139,19 +139,15 @@ static void Image_BaseColorSearch( byte *blkaddr, byte srccolors[4][4][4], byte
if( nrcolor[0] == 0 ) nrcolor[0] = 1;
if( nrcolor[1] == 0 ) nrcolor[1] = 1;
for( i = 0; i < 3; i++ )
for( j = 0; j < 2; j++ )
{
if((testcolor[0][i] + blockerrlin[0][i] / nrcolor[0]) <= 0)
testcolor[0][i] = 0;
else testcolor[0][i] = (testcolor[0][i] + blockerrlin[0][i] / nrcolor[0]);
}
for( i = 0; i < 3; i++ )
{
if((testcolor[1][i] + blockerrlin[1][i] / nrcolor[1]) >= 255)
testcolor[1][i] = 255;
else testcolor[1][i] = (testcolor[1][i] + blockerrlin[1][i] / nrcolor[1]);
for( i = 0; i < 3; i++ )
{
int newvalue = testcolor[j][i] + blockerrlin[j][i] / nrcolor[j];
if( newvalue <= 0 ) testcolor[j][i] = 0;
else if( newvalue >= 255 ) testcolor[j][i] = 255;
else testcolor[j][i] = newvalue;
}
}
if((abs(testcolor[0][0] - testcolor[1][0]) < 8) && (abs(testcolor[0][1] - testcolor[1][1]) < 4) && (abs(testcolor[0][2] - testcolor[1][2]) < 8))
@ -259,8 +255,12 @@ static void Image_StoreBlock( byte *blkaddr, byte srccolors[4][4][4], byte *best
if( color0 < color1 )
{
tempcolor = color0; color0 = color1; color1 = tempcolor;
colorptr = bestcolor[0]; bestcolor[0] = bestcolor[1]; bestcolor[1] = colorptr;
tempcolor = color0;
color0 = color1;
color1 = tempcolor;
colorptr = bestcolor[0];
bestcolor[0] = bestcolor[1];
bestcolor[1] = colorptr;
}
for( i = 0; i < 3; i++ )
@ -372,7 +372,7 @@ static void Image_StoreBlock( byte *blkaddr, byte srccolors[4][4][4], byte *best
}
}
static void Image_EncodeColorBlock( byte *blkaddr, byte srccolors[4][4][4], int numxpixels, int numypixels, uint type )
static void Image_EncodeColorBlock( byte *blkaddr, byte srccolors[4][4][4], int numxpixels, int numypixels, uint type, int flags )
{
// simplistic approach. We need two base colors, simply use the "highest" and the "lowest" color
// present in the picture as base colors
@ -413,6 +413,13 @@ static void Image_EncodeColorBlock( byte *blkaddr, byte srccolors[4][4][4], int
}
}
if( type != PF_DXT1 )
{
// manually set alpha for DXT3 or DXT5
if( flags & IMAGE_HAS_ALPHA ) haveAlpha = true;
else haveAlpha = false;
}
// make sure the original color values won't get touched...
for( j = 0; j < 2; j++ )
{
@ -431,6 +438,18 @@ static void Image_EncodeColorBlock( byte *blkaddr, byte srccolors[4][4][4], int
Image_StoreBlock( blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha );
}
static void Image_StoreAlphaBlock( byte *blkaddr, byte alphabase1, byte alphabase2, byte alphaenc[16] )
{
*blkaddr++ = alphabase1;
*blkaddr++ = alphabase2;
*blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6);
*blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7);
*blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5);
*blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6);
*blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7);
*blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5);
}
static void Image_EncodeDXT5alpha( byte *blkaddr, byte srccolors[4][4][4], int numxpixels, int numypixels )
{
byte alphabase[2], alphause[2];
@ -486,8 +505,8 @@ static void Image_EncodeDXT5alpha( byte *blkaddr, byte srccolors[4][4][4], int n
// find best encoding for alpha0 > alpha1
// it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true
alphablockerror1 = 0x0;
alphablockerror2 = 0xFFFFFF;
alphablockerror3 = 0xFFFFFF;
alphablockerror2 = 0xffffffff;
alphablockerror3 = 0xffffffff;
if( alphaabsmin ) alphause[0] = 0;
else alphause[0] = alphabase[0];
@ -788,38 +807,10 @@ static void Image_EncodeDXT5alpha( byte *blkaddr, byte srccolors[4][4][4], int n
// write the alpha values and encoding back.
if((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3))
{
*blkaddr++ = alphause[1];
*blkaddr++ = alphause[0];
*blkaddr++ = alphaenc1[0] | (alphaenc1[1] << 3) | ((alphaenc1[2] & 3) << 6);
*blkaddr++ = (alphaenc1[2] >> 2) | (alphaenc1[3] << 1) | (alphaenc1[4] << 4) | ((alphaenc1[5] & 1) << 7);
*blkaddr++ = (alphaenc1[5] >> 1) | (alphaenc1[6] << 2) | (alphaenc1[7] << 5);
*blkaddr++ = alphaenc1[8] | (alphaenc1[9] << 3) | ((alphaenc1[10] & 3) << 6);
*blkaddr++ = (alphaenc1[10] >> 2) | (alphaenc1[11] << 1) | (alphaenc1[12] << 4) | ((alphaenc1[13] & 1) << 7);
*blkaddr++ = (alphaenc1[13] >> 1) | (alphaenc1[14] << 2) | (alphaenc1[15] << 5);
}
Image_StoreAlphaBlock( blkaddr, alphause[1], alphause[0], alphaenc1 );
else if( alphablockerror2 <= alphablockerror3 )
{
*blkaddr++ = alphabase[0];
*blkaddr++ = alphabase[1];
*blkaddr++ = alphaenc2[0] | (alphaenc2[1] << 3) | ((alphaenc2[2] & 3) << 6);
*blkaddr++ = (alphaenc2[2] >> 2) | (alphaenc2[3] << 1) | (alphaenc2[4] << 4) | ((alphaenc2[5] & 1) << 7);
*blkaddr++ = (alphaenc2[5] >> 1) | (alphaenc2[6] << 2) | (alphaenc2[7] << 5);
*blkaddr++ = alphaenc2[8] | (alphaenc2[9] << 3) | ((alphaenc2[10] & 3) << 6);
*blkaddr++ = (alphaenc2[10] >> 2) | (alphaenc2[11] << 1) | (alphaenc2[12] << 4) | ((alphaenc2[13] & 1) << 7);
*blkaddr++ = (alphaenc2[13] >> 1) | (alphaenc2[14] << 2) | (alphaenc2[15] << 5);
}
else
{
*blkaddr++ = alphatest[0];
*blkaddr++ = alphatest[1];
*blkaddr++ = alphaenc3[0] | (alphaenc3[1] << 3) | ((alphaenc3[2] & 3) << 6);
*blkaddr++ = (alphaenc3[2] >> 2) | (alphaenc3[3] << 1) | (alphaenc3[4] << 4) | ((alphaenc3[5] & 1) << 7);
*blkaddr++ = (alphaenc3[5] >> 1) | (alphaenc3[6] << 2) | (alphaenc3[7] << 5);
*blkaddr++ = alphaenc3[8] | (alphaenc3[9] << 3) | ((alphaenc3[10] & 3) << 6);
*blkaddr++ = (alphaenc3[10] >> 2) | (alphaenc3[11] << 1) | (alphaenc3[12] << 4) | ((alphaenc3[13] & 1) << 7);
*blkaddr++ = (alphaenc3[13] >> 1) | (alphaenc3[14] << 2) | (alphaenc3[15] << 5);
}
Image_StoreAlphaBlock( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
else Image_StoreAlphaBlock( blkaddr, (byte)alphatest[0], (byte)alphatest[1], alphaenc3 );
}
static void Image_ExtractColors( byte srcpixels[4][4][4], const byte *srcaddr, int srcRowStride, int numxpixels, int numypixels, int comps )
@ -1509,9 +1500,9 @@ size_t Image_CompressDXT( vfile_t *f, int saveformat, rgbdata_t *pix )
{
byte srcpixels[4][4][4];
int numxpixels, numypixels;
byte *blkaddr, *dest, *flip = NULL;
int i, j, width, height;
const byte *srcaddr;
byte *blkaddr, *dest;
size_t dst_size;
int srccomps;
@ -1528,14 +1519,13 @@ size_t Image_CompressDXT( vfile_t *f, int saveformat, rgbdata_t *pix )
int x, y, c;
byte *in = pix->buffer;
uint line = pix->width * srccomps;
byte *out = Mem_Alloc( zonepool, pix->size ); // alloc src image size
flip = Mem_Alloc( zonepool, pix->size ); // alloc src image size
for( y = pix->height - 1; y >= 0; y-- )
for( x = 0; x < pix->width; x++ )
for( c = 0; c < srccomps; c++, in++)
pix->buffer[y*line+x*srccomps+c] = *in;
//FIXME: Mem_Free( pix->buffer );
pix->buffer = out;
flip[y*line+x*srccomps+c] = *in;
pix->buffer = flip;
}
blkaddr = dest = Mem_Alloc( zonepool, dst_size ); // alloc dst image size
@ -1553,7 +1543,7 @@ size_t Image_CompressDXT( vfile_t *f, int saveformat, rgbdata_t *pix )
if( width > i + 3 ) numxpixels = 4;
else numxpixels = width - i;
Image_ExtractColors( srcpixels, srcaddr, width, numxpixels, numypixels, srccomps );
Image_EncodeColorBlock( blkaddr, srcpixels, numxpixels, numypixels, saveformat );
Image_EncodeColorBlock( blkaddr, srcpixels, numxpixels, numypixels, saveformat, pix->flags );
srcaddr += srccomps * numxpixels;
blkaddr += 8;
}
@ -1579,7 +1569,7 @@ size_t Image_CompressDXT( vfile_t *f, int saveformat, rgbdata_t *pix )
*blkaddr++ = (srcpixels[2][2][3] >> 4) | (srcpixels[2][3][3] & 0xf0);
*blkaddr++ = (srcpixels[3][0][3] >> 4) | (srcpixels[3][1][3] & 0xf0);
*blkaddr++ = (srcpixels[3][2][3] >> 4) | (srcpixels[3][3][3] & 0xf0);
Image_EncodeColorBlock( blkaddr, srcpixels, numxpixels, numypixels, saveformat );
Image_EncodeColorBlock( blkaddr, srcpixels, numxpixels, numypixels, saveformat, pix->flags );
srcaddr += srccomps * numxpixels;
blkaddr += 8;
}
@ -1599,7 +1589,7 @@ size_t Image_CompressDXT( vfile_t *f, int saveformat, rgbdata_t *pix )
Image_ExtractColors( srcpixels, srcaddr, width, numxpixels, numypixels, srccomps );
Image_EncodeDXT5alpha( blkaddr, srcpixels, numxpixels, numypixels );
Image_EncodeColorBlock( blkaddr + 8, srcpixels, numxpixels, numypixels, saveformat );
Image_EncodeColorBlock( blkaddr + 8, srcpixels, numxpixels, numypixels, saveformat, pix->flags );
srcaddr += srccomps * numxpixels;
blkaddr += 16;
}
@ -1612,6 +1602,7 @@ size_t Image_CompressDXT( vfile_t *f, int saveformat, rgbdata_t *pix )
}
dst_size = VFS_Write( f, dest, dst_size );
if( dest ) Mem_Free( dest );
if( flip ) Mem_Free( flip );
return dst_size;
}

View File

@ -1393,9 +1393,9 @@ void FS_CreateGameInfo( const char *filename )
com_strncat(buffer, va("gamemode\t\t\"singleplayer\"\rgamekey\t\t\"%s\"", GI.key), MAX_SYSPATH );
com_strncat(buffer, "\nstartmap\t\t\"newmap\"\n\n", MAX_SYSPATH );
com_strncat(buffer, "// name or each prog (\"\" - ignore to load)", MAX_SYSPATH );
com_strncat(buffer, "\nserver\t\t\"server.dat\"", MAX_SYSPATH );
com_strncat(buffer, "\nclient\t\t\"client.dat\"", MAX_SYSPATH );
com_strncat(buffer, "\nuimenu\t\t\"uimenu.dat\"", MAX_SYSPATH );
com_strncat(buffer, "\nserver\t\t\"vprogs/server.dat\"", MAX_SYSPATH );
com_strncat(buffer, "\nclient\t\t\"vprogs/client.dat\"", MAX_SYSPATH );
com_strncat(buffer, "\nuimenu\t\t\"vrpogs/uimenu.dat\"", MAX_SYSPATH );
FS_WriteFile( filename, buffer, com_strlen(buffer));
Mem_Free( buffer );

View File

@ -309,6 +309,7 @@ enum
PRVM_SERVERPROG = 0,
PRVM_CLIENTPROG,
PRVM_MENUPROG,
PRVM_DECOMPILED,
PRVM_MAXPROGS, // must be last
};
@ -561,6 +562,7 @@ typedef struct prvm_prog_s
ddef_t *fielddefs;
ddef_t *globaldefs;
dstatement_t *statements;
includeddatafile_t *sources; // debug version include packed source files
int *linenums; // debug versions only
type_t *types;
int edict_size; // in bytes

View File

@ -423,6 +423,7 @@ typedef struct vprogs_exp_s
// compiler functions
void ( *PrepareDAT )( const char *dir, const char *name );
void ( *CompileDAT )( void );
bool ( *DecompileDAT )( void );
// edict operations
void (*WriteGlobals)( vfile_t *f );

View File

@ -570,7 +570,7 @@ bool VID_ScreenShot( const char *filename, bool levelshot )
r_shot->width = r_width->integer;
r_shot->height = r_height->integer;
r_shot->type = PF_RGB_24_FLIP;
r_shot->hint = PF_DXT3; // save format
r_shot->hint = PF_RGB_24; // save format
r_shot->size = r_shot->width * r_shot->height * 3;
r_shot->numLayers = 1;
r_shot->numMips = 1;

View File

@ -7,7 +7,9 @@
#include "pal_utils.h"
dll_info_t imglib_dll = { "imglib.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(imglib_exp_t) };
dll_info_t vprogs_dll = { "vprogs.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(vprogs_exp_t) };
imglib_exp_t *Image;
vprogs_exp_t *PRVM;
stdlib_api_t com;
byte *basepool;
byte *zonepool;
@ -112,8 +114,9 @@ so do it manually
*/
void InitConvertor ( uint funcname, int argc, char **argv )
{
launch_t CreateImglib;
launch_t CreateImglib, CreateVprogs;
string source, gamedir;
// init pools
basepool = Mem_AllocPool( "Temp" );
zonepool = Mem_AllocPool( "Zone" );
@ -123,13 +126,34 @@ void InitConvertor ( uint funcname, int argc, char **argv )
CreateImglib = (void *)imglib_dll.main;
Image = CreateImglib( &com, NULL ); // second interface not allowed
FS_InitRootDir(".");
Image->Init( funcname ); // initialize image support
switch( funcname )
{
case RIPP_QCCDEC:
Sys_LoadLibrary( &vprogs_dll ); // load qcclib
CreateVprogs = (void *)vprogs_dll.main;
PRVM = CreateVprogs( &com, NULL ); // second interface not allowed
PRVM->Init( funcname, argc, argv );
if(!FS_GetParmFromCmdLine("-dir", gamedir ))
com.strncpy( gamedir, ".", sizeof(gamedir));
if(!FS_GetParmFromCmdLine("+dat", source ))
com.strncpy( source, "progs.dat", sizeof(source));
start = Sys_DoubleTime();
PRVM->PrepareDAT( gamedir, source );
break;
default:
FS_InitRootDir(".");
Image->Init( funcname ); // initialize image support
break;
}
start = Sys_DoubleTime();
Msg("Converting ...\n\n");
}
void RunConvertor ( void )
void RunConvertor( void )
{
search_t *search;
string errorstring;
@ -183,9 +207,13 @@ void RunConvertor ( void )
AddMask( "*.snd" );
AddMask( "*.mus" );
break;
case RIPP_BSPDEC:
case RIPP_QCCDEC:
Sys_Break(" not implemented\n");
if(PRVM->DecompileDAT())
numConvertedRes++;
break;
case RIPP_BSPDEC:
Sys_Break(" not implemented\n");
break;
case HOST_OFFLINE:
default: return;
}
@ -197,7 +225,7 @@ void RunConvertor ( void )
}
// directory to extract
com.strncpy(gs_gamedir, "tmpQuArK", sizeof(gs_gamedir));
com.strncpy( gs_gamedir, "tmpQuArK", sizeof(gs_gamedir));
// search by mask
for( i = 0; i < num_searchmask; i++)
@ -214,7 +242,7 @@ void RunConvertor ( void )
}
Mem_Free( search );
}
if(numConvertedRes == 0)
if( numConvertedRes == 0 )
{
for(j = 0; j < 16; j++)
{

View File

@ -44,7 +44,7 @@ bool PCX_ConvertImage( const char *name, char *buffer, int filesize )
MsgDev( D_ERROR, "ConvPCX: (%s) have illegal pixel size '%d'\n", name, pcx.bits_per_pixel );
return false;
}
if(pic.width > 640 || pic.height > 640 || pic.width <= 0 || pic.height <= 0)
if(pic.width >= 640 || pic.height >= 480 || pic.width <= 0 || pic.height <= 0)
{
MsgDev( D_ERROR, "ConvPCX: (%s) dimensions out of range [%dx%d]\n", name, pic.width, pic.height );
return false;
@ -89,7 +89,7 @@ bool PCX_ConvertImage( const char *name, char *buffer, int filesize )
for (i = 0; i < s; i++)
{
p = pbuf[i];
if (p == 255)
if( p == 255 )
{
pic.flags |= IMAGE_HAS_ALPHA; // found alpha channel
((byte *)&trans[i])[0] = ((byte *)&d_currentpal[0])[0];

View File

@ -282,6 +282,7 @@ bool ConvLMP( const char *name, char *buffer, int filesize )
pic.buffer = (byte *)Mem_Alloc(zonepool, pic.size );
pic.numLayers = 1;
pic.type = PF_RGBA_32;
pic.hint = PF_RGBA_32;
// half-life 1.0.0.1 lmp version with palette
if( filesize > (int)sizeof(lmp) + pixels )
@ -301,7 +302,7 @@ bool ConvLMP( const char *name, char *buffer, int filesize )
FS_StripExtension((char *)name );
Conv_GetPaletteLMP( pal, LUMP_NORMAL );
Conv_Copy8bitRGBA( fin, pic.buffer, pixels );
Image->SaveImage(va("%s/gfx/%s.tga", gs_gamedir, name ), &pic ); // save converted image
Image->SaveImage(va("%s/%s.tga", gs_gamedir, name ), &pic ); // save converted image
Mem_Free( pic.buffer ); // release buffer
Msg("%s.lmp\n", name ); // echo to console about current image

View File

@ -45,7 +45,7 @@ fopen
NEW RENDERER
1. Доделать поддержку DXT-форматов
1. Доделать поддержку DXT-форматов OK
2. Íîðìàëüíàÿ ëèíêîâêà OpenGL32.dll

794
vprogs/pr_decomp.c Normal file
View File

@ -0,0 +1,794 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// pr_decomp.c - progs decompiler
//=======================================================================
#include "vprogs.h"
#include "mathlib.h"
type_t **ofstype;
byte *ofsflags;
file_t *file;
char *PR_VarAtOfs( int ofs )
{
static char buf[MAX_INPUTLINE];
int typen;
ddef_t *def;
if( ofsflags[ofs] & 8 ) def = PRVM_ED_GlobalAtOfs( ofs );
else def = NULL;
if( !def )
{
if( ofsflags[ofs] & 3 )
{
if( ofstype[ofs] ) com.sprintf( buf, "_v_%s_%i", ofstype[ofs]->name, ofs );
else com.sprintf( buf, "_v_%i", ofs );
}
else
{
if( ofstype[ofs] )
{
typen = ofstype[ofs]->type;
goto evaluate_immediate;
}
else com.sprintf( buf, "_c_%i", ofs );
}
return buf;
}
if(!PRVM_GetString( def->s_name ) || !com.strcmp(PRVM_GetString( def->s_name ), "IMMEDIATE" ))
{
if( vm.prog->types ) typen = vm.prog->types[def->type & ~DEF_SHARED].type;
else typen = def->type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
evaluate_immediate:
switch( typen )
{
case ev_float:
com.sprintf( buf, "%f", PRVM_G_FLOAT(ofs));
return buf;
case ev_vector:
com.sprintf( buf, "\'%f %f %f\'", PRVM_G_FLOAT(ofs+0), PRVM_G_FLOAT(ofs+1), PRVM_G_FLOAT(ofs+2));
return buf;
case ev_string:
{
char *s, *s2;
s = buf;
*s++ = '\"';
s2 = vm.prog->strings + PRVM_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:
com.sprintf( buf, "_c_pointer_%i", ofs );
return buf;
default:
com.sprintf( buf, "_c_%i", ofs );
return buf;
}
}
return (char *)PRVM_GetString( def->s_name );
}
int PR_ImmediateReadLater( uint ofs, int firstst )
{
dstatement_t *st;
if( ofsflags[ofs] & 8 ) return false; // this is a global/local/pramater, not a temp
if(!(ofsflags[ofs] & 3)) return false; // this is a constant.
for( st = &((dstatement_t*)vm.prog->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*((uint)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;
}
// we missed our chance. (return/done ends any code coherancy).
if( st->op == OP_DONE || st->op == OP_RETURN )
return false;
}
return false;
}
int PR_ProductReadLater( int stnum )
{
dstatement_t *st = &((dstatement_t*)vm.prog->statements)[stnum];
if( pr_opcodes[st->op].priority == -1 )
{
if( st->op >= OP_CALL0 && st->op <= OP_CALL7 )
return PR_ImmediateReadLater( OFS_RETURN, stnum + 1 );
return false; // these don't have products...
}
if( pr_opcodes[st->op].associative == ASSOC_RIGHT )
return PR_ImmediateReadLater( st->b, stnum + 1 );
else return PR_ImmediateReadLater( st->c, stnum + 1 );
}
/*
=======================
PR_WriteStatementProducingOfs
recursive, works backwards
=======================
*/
void PR_WriteStatementProducingOfs( int lastnum, int firstpossible, int ofs )
{
dstatement_t *st;
ddef_t *def;
int i;
if( ofs == 0 ) longjmp( pr_parse_abort, 1 );
for( ; lastnum >= firstpossible; lastnum-- )
{
st = &((dstatement_t*)vm.prog->statements)[lastnum];
if( st->op >= OP_CALL0 && st->op < OP_CALL7 )
{
if( ofs != OFS_RETURN ) continue;
PR_WriteStatementProducingOfs( lastnum - 1, firstpossible, st->a );
FS_Printf( file, "(" );
for( i = 0; i < st->op - OP_CALL0; i++ )
{
PR_WriteStatementProducingOfs( lastnum-1, firstpossible, OFS_PARM0 + i*3 );
if( i != st->op - OP_CALL0 - 1 ) FS_Printf( file, ", " );
}
FS_Printf( file, ")" );
return;
}
else if( pr_opcodes[st->op].associative == ASSOC_RIGHT )
{
if( st->b != ofs ) continue;
if(!PR_ImmediateReadLater( st->b, lastnum + 1 ))
{
FS_Printf( file, "(" );
PR_WriteStatementProducingOfs( lastnum - 1, firstpossible, st->b );
FS_Printf( file, " " );
FS_Printf( file, pr_opcodes[st->op].name );
FS_Printf( file, " ");
PR_WriteStatementProducingOfs( lastnum - 1, firstpossible, st->a );
FS_Printf( file, ")" );
return;
}
PR_WriteStatementProducingOfs( lastnum - 1, firstpossible, st->a );
return;
}
else
{
if( st->c != ofs ) continue;
if(!PR_ImmediateReadLater( st->c, lastnum + 1 ))
{
PR_WriteStatementProducingOfs( lastnum - 1, firstpossible, st->c );
FS_Printf( file, " = " );
}
FS_Printf( file, "(" );
PR_WriteStatementProducingOfs( lastnum-1, firstpossible, st->a );
if( !com.strcmp( pr_opcodes[st->op].name, "." ))
FS_Printf( file, pr_opcodes[st->op].name ); // extra spaces around .s are ugly.
else
{
FS_Printf( file, " " );
FS_Printf( file, pr_opcodes[st->op].name);
FS_Printf( file, " " );
}
PR_WriteStatementProducingOfs( lastnum-1, firstpossible, st->b );
FS_Printf( file, ")" );
return;
}
}
def = PRVM_ED_GlobalAtOfs( ofs );
if( def )
{
if(!com.strcmp( PRVM_GetString( def->s_name ), "IMMEDIATE" ))
FS_Printf( file, "%s", PR_VarAtOfs( ofs ));
else FS_Printf( file, "%s", PRVM_GetString( def->s_name ));
}
else FS_Printf( file, "%s", PR_VarAtOfs( ofs ));
}
int PR_WriteStatement( int stnum, int firstpossible )
{
int count, skip;
dstatement_t *st = &((dstatement_t*)vm.prog->statements)[stnum];
switch( st->op )
{
case OP_IFNOT:
count = (signed short)st->b;
FS_Printf(file, "if (");
PR_WriteStatementProducingOfs( stnum, firstpossible, st->a );
FS_Printf( file, ")\r\n" );
FS_Printf( file, "{\r\n" );
firstpossible = stnum + 1;
count--;
stnum++;
while( count )
{
if(PR_ProductReadLater( stnum ))
{
count--;
stnum++;
continue;
}
skip = PR_WriteStatement( stnum, firstpossible );
count -= skip;
stnum += skip;
}
FS_Printf( file, "}\r\n" );
st = &((dstatement_t*)vm.prog->statements)[stnum];
if( st->op == OP_GOTO )
{
count = (signed short)st->b;
count--;
stnum++;
FS_Printf( file, "else\r\n" );
FS_Printf( file, "{\r\n" );
while( count )
{
if( PR_ProductReadLater( stnum ))
{
count--;
stnum++;
continue;
}
skip = PR_WriteStatement( stnum, firstpossible );
count -= skip;
stnum += skip;
}
FS_Printf( file, "}\r\n" );
}
break;
case OP_IF:
longjmp( pr_parse_abort, 1 );
break;
case OP_GOTO:
longjmp( pr_parse_abort, 1 );
break;
case OP_RETURN:
case OP_DONE:
if( st->a ) PR_WriteStatementProducingOfs( 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:
PR_WriteStatementProducingOfs( stnum, firstpossible, OFS_RETURN );
FS_Printf( file, ";\r\n" );
break;
default:
if( pr_opcodes[st->op].associative == ASSOC_RIGHT )
PR_WriteStatementProducingOfs( stnum, firstpossible, st->b );
else PR_WriteStatementProducingOfs( stnum, firstpossible, st->c );
FS_Printf( file, ";\r\n" );
break;
}
return 1;
}
void PR_WriteAsmStatements( file_t *f, int num, const char *functionname )
{
int stn = vm.prog->functions[num].first_statement;
int fileofs, ofs, i;
dstatement_t *st = NULL;
ddef_t *def;
opcode_t *op;
prvm_eval_t *v;
// we wrote this one...
if( !functionname && stn < 0 ) return;
if( stn >= 0 )
{
for( stn = vm.prog->functions[num].first_statement; stn < (signed int)vm.prog->progs->numstatements; stn++ )
{
st = &((dstatement_t*)vm.prog->statements)[stn];
if( st->op == OP_DONE || st->op == OP_RETURN )
{
if( !st->a ) FS_Printf(f, "void(");
else if( ofstype[st->a] )
{
FS_Printf( f, "%s", ofstype[st->a]->name );
FS_Printf( f, "(" );
}
else FS_Printf( f, "function(" );
break;
}
}
st = NULL;
stn = vm.prog->functions[num].first_statement;
}
else FS_Printf( f, "function(" );
for( ofs = vm.prog->functions[num].parm_start, i = 0; i < vm.prog->functions[num].numparms; i++, ofs += vm.prog->functions[num].parm_size[i] )
{
ofsflags[ofs] |= 4;
def = PRVM_ED_GlobalAtOfs( ofs );
if( def && stn >= 0 )
{
if( st ) FS_Printf( f, ", " );
st = (void *)0xffff;
if( !PRVM_GetString( def->s_name ))
{
char mem[64];
com.sprintf( mem, "_p_%i", def->ofs );
def->s_name = PRVM_SetTempString( mem );
}
if( vm.prog->types )
{
FS_Printf( f, "%s %s", vm.prog->types[def->type&~(DEF_SHARED|DEF_SAVEGLOBAL)].name, PRVM_GetString( def->s_name ));
}
else
switch( def->type&~(DEF_SHARED|DEF_SAVEGLOBAL))
{
case ev_string:
FS_Printf( f, "%s %s", "string", PRVM_GetString( def->s_name ));
break;
case ev_float:
FS_Printf(f, "%s %s", "float", PRVM_GetString( def->s_name ));
break;
case ev_entity:
FS_Printf(f, "%s %s", "entity", PRVM_GetString( def->s_name ));
break;
case ev_vector:
FS_Printf(f, "%s %s", "vector", PRVM_GetString( def->s_name ));
break;
default:
FS_Printf(f, "%s %s", "unknown", PRVM_GetString( def->s_name ));
break;
}
}
}
for( ofs = vm.prog->functions[num].parm_start + vm.prog->functions[num].numparms, i = vm.prog->functions[num].numparms; i < vm.prog->functions[num].locals; i++, ofs++ )
ofsflags[ofs] |= 4;
if( !PRVM_GetString( vm.prog->functions[num].s_name ))
{
if( !functionname )
{
char mem[64];
com.sprintf( mem, "_bi_%i", num );
vm.prog->functions[num].s_name = PRVM_SetTempString( mem );
}
else vm.prog->functions[num].s_name = PRVM_SetTempString( functionname );
}
FS_Printf( f, ") %s", PRVM_GetString( vm.prog->functions[num].s_name ));
if( stn < 0 )
{
stn *= -1;
FS_Printf( f, " = #%i;\r\n", stn );
return;
}
if( functionname )
{
// parsing defs
FS_Printf(f, ";\r\n");
return;
}
fileofs = FS_Seek( f, 0, SEEK_CUR );
if( setjmp(pr_parse_abort))
{
FS_Printf( f, "*/\r\n" );
FS_Printf( f, " = asm {\r\n" );
stn = vm.prog->functions[num].first_statement;
for( ofs = vm.prog->functions[num].parm_start + vm.prog->functions[num].numparms, i = vm.prog->functions[num].numparms; i < vm.prog->functions[num].locals; i++, ofs++ )
{
def = PRVM_ED_GlobalAtOfs( ofs );
if( def )
{
v = (prvm_eval_t *)&((int *)vm.prog->globals.gp)[def->ofs];
if( vm.prog->types )
FS_Printf( f, "\tlocal %s %s;\r\n", vm.prog->types[def->type&~(DEF_SHARED|DEF_SAVEGLOBAL)].name, PRVM_GetString( def->s_name ));
else
{
if(!PRVM_GetString( def->s_name ))
{
char mem[64];
com.sprintf( mem, "_l_%i", def->ofs );
def->s_name = PRVM_SetTempString( mem );
}
switch( def->type&~(DEF_SHARED|DEF_SAVEGLOBAL))
{
case ev_string:
FS_Printf( f, "\tlocal %s %s;\r\n", "string", PRVM_GetString( def->s_name ));
break;
case ev_float:
FS_Printf(f, "\tlocal %s %s;\r\n", "float", PRVM_GetString( def->s_name ));
break;
case ev_entity:
FS_Printf(f, "\tlocal %s %s;\r\n", "entity", PRVM_GetString( def->s_name ));
break;
case ev_vector:
if(!VectorIsNull( v->vector ))
FS_Printf( f, "\tlocal vector %s = '%f %f %f';\r\n", PRVM_GetString( def->s_name ), v->vector[0], v->vector[1], v->vector[2] );
else FS_Printf( f, "\tlocal %s %s;\r\n", "vector", PRVM_GetString( def->s_name ));
ofs += 2; // skip floats;
break;
default:
FS_Printf( f, "\tlocal %s %s;\r\n", "unknown", PRVM_GetString( def->s_name ));
break;
}
}
}
}
while( 1 )
{
st = &((dstatement_t*)vm.prog->statements)[stn];
if( !st->op ) break; // end of function statement!
op = &pr_opcodes[st->op];
FS_Printf( 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 ) FS_Printf( f, " %i", (signed short)st->a );
}
else if( op->type_c == &type_void )
{
if( st->a ) FS_Printf( f, " %s", PR_VarAtOfs(st->a));
if( st->b ) FS_Printf( f, " %i", (signed short)st->b );
}
else
{
if( st->a ) FS_Printf( f, " %s", PR_VarAtOfs(st->a));
if( st->b ) FS_Printf( f, " %s", PR_VarAtOfs(st->b));
if( st->c ) FS_Printf( f, " %i", (signed short)st->c ); // rightness means it uses a as c
}
}
else
{
if( st->a )
{
if( op->type_a == NULL ) FS_Printf( f, " %i", (signed short)st->a );
else FS_Printf(f, " %s", PR_VarAtOfs(st->a));
}
if( st->b )
{
if( op->type_b == NULL ) FS_Printf( f, " %i", (signed short)st->b );
else FS_Printf( f, " %s", PR_VarAtOfs(st->b));
}
if( st->c && op->associative != ASSOC_RIGHT )
{
// rightness means it uses a as c
if( op->type_c == NULL ) FS_Printf( f, " %i", (signed short)st->c );
else FS_Printf( f, " %s", PR_VarAtOfs(st->c));
}
}
FS_Printf( f, ";\r\n" );
stn++;
}
}
else
{
if( !com.strcmp(PRVM_GetString( vm.prog->functions[num].s_name ), "SUB_Remove" ))
file = NULL;
file = f;
FS_Printf( f, "/*\r\n" );
FS_Printf( f, " =\r\n{\r\n" );
for( ofs = vm.prog->functions[num].parm_start + vm.prog->functions[num].numparms, i = vm.prog->functions[num].numparms; i < vm.prog->functions[num].locals; i++, ofs++ )
{
def = PRVM_ED_GlobalAtOfs( ofs );
if( def )
{
v = (prvm_eval_t *)&((int *)vm.prog->globals.gp)[def->ofs];
if( vm.prog->types) FS_Printf( f, "\tlocal %s %s;\r\n", vm.prog->types[def->type&~(DEF_SHARED|DEF_SAVEGLOBAL)].name, PRVM_GetString( def->s_name ));
else
{
if(!PRVM_GetString( def->s_name ))
{
char mem[64];
com.sprintf( mem, "_l_%i", def->ofs );
def->s_name = PRVM_SetTempString( mem );
}
switch( def->type&~(DEF_SHARED|DEF_SAVEGLOBAL))
{
case ev_string:
FS_Printf( f, "\tlocal %s %s;\r\n", "string", PRVM_GetString( def->s_name ));
break;
case ev_float:
FS_Printf( f, "\tlocal %s %s;\r\n", "float", PRVM_GetString( def->s_name ));
break;
case ev_entity:
FS_Printf( f, "\tlocal %s %s;\r\n", "entity", PRVM_GetString( def->s_name ));
break;
case ev_vector:
if(!VectorIsNull( v->vector ))
FS_Printf( f, "\tlocal vector %s = '%f %f %f';\r\n", PRVM_GetString( def->s_name ), v->vector[0], v->vector[1], v->vector[2] );
else FS_Printf( f, "\tlocal %s %s;\r\n", "vector", PRVM_GetString( def->s_name ));
ofs += 2; // skip floats;
break;
default:
FS_Printf( f, "\tlocal %s %s;\r\n", "unknown", PRVM_GetString( def->s_name ));
break;
}
}
}
}
for( stn = vm.prog->functions[num].first_statement; stn < (signed int)vm.prog->progs->numstatements; stn++ )
{
if( PR_ProductReadLater( stn )) continue;
st = &((dstatement_t*)vm.prog->statements)[stn];
if( !st->op ) break;
PR_WriteStatement( stn, vm.prog->functions[num].first_statement );
}
longjmp( pr_parse_abort, 1 );
}
FS_Printf( f, "};\r\n" );
}
void PR_FigureOutTypes( void )
{
ddef_t *def;
opcode_t *op;
uint i, p;
dstatement_t *st;
int parmofs[MAX_PARMS];
ofstype = Qalloc(sizeof(*ofstype ) * 65535);
ofsflags = Qalloc(sizeof(*ofsflags) * 65535);
maxtypeinfos = 256;
qcc_typeinfo = (void *)Qalloc( sizeof(type_t) * maxtypeinfos );
numtypeinfos = 0;
memset( ofstype, 0, sizeof(*ofstype)*65535);
memset( ofsflags, 0, sizeof(*ofsflags)*65535);
type_void = PR_NewType( "void", ev_void );
type_string = PR_NewType( "string", ev_string );
type_float = PR_NewType( "float", ev_float );
type_vector = PR_NewType( "vector", ev_vector );
type_entity = PR_NewType( "entity", ev_entity );
type_field = PR_NewType( "field", ev_field );
type_function = PR_NewType( "function", ev_function );
type_pointer = PR_NewType( "pointer", ev_pointer );
type_integer = PR_NewType( "integer", ev_integer );
type_floatfield = PR_NewType("fieldfloat", ev_field);
type_floatfield->aux_type = type_float;
type_pointer->aux_type = PR_NewType( "pointeraux", ev_float );
type_function->aux_type = type_void;
for( i = 0, st = vm.prog->statements; i < vm.prog->progs->numstatements; i++, st++ )
{
op = &pr_opcodes[st->op];
if( st->op >= OP_CALL1 && st->op <= OP_CALL8 )
{
for( p = 0; p < (uint)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( 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( 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 < vm.prog->progs->numglobaldefs; i++ )
{
def = &vm.prog->globaldefs[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;
}
}
}
bool PR_Decompile( void )
{
uint i, fld = 0;
int type;
prvm_eval_t *v;
file_t *f;
if(!FS_FileExists( sourcefilename ))
return false;
PRVM_LoadProgs( sourcefilename, 0, NULL, 0, NULL );
f = FS_Open( "qcdtest/defs.qc", "w" );
FS_Print( f, "// decompiled code can contain little type info.\r\n" );
PR_FigureOutTypes();
for( i = 1; i < vm.prog->progs->numglobaldefs; i++ )
{
if( !com.strcmp(PRVM_GetString( vm.prog->globaldefs[i].s_name ), "IMMEDIATE" ))
continue;
if( ofsflags[vm.prog->globaldefs[i].ofs] & 4 )
continue; // this is a local.
if( vm.prog->types )
type = vm.prog->types[vm.prog->globaldefs[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL)].type;
else type = vm.prog->globaldefs[i].type & ~(DEF_SHARED|DEF_SAVEGLOBAL);
v = (prvm_eval_t *)&((int *)vm.prog->globals.gp)[vm.prog->globaldefs[i].ofs];
if(!PRVM_GetString( vm.prog->globaldefs[i].s_name ))
{
char mem[64];
if( ofsflags[vm.prog->globaldefs[i].ofs] & 3 )
{
ofsflags[vm.prog->globaldefs[i].ofs] &= ~8;
continue; // this is a constant...
}
com.sprintf( mem, "_g_%i", vm.prog->globaldefs[i].ofs );
vm.prog->globaldefs[i].s_name = PRVM_SetTempString( mem );
}
switch( type )
{
case ev_void:
FS_Printf( f, "void %s;\r\n", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_string:
if( v->string && *(vm.prog->strings + v->_int ))
FS_Printf( f, "string %s = \"%s\";\r\n", PRVM_GetString(vm.prog->globaldefs[i].s_name ), PRVM_GetString( v->_int ));
else FS_Printf( f, "string %s;\r\n", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_float:
if( v->_float ) FS_Printf( f, "float %s = %f;\r\n", PRVM_GetString( vm.prog->globaldefs[i].s_name ), v->_float);
else FS_Printf( f, "float %s;\r\n", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_vector:
if(!VectorIsNull( v->vector ))
FS_Printf( f, "vector %s = '%f %f %f';\r\n", PRVM_GetString(vm.prog->globaldefs[i].s_name ), v->vector[0], v->vector[1], v->vector[2]);
else FS_Printf( f, "vector %s;\r\n", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
i += 3; // skip the floats
break;
case ev_entity:
FS_Printf( f, "entity %s;\r\n", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_field:
fld++; // wierd
if( !v->_int ) FS_Printf( f, "var " );
switch( vm.prog->fielddefs[fld].type )
{
case ev_string:
FS_Printf(f, ".string %s;", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_float:
FS_Printf(f, ".float %s;", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_vector:
FS_Printf(f, ".float %s;", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_entity:
FS_Printf(f, ".float %s;", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_function:
FS_Printf(f, ".void() %s;", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
default:
FS_Printf(f, "field %s;", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
}
if( v->_int ) FS_Printf( f, "/* %i */", v->_int );
FS_Printf( f, "\r\n" );
break;
case ev_function:
// wierd
PR_WriteAsmStatements( f, ((int *)vm.prog->globals.gp)[vm.prog->globaldefs[i].ofs], PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_pointer:
FS_Printf( f, "pointer %s;\r\n", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_integer:
FS_Printf( f, "integer %s;\r\n", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_union:
FS_Printf(f, "union %s;\r\n", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
case ev_struct:
FS_Printf(f, "struct %s;\r\n", PRVM_GetString(vm.prog->globaldefs[i].s_name ));
break;
default: break;
}
}
for( i = 0; i < vm.prog->progs->numfunctions; i++ )
{
PR_WriteAsmStatements( f, i, NULL );
}
FS_Close( f );
return true;
}

View File

@ -259,15 +259,15 @@ void PRVM_ED_Free (edict_t *ed)
PRVM_ED_GlobalAtOfs
============
*/
ddef_t *PRVM_ED_GlobalAtOfs (int ofs)
ddef_t *PRVM_ED_GlobalAtOfs( int ofs )
{
ddef_t *def;
int i;
for (i=0 ; i<vm.prog->progs->numglobaldefs ; i++)
for( i = 0; i < vm.prog->progs->numglobaldefs; i++ )
{
def = &vm.prog->globaldefs[i];
if (def->ofs == ofs)
if( def->ofs == ofs )
return def;
}
return NULL;
@ -1244,7 +1244,7 @@ void PRVM_LoadLNO( const char *progname )
PRVM_LoadProgs
===============
*/
void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int numedfields, fields_t *ed_field)
void PRVM_LoadProgs( const char *filename, int numedfunc, char **ed_func, int numedfields, fields_t *ed_field )
{
dstatement_t *st;
ddef_t *infielddefs;
@ -1259,16 +1259,13 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
}
if( vm.prog->progs ) Mem_Free( vm.prog->progs ); // release progs file
vm.prog->progs = (dprograms_t *)FS_LoadFile(va("vprogs/%s", filename ), &filesize);
vm.prog->progs = (dprograms_t *)FS_LoadFile(va("%s", filename ), &filesize);
if (vm.prog->progs == NULL || filesize < (fs_offset_t)sizeof(dprograms_t))
PRVM_ERROR("PRVM_LoadProgs: couldn't load %s for %s\n", filename, PRVM_NAME);
MsgDev(D_INFO, "%s programs occupy %iK.\n", PRVM_NAME, filesize/1024);
vm.prog->filecrc = CRC_Block((byte *)vm.prog->progs, filesize);
// byte swap the header
SwapBlock((int *)vm.prog->progs, sizeof(*vm.prog->progs));
SwapBlock((int *)vm.prog->progs, sizeof(*vm.prog->progs)); // byte swap the header
switch( vm.prog->progs->version )
{
@ -1276,29 +1273,27 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
vm.prog->intsize = 16;
break;
case FPROGS_VERSION:
if(vm.prog->progs->ident == VPROGSHEADER16)
if( vm.prog->progs->ident == VPROGSHEADER16 )
vm.prog->intsize = 16;
if(vm.prog->progs->ident == VPROGSHEADER32)
if( vm.prog->progs->ident == VPROGSHEADER32 )
vm.prog->intsize = 32;
break;
case VPROGS_VERSION:
default:
PRVM_ERROR ("%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, vm.prog->progs->version, VPROGS_VERSION);
PRVM_ERROR( "%s: %s has wrong version number (%i should be %i)", PRVM_NAME, filename, vm.prog->progs->version, VPROGS_VERSION);
break;
}
// try to recognize progs.dat by crc
switch(vm.prog->progs->crc)
if( PRVM_GetProgNr() == PRVM_DECOMPILED )
{
case PROG_CRC_SERVER:
case PROG_CRC_CLIENT:
case PROG_CRC_UIMENU:
break;
default:
PRVM_ERROR("%s: %s system vars have been modified, progdefs.h is out of date", PRVM_NAME, filename);
break;
MsgDev(D_INFO, "Prepare %s [CRC %d]\n", filename, vm.prog->progs->crc );
}
MsgDev(D_INFO, "Loading %s [CRC %d]\n", filename, vm.prog->progs->crc );
else if( vm.prog->progs->crc != vm.prog->filecrc )
{
PRVM_ERROR("%s: %s system vars have been modified, progdefs.h is out of date %d\n", PRVM_NAME, filename );
}
else MsgDev(D_INFO, "Loading %s [CRC %d]\n", filename, vm.prog->progs->crc );
// set initial pointers
vm.prog->statements = (dstatement_t *)((byte *)vm.prog->progs + vm.prog->progs->ofs_statements);
@ -1308,12 +1303,19 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
vm.prog->strings = (char *)vm.prog->progs + vm.prog->progs->ofs_strings;
vm.prog->globals.gp = (float *)((byte *)vm.prog->progs + vm.prog->progs->ofs_globals);
// debug info
if(vm.prog->progs->ofslinenums) vm.prog->linenums = (int *)((byte *)vm.prog->progs + vm.prog->progs->ofslinenums);
if(vm.prog->progs->ofs_types) vm.prog->types = (type_t *)((byte *)vm.prog->progs + vm.prog->progs->ofs_types);
if( vm.prog->progs->version >= FPROGS_VERSION )
{
// debug info
if( vm.prog->progs->ofsfiles )
vm.prog->sources = (includeddatafile_t*)((byte *)vm.prog->progs + vm.prog->progs->ofsfiles);
if( vm.prog->progs->ofslinenums )
vm.prog->linenums = (int *)((byte *)vm.prog->progs + vm.prog->progs->ofslinenums);
if( vm.prog->progs->ofs_types )
vm.prog->types = (type_t *)((byte *)vm.prog->progs + vm.prog->progs->ofs_types);
}
// decompress progs if needed
if (vm.prog->progs->blockscompressed & COMP_STATEMENTS)
if( vm.prog->progs->blockscompressed & COMP_STATEMENTS )
{
switch(vm.prog->intsize)
{
@ -1334,7 +1336,7 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
filesize += len - complen - sizeof(int); //merge filesize
}
if (vm.prog->progs->blockscompressed & COMP_DEFS)
if( vm.prog->progs->blockscompressed & COMP_DEFS )
{
switch(vm.prog->intsize)
{
@ -1355,7 +1357,7 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
filesize += len - complen - sizeof(int); //merge filesize
}
if (vm.prog->progs->blockscompressed & COMP_FIELDS)
if( vm.prog->progs->blockscompressed & COMP_FIELDS )
{
switch(vm.prog->intsize)
{
@ -1376,7 +1378,7 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
filesize += len - complen - sizeof(int); //merge filesize
}
if (vm.prog->progs->blockscompressed & COMP_FUNCTIONS)
if( vm.prog->progs->blockscompressed & COMP_FUNCTIONS )
{
len = sizeof(dfunction_t) * vm.prog->progs->numfunctions;
complen = LittleLong(*(int*)dfunctions);
@ -1388,7 +1390,7 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
filesize += len - complen - sizeof(int); //merge filesize
}
if (vm.prog->progs->blockscompressed & COMP_STRINGS)
if( vm.prog->progs->blockscompressed & COMP_STRINGS )
{
len = sizeof(char) * vm.prog->progs->numstrings;
complen = LittleLong(*(int*)vm.prog->strings);
@ -1402,7 +1404,7 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
filesize += len - complen - sizeof(int); //merge filesize
}
if (vm.prog->progs->blockscompressed & COMP_GLOBALS)
if( vm.prog->progs->blockscompressed & COMP_GLOBALS )
{
len = sizeof(float) * vm.prog->progs->numglobals;
complen = LittleLong(*(int*)vm.prog->globals.gp);
@ -1414,7 +1416,19 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
filesize += len - complen - sizeof(int); //merge filesize
}
if (vm.prog->linenums && vm.prog->progs->blockscompressed & COMP_LINENUMS)
if( vm.prog->sources ) // source always are packed
{
int i, numsources = LittleLong(*(int*)vm.prog->sources);
includeddatafile_t *src = (includeddatafile_t *)(((int *)vm.prog->sources)+1);
for( i = 0; i < numsources; i++, src++ )
{
Msg("Source: %s\n", src->filename );
Msg("Ofs, size: %d, %d\n", src->ofs, src->size );
}
}
if( vm.prog->linenums && vm.prog->progs->blockscompressed & COMP_LINENUMS )
{
len = sizeof(int) * vm.prog->progs->numstatements;
complen = LittleLong(*(int*)vm.prog->linenums);
@ -1426,7 +1440,7 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
filesize += len - complen - sizeof(int); //merge filesize
}
if (vm.prog->types && vm.prog->progs->blockscompressed & COMP_TYPES)
if( vm.prog->types && vm.prog->progs->blockscompressed & COMP_TYPES )
{
len = sizeof(type_t) * vm.prog->progs->numtypes;
complen = LittleLong(*(int*)vm.prog->types);
@ -1440,9 +1454,9 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
vm.prog->stringssize = 0;
for (i = 0; vm.prog->stringssize < vm.prog->progs->numstrings; i++)
for( i = 0; vm.prog->stringssize < vm.prog->progs->numstrings; i++ )
{
if (vm.prog->progs->ofs_strings + vm.prog->stringssize >= (int)filesize)
if( vm.prog->progs->ofs_strings + vm.prog->stringssize >= (int)filesize )
PRVM_ERROR ("%s: %s strings go past end of file", PRVM_NAME, filename);
vm.prog->stringssize += (int)com.strlen(vm.prog->strings + vm.prog->stringssize) + 1;
}
@ -1495,16 +1509,16 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
}
// append the ed fields
for (i = 0; i < (int)numedfields; i++)
for( i = 0; i < (int)numedfields; i++ )
{
vm.prog->fielddefs[vm.prog->progs->numfielddefs].type = ed_field[i].type;
vm.prog->fielddefs[vm.prog->progs->numfielddefs].ofs = ed_field[i].ofs;
vm.prog->fielddefs[vm.prog->progs->numfielddefs].s_name = PRVM_SetEngineString(ed_field[i].name);
vm.prog->fielddefs[vm.prog->progs->numfielddefs].s_name = PRVM_SetEngineString( ed_field[i].name );
}
// check ed functions
for(i=0 ; i < numedfunc ; i++)
if(PRVM_ED_FindFunction(ed_func[i]) == 0)
for( i = 0; i < numedfunc; i++ )
if( PRVM_ED_FindFunction( ed_func[i] ) == 0 )
PRVM_ERROR("%s: %s not found in %s",PRVM_NAME, ed_func[i], filename);
for (i=0 ; i<vm.prog->progs->numglobals ; i++)
@ -1669,7 +1683,7 @@ void PRVM_LoadProgs (const char *filename, int numedfunc, char **ed_func, int nu
// set flags & ddef_ts in prog
vm.prog->flag = 0;
vm.prog->pev = PRVM_ED_FindGlobal("pev"); // critical stuff
vm.prog->pev = PRVM_ED_FindGlobal( "pev" ); // critical stuff
if( PRVM_ED_FindGlobal("time") && PRVM_ED_FindGlobal("time")->type & ev_float )
vm.prog->time = &PRVM_G_FLOAT(PRVM_ED_FindGlobal("time")->ofs);

View File

@ -563,6 +563,13 @@ extern int numtypeinfos;
extern int maxtypeinfos;
extern int numtemps;
//
// pr_main.c
//
void PR_InitCompile( const char *name );
void PR_InitDecompile( const char *name );
bool PRVM_DecompileProgs( void );
//
// pr_utils.c
//
@ -660,4 +667,9 @@ void PR_BeginCompilation ( void );
bool PR_ContinueCompile ( void );
void PR_FinishCompilation ( void );
//
// pr_decomp.c
//
bool PR_Decompile( void );
#endif//PR_LOCAL_H

View File

@ -35,18 +35,19 @@ int *statement_linenums;
char sourcedir[MAX_SYSPATH];
cachedsourcefile_t *sourcefile;
dfunction_t *functions;
int numfunctions;
ddef_t *qcc_globals;
int numglobaldefs;
ddef_t *fields;
int numfielddefs;
bool pr_warning[WARN_MAX];
int target_version;
bool bodylessfuncs;
type_t *qcc_typeinfo;
int numtypeinfos;
int maxtypeinfos;
int prvm_developer;
int numfunctions;
ddef_t *qcc_globals;
int numglobaldefs;
ddef_t *fields;
int numfielddefs;
bool pr_warning[WARN_MAX];
int target_version;
bool bodylessfuncs;
type_t *qcc_typeinfo;
int numtypeinfos;
int maxtypeinfos;
int prvm_developer;
int host_instance;
vprogs_exp_t vm;
hashtable_t compconstantstable;
@ -61,7 +62,7 @@ cvar_t *prvm_traceqc;
cvar_t *prvm_boundscheck;
cvar_t *prvm_statementprofiling;
void PR_SetDefaultProperties (void)
void PR_SetDefaultProperties( void )
{
const_t *cnst;
int i, j;
@ -158,7 +159,7 @@ PR_Init
initialize compiler and hash tables
===================
*/
void PR_Init( const char *name )
void PR_InitCompile( const char *name )
{
static char parmname[12][MAX_PARMS];
static temp_t ret_temp;
@ -245,6 +246,28 @@ void PR_Init( const char *name )
}
}
void PR_InitDecompile( const char *name )
{
string progsname;
com.strncpy( sourcefilename, name, sizeof(sourcefilename));
FS_FileBase( name, progsname );
PRVM_InitProg( PRVM_DECOMPILED );
vm.prog->reserved_edicts = 1;
vm.prog->loadintoworld = true;
vm.prog->name = copystring( progsname );
vm.prog->builtins = NULL;
vm.prog->numbuiltins = 0;
vm.prog->max_edicts = 4096;
vm.prog->limit_edicts = 4096;
vm.prog->edictprivate_size = sizeof(vm_edict_t);
vm.prog->error_cmd = VM_Error;
vm.prog->flag |= PRVM_OP_STATE; // enable op_state feature
vm.prog->progs_mempool = qccpool;
}
void PRVM_Init( uint funcname, int argc, char **argv )
{
char dev_level[4];
@ -253,6 +276,7 @@ void PRVM_Init( uint funcname, int argc, char **argv )
com_argv = argv;
qccpool = Mem_AllocPool( "VM progs" );
host_instance = funcname;
if(FS_GetParmFromCmdLine("-dev", dev_level ))
prvm_developer = com.atoi(dev_level);
@ -274,7 +298,7 @@ void PRVM_Init( uint funcname, int argc, char **argv )
prvm_statementprofiling = Cvar_Get ("prvm_statementprofiling", "0", 0, "counts how many times each QC statement has been executed" );
prvm_maxedicts = Cvar_Get( "prvm_maxedicts", "4096", CVAR_SYSTEMINFO, "user limit edicts number fof server, client and renderer, absolute limit 65535" );
if( funcname == HOST_NORMAL || funcname == HOST_DEDICATED )
if( host_instance == HOST_NORMAL || host_instance == HOST_DEDICATED )
{
// dump internal copies of progs into hdd if missing
if(!FS_FileExists("vprogs/server.dat")) FS_WriteFile( "vprogs/server.dat", server_dat, sizeof(server_dat));
@ -290,8 +314,24 @@ void PRVM_Shutdown( void )
void PRVM_PrepareProgs( const char *dir, const char *name )
{
FS_InitRootDir((char *)dir);
PR_Init( name );
switch( host_instance )
{
case COMP_QCCLIB:
FS_InitRootDir((char *)dir);
PR_InitCompile( name );
break;
case RIPP_QCCDEC:
FS_InitRootDir((char *)dir);
PR_InitDecompile( name );
break;
case HOST_NORMAL:
case HOST_DEDICATED:
PR_InitCompile( name );
break;
default:
Sys_Break("PRVM_PrepareProgs: can't prepare progs for instance %d\n", host_instance );
break;
}
}
void PRVM_CompileProgs( void )
@ -301,6 +341,11 @@ void PRVM_CompileProgs( void )
PR_FinishCompilation();
}
bool PRVM_DecompileProgs( void )
{
return PR_Decompile();
}
vprogs_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, void *unused )
{
com = *input;
@ -312,6 +357,7 @@ vprogs_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, void *unused )
vm.Free = PRVM_Shutdown;
vm.PrepareDAT = PRVM_PrepareProgs;
vm.CompileDAT = PRVM_CompileProgs;
vm.DecompileDAT = PRVM_DecompileProgs;
vm.WriteGlobals = PRVM_ED_WriteGlobals;
vm.ParseGlobals = PRVM_ED_ParseGlobals;

View File

@ -294,11 +294,11 @@ int PR_WriteSourceFiles(file_t *h, dprograms_t *progs, bool sourceaswell)
if (!num) return 0;
idf = Qalloc(sizeof(includeddatafile_t) * num);
for (f = sourcefile, num = 0; f; f = f->next)
for( f = sourcefile, num = 0; f; f = f->next )
{
if (f->type == FT_CODE && !sourceaswell)
if( f->type == FT_CODE && !sourceaswell )
continue;
com.strcpy(idf[num].filename, f->filename);
com.strcpy( idf[num].filename, f->filename );
idf[num].size = f->size;
idf[num].compmethod = CMPW_DEFLATE;
idf[num].ofs = FS_Tell(h);
@ -306,8 +306,8 @@ int PR_WriteSourceFiles(file_t *h, dprograms_t *progs, bool sourceaswell)
num++;
}
ofs = FS_Tell(h);
FS_Write(h, &num, sizeof(int));
FS_Write(h, idf, sizeof(includeddatafile_t)*num);
FS_Write( h, &num, sizeof(int));
FS_Write( h, idf, sizeof(includeddatafile_t) * num );
sourcefile = NULL;
return ofs;
@ -538,15 +538,15 @@ word PR_WriteProgdefs (char *filename)
PR_Message("Quake1 unmodified progs.dat\n");
if(!com.strcmp(progsoutname, "unknown.dat")) com.strcpy(progsoutname, "progs.dat");
break;
case PROG_CRC_SERVER:
case 1320:
PR_Message("Xash3D unmodified server.dat\n");
if(!com.strcmp(progsoutname, "unknown.dat")) com.strcpy(progsoutname, "server.dat");
break;
case PROG_CRC_CLIENT:
case 9488:
PR_Message("Xash3D unmodified client.dat\n");
if(!com.strcmp(progsoutname, "unknown.dat")) com.strcpy(progsoutname, "client.dat");
break;
case PROG_CRC_UIMENU:
case 2460:
PR_Message("Xash3D unmodified uimenu.dat\n");
if(!com.strcmp(progsoutname, "unknown.dat")) com.strcpy(progsoutname, "uimenu.dat");
break;

View File

@ -117,6 +117,10 @@ SOURCE=.\pr_comp.c
# End Source File
# Begin Source File
SOURCE=.\pr_decomp.c
# End Source File
# Begin Source File
SOURCE=.\pr_edict.c
# End Source File
# Begin Source File

View File

@ -23,10 +23,6 @@ extern int prvm_developer;
#define Host_Error com.error
#define PROG_CRC_SERVER 1320
#define PROG_CRC_CLIENT 9488
#define PROG_CRC_UIMENU 2460
enum op_state
{
OP_DONE, // 0
@ -357,7 +353,7 @@ void PRVM_MEM_IncreaseEdicts(void);
edict_t *PRVM_ED_Alloc (void);
void PRVM_ED_Free (edict_t *ed);
void PRVM_ED_ClearEdict (edict_t *e);
ddef_t *PRVM_ED_GlobalAtOfs( int ofs );
void PRVM_PrintFunctionStatements (const char *name);
void PRVM_ED_Print(edict_t *ed);
void PRVM_ED_Write (vfile_t *f, edict_t *ed);