Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
FriskTheFallenHuman committed Nov 9, 2024
2 parents 9e501a4 + d94bb42 commit 565fe07
Show file tree
Hide file tree
Showing 18 changed files with 2,004 additions and 4,214 deletions.
24 changes: 12 additions & 12 deletions neo/d3xp/gamesys/Class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,18 +460,18 @@ idClass::new
#endif

void * idClass::operator new( size_t s ) {
int *p;
intptr_t *p;

s += sizeof( int );
p = (int *)Mem_Alloc( s );
s += sizeof( intptr_t );
p = (intptr_t *)Mem_Alloc( s );
*p = s;
memused += s;
numobjects++;

#ifdef ID_DEBUG_UNINITIALIZED_MEMORY
unsigned int *ptr = (unsigned int *)p;
int size = s;
assert( ( size & 3 ) == 0 );
assert( ( size & (sizeof(intptr_t) - 1) ) == 0 );
size >>= 3;
for ( int i = 1; i < size; i++ ) {
ptr[i] = 0xcdcdcdcd;
Expand All @@ -482,18 +482,18 @@ void * idClass::operator new( size_t s ) {
}

void * idClass::operator new( size_t s, int, int, char *, int ) {
int *p;
intptr_t *p;

s += sizeof( int );
p = (int *)Mem_Alloc( s );
s += sizeof( intptr_t );
p = (intptr_t *)Mem_Alloc( s );
*p = s;
memused += s;
numobjects++;

#ifdef ID_DEBUG_UNINITIALIZED_MEMORY
unsigned int *ptr = (unsigned int *)p;
int size = s;
assert( ( size & 3 ) == 0 );
assert( ( size & (sizeof(intptr_t) - 1) ) == 0 );
size >>= 3;
for ( int i = 1; i < size; i++ ) {
ptr[i] = 0xcdcdcdcd;
Expand All @@ -513,21 +513,21 @@ idClass::delete
================
*/
void idClass::operator delete( void *ptr ) {
int *p;
intptr_t *p;

if ( ptr ) {
p = ( ( int * )ptr ) - 1;
p = ( ( intptr_t * )ptr ) - 1;
memused -= *p;
numobjects--;
Mem_Free( p );
}
}

void idClass::operator delete( void *ptr, int, int, char *, int ) {
int *p;
intptr_t *p;

if ( ptr ) {
p = ( ( int * )ptr ) - 1;
p = ( ( intptr_t * )ptr ) - 1;
memused -= *p;
numobjects--;
Mem_Free( p );
Expand Down
20 changes: 18 additions & 2 deletions neo/d3xp/script/Script_Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -781,11 +781,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;

Expand Down Expand Up @@ -911,7 +922,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 :
Expand Down
21 changes: 20 additions & 1 deletion neo/d3xp/script/Script_Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,26 @@ ID_INLINE void idInterpreter::Push( intptr_t value ) {
if ( localstackUsed + sizeof( intptr_t ) > LOCALSTACK_SIZE ) {
Error( "Push: locals stack overflow\n" );
}
*( intptr_t * )&localstack[ localstackUsed ] = value;
// DG: fix for 64bit Big Endian machines
//*( intptr_t * )&localstack[ localstackUsed ] = value;
int val = value;
assert(value == val && "I really assumed that value would always fit into 32bit");
// dhewm3 used to store these values on localstack[] as intptr_t, even though
// they always seem to be int32. Unfortunately, all the code reading localstack[]
// gets the pointer to &localstack[ localstackUsed ] and then interprets that
// as int* or float* or whatever.
// So with 64bit machines it's stored as the wrong size (intptr_t is int64, int is int32),
// and on Big Endian the values are just 0 (or UINT_MAX if value < 0) - on Little Endian
// the first 4 bytes are the ones with actual data so the bug was hidden).
// To fix this, now a regular itn is stored at `&localstack[ localstackUsed ]`,
// as expected by the code using localstack[].
// TODO: once this has been tested more (and the assertion above has never triggered),
// change idInterpreter::Push() to take a regular int argument instead of intptr_t.
int *stackVar = ( int * )&localstack[ localstackUsed ];
*stackVar = val;

// even though a 32bit int is put onto the stack, increase it by sizeof(intptr_t)
// so it remains aligned to multiples of the native pointer size
localstackUsed += sizeof( intptr_t );
}

Expand Down
22 changes: 18 additions & 4 deletions neo/framework/Common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2725,13 +2725,27 @@ void idCommonLocal::LoadGameDLL( void ) {
// there was no gamelib for this mod, use default one from base game
if (!gameDLL) {
common->Printf( "\n" );
common->Warning( "couldn't load mod-specific %s, defaulting to base game's library!\n", dll );
sys->DLL_GetFileName(fs_base, dll, sizeof(dll)); // DEFUNKT sys->DLL_GetFileName(BASE_GAMEDIR, dll, sizeof(dll));
LoadGameDLLbyName(dll, s);

const char *fs_base = cvarSystem->GetCVarString("fs_game_base");
if (fs_base && fs_base[0]) {
common->Warning( "couldn't load mod-specific %s, defaulting to library of fs_game_base (%s)!\n", dll, fs_base);
sys->DLL_GetFileName(fs_base, dll, sizeof(dll));
LoadGameDLLbyName(dll, s);
if ( !gameDLL ) {
common->Warning( "couldn't load fs_game_base lib %s either, defaulting to base game's library!\n", dll);
}
} else {
common->Warning( "couldn't load mod-specific %s, defaulting to base game's library!\n", dll );
}

if ( !gameDLL ) {
sys->DLL_GetFileName(BASE_GAMEDIR, dll, sizeof(dll));
LoadGameDLLbyName(dll, s);
}
}

if ( !gameDLL ) {
common->FatalError( "couldn't load game dynamic library" );
common->FatalError( "couldn't load game dynamic library '%s'", dll );
return;
}

Expand Down
24 changes: 12 additions & 12 deletions neo/game/gamesys/Class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,18 +460,18 @@ idClass::new
#endif

void * idClass::operator new( size_t s ) {
int *p;
intptr_t *p;

s += sizeof( int );
p = (int *)Mem_Alloc( s );
s += sizeof( intptr_t );
p = (intptr_t *)Mem_Alloc( s );
*p = s;
memused += s;
numobjects++;

#ifdef ID_DEBUG_UNINITIALIZED_MEMORY
unsigned int *ptr = (unsigned int *)p;
int size = s;
assert( ( size & 3 ) == 0 );
assert( ( size & (sizeof(intptr_t) - 1) ) == 0 );
size >>= 3;
for ( int i = 1; i < size; i++ ) {
ptr[i] = 0xcdcdcdcd;
Expand All @@ -482,18 +482,18 @@ void * idClass::operator new( size_t s ) {
}

void * idClass::operator new( size_t s, int, int, char *, int ) {
int *p;
intptr_t *p;

s += sizeof( int );
p = (int *)Mem_Alloc( s );
s += sizeof( intptr_t );
p = (intptr_t *)Mem_Alloc( s );
*p = s;
memused += s;
numobjects++;

#ifdef ID_DEBUG_UNINITIALIZED_MEMORY
unsigned int *ptr = (unsigned int *)p;
int size = s;
assert( ( size & 3 ) == 0 );
assert( ( size & (sizeof(intptr_t) - 1) ) == 0 );
size >>= 3;
for ( int i = 1; i < size; i++ ) {
ptr[i] = 0xcdcdcdcd;
Expand All @@ -513,21 +513,21 @@ idClass::delete
================
*/
void idClass::operator delete( void *ptr ) {
int *p;
intptr_t *p;

if ( ptr ) {
p = ( ( int * )ptr ) - 1;
p = ( ( intptr_t * )ptr ) - 1;
memused -= *p;
numobjects--;
Mem_Free( p );
}
}

void idClass::operator delete( void *ptr, int, int, char *, int ) {
int *p;
intptr_t *p;

if ( ptr ) {
p = ( ( int * )ptr ) - 1;
p = ( ( intptr_t * )ptr ) - 1;
memused -= *p;
numobjects--;
Mem_Free( p );
Expand Down
20 changes: 18 additions & 2 deletions neo/game/script/Script_Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -781,11 +781,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;

Expand Down Expand Up @@ -911,7 +922,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 :
Expand Down
21 changes: 20 additions & 1 deletion neo/game/script/Script_Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,26 @@ ID_INLINE void idInterpreter::Push( intptr_t value ) {
if ( localstackUsed + sizeof( intptr_t ) > LOCALSTACK_SIZE ) {
Error( "Push: locals stack overflow\n" );
}
*( intptr_t * )&localstack[ localstackUsed ] = value;
// DG: fix for 64bit Big Endian machines
//*( intptr_t * )&localstack[ localstackUsed ] = value;
int val = value;
assert(value == val && "I really assumed that value would always fit into 32bit");
// dhewm3 used to store these values on localstack[] as intptr_t, even though
// they always seem to be int32. Unfortunately, all the code reading localstack[]
// gets the pointer to &localstack[ localstackUsed ] and then interprets that
// as int* or float* or whatever.
// So with 64bit machines it's stored as the wrong size (intptr_t is int64, int is int32),
// and on Big Endian the values are just 0 (or UINT_MAX if value < 0) - on Little Endian
// the first 4 bytes are the ones with actual data so the bug was hidden).
// To fix this, now a regular itn is stored at `&localstack[ localstackUsed ]`,
// as expected by the code using localstack[].
// TODO: once this has been tested more (and the assertion above has never triggered),
// change idInterpreter::Push() to take a regular int argument instead of intptr_t.
int *stackVar = ( int * )&localstack[ localstackUsed ];
*stackVar = val;

// even though a 32bit int is put onto the stack, increase it by sizeof(intptr_t)
// so it remains aligned to multiples of the native pointer size
localstackUsed += sizeof( intptr_t );
}

Expand Down
18 changes: 18 additions & 0 deletions neo/idlib/Heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,24 @@ __inline void operator delete[]( void *p ) {
#endif /* ID_DEBUG_MEMORY */


// allocate SIZE bytes, aligned to 16 bytes - possibly on the stack (like _alloca16())
// if it's too big (> ID_MAX_ALLOCA_SIZE, 1MB), it gets allocated on the Heap instead.
// ON_STACK should be a bool and will be set to true if it was allocated on the stack
// and false if it was allocated on the heap.
// if ON_STACK is false, you must free this with Mem_FreeA() or Mem_Free16()!
// (just pass your ON_STACK bool to Mem_FreeA() and it will do the right thing)
#define Mem_MallocA( SIZE, ON_STACK ) \
( (SIZE) < ID_MAX_ALLOCA_SIZE ? ( ON_STACK=true, _alloca16(SIZE) ) : ( ON_STACK=false, Mem_Alloc16(SIZE) ) )

// free memory allocated with Mem_MallocA()
ID_INLINE void Mem_FreeA( void* ptr, bool onStack )
{
if( !onStack ) {
Mem_Free16( ptr );
}
}


/*
===============================================================================
Expand Down
10 changes: 10 additions & 0 deletions neo/libs/imgui/imconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,13 @@ namespace ImGui
void MyFunction(const char* name, MyMatrix44* mtx);
}
*/

// DG: on Big Endian systems the order of color channels in an uint32 color is inverted.
// this seems to be the official way to support Big Endian platforms in ImGUI:
#if D3_IS_BIG_ENDIAN
#define IM_COL32_R_SHIFT 24
#define IM_COL32_G_SHIFT 16
#define IM_COL32_B_SHIFT 8
#define IM_COL32_A_SHIFT 0
#define IM_COL32_A_MASK 0x000000FF
#endif
15 changes: 13 additions & 2 deletions neo/renderer/ModelOverlay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,16 @@ void idRenderModelOverlay::CreateOverlay( const idRenderModel *model, const idPl
}

// make temporary buffers for the building process
overlayVertex_t *overlayVerts = (overlayVertex_t *)_alloca( maxVerts * sizeof( *overlayVerts ) );
glIndex_t *overlayIndexes = (glIndex_t *)_alloca16( maxIndexes * sizeof( *overlayIndexes ) );
// DG: using Mem_MallocA() instead of alloca() to avoid stack overflows with large models
size_t vertSize = maxVerts * sizeof( overlayVertex_t );
bool vertsOnStack;
overlayVertex_t *overlayVerts = (overlayVertex_t *)Mem_MallocA( vertSize, vertsOnStack );

// Note: here we have two Mem_MallocA() calls, this relies on the stack being
// big enough for two alloca(ID_MAX_ALLOCA_SIZE) calls!
size_t idxSize = maxIndexes * sizeof( glIndex_t );
bool idxOnStack;
glIndex_t *overlayIndexes = (glIndex_t *)Mem_MallocA( idxSize, idxOnStack );

// pull out the triangles we need from the base surfaces
for ( surfNum = 0; surfNum < model->NumBaseSurfaces(); surfNum++ ) {
Expand Down Expand Up @@ -225,6 +233,9 @@ void idRenderModelOverlay::CreateOverlay( const idRenderModel *model, const idPl
materials[i]->surfaces.RemoveIndex( 0 );
}
}

Mem_FreeA(overlayVerts, vertsOnStack);
Mem_FreeA(overlayIndexes, idxOnStack);
}

/*
Expand Down
Loading

0 comments on commit 565fe07

Please sign in to comment.