diff --git a/neo/d3xp/gamesys/Event.cpp b/neo/d3xp/gamesys/Event.cpp index 33b2c48f..2214b6ae 100644 --- a/neo/d3xp/gamesys/Event.cpp +++ b/neo/d3xp/gamesys/Event.cpp @@ -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 : diff --git a/neo/d3xp/gamesys/Event.h b/neo/d3xp/gamesys/Event.h index 5212eee7..71061093 100644 --- a/neo/d3xp/gamesys/Event.h +++ b/neo/d3xp/gamesys/Event.h @@ -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' diff --git a/neo/d3xp/script/Script_Interpreter.cpp b/neo/d3xp/script/Script_Interpreter.cpp index 77ac955f..3ffa5ab3 100644 --- a/neo/d3xp/script/Script_Interpreter.cpp +++ b/neo/d3xp/script/Script_Interpreter.cpp @@ -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( &var_a.vectorPtr->x ) ); - Push( *reinterpret_cast( &var_a.vectorPtr->y ) ); - Push( *reinterpret_cast( &var_a.vectorPtr->z ) ); + PushVector(*var_a.vectorPtr); break; case OP_PUSH_OBJ: diff --git a/neo/d3xp/script/Script_Interpreter.h b/neo/d3xp/script/Script_Interpreter.h index c9db249c..b8525710 100644 --- a/neo/d3xp/script/Script_Interpreter.h +++ b/neo/d3xp/script/Script_Interpreter.h @@ -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; } /* diff --git a/neo/d3xp/script/Script_Program.cpp b/neo/d3xp/script/Script_Program.cpp index c58e4bf1..8603029a 100644 --- a/neo/d3xp/script/Script_Program.cpp +++ b/neo/d3xp/script/Script_Program.cpp @@ -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, "", sizeof( int ), NULL ); // only used for jump opcodes -idTypeDef type_argsize( ev_argsize, &def_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, "", sizeof( intptr_t ), NULL ); // only used for jump opcodes +idTypeDef type_argsize( ev_argsize, &def_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; diff --git a/neo/d3xp/script/Script_Program.h b/neo/d3xp/script/Script_Program.h index 2d53f689..be9094e7 100644 --- a/neo/d3xp/script/Script_Program.h +++ b/neo/d3xp/script/Script_Program.h @@ -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; diff --git a/neo/game/gamesys/Event.cpp b/neo/game/gamesys/Event.cpp index 963c9cba..7d6a6578 100644 --- a/neo/game/gamesys/Event.cpp +++ b/neo/game/gamesys/Event.cpp @@ -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 : diff --git a/neo/game/gamesys/Event.h b/neo/game/gamesys/Event.h index 54b18b0e..4e2c517a 100644 --- a/neo/game/gamesys/Event.h +++ b/neo/game/gamesys/Event.h @@ -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' diff --git a/neo/game/script/Script_Interpreter.cpp b/neo/game/script/Script_Interpreter.cpp index 0ba959e4..c7de466a 100644 --- a/neo/game/script/Script_Interpreter.cpp +++ b/neo/game/script/Script_Interpreter.cpp @@ -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( &var_a.vectorPtr->x ) ); - Push( *reinterpret_cast( &var_a.vectorPtr->y ) ); - Push( *reinterpret_cast( &var_a.vectorPtr->z ) ); + PushVector(*var_a.vectorPtr); break; case OP_PUSH_OBJ: diff --git a/neo/game/script/Script_Interpreter.h b/neo/game/script/Script_Interpreter.h index c9db249c..b8525710 100644 --- a/neo/game/script/Script_Interpreter.h +++ b/neo/game/script/Script_Interpreter.h @@ -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; } /* diff --git a/neo/game/script/Script_Program.cpp b/neo/game/script/Script_Program.cpp index c58e4bf1..8603029a 100644 --- a/neo/game/script/Script_Program.cpp +++ b/neo/game/script/Script_Program.cpp @@ -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, "", sizeof( int ), NULL ); // only used for jump opcodes -idTypeDef type_argsize( ev_argsize, &def_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, "", sizeof( intptr_t ), NULL ); // only used for jump opcodes +idTypeDef type_argsize( ev_argsize, &def_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; diff --git a/neo/game/script/Script_Program.h b/neo/game/script/Script_Program.h index e9a04f9f..937f1f0e 100644 --- a/neo/game/script/Script_Program.h +++ b/neo/game/script/Script_Program.h @@ -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;