mirror of
https://github.com/dhewm/dhewm3-sdk.git
synced 2024-11-21 20:21:19 +00:00
Fix script interpreter stack for x86_64
Alot of stack and event variables are pointers. Align the size of all script and event variable types to sizeof(intptr_t) so that the CPU needs only one fetch insn on 64bit archs. Tested on x86 and x86_64 and found no different script behaviours compared to the binary from id. Savegames on x86_64 do work, but are not compatible to x86 and vice versa (among other issues, the stack is written to file as-is). x86 builds can still load savegames from the official binary and vice versa.
This commit is contained in:
parent
dc86a8a02c
commit
f8efcf5e90
12 changed files with 240 additions and 110 deletions
|
@ -92,15 +92,15 @@ idEventDef::idEventDef( const char *command, const char *formatspec, char return
|
|||
switch( formatspec[ i ] ) {
|
||||
case D_EVENT_FLOAT :
|
||||
bits |= 1 << i;
|
||||
argsize += sizeof( float );
|
||||
argsize += sizeof( intptr_t );
|
||||
break;
|
||||
|
||||
case D_EVENT_INTEGER :
|
||||
argsize += sizeof( int );
|
||||
argsize += sizeof( intptr_t );
|
||||
break;
|
||||
|
||||
case D_EVENT_VECTOR :
|
||||
argsize += sizeof( idVec3 );
|
||||
argsize += E_EVENT_SIZEOF_VEC;
|
||||
break;
|
||||
|
||||
case D_EVENT_STRING :
|
||||
|
|
|
@ -36,6 +36,9 @@ Event are used for scheduling tasks and for linking script commands.
|
|||
#define D_EVENT_MAXARGS 8 // if changed, enable the CREATE_EVENT_CODE define in Event.cpp to generate switch statement for idClass::ProcessEventArgPtr.
|
||||
// running the game will then generate c:\doom\base\events.txt, the contents of which should be copied into the switch statement.
|
||||
|
||||
// stack size of idVec3, aligned to native pointer size
|
||||
#define E_EVENT_SIZEOF_VEC ((sizeof(idVec3) + (sizeof(intptr_t) - 1)) & ~(sizeof(intptr_t) - 1))
|
||||
|
||||
#define D_EVENT_VOID ( ( char )0 )
|
||||
#define D_EVENT_INTEGER 'd'
|
||||
#define D_EVENT_FLOAT 'f'
|
||||
|
|
|
@ -745,7 +745,7 @@ void idInterpreter::CallEvent( const function_t *func, int argsize ) {
|
|||
switch( format[ i ] ) {
|
||||
case D_EVENT_INTEGER :
|
||||
var.intPtr = ( int * )&localstack[ start + pos ];
|
||||
data[ i ] = int( *var.floatPtr );
|
||||
( *( int * )&data[ i ] ) = int( *var.floatPtr );
|
||||
break;
|
||||
|
||||
case D_EVENT_FLOAT :
|
||||
|
@ -1808,9 +1808,7 @@ bool idInterpreter::Execute( void ) {
|
|||
|
||||
case OP_PUSH_V:
|
||||
var_a = GetVariable( st->a );
|
||||
Push( *reinterpret_cast<int *>( &var_a.vectorPtr->x ) );
|
||||
Push( *reinterpret_cast<int *>( &var_a.vectorPtr->y ) );
|
||||
Push( *reinterpret_cast<int *>( &var_a.vectorPtr->z ) );
|
||||
PushVector(*var_a.vectorPtr);
|
||||
break;
|
||||
|
||||
case OP_PUSH_OBJ:
|
||||
|
|
|
@ -30,7 +30,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#define __SCRIPT_INTERPRETER_H__
|
||||
|
||||
#define MAX_STACK_DEPTH 64
|
||||
#define LOCALSTACK_SIZE 6144
|
||||
#define LOCALSTACK_SIZE (6144 * 2)
|
||||
|
||||
typedef struct prstack_s {
|
||||
int s;
|
||||
|
@ -60,7 +60,8 @@ private:
|
|||
|
||||
void PopParms( int numParms );
|
||||
void PushString( const char *string );
|
||||
void Push( int value );
|
||||
void PushVector( const idVec3 &vector );
|
||||
void Push( intptr_t value );
|
||||
const char *FloatToString( float value );
|
||||
void AppendString( idVarDef *def, const char *from );
|
||||
void SetString( idVarDef *def, const char *from );
|
||||
|
@ -135,12 +136,25 @@ ID_INLINE void idInterpreter::PopParms( int numParms ) {
|
|||
idInterpreter::Push
|
||||
====================
|
||||
*/
|
||||
ID_INLINE void idInterpreter::Push( int value ) {
|
||||
if ( localstackUsed + sizeof( int ) > LOCALSTACK_SIZE ) {
|
||||
ID_INLINE void idInterpreter::Push( intptr_t value ) {
|
||||
if ( localstackUsed + sizeof( intptr_t ) > LOCALSTACK_SIZE ) {
|
||||
Error( "Push: locals stack overflow\n" );
|
||||
}
|
||||
*( int * )&localstack[ localstackUsed ] = value;
|
||||
localstackUsed += sizeof( int );
|
||||
*( intptr_t * )&localstack[ localstackUsed ] = value;
|
||||
localstackUsed += sizeof( intptr_t );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idInterpreter::PushVector
|
||||
====================
|
||||
*/
|
||||
ID_INLINE void idInterpreter::PushVector( const idVec3 &vector ) {
|
||||
if ( localstackUsed + E_EVENT_SIZEOF_VEC > LOCALSTACK_SIZE ) {
|
||||
Error( "Push: locals stack overflow\n" );
|
||||
}
|
||||
*( idVec3 * )&localstack[ localstackUsed ] = vector;
|
||||
localstackUsed += E_EVENT_SIZEOF_VEC;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -33,20 +33,20 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
// simple types. function types are dynamically allocated
|
||||
idTypeDef type_void( ev_void, &def_void, "void", 0, NULL );
|
||||
idTypeDef type_scriptevent( ev_scriptevent, &def_scriptevent, "scriptevent", sizeof( void * ), NULL );
|
||||
idTypeDef type_namespace( ev_namespace, &def_namespace, "namespace", sizeof( void * ), NULL );
|
||||
idTypeDef type_scriptevent( ev_scriptevent, &def_scriptevent, "scriptevent", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_namespace( ev_namespace, &def_namespace, "namespace", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_string( ev_string, &def_string, "string", MAX_STRING_LEN, NULL );
|
||||
idTypeDef type_float( ev_float, &def_float, "float", sizeof( float ), NULL );
|
||||
idTypeDef type_vector( ev_vector, &def_vector, "vector", sizeof( idVec3 ), NULL );
|
||||
idTypeDef type_entity( ev_entity, &def_entity, "entity", sizeof( int * ), NULL ); // stored as entity number pointer
|
||||
idTypeDef type_field( ev_field, &def_field, "field", sizeof( void * ), NULL );
|
||||
idTypeDef type_function( ev_function, &def_function, "function", sizeof( void * ), &type_void );
|
||||
idTypeDef type_virtualfunction( ev_virtualfunction, &def_virtualfunction, "virtual function", sizeof( int ), NULL );
|
||||
idTypeDef type_pointer( ev_pointer, &def_pointer, "pointer", sizeof( void * ), NULL );
|
||||
idTypeDef type_object( ev_object, &def_object, "object", sizeof( int * ), NULL ); // stored as entity number pointer
|
||||
idTypeDef type_jumpoffset( ev_jumpoffset, &def_jumpoffset, "<jump>", sizeof( int ), NULL ); // only used for jump opcodes
|
||||
idTypeDef type_argsize( ev_argsize, &def_argsize, "<argsize>", sizeof( int ), NULL ); // only used for function call and thread opcodes
|
||||
idTypeDef type_boolean( ev_boolean, &def_boolean, "boolean", sizeof( int ), NULL );
|
||||
idTypeDef type_float( ev_float, &def_float, "float", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_vector( ev_vector, &def_vector, "vector", E_EVENT_SIZEOF_VEC, NULL );
|
||||
idTypeDef type_entity( ev_entity, &def_entity, "entity", sizeof( intptr_t ), NULL ); // stored as entity number pointer
|
||||
idTypeDef type_field( ev_field, &def_field, "field", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_function( ev_function, &def_function, "function", sizeof( intptr_t ), &type_void );
|
||||
idTypeDef type_virtualfunction( ev_virtualfunction, &def_virtualfunction, "virtual function", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_pointer( ev_pointer, &def_pointer, "pointer", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_object( ev_object, &def_object, "object", sizeof( intptr_t ), NULL ); // stored as entity number pointer
|
||||
idTypeDef type_jumpoffset( ev_jumpoffset, &def_jumpoffset, "<jump>", sizeof( intptr_t ), NULL ); // only used for jump opcodes
|
||||
idTypeDef type_argsize( ev_argsize, &def_argsize, "<argsize>", sizeof( intptr_t ), NULL ); // only used for function call and thread opcodes
|
||||
idTypeDef type_boolean( ev_boolean, &def_boolean, "boolean", sizeof( intptr_t ), NULL );
|
||||
|
||||
idVarDef def_void( &type_void );
|
||||
idVarDef def_scriptevent( &type_scriptevent );
|
||||
|
@ -898,7 +898,7 @@ idScriptObject::Save
|
|||
================
|
||||
*/
|
||||
void idScriptObject::Save( idSaveGame *savefile ) const {
|
||||
size_t size;
|
||||
int size;
|
||||
|
||||
if ( type == &type_object && data == NULL ) {
|
||||
// Write empty string for uninitialized object
|
||||
|
@ -918,7 +918,7 @@ idScriptObject::Restore
|
|||
*/
|
||||
void idScriptObject::Restore( idRestoreGame *savefile ) {
|
||||
idStr typeName;
|
||||
size_t size;
|
||||
int size;
|
||||
|
||||
savefile->ReadString( typeName );
|
||||
|
||||
|
@ -931,7 +931,7 @@ void idScriptObject::Restore( idRestoreGame *savefile ) {
|
|||
savefile->Error( "idScriptObject::Restore: failed to restore object of type '%s'.", typeName.c_str() );
|
||||
}
|
||||
|
||||
savefile->ReadInt( (int &)size );
|
||||
savefile->ReadInt( size );
|
||||
if ( size != type->Size() ) {
|
||||
savefile->Error( "idScriptObject::Restore: size of object '%s' doesn't match size in save game.", typeName.c_str() );
|
||||
}
|
||||
|
@ -1226,6 +1226,44 @@ void idProgram::AddDefToNameList( idVarDef *def, const char *name ) {
|
|||
varDefNames[i]->AddDef( def );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
idProgram::ReserveMem
|
||||
|
||||
reserves memory for global variables and returns the starting pointer
|
||||
==============
|
||||
*/
|
||||
byte *idProgram::ReserveMem(int size) {
|
||||
byte *res = &variables[ numVariables ];
|
||||
numVariables += size;
|
||||
if ( numVariables > sizeof( variables ) ) {
|
||||
throw idCompileError( va( "Exceeded global memory size (%d bytes)", sizeof( variables ) ) );
|
||||
}
|
||||
|
||||
memset( res, 0, size );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idProgram::AllocVarDef
|
||||
============
|
||||
*/
|
||||
idVarDef *idProgram::AllocVarDef(idTypeDef *type, const char *name, idVarDef *scope) {
|
||||
idVarDef *def;
|
||||
|
||||
def = new idVarDef( type );
|
||||
def->scope = scope;
|
||||
def->numUsers = 1;
|
||||
def->num = varDefs.Append( def );
|
||||
|
||||
// add the def to the list with defs with this name and set the name pointer
|
||||
AddDefToNameList( def, name );
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idProgram::AllocDef
|
||||
|
@ -1239,13 +1277,7 @@ idVarDef *idProgram::AllocDef( idTypeDef *type, const char *name, idVarDef *scop
|
|||
idVarDef *def_z;
|
||||
|
||||
// allocate a new def
|
||||
def = new idVarDef( type );
|
||||
def->scope = scope;
|
||||
def->numUsers = 1;
|
||||
def->num = varDefs.Append( def );
|
||||
|
||||
// add the def to the list with defs with this name and set the name pointer
|
||||
AddDefToNameList( def, name );
|
||||
def = AllocVarDef(type, name, scope);
|
||||
|
||||
if ( ( type->Type() == ev_vector ) || ( ( type->Type() == ev_field ) && ( type->FieldType()->Type() == ev_vector ) ) ) {
|
||||
//
|
||||
|
@ -1259,7 +1291,7 @@ idVarDef *idProgram::AllocDef( idTypeDef *type, const char *name, idVarDef *scop
|
|||
scope->value.functionPtr->locals += type->Size();
|
||||
} else if ( scope->TypeDef()->Inherits( &type_object ) ) {
|
||||
idTypeDef newtype( ev_field, NULL, "float field", 0, &type_float );
|
||||
idTypeDef *type = GetType( newtype, true );
|
||||
idTypeDef *ftype = GetType( newtype, true );
|
||||
|
||||
// set the value to the variable's position in the object
|
||||
def->value.ptrOffset = scope->TypeDef()->Size();
|
||||
|
@ -1267,30 +1299,52 @@ idVarDef *idProgram::AllocDef( idTypeDef *type, const char *name, idVarDef *scop
|
|||
// make automatic defs for the vectors elements
|
||||
// origin can be accessed as origin_x, origin_y, and origin_z
|
||||
sprintf( element, "%s_x", def->Name() );
|
||||
def_x = AllocDef( type, element, scope, constant );
|
||||
def_x = AllocDef( ftype, element, scope, constant );
|
||||
|
||||
sprintf( element, "%s_y", def->Name() );
|
||||
def_y = AllocDef( type, element, scope, constant );
|
||||
def_y->value.ptrOffset = def_x->value.ptrOffset + type_float.Size();
|
||||
def_y = AllocDef( ftype, element, scope, constant );
|
||||
def_y->value.ptrOffset = def_x->value.ptrOffset + sizeof(float);
|
||||
|
||||
sprintf( element, "%s_z", def->Name() );
|
||||
def_z = AllocDef( type, element, scope, constant );
|
||||
def_z->value.ptrOffset = def_y->value.ptrOffset + type_float.Size();
|
||||
def_z = AllocDef( ftype, element, scope, constant );
|
||||
def_z->value.ptrOffset = def_y->value.ptrOffset + sizeof(float);
|
||||
} else {
|
||||
idTypeDef newtype( ev_float, &def_float, "vector float", 0, NULL );
|
||||
idTypeDef *ftype = GetType( newtype, true );
|
||||
|
||||
// make automatic defs for the vectors elements
|
||||
// origin can be accessed as origin_x, origin_y, and origin_z
|
||||
sprintf( element, "%s_x", def->Name() );
|
||||
def_x = AllocDef( &type_float, element, scope, constant );
|
||||
def_x = AllocVarDef( ftype, element, scope );
|
||||
|
||||
sprintf( element, "%s_y", def->Name() );
|
||||
def_y = AllocDef( &type_float, element, scope, constant );
|
||||
def_y = AllocVarDef( ftype, element, scope );
|
||||
|
||||
sprintf( element, "%s_z", def->Name() );
|
||||
def_z = AllocDef( &type_float, element, scope, constant );
|
||||
def_z = AllocVarDef( ftype, element, scope );
|
||||
|
||||
// point the vector def to the x coordinate
|
||||
def->value = def_x->value;
|
||||
def->initialized = def_x->initialized;
|
||||
// get the memory for the full vector and point the _x, _y and _z
|
||||
// defs at the vector member offsets
|
||||
if ( scope->Type() == ev_function ) {
|
||||
// vector on stack
|
||||
def->value.stackOffset = scope->value.functionPtr->locals;
|
||||
def->initialized = idVarDef::stackVariable;
|
||||
scope->value.functionPtr->locals += type->Size();
|
||||
|
||||
def_x->value.stackOffset = def->value.stackOffset;
|
||||
def_y->value.stackOffset = def_x->value.stackOffset + sizeof(float);
|
||||
def_z->value.stackOffset = def_y->value.stackOffset + sizeof(float);
|
||||
} else {
|
||||
// global vector
|
||||
def->value.bytePtr = ReserveMem(type->Size());
|
||||
def_x->value.bytePtr = def->value.bytePtr;
|
||||
def_y->value.bytePtr = def_x->value.bytePtr + sizeof(float);
|
||||
def_z->value.bytePtr = def_y->value.bytePtr + sizeof(float);
|
||||
}
|
||||
|
||||
def_x->initialized = def->initialized;
|
||||
def_y->initialized = def->initialized;
|
||||
def_z->initialized = def->initialized;
|
||||
}
|
||||
} else if ( scope->TypeDef()->Inherits( &type_object ) ) {
|
||||
//
|
||||
|
@ -1317,13 +1371,7 @@ idVarDef *idProgram::AllocDef( idTypeDef *type, const char *name, idVarDef *scop
|
|||
//
|
||||
// global variable
|
||||
//
|
||||
def->value.bytePtr = &variables[ numVariables ];
|
||||
numVariables += def->TypeDef()->Size();
|
||||
if ( numVariables > sizeof( variables ) ) {
|
||||
throw idCompileError( va( "Exceeded global memory size (%d bytes)", sizeof( variables ) ) );
|
||||
}
|
||||
|
||||
memset( def->value.bytePtr, 0, def->TypeDef()->Size() );
|
||||
def->value.bytePtr = ReserveMem(def->TypeDef()->Size());
|
||||
}
|
||||
|
||||
return def;
|
||||
|
|
|
@ -470,6 +470,8 @@ private:
|
|||
int top_files;
|
||||
|
||||
void CompileStats( void );
|
||||
byte *ReserveMem(int size);
|
||||
idVarDef *AllocVarDef(idTypeDef *type, const char *name, idVarDef *scope);
|
||||
|
||||
public:
|
||||
idVarDef *returnDef;
|
||||
|
|
|
@ -92,15 +92,15 @@ idEventDef::idEventDef( const char *command, const char *formatspec, char return
|
|||
switch( formatspec[ i ] ) {
|
||||
case D_EVENT_FLOAT :
|
||||
bits |= 1 << i;
|
||||
argsize += sizeof( float );
|
||||
argsize += sizeof( intptr_t );
|
||||
break;
|
||||
|
||||
case D_EVENT_INTEGER :
|
||||
argsize += sizeof( int );
|
||||
argsize += sizeof( intptr_t );
|
||||
break;
|
||||
|
||||
case D_EVENT_VECTOR :
|
||||
argsize += sizeof( idVec3 );
|
||||
argsize += E_EVENT_SIZEOF_VEC;
|
||||
break;
|
||||
|
||||
case D_EVENT_STRING :
|
||||
|
|
|
@ -36,6 +36,9 @@ Event are used for scheduling tasks and for linking script commands.
|
|||
#define D_EVENT_MAXARGS 8 // if changed, enable the CREATE_EVENT_CODE define in Event.cpp to generate switch statement for idClass::ProcessEventArgPtr.
|
||||
// running the game will then generate c:\doom\base\events.txt, the contents of which should be copied into the switch statement.
|
||||
|
||||
// stack size of idVec3, aligned to native pointer size
|
||||
#define E_EVENT_SIZEOF_VEC ((sizeof(idVec3) + (sizeof(intptr_t) - 1)) & ~(sizeof(intptr_t) - 1))
|
||||
|
||||
#define D_EVENT_VOID ( ( char )0 )
|
||||
#define D_EVENT_INTEGER 'd'
|
||||
#define D_EVENT_FLOAT 'f'
|
||||
|
|
|
@ -745,7 +745,7 @@ void idInterpreter::CallEvent( const function_t *func, int argsize ) {
|
|||
switch( format[ i ] ) {
|
||||
case D_EVENT_INTEGER :
|
||||
var.intPtr = ( int * )&localstack[ start + pos ];
|
||||
data[ i ] = int( *var.floatPtr );
|
||||
( *( int * )&data[ i ] ) = int( *var.floatPtr );
|
||||
break;
|
||||
|
||||
case D_EVENT_FLOAT :
|
||||
|
@ -1808,9 +1808,7 @@ bool idInterpreter::Execute( void ) {
|
|||
|
||||
case OP_PUSH_V:
|
||||
var_a = GetVariable( st->a );
|
||||
Push( *reinterpret_cast<int *>( &var_a.vectorPtr->x ) );
|
||||
Push( *reinterpret_cast<int *>( &var_a.vectorPtr->y ) );
|
||||
Push( *reinterpret_cast<int *>( &var_a.vectorPtr->z ) );
|
||||
PushVector(*var_a.vectorPtr);
|
||||
break;
|
||||
|
||||
case OP_PUSH_OBJ:
|
||||
|
|
|
@ -30,7 +30,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#define __SCRIPT_INTERPRETER_H__
|
||||
|
||||
#define MAX_STACK_DEPTH 64
|
||||
#define LOCALSTACK_SIZE 6144
|
||||
#define LOCALSTACK_SIZE (6144 * 2)
|
||||
|
||||
typedef struct prstack_s {
|
||||
int s;
|
||||
|
@ -60,7 +60,8 @@ private:
|
|||
|
||||
void PopParms( int numParms );
|
||||
void PushString( const char *string );
|
||||
void Push( int value );
|
||||
void PushVector( const idVec3 &vector );
|
||||
void Push( intptr_t value );
|
||||
const char *FloatToString( float value );
|
||||
void AppendString( idVarDef *def, const char *from );
|
||||
void SetString( idVarDef *def, const char *from );
|
||||
|
@ -135,12 +136,25 @@ ID_INLINE void idInterpreter::PopParms( int numParms ) {
|
|||
idInterpreter::Push
|
||||
====================
|
||||
*/
|
||||
ID_INLINE void idInterpreter::Push( int value ) {
|
||||
if ( localstackUsed + sizeof( int ) > LOCALSTACK_SIZE ) {
|
||||
ID_INLINE void idInterpreter::Push( intptr_t value ) {
|
||||
if ( localstackUsed + sizeof( intptr_t ) > LOCALSTACK_SIZE ) {
|
||||
Error( "Push: locals stack overflow\n" );
|
||||
}
|
||||
*( int * )&localstack[ localstackUsed ] = value;
|
||||
localstackUsed += sizeof( int );
|
||||
*( intptr_t * )&localstack[ localstackUsed ] = value;
|
||||
localstackUsed += sizeof( intptr_t );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
idInterpreter::PushVector
|
||||
====================
|
||||
*/
|
||||
ID_INLINE void idInterpreter::PushVector( const idVec3 &vector ) {
|
||||
if ( localstackUsed + E_EVENT_SIZEOF_VEC > LOCALSTACK_SIZE ) {
|
||||
Error( "Push: locals stack overflow\n" );
|
||||
}
|
||||
*( idVec3 * )&localstack[ localstackUsed ] = vector;
|
||||
localstackUsed += E_EVENT_SIZEOF_VEC;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -33,20 +33,20 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
// simple types. function types are dynamically allocated
|
||||
idTypeDef type_void( ev_void, &def_void, "void", 0, NULL );
|
||||
idTypeDef type_scriptevent( ev_scriptevent, &def_scriptevent, "scriptevent", sizeof( void * ), NULL );
|
||||
idTypeDef type_namespace( ev_namespace, &def_namespace, "namespace", sizeof( void * ), NULL );
|
||||
idTypeDef type_scriptevent( ev_scriptevent, &def_scriptevent, "scriptevent", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_namespace( ev_namespace, &def_namespace, "namespace", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_string( ev_string, &def_string, "string", MAX_STRING_LEN, NULL );
|
||||
idTypeDef type_float( ev_float, &def_float, "float", sizeof( float ), NULL );
|
||||
idTypeDef type_vector( ev_vector, &def_vector, "vector", sizeof( idVec3 ), NULL );
|
||||
idTypeDef type_entity( ev_entity, &def_entity, "entity", sizeof( int * ), NULL ); // stored as entity number pointer
|
||||
idTypeDef type_field( ev_field, &def_field, "field", sizeof( void * ), NULL );
|
||||
idTypeDef type_function( ev_function, &def_function, "function", sizeof( void * ), &type_void );
|
||||
idTypeDef type_virtualfunction( ev_virtualfunction, &def_virtualfunction, "virtual function", sizeof( int ), NULL );
|
||||
idTypeDef type_pointer( ev_pointer, &def_pointer, "pointer", sizeof( void * ), NULL );
|
||||
idTypeDef type_object( ev_object, &def_object, "object", sizeof( int * ), NULL ); // stored as entity number pointer
|
||||
idTypeDef type_jumpoffset( ev_jumpoffset, &def_jumpoffset, "<jump>", sizeof( int ), NULL ); // only used for jump opcodes
|
||||
idTypeDef type_argsize( ev_argsize, &def_argsize, "<argsize>", sizeof( int ), NULL ); // only used for function call and thread opcodes
|
||||
idTypeDef type_boolean( ev_boolean, &def_boolean, "boolean", sizeof( int ), NULL );
|
||||
idTypeDef type_float( ev_float, &def_float, "float", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_vector( ev_vector, &def_vector, "vector", E_EVENT_SIZEOF_VEC, NULL );
|
||||
idTypeDef type_entity( ev_entity, &def_entity, "entity", sizeof( intptr_t ), NULL ); // stored as entity number pointer
|
||||
idTypeDef type_field( ev_field, &def_field, "field", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_function( ev_function, &def_function, "function", sizeof( intptr_t ), &type_void );
|
||||
idTypeDef type_virtualfunction( ev_virtualfunction, &def_virtualfunction, "virtual function", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_pointer( ev_pointer, &def_pointer, "pointer", sizeof( intptr_t ), NULL );
|
||||
idTypeDef type_object( ev_object, &def_object, "object", sizeof( intptr_t ), NULL ); // stored as entity number pointer
|
||||
idTypeDef type_jumpoffset( ev_jumpoffset, &def_jumpoffset, "<jump>", sizeof( intptr_t ), NULL ); // only used for jump opcodes
|
||||
idTypeDef type_argsize( ev_argsize, &def_argsize, "<argsize>", sizeof( intptr_t ), NULL ); // only used for function call and thread opcodes
|
||||
idTypeDef type_boolean( ev_boolean, &def_boolean, "boolean", sizeof( intptr_t ), NULL );
|
||||
|
||||
idVarDef def_void( &type_void );
|
||||
idVarDef def_scriptevent( &type_scriptevent );
|
||||
|
@ -898,7 +898,7 @@ idScriptObject::Save
|
|||
================
|
||||
*/
|
||||
void idScriptObject::Save( idSaveGame *savefile ) const {
|
||||
size_t size;
|
||||
int size;
|
||||
|
||||
if ( type == &type_object && data == NULL ) {
|
||||
// Write empty string for uninitialized object
|
||||
|
@ -918,7 +918,7 @@ idScriptObject::Restore
|
|||
*/
|
||||
void idScriptObject::Restore( idRestoreGame *savefile ) {
|
||||
idStr typeName;
|
||||
size_t size;
|
||||
int size;
|
||||
|
||||
savefile->ReadString( typeName );
|
||||
|
||||
|
@ -931,7 +931,7 @@ void idScriptObject::Restore( idRestoreGame *savefile ) {
|
|||
savefile->Error( "idScriptObject::Restore: failed to restore object of type '%s'.", typeName.c_str() );
|
||||
}
|
||||
|
||||
savefile->ReadInt( (int &)size );
|
||||
savefile->ReadInt( size );
|
||||
if ( size != type->Size() ) {
|
||||
savefile->Error( "idScriptObject::Restore: size of object '%s' doesn't match size in save game.", typeName.c_str() );
|
||||
}
|
||||
|
@ -1226,6 +1226,44 @@ void idProgram::AddDefToNameList( idVarDef *def, const char *name ) {
|
|||
varDefNames[i]->AddDef( def );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
idProgram::ReserveMem
|
||||
|
||||
reserves memory for global variables and returns the starting pointer
|
||||
==============
|
||||
*/
|
||||
byte *idProgram::ReserveMem(int size) {
|
||||
byte *res = &variables[ numVariables ];
|
||||
numVariables += size;
|
||||
if ( numVariables > sizeof( variables ) ) {
|
||||
throw idCompileError( va( "Exceeded global memory size (%d bytes)", sizeof( variables ) ) );
|
||||
}
|
||||
|
||||
memset( res, 0, size );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idProgram::AllocVarDef
|
||||
============
|
||||
*/
|
||||
idVarDef *idProgram::AllocVarDef(idTypeDef *type, const char *name, idVarDef *scope) {
|
||||
idVarDef *def;
|
||||
|
||||
def = new idVarDef( type );
|
||||
def->scope = scope;
|
||||
def->numUsers = 1;
|
||||
def->num = varDefs.Append( def );
|
||||
|
||||
// add the def to the list with defs with this name and set the name pointer
|
||||
AddDefToNameList( def, name );
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idProgram::AllocDef
|
||||
|
@ -1239,13 +1277,7 @@ idVarDef *idProgram::AllocDef( idTypeDef *type, const char *name, idVarDef *scop
|
|||
idVarDef *def_z;
|
||||
|
||||
// allocate a new def
|
||||
def = new idVarDef( type );
|
||||
def->scope = scope;
|
||||
def->numUsers = 1;
|
||||
def->num = varDefs.Append( def );
|
||||
|
||||
// add the def to the list with defs with this name and set the name pointer
|
||||
AddDefToNameList( def, name );
|
||||
def = AllocVarDef(type, name, scope);
|
||||
|
||||
if ( ( type->Type() == ev_vector ) || ( ( type->Type() == ev_field ) && ( type->FieldType()->Type() == ev_vector ) ) ) {
|
||||
//
|
||||
|
@ -1259,7 +1291,7 @@ idVarDef *idProgram::AllocDef( idTypeDef *type, const char *name, idVarDef *scop
|
|||
scope->value.functionPtr->locals += type->Size();
|
||||
} else if ( scope->TypeDef()->Inherits( &type_object ) ) {
|
||||
idTypeDef newtype( ev_field, NULL, "float field", 0, &type_float );
|
||||
idTypeDef *type = GetType( newtype, true );
|
||||
idTypeDef *ftype = GetType( newtype, true );
|
||||
|
||||
// set the value to the variable's position in the object
|
||||
def->value.ptrOffset = scope->TypeDef()->Size();
|
||||
|
@ -1267,30 +1299,52 @@ idVarDef *idProgram::AllocDef( idTypeDef *type, const char *name, idVarDef *scop
|
|||
// make automatic defs for the vectors elements
|
||||
// origin can be accessed as origin_x, origin_y, and origin_z
|
||||
sprintf( element, "%s_x", def->Name() );
|
||||
def_x = AllocDef( type, element, scope, constant );
|
||||
def_x = AllocDef( ftype, element, scope, constant );
|
||||
|
||||
sprintf( element, "%s_y", def->Name() );
|
||||
def_y = AllocDef( type, element, scope, constant );
|
||||
def_y->value.ptrOffset = def_x->value.ptrOffset + type_float.Size();
|
||||
def_y = AllocDef( ftype, element, scope, constant );
|
||||
def_y->value.ptrOffset = def_x->value.ptrOffset + sizeof(float);
|
||||
|
||||
sprintf( element, "%s_z", def->Name() );
|
||||
def_z = AllocDef( type, element, scope, constant );
|
||||
def_z->value.ptrOffset = def_y->value.ptrOffset + type_float.Size();
|
||||
def_z = AllocDef( ftype, element, scope, constant );
|
||||
def_z->value.ptrOffset = def_y->value.ptrOffset + sizeof(float);
|
||||
} else {
|
||||
idTypeDef newtype( ev_float, &def_float, "vector float", 0, NULL );
|
||||
idTypeDef *ftype = GetType( newtype, true );
|
||||
|
||||
// make automatic defs for the vectors elements
|
||||
// origin can be accessed as origin_x, origin_y, and origin_z
|
||||
sprintf( element, "%s_x", def->Name() );
|
||||
def_x = AllocDef( &type_float, element, scope, constant );
|
||||
def_x = AllocVarDef( ftype, element, scope );
|
||||
|
||||
sprintf( element, "%s_y", def->Name() );
|
||||
def_y = AllocDef( &type_float, element, scope, constant );
|
||||
def_y = AllocVarDef( ftype, element, scope );
|
||||
|
||||
sprintf( element, "%s_z", def->Name() );
|
||||
def_z = AllocDef( &type_float, element, scope, constant );
|
||||
def_z = AllocVarDef( ftype, element, scope );
|
||||
|
||||
// point the vector def to the x coordinate
|
||||
def->value = def_x->value;
|
||||
def->initialized = def_x->initialized;
|
||||
// get the memory for the full vector and point the _x, _y and _z
|
||||
// defs at the vector member offsets
|
||||
if ( scope->Type() == ev_function ) {
|
||||
// vector on stack
|
||||
def->value.stackOffset = scope->value.functionPtr->locals;
|
||||
def->initialized = idVarDef::stackVariable;
|
||||
scope->value.functionPtr->locals += type->Size();
|
||||
|
||||
def_x->value.stackOffset = def->value.stackOffset;
|
||||
def_y->value.stackOffset = def_x->value.stackOffset + sizeof(float);
|
||||
def_z->value.stackOffset = def_y->value.stackOffset + sizeof(float);
|
||||
} else {
|
||||
// global vector
|
||||
def->value.bytePtr = ReserveMem(type->Size());
|
||||
def_x->value.bytePtr = def->value.bytePtr;
|
||||
def_y->value.bytePtr = def_x->value.bytePtr + sizeof(float);
|
||||
def_z->value.bytePtr = def_y->value.bytePtr + sizeof(float);
|
||||
}
|
||||
|
||||
def_x->initialized = def->initialized;
|
||||
def_y->initialized = def->initialized;
|
||||
def_z->initialized = def->initialized;
|
||||
}
|
||||
} else if ( scope->TypeDef()->Inherits( &type_object ) ) {
|
||||
//
|
||||
|
@ -1317,13 +1371,7 @@ idVarDef *idProgram::AllocDef( idTypeDef *type, const char *name, idVarDef *scop
|
|||
//
|
||||
// global variable
|
||||
//
|
||||
def->value.bytePtr = &variables[ numVariables ];
|
||||
numVariables += def->TypeDef()->Size();
|
||||
if ( numVariables > sizeof( variables ) ) {
|
||||
throw idCompileError( va( "Exceeded global memory size (%d bytes)", sizeof( variables ) ) );
|
||||
}
|
||||
|
||||
memset( def->value.bytePtr, 0, def->TypeDef()->Size() );
|
||||
def->value.bytePtr = ReserveMem(def->TypeDef()->Size());
|
||||
}
|
||||
|
||||
return def;
|
||||
|
|
|
@ -456,6 +456,8 @@ private:
|
|||
int top_files;
|
||||
|
||||
void CompileStats( void );
|
||||
byte *ReserveMem(int size);
|
||||
idVarDef *AllocVarDef(idTypeDef *type, const char *name, idVarDef *scope);
|
||||
|
||||
public:
|
||||
idVarDef *returnDef;
|
||||
|
|
Loading…
Reference in a new issue