Merge pull request #626 from DanielGibson/fix-ppc64be

Fix dhewm3 on 64bit Big Endian platforms like PPC64 BE
This commit is contained in:
Daniel Gibson 2024-11-07 14:54:06 +01:00 committed by GitHub
commit d94bb42d50
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 1890 additions and 4178 deletions

View file

@ -444,10 +444,10 @@ 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++;
@ -455,7 +455,7 @@ void * idClass::operator new( size_t s ) {
#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;
@ -466,10 +466,10 @@ 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++;
@ -477,7 +477,7 @@ void * idClass::operator new( size_t s, int, int, char *, int ) {
#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;
@ -497,10 +497,10 @@ 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 );
@ -508,10 +508,10 @@ void idClass::operator delete( void *ptr ) {
}
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 );

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

@ -146,7 +146,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 );
}

View file

@ -444,10 +444,10 @@ 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++;
@ -455,7 +455,7 @@ void * idClass::operator new( size_t s ) {
#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;
@ -466,10 +466,10 @@ 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++;
@ -477,7 +477,7 @@ void * idClass::operator new( size_t s, int, int, char *, int ) {
#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;
@ -497,10 +497,10 @@ 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 );
@ -508,10 +508,10 @@ void idClass::operator delete( void *ptr ) {
}
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 );

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

@ -146,7 +146,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 );
}

View file

@ -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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -79,7 +79,7 @@ extern ImGuiTextBuffer WriteImGuiStyleToCode( const ImGuiStyle& style, const ImG
namespace D3 {
namespace ImGuiHooks {
#include "proggyvector_font.h"
#include "proggyvector_font_base85.h"
static SDL_Window* sdlWindow = NULL;
ImGuiContext* imguiCtx = NULL;
@ -365,7 +365,7 @@ void NewFrame()
strcpy( fontCfg.Name, "ProggyVector" );
float fontSize = 18.0f * GetScale();
float fontSizeInt = roundf( fontSize ); // font sizes are supposed to be rounded to integers
ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(ProggyVector_compressed_data, ProggyVector_compressed_size, fontSizeInt, nullptr);
io.Fonts->AddFontFromMemoryCompressedBase85TTF(ProggyVector_compressed_data_base85, fontSizeInt, &fontCfg);
}
// Start the Dear ImGui frame