2004-08-23 01:38:21 +00:00
# define PROGSUSED
# include "progsint.h"
# define HunkAlloc BADGDFG sdfhhsf FHS
void PR_SetBuiltins ( int type ) ;
/*
progstate_t * pr_progstate ;
progsnum_t pr_typecurrent ;
int maxprogs ;
progstate_t * current_progstate ;
int numshares ;
sharedvar_t * shares ; //shared globals, not including parms
int maxshares ;
*/
pbool PR_SwitchProgs ( progfuncs_t * progfuncs , progsnum_t type )
{
2005-10-07 16:27:20 +00:00
if ( ( unsigned ) type > = maxprogs )
2011-12-05 15:23:40 +00:00
{
if ( type = = - 1 )
{
pr_typecurrent = - 1 ;
current_progstate = NULL ;
return true ;
}
2004-08-23 01:38:21 +00:00
PR_RunError ( progfuncs , " QCLIB: Bad prog type - %i " , type ) ;
// Sys_Error("Bad prog type - %i", type);
2011-12-05 15:23:40 +00:00
}
2004-08-23 01:38:21 +00:00
2005-10-07 16:27:20 +00:00
if ( pr_progstate [ ( unsigned ) type ] . progs = = NULL ) //we havn't loaded it yet, for some reason
2004-08-23 01:38:21 +00:00
return false ;
2005-10-07 16:27:20 +00:00
current_progstate = & pr_progstate [ ( unsigned ) type ] ;
2004-08-23 01:38:21 +00:00
pr_typecurrent = type ;
return true ;
}
2011-12-05 15:23:40 +00:00
void PR_MoveParms ( progfuncs_t * progfuncs , progsnum_t newpr , progsnum_t oldpr ) //from 2 to 1
2004-08-23 01:38:21 +00:00
{
unsigned int a ;
2011-12-05 15:23:40 +00:00
progstate_t * np ;
progstate_t * op ;
2004-08-23 01:38:21 +00:00
2011-12-05 15:23:40 +00:00
if ( newpr = = oldpr )
2004-08-23 01:38:21 +00:00
return ; //don't bother coping variables to themselves...
2011-12-05 15:23:40 +00:00
np = & pr_progstate [ ( int ) newpr ] ;
op = & pr_progstate [ ( int ) oldpr ] ;
2004-08-23 01:38:21 +00:00
2011-12-05 15:23:40 +00:00
if ( ( unsigned ) newpr > = maxprogs | | ! np - > globals )
PR_RunError ( progfuncs , " QCLIB: Bad prog type - %i " , newpr ) ;
if ( ( unsigned ) oldpr > = maxprogs | | ! op - > globals )
return ;
2004-08-23 01:38:21 +00:00
//copy parms.
for ( a = 0 ; a < MAX_PARMS ; a + + )
{
2011-12-05 15:23:40 +00:00
* ( int * ) & np - > globals [ OFS_PARM0 + 3 * a ] = * ( int * ) & op - > globals [ OFS_PARM0 + 3 * a ] ;
* ( int * ) & np - > globals [ OFS_PARM0 + 3 * a + 1 ] = * ( int * ) & op - > globals [ OFS_PARM0 + 3 * a + 1 ] ;
* ( int * ) & np - > globals [ OFS_PARM0 + 3 * a + 2 ] = * ( int * ) & op - > globals [ OFS_PARM0 + 3 * a + 2 ] ;
2004-08-23 01:38:21 +00:00
}
2011-12-05 15:23:40 +00:00
np - > globals [ OFS_RETURN ] = op - > globals [ OFS_RETURN ] ;
np - > globals [ OFS_RETURN + 1 ] = op - > globals [ OFS_RETURN + 1 ] ;
np - > globals [ OFS_RETURN + 2 ] = op - > globals [ OFS_RETURN + 2 ] ;
2004-08-23 01:38:21 +00:00
//move the vars defined as shared.
for ( a = 0 ; a < numshares ; a + + ) //fixme: make offset per progs
{
2011-12-05 15:23:40 +00:00
memmove ( & ( ( int * ) np - > globals ) [ shares [ a ] . varofs ] , & ( ( int * ) op - > globals ) [ shares [ a ] . varofs ] , shares [ a ] . size * 4 ) ;
2004-08-23 01:38:21 +00:00
/* ((int *)p1->globals)[shares[a].varofs] = ((int *)p2->globals)[shares[a].varofs];
if ( shares [ a ] . size > 1 )
{
( ( int * ) p1 - > globals ) [ shares [ a ] . varofs + 1 ] = ( ( int * ) p2 - > globals ) [ shares [ a ] . varofs + 1 ] ;
if ( shares [ a ] . size > 2 )
( ( int * ) p1 - > globals ) [ shares [ a ] . varofs + 2 ] = ( ( int * ) p2 - > globals ) [ shares [ a ] . varofs + 2 ] ;
}
*/
}
}
progsnum_t PR_LoadProgs ( progfuncs_t * progfuncs , char * s , int headercrc , builtin_t * builtins , int numbuiltins )
{
2005-10-07 16:27:20 +00:00
unsigned int a ;
2004-08-23 01:38:21 +00:00
progsnum_t oldtype ;
oldtype = pr_typecurrent ;
for ( a = 0 ; a < maxprogs ; a + + )
{
2005-10-07 16:27:20 +00:00
if ( pr_progstate [ a ] . progs = = NULL )
2004-08-23 01:38:21 +00:00
{
pr_typecurrent = a ;
2005-10-07 16:27:20 +00:00
current_progstate = & pr_progstate [ a ] ;
2004-08-23 01:38:21 +00:00
if ( PR_ReallyLoadProgs ( progfuncs , s , headercrc , & pr_progstate [ a ] , false ) ) //try and load it
{
current_progstate - > builtins = builtins ;
current_progstate - > numbuiltins = numbuiltins ;
2011-05-20 04:10:46 +00:00
if ( a < = progfuncs - > numprogs )
progfuncs - > numprogs = a + 1 ;
2009-08-29 14:56:42 +00:00
# ifdef QCJIT
2011-07-30 14:14:56 +00:00
current_progstate - > jit = PR_GenerateJit ( progfuncs ) ;
2009-08-29 14:56:42 +00:00
# endif
2011-12-05 15:23:40 +00:00
if ( oldtype ! = - 1 )
2009-08-29 14:56:42 +00:00
PR_SwitchProgs ( progfuncs , oldtype ) ;
2004-08-23 01:38:21 +00:00
return a ; //we could load it. Yay!
}
2011-12-05 15:23:40 +00:00
PR_SwitchProgs ( progfuncs , oldtype ) ;
2004-08-23 01:38:21 +00:00
return - 1 ; // loading failed.
}
}
PR_SwitchProgs ( progfuncs , oldtype ) ;
return - 1 ;
}
void PR_ShiftParms ( progfuncs_t * progfuncs , int amount )
{
int a ;
for ( a = 0 ; a < MAX_PARMS - amount ; a + + )
* ( int * ) & pr_globals [ OFS_PARM0 + 3 * a ] = * ( int * ) & pr_globals [ OFS_PARM0 + 3 * ( amount + a ) ] ;
}
//forget a progs
void PR_Clear ( progfuncs_t * progfuncs )
{
2005-10-07 16:27:20 +00:00
unsigned int a ;
2004-08-23 01:38:21 +00:00
for ( a = 0 ; a < maxprogs ; a + + )
{
2011-07-30 14:14:56 +00:00
# ifdef QCJIT
if ( pr_progstate [ a ] . jit )
PR_CloseJit ( pr_progstate [ a ] . jit ) ;
# endif
2004-08-23 01:38:21 +00:00
pr_progstate [ a ] . progs = NULL ;
}
}
void QC_StartShares ( progfuncs_t * progfuncs )
{
numshares = 0 ;
maxshares = 32 ;
if ( shares )
memfree ( shares ) ;
shares = memalloc ( sizeof ( sharedvar_t ) * maxshares ) ;
}
void QC_AddSharedVar ( progfuncs_t * progfuncs , int start , int size ) //fixme: make offset per progs and optional
{
int ofs ;
unsigned int a ;
if ( numshares > = maxshares )
{
void * buf ;
buf = shares ;
maxshares + = 16 ;
shares = memalloc ( sizeof ( sharedvar_t ) * maxshares ) ;
memcpy ( shares , buf , sizeof ( sharedvar_t ) * numshares ) ;
memfree ( buf ) ;
}
ofs = start ;
for ( a = 0 ; a < numshares ; a + + )
{
if ( shares [ a ] . varofs + shares [ a ] . size = = ofs )
{
shares [ a ] . size + = size ; //expand size.
return ;
}
if ( shares [ a ] . varofs = = start )
return ;
}
shares [ numshares ] . varofs = start ;
shares [ numshares ] . size = size ;
numshares + + ;
}
//void ShowWatch(void);
void QC_InitShares ( progfuncs_t * progfuncs )
{
// ShowWatch();
if ( ! field ) //don't make it so we will just need to remalloc everything
{
maxfields = 64 ;
2008-05-11 12:55:53 +00:00
field = memalloc ( sizeof ( fdef_t ) * maxfields ) ;
2004-08-23 01:38:21 +00:00
}
numfields = 0 ;
progfuncs - > fieldadjust = 0 ;
}
2005-09-14 04:36:07 +00:00
void QC_FlushProgsOffsets ( progfuncs_t * progfuncs )
{ //sets the fields up for loading a new progs.
//fields are matched by name to other progs
//not by offset
unsigned int i ;
for ( i = 0 ; i < numfields ; i + + )
field [ i ] . progsofs = - 1 ;
}
2004-08-23 01:38:21 +00:00
//called if a global is defined as a field
//returns offset.
2007-10-05 17:43:26 +00:00
//vectors must be added before any of their corresponding _x/y/z vars
2004-08-23 01:38:21 +00:00
//in this way, even screwed up progs work.
2005-09-14 04:36:07 +00:00
//requestedpos is the offset the engine WILL put it at.
//origionaloffs is used to track matching field offsets. fields with the same progs offset overlap
//note: we probably suffer from progs with renamed system globals.
2010-07-18 08:42:59 +00:00
int QC_RegisterFieldVar ( progfuncs_t * progfuncs , unsigned int type , char * name , signed long engineofs , signed long progsofs )
2004-08-23 01:38:21 +00:00
{
// progstate_t *p;
// int pnum;
unsigned int i ;
int namelen ;
int ofs ;
int fnum ;
2005-03-28 00:11:59 +00:00
if ( ! name ) //engine can use this to offset all progs fields
{ //which fixes constant field offsets (some ktpro arrays)
progfuncs - > fieldadjust = fields_size / 4 ;
2004-08-23 01:38:21 +00:00
return 0 ;
}
prinst - > reorganisefields = true ;
//look for an existing match
for ( i = 0 ; i < numfields ; i + + )
{
2005-05-15 18:49:04 +00:00
if ( ! strcmp ( name , field [ i ] . name ) )
2004-08-23 01:38:21 +00:00
{
if ( field [ i ] . type ! = type )
{
2010-07-11 02:22:39 +00:00
printf ( " Field type mismatch on \" %s \" . %i != %i \n " , name , field [ i ] . type , type ) ;
2004-08-23 01:38:21 +00:00
continue ;
}
2005-09-14 04:36:07 +00:00
if ( ! progfuncs - > fieldadjust & & engineofs > = 0 )
2005-09-16 04:26:11 +00:00
if ( ( unsigned ) engineofs / 4 ! = field [ i ] . ofs )
2004-08-23 01:38:21 +00:00
Sys_Error ( " Field %s at wrong offset " , name ) ;
2005-09-14 04:36:07 +00:00
if ( field [ i ] . progsofs = = - 1 )
field [ i ] . progsofs = progsofs ;
2005-10-10 22:29:05 +00:00
// printf("Dupfield %s %i -> %i\n", name, field[i].progsofs,field[i].ofs);
2005-09-14 04:36:07 +00:00
return field [ i ] . ofs - progfuncs - > fieldadjust ; //got a match
2004-08-23 01:38:21 +00:00
}
}
if ( numfields + 1 > maxfields )
{
fdef_t * nf ;
i = maxfields ;
maxfields + = 32 ;
nf = memalloc ( sizeof ( fdef_t ) * maxfields ) ;
memcpy ( nf , field , sizeof ( fdef_t ) * i ) ;
memfree ( field ) ;
field = nf ;
}
//try to add a new one
fnum = numfields ;
numfields + + ;
2005-05-15 18:49:04 +00:00
field [ fnum ] . name = name ;
2005-09-14 04:36:07 +00:00
if ( type = = ev_vector )
2004-08-23 01:38:21 +00:00
{
char * n ;
namelen = strlen ( name ) + 5 ;
n = PRHunkAlloc ( progfuncs , namelen ) ;
sprintf ( n , " %s_x " , name ) ;
2005-09-14 04:36:07 +00:00
ofs = QC_RegisterFieldVar ( progfuncs , ev_float , n , engineofs , progsofs ) ;
2005-09-16 04:26:11 +00:00
field [ fnum ] . ofs = ofs + progfuncs - > fieldadjust ;
2004-08-23 01:38:21 +00:00
n = PRHunkAlloc ( progfuncs , namelen ) ;
sprintf ( n , " %s_y " , name ) ;
2005-09-14 04:36:07 +00:00
QC_RegisterFieldVar ( progfuncs , ev_float , n , ( engineofs = = - 1 ) ? - 1 : ( engineofs + 4 ) , ( progsofs = = - 1 ) ? - 1 : progsofs + 1 ) ;
2004-08-23 01:38:21 +00:00
n = PRHunkAlloc ( progfuncs , namelen ) ;
sprintf ( n , " %s_z " , name ) ;
2005-09-14 04:36:07 +00:00
QC_RegisterFieldVar ( progfuncs , ev_float , n , ( engineofs = = - 1 ) ? - 1 : ( engineofs + 8 ) , ( progsofs = = - 1 ) ? - 1 : progsofs + 2 ) ;
2004-08-23 01:38:21 +00:00
}
2005-09-14 04:36:07 +00:00
else if ( engineofs > = 0 )
{ //the engine is setting up a list of required field indexes.
//paranoid checking of the offset.
2005-09-28 16:57:10 +00:00
/* for (i = 0; i < numfields-1; i++)
2004-08-23 01:38:21 +00:00
{
2005-09-16 04:26:11 +00:00
if ( field [ i ] . ofs = = ( ( unsigned ) engineofs ) / 4 )
2004-08-23 01:38:21 +00:00
{
if ( type = = ev_float & & field [ i ] . type = = ev_vector ) //check names
{
2005-05-15 18:49:04 +00:00
if ( strncmp ( field [ i ] . name , name , strlen ( field [ i ] . name ) ) )
2004-08-23 01:38:21 +00:00
Sys_Error ( " Duplicated offset " ) ;
}
else
Sys_Error ( " Duplicated offset " ) ;
}
2005-09-28 16:57:10 +00:00
} */
2005-09-14 04:36:07 +00:00
if ( engineofs & 3 )
2010-07-11 10:53:13 +00:00
Sys_Error ( " field %s is %i&3 " , name , ( int ) engineofs ) ;
2005-09-14 04:36:07 +00:00
field [ fnum ] . ofs = ofs = engineofs / 4 ;
2004-08-23 01:38:21 +00:00
}
else
2005-09-14 04:36:07 +00:00
{ //we just found a new fieldname inside a progs
field [ fnum ] . ofs = ofs = fields_size / 4 ; //add on the end
//if the progs field offset matches annother offset in the same progs, make it match up with the earlier one.
if ( progsofs > = 0 )
{
for ( i = 0 ; i < numfields - 1 ; i + + )
{
if ( field [ i ] . progsofs = = ( unsigned ) progsofs )
{
2005-10-10 22:29:05 +00:00
// printf("found union field %s %i -> %i\n", field[i].name, field[i].progsofs, field[i].ofs);
2005-09-14 04:36:07 +00:00
field [ fnum ] . ofs = ofs = field [ i ] . ofs ;
break ;
}
}
}
}
2004-08-23 01:38:21 +00:00
// if (type != ev_vector)
2005-03-28 00:11:59 +00:00
if ( fields_size < ( ofs + type_size [ type ] ) * 4 )
fields_size = ( ofs + type_size [ type ] ) * 4 ;
2004-08-23 01:38:21 +00:00
2005-03-28 00:11:59 +00:00
if ( max_fields_size & & fields_size > max_fields_size )
2004-08-23 01:38:21 +00:00
Sys_Error ( " Allocated too many additional fields after ents were inited. " ) ;
field [ fnum ] . type = type ;
2005-09-14 04:36:07 +00:00
field [ fnum ] . progsofs = progsofs ;
2005-10-10 22:29:05 +00:00
// printf("Field %s %i -> %i\n", name, field[fnum].progsofs,field[fnum].ofs);
2004-08-23 01:38:21 +00:00
//we've finished setting the structure
2005-09-14 04:36:07 +00:00
return ofs - progfuncs - > fieldadjust ;
2004-08-23 01:38:21 +00:00
}
//called if a global is defined as a field
2005-05-15 18:49:04 +00:00
void QC_AddSharedFieldVar ( progfuncs_t * progfuncs , int num , char * stringtable )
2004-08-23 01:38:21 +00:00
{
// progstate_t *p;
// int pnum;
unsigned int i , o ;
char * s ;
//look for an existing match not needed, cos we look a little later too.
/*
for ( i = 0 ; i < numfields ; i + + )
{
if ( ! strcmp ( pr_globaldefs [ num ] . s_name , field [ i ] . s_name ) )
{
//really we should look for a field def
* ( int * ) & pr_globals [ pr_globaldefs [ num ] . ofs ] = field [ i ] . ofs ; //got a match
return ;
}
}
*/
2011-03-04 13:59:06 +00:00
switch ( current_progstate - > structtype )
2004-08-23 01:38:21 +00:00
{
2011-03-04 13:59:06 +00:00
case PST_KKQWSV :
case PST_DEFAULT :
2004-08-23 01:38:21 +00:00
for ( i = 1 ; i < pr_progs - > numfielddefs ; i + + )
{
2005-05-15 18:49:04 +00:00
if ( ! strcmp ( pr_fielddefs16 [ i ] . s_name + stringtable , pr_globaldefs16 [ num ] . s_name + stringtable ) )
2004-08-23 01:38:21 +00:00
{
2005-09-28 16:57:10 +00:00
// int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
2005-09-14 04:36:07 +00:00
* ( int * ) & pr_globals [ pr_globaldefs16 [ num ] . ofs ] = QC_RegisterFieldVar ( progfuncs , pr_fielddefs16 [ i ] . type , pr_globaldefs16 [ num ] . s_name + stringtable , - 1 , * ( int * ) & pr_globals [ pr_globaldefs16 [ num ] . ofs ] ) ;
2005-09-28 16:57:10 +00:00
// printf("Field %s %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
2004-08-23 01:38:21 +00:00
return ;
}
}
2005-05-15 18:49:04 +00:00
s = pr_globaldefs16 [ num ] . s_name + stringtable ;
2004-08-23 01:38:21 +00:00
for ( i = 0 ; i < numfields ; i + + )
{
2005-09-14 04:36:07 +00:00
o = field [ i ] . progsofs ;
2004-08-23 01:38:21 +00:00
if ( o = = * ( unsigned int * ) & pr_globals [ pr_globaldefs16 [ num ] . ofs ] )
{
2005-09-28 16:57:10 +00:00
// int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
2004-08-23 01:38:21 +00:00
* ( int * ) & pr_globals [ pr_globaldefs16 [ num ] . ofs ] = field [ i ] . ofs - progfuncs - > fieldadjust ;
2005-09-28 16:57:10 +00:00
// printf("Field %s %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
2004-08-23 01:38:21 +00:00
return ;
}
}
//oh well, must be a parameter.
2006-11-03 15:53:04 +00:00
// if (*(int *)&pr_globals[pr_globaldefs16[num].ofs])
// Sys_Error("QCLIB: Global field var with no matching field \"%s\", from offset %i", pr_globaldefs16[num].s_name+stringtable, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
2004-08-23 01:38:21 +00:00
return ;
2011-03-04 13:59:06 +00:00
case PST_FTE32 :
case PST_QTEST :
2004-08-23 01:38:21 +00:00
for ( i = 1 ; i < pr_progs - > numfielddefs ; i + + )
{
2005-05-15 18:49:04 +00:00
if ( ! strcmp ( pr_fielddefs32 [ i ] . s_name + stringtable , pr_globaldefs32 [ num ] . s_name + stringtable ) )
2004-08-23 01:38:21 +00:00
{
2005-09-14 04:36:07 +00:00
* ( int * ) & pr_globals [ pr_globaldefs32 [ num ] . ofs ] = QC_RegisterFieldVar ( progfuncs , pr_fielddefs32 [ i ] . type , pr_globaldefs32 [ num ] . s_name + stringtable , - 1 , * ( int * ) & pr_globals [ pr_globaldefs32 [ num ] . ofs ] ) ;
2004-08-23 01:38:21 +00:00
return ;
}
}
2005-05-15 18:49:04 +00:00
s = pr_globaldefs32 [ num ] . s_name + stringtable ;
2004-08-23 01:38:21 +00:00
for ( i = 0 ; i < numfields ; i + + )
{
2005-09-14 04:36:07 +00:00
o = field [ i ] . progsofs ;
2004-08-23 01:38:21 +00:00
if ( o = = * ( unsigned int * ) & pr_globals [ pr_globaldefs32 [ num ] . ofs ] )
{
* ( int * ) & pr_globals [ pr_globaldefs32 [ num ] . ofs ] = field [ i ] . ofs - progfuncs - > fieldadjust ;
return ;
}
}
//oh well, must be a parameter.
if ( * ( int * ) & pr_globals [ pr_globaldefs32 [ num ] . ofs ] )
2005-05-15 18:49:04 +00:00
Sys_Error ( " QCLIB: Global field var with no matching field \" %s \" , from offset %i " , pr_globaldefs32 [ num ] . s_name + stringtable , * ( int * ) & pr_globals [ pr_globaldefs32 [ num ] . ofs ] ) ;
2004-08-23 01:38:21 +00:00
return ;
default :
Sys_Error ( " Bad bits " ) ;
break ;
}
Sys_Error ( " Should be unreachable " ) ;
}