mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-12-12 21:41:48 +00:00
609 lines
13 KiB
C++
609 lines
13 KiB
C++
|
/*
|
||
|
===========================================================================
|
||
|
|
||
|
Doom 3 BFG Edition GPL Source Code
|
||
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||
|
|
||
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||
|
|
||
|
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||
|
|
||
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||
|
|
||
|
===========================================================================
|
||
|
*/
|
||
|
|
||
|
#include "precompiled.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#if defined( MACOS_X )
|
||
|
#include <signal.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <unistd.h>
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
idLib
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
idSys * idLib::sys = NULL;
|
||
|
idCommon * idLib::common = NULL;
|
||
|
idCVarSystem * idLib::cvarSystem = NULL;
|
||
|
idFileSystem * idLib::fileSystem = NULL;
|
||
|
int idLib::frameNumber = 0;
|
||
|
bool idLib::mainThreadInitialized = 0;
|
||
|
ID_TLS idLib::isMainThread = 0;
|
||
|
|
||
|
char idException::error[2048];
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idLib::Init
|
||
|
================
|
||
|
*/
|
||
|
void idLib::Init() {
|
||
|
|
||
|
assert( sizeof( bool ) == 1 );
|
||
|
|
||
|
isMainThread = 1;
|
||
|
mainThreadInitialized = 1; // note that the thread-local isMainThread is now valid
|
||
|
|
||
|
// initialize little/big endian conversion
|
||
|
Swap_Init();
|
||
|
|
||
|
// init string memory allocator
|
||
|
idStr::InitMemory();
|
||
|
|
||
|
// initialize generic SIMD implementation
|
||
|
idSIMD::Init();
|
||
|
|
||
|
// initialize math
|
||
|
idMath::Init();
|
||
|
|
||
|
// test idMatX
|
||
|
//idMatX::Test();
|
||
|
|
||
|
// test idPolynomial
|
||
|
#ifdef _DEBUG
|
||
|
idPolynomial::Test();
|
||
|
#endif
|
||
|
|
||
|
// initialize the dictionary string pools
|
||
|
idDict::Init();
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
idLib::ShutDown
|
||
|
================
|
||
|
*/
|
||
|
void idLib::ShutDown() {
|
||
|
|
||
|
// shut down the dictionary string pools
|
||
|
idDict::Shutdown();
|
||
|
|
||
|
// shut down the string memory allocator
|
||
|
idStr::ShutdownMemory();
|
||
|
|
||
|
// shut down the SIMD engine
|
||
|
idSIMD::Shutdown();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
Colors
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
idVec4 colorBlack = idVec4( 0.00f, 0.00f, 0.00f, 1.00f );
|
||
|
idVec4 colorWhite = idVec4( 1.00f, 1.00f, 1.00f, 1.00f );
|
||
|
idVec4 colorRed = idVec4( 1.00f, 0.00f, 0.00f, 1.00f );
|
||
|
idVec4 colorGreen = idVec4( 0.00f, 1.00f, 0.00f, 1.00f );
|
||
|
idVec4 colorBlue = idVec4( 0.00f, 0.00f, 1.00f, 1.00f );
|
||
|
idVec4 colorYellow = idVec4( 1.00f, 1.00f, 0.00f, 1.00f );
|
||
|
idVec4 colorMagenta= idVec4( 1.00f, 0.00f, 1.00f, 1.00f );
|
||
|
idVec4 colorCyan = idVec4( 0.00f, 1.00f, 1.00f, 1.00f );
|
||
|
idVec4 colorOrange = idVec4( 1.00f, 0.50f, 0.00f, 1.00f );
|
||
|
idVec4 colorPurple = idVec4( 0.60f, 0.00f, 0.60f, 1.00f );
|
||
|
idVec4 colorPink = idVec4( 0.73f, 0.40f, 0.48f, 1.00f );
|
||
|
idVec4 colorBrown = idVec4( 0.40f, 0.35f, 0.08f, 1.00f );
|
||
|
idVec4 colorLtGrey = idVec4( 0.75f, 0.75f, 0.75f, 1.00f );
|
||
|
idVec4 colorMdGrey = idVec4( 0.50f, 0.50f, 0.50f, 1.00f );
|
||
|
idVec4 colorDkGrey = idVec4( 0.25f, 0.25f, 0.25f, 1.00f );
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
PackColor
|
||
|
================
|
||
|
*/
|
||
|
dword PackColor( const idVec4 &color ) {
|
||
|
byte dx = idMath::Ftob( color.x * 255.0f );
|
||
|
byte dy = idMath::Ftob( color.y * 255.0f );
|
||
|
byte dz = idMath::Ftob( color.z * 255.0f );
|
||
|
byte dw = idMath::Ftob( color.w * 255.0f );
|
||
|
return ( dx << 0 ) | ( dy << 8 ) | ( dz << 16 ) | ( dw << 24 );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
UnpackColor
|
||
|
================
|
||
|
*/
|
||
|
void UnpackColor( const dword color, idVec4 &unpackedColor ) {
|
||
|
unpackedColor.Set( ( ( color >> 0 ) & 255 ) * ( 1.0f / 255.0f ),
|
||
|
( ( color >> 8 ) & 255 ) * ( 1.0f / 255.0f ),
|
||
|
( ( color >> 16 ) & 255 ) * ( 1.0f / 255.0f ),
|
||
|
( ( color >> 24 ) & 255 ) * ( 1.0f / 255.0f ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
PackColor
|
||
|
================
|
||
|
*/
|
||
|
dword PackColor( const idVec3 &color ) {
|
||
|
byte dx = idMath::Ftob( color.x * 255.0f );
|
||
|
byte dy = idMath::Ftob( color.y * 255.0f );
|
||
|
byte dz = idMath::Ftob( color.z * 255.0f );
|
||
|
return ( dx << 0 ) | ( dy << 8 ) | ( dz << 16 );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
UnpackColor
|
||
|
================
|
||
|
*/
|
||
|
void UnpackColor( const dword color, idVec3 &unpackedColor ) {
|
||
|
unpackedColor.Set( ( ( color >> 0 ) & 255 ) * ( 1.0f / 255.0f ),
|
||
|
( ( color >> 8 ) & 255 ) * ( 1.0f / 255.0f ),
|
||
|
( ( color >> 16 ) & 255 ) * ( 1.0f / 255.0f ) );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idLib::FatalError
|
||
|
===============
|
||
|
*/
|
||
|
void idLib::FatalError( const char *fmt, ... ) {
|
||
|
va_list argptr;
|
||
|
char text[MAX_STRING_CHARS];
|
||
|
|
||
|
va_start( argptr, fmt );
|
||
|
idStr::vsnPrintf( text, sizeof( text ), fmt, argptr );
|
||
|
va_end( argptr );
|
||
|
|
||
|
common->FatalError( "%s", text );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idLib::Error
|
||
|
===============
|
||
|
*/
|
||
|
void idLib::Error( const char *fmt, ... ) {
|
||
|
va_list argptr;
|
||
|
char text[MAX_STRING_CHARS];
|
||
|
|
||
|
va_start( argptr, fmt );
|
||
|
idStr::vsnPrintf( text, sizeof( text ), fmt, argptr );
|
||
|
va_end( argptr );
|
||
|
|
||
|
common->Error( "%s", text );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idLib::Warning
|
||
|
===============
|
||
|
*/
|
||
|
void idLib::Warning( const char *fmt, ... ) {
|
||
|
va_list argptr;
|
||
|
char text[MAX_STRING_CHARS];
|
||
|
|
||
|
va_start( argptr, fmt );
|
||
|
idStr::vsnPrintf( text, sizeof( text ), fmt, argptr );
|
||
|
va_end( argptr );
|
||
|
|
||
|
common->Warning( "%s", text );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idLib::WarningIf
|
||
|
===============
|
||
|
*/
|
||
|
void idLib::WarningIf( const bool test, const char *fmt, ... ) {
|
||
|
if ( !test ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
va_list argptr;
|
||
|
char text[MAX_STRING_CHARS];
|
||
|
|
||
|
va_start( argptr, fmt );
|
||
|
idStr::vsnPrintf( text, sizeof( text ), fmt, argptr );
|
||
|
va_end( argptr );
|
||
|
|
||
|
common->Warning( "%s", text );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idLib::Printf
|
||
|
===============
|
||
|
*/
|
||
|
void idLib::Printf( const char *fmt, ... ) {
|
||
|
va_list argptr;
|
||
|
va_start( argptr, fmt );
|
||
|
if ( common ) {
|
||
|
common->VPrintf( fmt, argptr );
|
||
|
}
|
||
|
va_end( argptr );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
idLib::PrintfIf
|
||
|
===============
|
||
|
*/
|
||
|
void idLib::PrintfIf( const bool test, const char *fmt, ... ) {
|
||
|
if ( !test ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
va_list argptr;
|
||
|
va_start( argptr, fmt );
|
||
|
common->VPrintf( fmt, argptr );
|
||
|
va_end( argptr );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
Byte order functions
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
// can't just use function pointers, or dll linkage can mess up
|
||
|
static short (*_BigShort)( short l );
|
||
|
static short (*_LittleShort)( short l );
|
||
|
static int (*_BigLong)( int l );
|
||
|
static int (*_LittleLong)( int l );
|
||
|
static float (*_BigFloat)( float l );
|
||
|
static float (*_LittleFloat)( float l );
|
||
|
static void (*_BigRevBytes)( void *bp, int elsize, int elcount );
|
||
|
static void (*_LittleRevBytes)( void *bp, int elsize, int elcount );
|
||
|
static void (*_LittleBitField)( void *bp, int elsize );
|
||
|
static void (*_SixtetsForInt)( byte *out, int src );
|
||
|
static int (*_IntForSixtets)( byte *in );
|
||
|
|
||
|
short BigShort( short l ) { return _BigShort( l ); }
|
||
|
short LittleShort( short l ) { return _LittleShort( l ); }
|
||
|
int BigLong( int l ) { return _BigLong( l ); }
|
||
|
int LittleLong( int l ) { return _LittleLong( l ); }
|
||
|
float BigFloat( float l ) { return _BigFloat( l ); }
|
||
|
float LittleFloat( float l ) { return _LittleFloat( l ); }
|
||
|
void BigRevBytes( void *bp, int elsize, int elcount ) { _BigRevBytes( bp, elsize, elcount ); }
|
||
|
void LittleRevBytes( void *bp, int elsize, int elcount ){ _LittleRevBytes( bp, elsize, elcount ); }
|
||
|
void LittleBitField( void *bp, int elsize ){ _LittleBitField( bp, elsize ); }
|
||
|
|
||
|
void SixtetsForInt( byte *out, int src) { _SixtetsForInt( out, src ); }
|
||
|
int IntForSixtets( byte *in ) { return _IntForSixtets( in ); }
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
ShortSwap
|
||
|
================
|
||
|
*/
|
||
|
short ShortSwap( short l ) {
|
||
|
byte b1,b2;
|
||
|
|
||
|
b1 = l&255;
|
||
|
b2 = (l>>8)&255;
|
||
|
|
||
|
return (b1<<8) + b2;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
ShortNoSwap
|
||
|
================
|
||
|
*/
|
||
|
short ShortNoSwap( short l ) {
|
||
|
return l;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
LongSwap
|
||
|
================
|
||
|
*/
|
||
|
int LongSwap ( int l ) {
|
||
|
byte b1,b2,b3,b4;
|
||
|
|
||
|
b1 = l&255;
|
||
|
b2 = (l>>8)&255;
|
||
|
b3 = (l>>16)&255;
|
||
|
b4 = (l>>24)&255;
|
||
|
|
||
|
return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
LongNoSwap
|
||
|
================
|
||
|
*/
|
||
|
int LongNoSwap( int l ) {
|
||
|
return l;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
FloatSwap
|
||
|
================
|
||
|
*/
|
||
|
float FloatSwap( float f ) {
|
||
|
union {
|
||
|
float f;
|
||
|
byte b[4];
|
||
|
} dat1, dat2;
|
||
|
|
||
|
|
||
|
dat1.f = f;
|
||
|
dat2.b[0] = dat1.b[3];
|
||
|
dat2.b[1] = dat1.b[2];
|
||
|
dat2.b[2] = dat1.b[1];
|
||
|
dat2.b[3] = dat1.b[0];
|
||
|
return dat2.f;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
FloatNoSwap
|
||
|
================
|
||
|
*/
|
||
|
float FloatNoSwap( float f ) {
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================================================================
|
||
|
RevBytesSwap
|
||
|
|
||
|
Reverses byte order in place.
|
||
|
|
||
|
INPUTS
|
||
|
bp bytes to reverse
|
||
|
elsize size of the underlying data type
|
||
|
elcount number of elements to swap
|
||
|
|
||
|
RESULTS
|
||
|
Reverses the byte order in each of elcount elements.
|
||
|
===================================================================== */
|
||
|
void RevBytesSwap( void *bp, int elsize, int elcount ) {
|
||
|
register unsigned char *p, *q;
|
||
|
|
||
|
p = ( unsigned char * ) bp;
|
||
|
|
||
|
if ( elsize == 2 ) {
|
||
|
q = p + 1;
|
||
|
while ( elcount-- ) {
|
||
|
*p ^= *q;
|
||
|
*q ^= *p;
|
||
|
*p ^= *q;
|
||
|
p += 2;
|
||
|
q += 2;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
while ( elcount-- ) {
|
||
|
q = p + elsize - 1;
|
||
|
while ( p < q ) {
|
||
|
*p ^= *q;
|
||
|
*q ^= *p;
|
||
|
*p ^= *q;
|
||
|
++p;
|
||
|
--q;
|
||
|
}
|
||
|
p += elsize >> 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
=====================================================================
|
||
|
RevBytesSwap
|
||
|
|
||
|
Reverses byte order in place, then reverses bits in those bytes
|
||
|
|
||
|
INPUTS
|
||
|
bp bitfield structure to reverse
|
||
|
elsize size of the underlying data type
|
||
|
|
||
|
RESULTS
|
||
|
Reverses the bitfield of size elsize.
|
||
|
===================================================================== */
|
||
|
void RevBitFieldSwap( void *bp, int elsize) {
|
||
|
int i;
|
||
|
unsigned char *p, t, v;
|
||
|
|
||
|
LittleRevBytes( bp, elsize, 1 );
|
||
|
|
||
|
p = (unsigned char *) bp;
|
||
|
while ( elsize-- ) {
|
||
|
v = *p;
|
||
|
t = 0;
|
||
|
for (i = 7; i>=0; i--) {
|
||
|
t <<= 1;
|
||
|
v >>= 1;
|
||
|
t |= v & 1;
|
||
|
}
|
||
|
*p++ = t;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
RevBytesNoSwap
|
||
|
================
|
||
|
*/
|
||
|
void RevBytesNoSwap( void *bp, int elsize, int elcount ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
RevBytesNoSwap
|
||
|
================
|
||
|
*/
|
||
|
void RevBitFieldNoSwap( void *bp, int elsize ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
SixtetsForIntLittle
|
||
|
================
|
||
|
*/
|
||
|
void SixtetsForIntLittle( byte *out, int src) {
|
||
|
byte *b = (byte *)&src;
|
||
|
out[0] = ( b[0] & 0xfc ) >> 2;
|
||
|
out[1] = ( ( b[0] & 0x3 ) << 4 ) + ( ( b[1] & 0xf0 ) >> 4 );
|
||
|
out[2] = ( ( b[1] & 0xf ) << 2 ) + ( ( b[2] & 0xc0 ) >> 6 );
|
||
|
out[3] = b[2] & 0x3f;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
SixtetsForIntBig
|
||
|
TTimo: untested - that's the version from initial base64 encode
|
||
|
================
|
||
|
*/
|
||
|
void SixtetsForIntBig( byte *out, int src) {
|
||
|
for( int i = 0 ; i < 4 ; i++ ) {
|
||
|
out[i] = src & 0x3f;
|
||
|
src >>= 6;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
IntForSixtetsLittle
|
||
|
================
|
||
|
*/
|
||
|
int IntForSixtetsLittle( byte *in ) {
|
||
|
int ret = 0;
|
||
|
byte *b = (byte *)&ret;
|
||
|
b[0] |= in[0] << 2;
|
||
|
b[0] |= ( in[1] & 0x30 ) >> 4;
|
||
|
b[1] |= ( in[1] & 0xf ) << 4;
|
||
|
b[1] |= ( in[2] & 0x3c ) >> 2;
|
||
|
b[2] |= ( in[2] & 0x3 ) << 6;
|
||
|
b[2] |= in[3];
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
IntForSixtetsBig
|
||
|
TTimo: untested - that's the version from initial base64 decode
|
||
|
================
|
||
|
*/
|
||
|
int IntForSixtetsBig( byte *in ) {
|
||
|
int ret = 0;
|
||
|
ret |= in[0];
|
||
|
ret |= in[1] << 6;
|
||
|
ret |= in[2] << 2*6;
|
||
|
ret |= in[3] << 3*6;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
Swap_Init
|
||
|
================
|
||
|
*/
|
||
|
void Swap_Init() {
|
||
|
byte swaptest[2] = {1,0};
|
||
|
|
||
|
// set the byte swapping variables in a portable manner
|
||
|
if ( *(short *)swaptest == 1) {
|
||
|
// little endian ex: x86
|
||
|
_BigShort = ShortSwap;
|
||
|
_LittleShort = ShortNoSwap;
|
||
|
_BigLong = LongSwap;
|
||
|
_LittleLong = LongNoSwap;
|
||
|
_BigFloat = FloatSwap;
|
||
|
_LittleFloat = FloatNoSwap;
|
||
|
_BigRevBytes = RevBytesSwap;
|
||
|
_LittleRevBytes = RevBytesNoSwap;
|
||
|
_LittleBitField = RevBitFieldNoSwap;
|
||
|
_SixtetsForInt = SixtetsForIntLittle;
|
||
|
_IntForSixtets = IntForSixtetsLittle;
|
||
|
} else {
|
||
|
// big endian ex: ppc
|
||
|
_BigShort = ShortNoSwap;
|
||
|
_LittleShort = ShortSwap;
|
||
|
_BigLong = LongNoSwap;
|
||
|
_LittleLong = LongSwap;
|
||
|
_BigFloat = FloatNoSwap;
|
||
|
_LittleFloat = FloatSwap;
|
||
|
_BigRevBytes = RevBytesNoSwap;
|
||
|
_LittleRevBytes = RevBytesSwap;
|
||
|
_LittleBitField = RevBitFieldSwap;
|
||
|
_SixtetsForInt = SixtetsForIntBig;
|
||
|
_IntForSixtets = IntForSixtetsBig;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==========
|
||
|
Swap_IsBigEndian
|
||
|
==========
|
||
|
*/
|
||
|
bool Swap_IsBigEndian() {
|
||
|
byte swaptest[2] = {1,0};
|
||
|
return *(short *)swaptest != 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
========================
|
||
|
BreakOnListGrowth
|
||
|
|
||
|
debug tool to find uses of idlist that are dynamically growing
|
||
|
========================
|
||
|
*/
|
||
|
void BreakOnListGrowth() {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
========================
|
||
|
BreakOnListDefault
|
||
|
========================
|
||
|
*/
|
||
|
void BreakOnListDefault() {
|
||
|
}
|