idInterpreter::Call(Sys)Event(): Fix passing integers

All that code is kinda obfuscated, but the integer passing was plain
wrong (if sizeof(int) != sizeof(intptr_t), esp. noticeable on
 Big Endian).
data[i] is used by Callbacks.cpp, and for everything but floats it's
passed directly as an argument (interpreted as either an integer or
a pointer to idVec3 or whatever).
So storing an int in there with `( *( int * )&data[ i ] ) = int(...)`
only sets the first 4 bytes of that intptr_t, which is 8 bytes on 64bit
machines. On Little Endian that just happens to work, on Big Endian
it's the wrong 4 bytes.
This commit is contained in:
Daniel Gibson 2024-10-31 02:43:29 +01:00
parent fb3f0cc2b4
commit 76a9fdcebe
2 changed files with 36 additions and 4 deletions

View file

@ -785,11 +785,22 @@ void idInterpreter::CallEvent( const function_t *func, int argsize ) {
switch( format[ i ] ) {
case D_EVENT_INTEGER :
var.intPtr = ( int * )&localstack[ start + pos ];
( *( int * )&data[ i ] ) = int( *var.floatPtr );
//( *( int * )&data[ i ] ) = int( *var.floatPtr );
// DG: for int/intrptr_t arguments, the callbacks from Callbacks.cpp pass
// data[i] directly, not *(int*)&data[i] or some nonsense like that
// so the integer must be assigned to the intptr_t for the value to be
// passed correctly, esp. on 64bit Big Endian machines.
data[ i ] = int( *var.floatPtr );
break;
case D_EVENT_FLOAT :
var.intPtr = ( int * )&localstack[ start + pos ];
// NOTE: floats are the only type not passed as int or pointer in intptr_t,
// but as float-data in the first 4 bytes of data[i].
// So (unlike in the other cases), here this awkward code casting &data[i]
// to another pointer type is actually necessary (same in CallSysEvent()).
// In the other cases one could also use `data[i] = (intptr_t)var.blaPtr;`
// (not doing those changes here now to minimize potential merge conflicts)
( *( float * )&data[ i ] ) = *var.floatPtr;
break;
@ -915,7 +926,12 @@ void idInterpreter::CallSysEvent( const function_t *func, int argsize ) {
switch( format[ i ] ) {
case D_EVENT_INTEGER :
source.intPtr = ( int * )&localstack[ start + pos ];
*( int * )&data[ i ] = int( *source.floatPtr );
//*( int * )&data[ i ] = int( *source.floatPtr );
// DG: for int/intrptr_t arguments, the callbacks from Callbacks.cpp pass
// data[i] directly, not *(int*)&data[i] or some nonsense like that
// so the integer must be assigned to the intptr_t for the value to be
// passed correctly, esp. on 64bit Big Endian machines.
data[ i ] = int( *source.floatPtr );
break;
case D_EVENT_FLOAT :

View file

@ -785,11 +785,22 @@ void idInterpreter::CallEvent( const function_t *func, int argsize ) {
switch( format[ i ] ) {
case D_EVENT_INTEGER :
var.intPtr = ( int * )&localstack[ start + pos ];
( *( int * )&data[ i ] ) = int( *var.floatPtr );
//( *( int * )&data[ i ] ) = int( *var.floatPtr );
// DG: for int/intrptr_t arguments, the callbacks from Callbacks.cpp pass
// data[i] directly, not *(int*)&data[i] or some nonsense like that
// so the integer must be assigned to the intptr_t for the value to be
// passed correctly, esp. on 64bit Big Endian machines.
data[ i ] = int( *var.floatPtr );
break;
case D_EVENT_FLOAT :
var.intPtr = ( int * )&localstack[ start + pos ];
// NOTE: floats are the only type not passed as int or pointer in intptr_t,
// but as float-data in the first 4 bytes of data[i].
// So (unlike in the other cases), here this awkward code casting &data[i]
// to another pointer type is actually necessary (same in CallSysEvent()).
// In the other cases one could also use `data[i] = (intptr_t)var.blaPtr;`
// (not doing those changes here now to minimize potential merge conflicts)
( *( float * )&data[ i ] ) = *var.floatPtr;
break;
@ -915,7 +926,12 @@ void idInterpreter::CallSysEvent( const function_t *func, int argsize ) {
switch( format[ i ] ) {
case D_EVENT_INTEGER :
source.intPtr = ( int * )&localstack[ start + pos ];
*( int * )&data[ i ] = int( *source.floatPtr );
//*( int * )&data[ i ] = int( *source.floatPtr );
// DG: for int/intrptr_t arguments, the callbacks from Callbacks.cpp pass
// data[i] directly, not *(int*)&data[i] or some nonsense like that
// so the integer must be assigned to the intptr_t for the value to be
// passed correctly, esp. on 64bit Big Endian machines.
data[ i ] = int( *source.floatPtr );
break;
case D_EVENT_FLOAT :