10 Nov 2007

This commit is contained in:
g-cont 2007-11-10 00:00:00 +03:00 committed by Alibek Omarov
parent f5f108aa02
commit 3bb2588593
4 changed files with 966 additions and 26 deletions

172
launch/crclib.c Normal file
View File

@ -0,0 +1,172 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// crclib.c - generate crc stuff
//=======================================================================
#include "launcher.h"
/*
=============================================================================
this is a 16 bit, non-reflected CRC using the polynomial 0x1021
and the initial and final xor values shown below... in other words, the
CCITT standard CRC used by XMODEM
=============================================================================
*/
#define CRC_INIT_VALUE 0xffff
#define CRC_XOR_VALUE 0x0000
static word crctable[256] =
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
static byte chktbl[1024] =
{
0x84, 0x47, 0x51, 0xc1, 0x93, 0x22, 0x21, 0x24, 0x2f, 0x66, 0x60, 0x4d, 0xb0, 0x7c, 0xda,
0x88, 0x54, 0x15, 0x2b, 0xc6, 0x6c, 0x89, 0xc5, 0x9d, 0x48, 0xee, 0xe6, 0x8a, 0xb5, 0xf4,
0xcb, 0xfb, 0xf1, 0x0c, 0x2e, 0xa0, 0xd7, 0xc9, 0x1f, 0xd6, 0x06, 0x9a, 0x09, 0x41, 0x54,
0x67, 0x46, 0xc7, 0x74, 0xe3, 0xc8, 0xb6, 0x5d, 0xa6, 0x36, 0xc4, 0xab, 0x2c, 0x7e, 0x85,
0xa8, 0xa4, 0xa6, 0x4d, 0x96, 0x19, 0x19, 0x9a, 0xcc, 0xd8, 0xac, 0x39, 0x5e, 0x3c, 0xf2,
0xf5, 0x5a, 0x72, 0xe5, 0xa9, 0xd1, 0xb3, 0x23, 0x82, 0x6f, 0x29, 0xcb, 0xd1, 0xcc, 0x71,
0xfb, 0xea, 0x92, 0xeb, 0x1c, 0xca, 0x4c, 0x70, 0xfe, 0x4d, 0xc9, 0x67, 0x43, 0x47, 0x94,
0xb9, 0x47, 0xbc, 0x3f, 0x01, 0xab, 0x7b, 0xa6, 0xe2, 0x76, 0xef, 0x5a, 0x7a, 0x29, 0x0b,
0x51, 0x54, 0x67, 0xd8, 0x1c, 0x14, 0x3e, 0x29, 0xec, 0xe9, 0x2d, 0x48, 0x67, 0xff, 0xed,
0x54, 0x4f, 0x48, 0xc0, 0xaa, 0x61, 0xf7, 0x78, 0x12, 0x03, 0x7a, 0x9e, 0x8b, 0xcf, 0x83,
0x7b, 0xae, 0xca, 0x7b, 0xd9, 0xe9, 0x53, 0x2a, 0xeb, 0xd2, 0xd8, 0xcd, 0xa3, 0x10, 0x25,
0x78, 0x5a, 0xb5, 0x23, 0x06, 0x93, 0xb7, 0x84, 0xd2, 0xbd, 0x96, 0x75, 0xa5, 0x5e, 0xcf,
0x4e, 0xe9, 0x50, 0xa1, 0xe6, 0x9d, 0xb1, 0xe3, 0x85, 0x66, 0x28, 0x4e, 0x43, 0xdc, 0x6e,
0xbb, 0x33, 0x9e, 0xf3, 0x0d, 0x00, 0xc1, 0xcf, 0x67, 0x34, 0x06, 0x7c, 0x71, 0xe3, 0x63,
0xb7, 0xb7, 0xdf, 0x92, 0xc4, 0xc2, 0x25, 0x5c, 0xff, 0xc3, 0x6e, 0xfc, 0xaa, 0x1e, 0x2a,
0x48, 0x11, 0x1c, 0x36, 0x68, 0x78, 0x86, 0x79, 0x30, 0xc3, 0xd6, 0xde, 0xbc, 0x3a, 0x2a,
0x6d, 0x1e, 0x46, 0xdd, 0xe0, 0x80, 0x1e, 0x44, 0x3b, 0x6f, 0xaf, 0x31, 0xda, 0xa2, 0xbd,
0x77, 0x06, 0x56, 0xc0, 0xb7, 0x92, 0x4b, 0x37, 0xc0, 0xfc, 0xc2, 0xd5, 0xfb, 0xa8, 0xda,
0xf5, 0x57, 0xa8, 0x18, 0xc0, 0xdf, 0xe7, 0xaa, 0x2a, 0xe0, 0x7c, 0x6f, 0x77, 0xb1, 0x26,
0xba, 0xf9, 0x2e, 0x1d, 0x16, 0xcb, 0xb8, 0xa2, 0x44, 0xd5, 0x2f, 0x1a, 0x79, 0x74, 0x87,
0x4b, 0x00, 0xc9, 0x4a, 0x3a, 0x65, 0x8f, 0xe6, 0x5d, 0xe5, 0x0a, 0x77, 0xd8, 0x1a, 0x14,
0x41, 0x75, 0xb1, 0xe2, 0x50, 0x2c, 0x93, 0x38, 0x2b, 0x6d, 0xf3, 0xf6, 0xdb, 0x1f, 0xcd,
0xff, 0x14, 0x70, 0xe7, 0x16, 0xe8, 0x3d, 0xf0, 0xe3, 0xbc, 0x5e, 0xb6, 0x3f, 0xcc, 0x81,
0x24, 0x67, 0xf3, 0x97, 0x3b, 0xfe, 0x3a, 0x96, 0x85, 0xdf, 0xe4, 0x6e, 0x3c, 0x85, 0x05,
0x0e, 0xa3, 0x2b, 0x07, 0xc8, 0xbf, 0xe5, 0x13, 0x82, 0x62, 0x08, 0x61, 0x69, 0x4b, 0x47,
0x62, 0x73, 0x44, 0x64, 0x8e, 0xe2, 0x91, 0xa6, 0x9a, 0xb7, 0xe9, 0x04, 0xb6, 0x54, 0x0c,
0xc5, 0xa9, 0x47, 0xa6, 0xc9, 0x08, 0xfe, 0x4e, 0xa6, 0xcc, 0x8a, 0x5b, 0x90, 0x6f, 0x2b,
0x3f, 0xb6, 0x0a, 0x96, 0xc0, 0x78, 0x58, 0x3c, 0x76, 0x6d, 0x94, 0x1a, 0xe4, 0x4e, 0xb8,
0x38, 0xbb, 0xf5, 0xeb, 0x29, 0xd8, 0xb0, 0xf3, 0x15, 0x1e, 0x99, 0x96, 0x3c, 0x5d, 0x63,
0xd5, 0xb1, 0xad, 0x52, 0xb8, 0x55, 0x70, 0x75, 0x3e, 0x1a, 0xd5, 0xda, 0xf6, 0x7a, 0x48,
0x7d, 0x44, 0x41, 0xf9, 0x11, 0xce, 0xd7, 0xca, 0xa5, 0x3d, 0x7a, 0x79, 0x7e, 0x7d, 0x25,
0x1b, 0x77, 0xbc, 0xf7, 0xc7, 0x0f, 0x84, 0x95, 0x10, 0x92, 0x67, 0x15, 0x11, 0x5a, 0x5e,
0x41, 0x66, 0x0f, 0x38, 0x03, 0xb2, 0xf1, 0x5d, 0xf8, 0xab, 0xc0, 0x02, 0x76, 0x84, 0x28,
0xf4, 0x9d, 0x56, 0x46, 0x60, 0x20, 0xdb, 0x68, 0xa7, 0xbb, 0xee, 0xac, 0x15, 0x01, 0x2f,
0x20, 0x09, 0xdb, 0xc0, 0x16, 0xa1, 0x89, 0xf9, 0x94, 0x59, 0x00, 0xc1, 0x76, 0xbf, 0xc1,
0x4d, 0x5d, 0x2d, 0xa9, 0x85, 0x2c, 0xd6, 0xd3, 0x14, 0xcc, 0x02, 0xc3, 0xc2, 0xfa, 0x6b,
0xb7, 0xa6, 0xef, 0xdd, 0x12, 0x26, 0xa4, 0x63, 0xe3, 0x62, 0xbd, 0x56, 0x8a, 0x52, 0x2b,
0xb9, 0xdf, 0x09, 0xbc, 0x0e, 0x97, 0xa9, 0xb0, 0x82, 0x46, 0x08, 0xd5, 0x1a, 0x8e, 0x1b,
0xa7, 0x90, 0x98, 0xb9, 0xbb, 0x3c, 0x17, 0x9a, 0xf2, 0x82, 0xba, 0x64, 0x0a, 0x7f, 0xca,
0x5a, 0x8c, 0x7c, 0xd3, 0x79, 0x09, 0x5b, 0x26, 0xbb, 0xbd, 0x25, 0xdf, 0x3d, 0x6f, 0x9a,
0x8f, 0xee, 0x21, 0x66, 0xb0, 0x8d, 0x84, 0x4c, 0x91, 0x45, 0xd4, 0x77, 0x4f, 0xb3, 0x8c,
0xbc, 0xa8, 0x99, 0xaa, 0x19, 0x53, 0x7c, 0x02, 0x87, 0xbb, 0x0b, 0x7c, 0x1a, 0x2d, 0xdf,
0x48, 0x44, 0x06, 0xd6, 0x7d, 0x0c, 0x2d, 0x35, 0x76, 0xae, 0xc4, 0x5f, 0x71, 0x85, 0x97,
0xc4, 0x3d, 0xef, 0x52, 0xbe, 0x00, 0xe4, 0xcd, 0x49, 0xd1, 0xd1, 0x1c, 0x3c, 0xd0, 0x1c,
0x42, 0xaf, 0xd4, 0xbd, 0x58, 0x34, 0x07, 0x32, 0xee, 0xb9, 0xb5, 0xea, 0xff, 0xd7, 0x8c,
0x0d, 0x2e, 0x2f, 0xaf, 0x87, 0xbb, 0xe6, 0x52, 0x71, 0x22, 0xf5, 0x25, 0x17, 0xa1, 0x82,
0x04, 0xc2, 0x4a, 0xbd, 0x57, 0xc6, 0xab, 0xc8, 0x35, 0x0c, 0x3c, 0xd9, 0xc2, 0x43, 0xdb,
0x27, 0x92, 0xcf, 0xb8, 0x25, 0x60, 0xfa, 0x21, 0x3b, 0x04, 0x52, 0xc8, 0x96, 0xba, 0x74,
0xe3, 0x67, 0x3e, 0x8e, 0x8d, 0x61, 0x90, 0x92, 0x59, 0xb6, 0x1a, 0x1c, 0x5e, 0x21, 0xc1,
0x65, 0xe5, 0xa6, 0x34, 0x05, 0x6f, 0xc5, 0x60, 0xb1, 0x83, 0xc1, 0xd5, 0xd5, 0xed, 0xd9,
0xc7, 0x11, 0x7b, 0x49, 0x7a, 0xf9, 0xf9, 0x84, 0x47, 0x9b, 0xe2, 0xa5, 0x82, 0xe0, 0xc2,
0x88, 0xd0, 0xb2, 0x58, 0x88, 0x7f, 0x45, 0x09, 0x67, 0x74, 0x61, 0xbf, 0xe6, 0x40, 0xe2,
0x9d, 0xc2, 0x47, 0x05, 0x89, 0xed, 0xcb, 0xbb, 0xb7, 0x27, 0xe7, 0xdc, 0x7a, 0xfd, 0xbf,
0xa8, 0xd0, 0xaa, 0x10, 0x39, 0x3c, 0x20, 0xf0, 0xd3, 0x6e, 0xb1, 0x72, 0xf8, 0xe6, 0x0f,
0xef, 0x37, 0xe5, 0x09, 0x33, 0x5a, 0x83, 0x43, 0x80, 0x4f, 0x65, 0x2f, 0x7c, 0x8c, 0x6a,
0xa0, 0x82, 0x0c, 0xd4, 0xd4, 0xfa, 0x81, 0x60, 0x3d, 0xdf, 0x06, 0xf1, 0x5f, 0x08, 0x0d,
0x6d, 0x43, 0xf2, 0xe3, 0x11, 0x7d, 0x80, 0x32, 0xc5, 0xfb, 0xc5, 0xd9, 0x27, 0xec, 0xc6,
0x4e, 0x65, 0x27, 0x76, 0x87, 0xa6, 0xee, 0xee, 0xd7, 0x8b, 0xd1, 0xa0, 0x5c, 0xb0, 0x42,
0x13, 0x0e, 0x95, 0x4a, 0xf2, 0x06, 0xc6, 0x43, 0x33, 0xf4, 0xc7, 0xf8, 0xe7, 0x1f, 0xdd,
0xe4, 0x46, 0x4a, 0x70, 0x39, 0x6c, 0xd0, 0xed, 0xca, 0xbe, 0x60, 0x3b, 0xd1, 0x7b, 0x57,
0x48, 0xe5, 0x3a, 0x79, 0xc1, 0x69, 0x33, 0x53, 0x1b, 0x80, 0xb8, 0x91, 0x7d, 0xb4, 0xf6,
0x17, 0x1a, 0x1d, 0x5a, 0x32, 0xd6, 0xcc, 0x71, 0x29, 0x3f, 0x28, 0xbb, 0xf3, 0x5e, 0x71,
0xb8, 0x43, 0xaf, 0xf8, 0xb9, 0x64, 0xef, 0xc4, 0xa5, 0x6c, 0x08, 0x53, 0xc7, 0x00, 0x10,
0x39, 0x4f, 0xdd, 0xe4, 0xb6, 0x19, 0x27, 0xfb, 0xb8, 0xf5, 0x32, 0x73, 0xe5, 0xcb, 0x32
};
void CRC_Init(word *crcvalue)
{
*crcvalue = CRC_INIT_VALUE;
}
void CRC_ProcessByte(word *crcvalue, byte data)
{
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
}
word CRC_Block (byte *start, int count)
{
word crc;
CRC_Init (&crc);
while(count--) CRC_ProcessByte( &crc, *start++ );
return crc;
}
/*
====================
CRC_BlockSequence
For proxy protecting
====================
*/
byte CRC_BlockSequence(byte *base, int length, int sequence)
{
int n, x;
word crc;
byte *p, chkb[60 + 4];
if (sequence < 0) sequence = abs(sequence);
p = chktbl + (sequence % (sizeof(chktbl) - 4));
if (length > 60) length = 60;
memcpy(chkb, base, length);
chkb[length] = p[0];
chkb[length + 1] = p[1];
chkb[length + 2] = p[2];
chkb[length + 3] = p[3];
length += 4;
crc = CRC_Block(chkb, length);
for (x = 0, n = 0; n < length; n++) x += chkb[n];
crc = (crc ^ x) & 0xff;
return crc;
}

393
launch/memlib.c Normal file
View File

@ -0,0 +1,393 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// memory.c - zone memory allocation from DarkPlaces
//=======================================================================
#include "launcher.h"
#define MEMCLUMPSIZE (65536 - 1536) // give malloc padding so we can't waste most of a page at the end
#define MEMUNIT 8 // smallest unit we care about is this many bytes
#define MEMBITS (MEMCLUMPSIZE / MEMUNIT)
#define MEMBITINTS (MEMBITS / 32)
#define MEMCLUMP_SENTINEL 0xABADCAFE
#define MEMHEADER_SENTINEL1 0xDEADF00D
#define MEMHEADER_SENTINEL2 0xDF
typedef struct memheader_s
{
struct memheader_s *next; // next and previous memheaders in chain belonging to pool
struct memheader_s *prev;
struct mempool_s *pool; // pool this memheader belongs to
struct memclump_s *clump; // clump this memheader lives in, NULL if not in a clump
size_t size; // size of the memory after the header (excluding header and sentinel2)
const char *filename; // file name and line where Mem_Alloc was called
uint fileline;
uint sentinel1; // should always be MEMHEADER_SENTINEL1
// immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte
}
memheader_t;
typedef struct memclump_s
{
byte block[MEMCLUMPSIZE];// contents of the clump
uint sentinel1; // should always be MEMCLUMP_SENTINEL
int bits[MEMBITINTS]; // if a bit is on, it means that the MEMUNIT bytes it represents are allocated, otherwise free
uint sentinel2; // should always be MEMCLUMP_SENTINEL
size_t blocksinuse; // if this drops to 0, the clump is freed
size_t largestavailable; // largest block of memory available
struct memclump_s *chain; // next clump in the chain
}
memclump_t;
typedef struct mempool_s
{
uint sentinel1; // should always be MEMHEADER_SENTINEL1
struct memheader_s *chain; // chain of individual memory allocations
struct memclump_s *clumpchain; // chain of clumps (if any)
size_t totalsize; // total memory allocated in this pool (inside memheaders)
size_t realsize; // total memory allocated in this pool (actual malloc total)
size_t lastchecksize; // updated each time the pool is displayed by memlist
struct mempool_s *next; // linked into global mempool list
const char *filename; // file name and line where Mem_AllocPool was called
int fileline;
char name[MAX_QPATH]; // name of the pool
uint sentinel2; // should always be MEMHEADER_SENTINEL1
}
mempool_t;
mempool_t *poolchain = NULL;
void _mem_copy(void *dest, void *src, size_t size, const char *filename, int fileline)
{
if (src == NULL || size <= 0) return; // nothing to copy
if (dest == NULL) Sys_Error("Mem_Copy: dest == NULL (called at %s:%i)", filename, fileline);
// copy block
memcpy( dest, src, size );
}
void _mem_set(void *dest, int set, size_t size, const char *filename, int fileline)
{
if(size <= 0) return; // nothing to set
if(dest == NULL) Sys_Error("Mem_Set: dest == NULL (called at %s:%i)", filename, fileline);
// fill block
memset( dest, set, size );
}
void *_mem_alloc(byte *poolptr, size_t size, const char *filename, int fileline)
{
int i, j, k, needed, endbit, largest;
memclump_t *clump, **clumpchainpointer;
memheader_t *mem;
mempool_t *pool = (mempool_t *)((byte *)poolptr);
if (size <= 0) return NULL;
if (poolptr == NULL) Sys_Error("Mem_Alloc: pool == NULL (alloc at %s:%i)", filename, fileline);
pool->totalsize += size;
if (size < 4096)
{
// clumping
needed = (sizeof(memheader_t) + size + sizeof(int) + (MEMUNIT - 1)) / MEMUNIT;
endbit = MEMBITS - needed;
for (clumpchainpointer = &pool->clumpchain;*clumpchainpointer;clumpchainpointer = &(*clumpchainpointer)->chain)
{
clump = *clumpchainpointer;
if (clump->sentinel1 != MEMCLUMP_SENTINEL)
Sys_Error("Mem_Alloc: trashed clump sentinel 1 (alloc at %s:%d)", filename, fileline);
if (clump->sentinel2 != MEMCLUMP_SENTINEL)
Sys_Error("Mem_Alloc: trashed clump sentinel 2 (alloc at %s:%d)", filename, fileline);
if (clump->largestavailable >= needed)
{
largest = 0;
for (i = 0;i < endbit;i++)
{
if (clump->bits[i >> 5] & (1 << (i & 31)))
continue;
k = i + needed;
for (j = i;i < k;i++)
if (clump->bits[i >> 5] & (1 << (i & 31)))
goto loopcontinue;
goto choseclump;
loopcontinue:;
if (largest < j - i)
largest = j - i;
}
// since clump falsely advertised enough space (nothing wrong
// with that), update largest count to avoid wasting time in
// later allocations
clump->largestavailable = largest;
}
}
pool->realsize += sizeof(memclump_t);
clump = malloc(sizeof(memclump_t));
if (clump == NULL) Sys_Error("Mem_Alloc: out of memory (alloc at %s:%i)", filename, fileline);
memset(clump, 0, sizeof(memclump_t));
*clumpchainpointer = clump;
clump->sentinel1 = MEMCLUMP_SENTINEL;
clump->sentinel2 = MEMCLUMP_SENTINEL;
clump->chain = NULL;
clump->blocksinuse = 0;
clump->largestavailable = MEMBITS - needed;
j = 0;
choseclump:
mem = (memheader_t *)((byte *) clump->block + j * MEMUNIT);
mem->clump = clump;
clump->blocksinuse += needed;
for (i = j + needed;j < i;j++) clump->bits[j >> 5] |= (1 << (j & 31));
}
else
{
// big allocations are not clumped
pool->realsize += sizeof(memheader_t) + size + sizeof(int);
mem = (memheader_t *)malloc(sizeof(memheader_t) + size + sizeof(int));
if (mem == NULL) Sys_Error("Mem_Alloc: out of memory (alloc at %s:%i)", filename, fileline);
mem->clump = NULL;
}
mem->filename = filename;
mem->fileline = fileline;
mem->size = size;
mem->pool = pool;
mem->sentinel1 = MEMHEADER_SENTINEL1;
// we have to use only a single byte for this sentinel, because it may not be aligned
// and some platforms can't use unaligned accesses
*((byte *) mem + sizeof(memheader_t) + mem->size) = MEMHEADER_SENTINEL2;
// append to head of list
mem->next = pool->chain;
mem->prev = NULL;
pool->chain = mem;
if (mem->next) mem->next->prev = mem;
memset((void *)((byte *) mem + sizeof(memheader_t)), 0, mem->size);
return (void *)((byte *) mem + sizeof(memheader_t));
}
static void _mem_freeblock(memheader_t *mem, const char *filename, int fileline)
{
int i, firstblock, endblock;
memclump_t *clump, **clumpchainpointer;
mempool_t *pool;
if (mem->sentinel1 != MEMHEADER_SENTINEL1) Sys_Error("Mem_Free: trashed header sentinel 1 (alloc at %s:%i, free at %s:%i)", mem->filename, mem->fileline, filename, fileline);
if (*((byte *) mem + sizeof(memheader_t) + mem->size) != MEMHEADER_SENTINEL2)
Sys_Error("Mem_Free: trashed header sentinel 2 (alloc at %s:%i, free at %s:%i)", mem->filename, mem->fileline, filename, fileline);
pool = mem->pool;
// unlink memheader from doubly linked list
if ((mem->prev ? mem->prev->next != mem : pool->chain != mem) || (mem->next && mem->next->prev != mem))
Sys_Error("Mem_Free: not allocated or double freed (free at %s:%i)", filename, fileline);
if (mem->prev) mem->prev->next = mem->next;
else pool->chain = mem->next;
if (mem->next) mem->next->prev = mem->prev;
// memheader has been unlinked, do the actual free now
pool->totalsize -= mem->size;
if ((clump = mem->clump))
{
if (clump->sentinel1 != MEMCLUMP_SENTINEL)
Sys_Error("Mem_Free: trashed clump sentinel 1 (free at %s:%i)", filename, fileline);
if (clump->sentinel2 != MEMCLUMP_SENTINEL)
Sys_Error("Mem_Free: trashed clump sentinel 2 (free at %s:%i)", filename, fileline);
firstblock = ((byte *) mem - (byte *) clump->block);
if (firstblock & (MEMUNIT - 1))
Sys_Error("Mem_Free: address not valid in clump (free at %s:%i)", filename, fileline);
firstblock /= MEMUNIT;
endblock = firstblock + ((sizeof(memheader_t) + mem->size + sizeof(int) + (MEMUNIT - 1)) / MEMUNIT);
clump->blocksinuse -= endblock - firstblock;
// could use &, but we know the bit is set
for (i = firstblock;i < endblock;i++)
clump->bits[i >> 5] -= (1 << (i & 31));
if (clump->blocksinuse <= 0)
{
// unlink from chain
for (clumpchainpointer = &pool->clumpchain;*clumpchainpointer;clumpchainpointer = &(*clumpchainpointer)->chain)
{
if (*clumpchainpointer == clump)
{
*clumpchainpointer = clump->chain;
break;
}
}
pool->realsize -= sizeof(memclump_t);
memset(clump, 0xBF, sizeof(memclump_t));
free(clump);
}
else
{
// clump still has some allocations
// force re-check of largest available space on next alloc
clump->largestavailable = MEMBITS - clump->blocksinuse;
}
}
else
{
pool->realsize -= sizeof(memheader_t) + mem->size + sizeof(int);
free(mem);
}
}
void _mem_free(void *data, const char *filename, int fileline)
{
if (data == NULL) Sys_Error("Mem_Free: data == NULL (called at %s:%i)", filename, fileline);
_mem_freeblock((memheader_t *)((byte *) data - sizeof(memheader_t)), filename, fileline);
}
void *_mem_realloc(byte *poolptr, void *memptr, size_t size, const char *filename, int fileline)
{
char *nb;
memheader_t *memhdr;
if (size <= 0) return memptr; // no need to reallocate
nb = _mem_alloc(poolptr, size, filename, fileline);
if( memptr ) // first allocate?
{
// get size of old block
memhdr = (memheader_t *)((byte *)memptr - sizeof(memheader_t));
_mem_copy( nb, memptr, memhdr->size, filename, fileline );
_mem_free( memptr, filename, fileline); // free unused old block
}
return (void *)nb;
}
void _mem_move(byte *poolptr, void **dest, void *src, size_t size, const char *filename, int fileline)
{
memheader_t *mem;
void *memptr = *dest;
if(!memptr) Sys_Error("Mem_Move: dest == NULL (called at %s:%i)", filename, fileline);
if(!src) Sys_Error("Mem_Move: src == NULL (called at %s:%i)", filename, fileline);
if (size <= 0)
{
// just free memory
_mem_free( memptr, filename, fileline );
*dest = src; // swap blocks
return;
}
mem = (memheader_t *)((byte *) memptr - sizeof(memheader_t)); // get size of old block
if(mem->size != size)
{
_mem_free( memptr, filename, fileline ); // release old buffer
memptr = _mem_alloc( poolptr, size, filename, fileline ); // alloc new size
}
else _mem_set( memptr, 0, size, filename, fileline ); // no need to reallocate buffer
_mem_copy( memptr, src, size, filename, fileline ); // move memory...
_mem_free( src, filename, fileline ); // ...and free old pointer
*dest = memptr;
}
byte *_mem_allocpool(const char *name, const char *filename, int fileline)
{
mempool_t *pool;
pool = (mempool_t *)malloc(sizeof(mempool_t));
if (pool == NULL) Sys_Error("Mem_AllocPool: out of memory (allocpool at %s:%i)", filename, fileline);
_mem_set(pool, 0, sizeof(mempool_t), filename, fileline );
// fill header
pool->sentinel1 = MEMHEADER_SENTINEL1;
pool->sentinel2 = MEMHEADER_SENTINEL1;
pool->filename = filename;
pool->fileline = fileline;
pool->chain = NULL;
pool->totalsize = 0;
pool->realsize = sizeof(mempool_t);
strlcpy (pool->name, name, sizeof (pool->name));
pool->next = poolchain;
poolchain = pool;
return (byte *)((mempool_t *)pool);
}
void _mem_freepool(byte **poolptr, const char *filename, int fileline)
{
mempool_t *pool = (mempool_t *)((byte *) *poolptr);
mempool_t **chainaddress;
if (pool)
{
// unlink pool from chain
for (chainaddress = &poolchain;*chainaddress && *chainaddress != pool;chainaddress = &((*chainaddress)->next));
if (*chainaddress != pool) Sys_Error("Mem_FreePool: pool already free (freepool at %s:%i)", filename, fileline);
if (pool->sentinel1 != MEMHEADER_SENTINEL1) Sys_Error("Mem_FreePool: trashed pool sentinel 1 (allocpool at %s:%i, freepool at %s:%i)", pool->filename, pool->fileline, filename, fileline);
if (pool->sentinel2 != MEMHEADER_SENTINEL1) Sys_Error("Mem_FreePool: trashed pool sentinel 2 (allocpool at %s:%i, freepool at %s:%i)", pool->filename, pool->fileline, filename, fileline);
*chainaddress = pool->next;
// free memory owned by the pool
while (pool->chain) _mem_freeblock(pool->chain, filename, fileline);
// free the pool itself
_mem_set(pool, 0xBF, sizeof(mempool_t), filename, fileline);
free(pool);
*poolptr = NULL;
}
}
void _mem_emptypool(byte *poolptr, const char *filename, int fileline)
{
mempool_t *pool = (mempool_t *)((byte *)poolptr);
if (poolptr == NULL) Sys_Error("Mem_EmptyPool: pool == NULL (emptypool at %s:%i)", filename, fileline);
if (pool->sentinel1 != MEMHEADER_SENTINEL1) Sys_Error("Mem_EmptyPool: trashed pool sentinel 1 (allocpool at %s:%i, emptypool at %s:%i)", pool->filename, pool->fileline, filename, fileline);
if (pool->sentinel2 != MEMHEADER_SENTINEL1) Sys_Error("Mem_EmptyPool: trashed pool sentinel 2 (allocpool at %s:%i, emptypool at %s:%i)", pool->filename, pool->fileline, filename, fileline);
// free memory owned by the pool
while (pool->chain) _mem_freeblock(pool->chain, filename, fileline);
}
void _mem_checkheadersentinels(void *data, const char *filename, int fileline)
{
memheader_t *mem;
if (data == NULL) Sys_Error("Mem_CheckSentinels: data == NULL (sentinel check at %s:%i)", filename, fileline);
mem = (memheader_t *)((byte *) data - sizeof(memheader_t));
if (mem->sentinel1 != MEMHEADER_SENTINEL1)
Sys_Error("Mem_CheckSentinels: trashed header sentinel 1 (block allocated at %s:%i, sentinel check at %s:%i)", mem->filename, mem->fileline, filename, fileline);
if (*((byte *) mem + sizeof(memheader_t) + mem->size) != MEMHEADER_SENTINEL2)
Sys_Error("Mem_CheckSentinels: trashed header sentinel 2 (block allocated at %s:%i, sentinel check at %s:%i)", mem->filename, mem->fileline, filename, fileline);
}
static void _mem_checkclumpsentinels(memclump_t *clump, const char *filename, int fileline)
{
// this isn't really very useful
if (clump->sentinel1 != MEMCLUMP_SENTINEL)
Sys_Error("Mem_CheckClumpSentinels: trashed sentinel 1 (sentinel check at %s:%i)", filename, fileline);
if (clump->sentinel2 != MEMCLUMP_SENTINEL)
Sys_Error("Mem_CheckClumpSentinels: trashed sentinel 2 (sentinel check at %s:%i)", filename, fileline);
}
void _mem_check(const char *filename, int fileline)
{
memheader_t *mem;
mempool_t *pool;
memclump_t *clump;
for (pool = poolchain;pool;pool = pool->next)
{
if (pool->sentinel1 != MEMHEADER_SENTINEL1)
Sys_Error("Mem_CheckSentinelsGlobal: trashed pool sentinel 1 (allocpool at %s:%i, sentinel check at %s:%i)", pool->filename, pool->fileline, filename, fileline);
if (pool->sentinel2 != MEMHEADER_SENTINEL1)
Sys_Error("Mem_CheckSentinelsGlobal: trashed pool sentinel 2 (allocpool at %s:%i, sentinel check at %s:%i)", pool->filename, pool->fileline, filename, fileline);
}
for (pool = poolchain;pool;pool = pool->next)
for (mem = pool->chain;mem;mem = mem->next)
_mem_checkheadersentinels((void *)((byte *) mem + sizeof(memheader_t)), filename, fileline);
for (pool = poolchain;pool;pool = pool->next)
for (clump = pool->clumpchain;clump;clump = clump->chain)
_mem_checkclumpsentinels(clump, filename, fileline);
}
/*
========================
Memory_Init
========================
*/
void InitMemory (void)
{
poolchain = NULL;//init mem chain
}

81
launch/memory.h Normal file
View File

@ -0,0 +1,81 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// basemem.h - base memory manager
//=======================================================================
#ifndef BASEMEMORY_H
#define BASEMEMORY_H
// give malloc padding so we can't waste most of a page at the end
#define MEMCLUMPSIZE (65536 - 1536)
// smallest unit we care about is this many bytes
#define MEMUNIT 8
#define MEMBITS (MEMCLUMPSIZE / MEMUNIT)
#define MEMBITINTS (MEMBITS / 32)
#define MEMCLUMP_SENTINEL 0xABADCAFE
#define MEMHEADER_SENTINEL1 0xDEADF00D
#define MEMHEADER_SENTINEL2 0xDF
#include <setjmp.h>
typedef struct memheader_s
{
// next and previous memheaders in chain belonging to pool
struct memheader_s *next;
struct memheader_s *prev;
struct mempool_s *pool;// pool this memheader belongs to
// clump this memheader lives in, NULL if not in a clump
struct memclump_s *clump;
size_t size; // size of the memory after the header (excluding header and sentinel2)
const char *filename;// file name and line where Mem_Alloc was called
int fileline;
uint sentinel1;// should always be MEMHEADER_SENTINEL1
// immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte
}
memheader_t;
typedef struct memclump_s
{
// contents of the clump
byte block[MEMCLUMPSIZE];
// should always be MEMCLUMP_SENTINEL
unsigned int sentinel1;
// if a bit is on, it means that the MEMUNIT bytes it represents are
// allocated, otherwise free
int bits[MEMBITINTS];
// should always be MEMCLUMP_SENTINEL
unsigned int sentinel2;
// if this drops to 0, the clump is freed
size_t blocksinuse;
// largest block of memory available (this is reset to an optimistic
// number when anything is freed, and updated when alloc fails the clump)
size_t largestavailable;
// next clump in the chain
struct memclump_s *chain;
}
memclump_t;
typedef struct mempool_s
{
unsigned int sentinel1;// should always be MEMHEADER_SENTINEL1
struct memheader_s *chain;// chain of individual memory allocations
struct memclump_s *clumpchain;// chain of clumps (if any)
size_t totalsize;// total memory allocated in this pool (inside memheaders)
size_t realsize;// total memory allocated in this pool (actual malloc total)
// updated each time the pool is displayed by memlist, shows change from previous time (unless pool was freed)
size_t lastchecksize;
struct mempool_s *next;// linked into global mempool list
const char *filename;// file name and line where Mem_AllocPool was called
int fileline;
char name[128];// name of the pool
unsigned int sentinel2;// should always be MEMHEADER_SENTINEL1
}
mempool_t;
extern byte *basepool;
extern byte *zonepool;
#endif//BASEMEMORY_H

View File

@ -5,16 +5,107 @@
#include "launcher.h"
char *strupper(char *start)
void strupper(const char *in, char *out, size_t size_out)
{
char *in;
in = start;
while (*in)
if (size_out == 0) return;
while (*in && size_out > 1)
{
*in = toupper(*in);
in++;
if (*in >= 'a' && *in <= 'z')
*out++ = *in++ + 'A' - 'a';
else *out++ = *in++;
size_out--;
}
return start;
*out = '\0';
}
void strlower(const char *in, char *out, size_t size_out)
{
if (size_out == 0) return;
while (*in && size_out > 1)
{
if (*in >= 'A' && *in <= 'Z')
*out++ = *in++ + 'a' - 'A';
else *out++ = *in++;
size_out--;
}
*out = '\0';
}
/*
============
strlength
returned string length
============
*/
int strlength( const char *string )
{
int len;
const char *p;
if( !string ) return 0;
len = 0;
p = string;
while( *p )
{
p++;
len++;
}
return len;
}
/*
============
qstrlength
skipped color prefixes
============
*/
int qstrlength( const char *string )
{
int len;
const char *p;
if( !string ) return 0;
len = 0;
p = string;
while( *p )
{
if(IsColorString( p ))
{
p += 2;
continue;
}
p++;
len++;
}
return len;
}
char caseupper(const char in )
{
char out;
if (in >= 'a' && in <= 'z')
out = in + 'A' - 'a';
else out = in;
return out;
}
char caselower(const char in )
{
char out;
if (in >= 'A' && in <= 'Z')
out = in + 'a' - 'A';
else out = in;
return out;
}
size_t strlcat(char *dst, const char *src, size_t siz)
@ -29,7 +120,7 @@ size_t strlcat(char *dst, const char *src, size_t siz)
dlen = d - dst;
n = siz - dlen;
if (n == 0) return(dlen + strlen(s));
if (n == 0) return(dlen + strlength(s));
while (*s != '\0')
{
if (n != 1)
@ -60,15 +151,188 @@ size_t strlcpy(char *dst, const char *src, size_t siz)
} while (--n != 0);
}
// Not enough room in dst, add NUL and traverse rest of src
// Not enough room in dst, add NULL and traverse rest of src
if (n == 0)
{
if (siz != 0) *d = '\0'; //NUL-terminate dst
if (siz != 0) *d = '\0'; //NULL-terminate dst
while (*s++);
}
return(s - src - 1); //count does not include NUL
return(s - src - 1); // count does not include NULL
}
int strtoint(const char *str)
{
int val = 0;
int c, sign;
if( !str ) return 0;
if(*str == '-')
{
sign = -1;
str++;
}
else sign = 1;
// check for hex
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') )
{
str += 2;
while(1)
{
c = *str++;
if (c >= '0' && c <= '9') val = (val<<4) + c - '0';
else if (c >= 'a' && c <= 'f') val = (val<<4) + c - 'a' + 10;
else if (c >= 'A' && c <= 'F') val = (val<<4) + c - 'A' + 10;
else return val * sign;
}
}
// check for character
if (str[0] == '\'') return sign * str[1];
// assume decimal
while (1)
{
c = *str++;
if (c <'0' || c > '9')
return val * sign;
val = val*10 + c - '0';
}
return 0;
}
float strtofloat(const char *str)
{
double val = 0;
int c, sign, decimal, total;
if( !str ) return 0.0f;
if (*str == '-')
{
sign = -1;
str++;
}
else sign = 1;
// check for hex
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
{
str += 2;
while (1)
{
c = *str++;
if (c >= '0' && c <= '9') val = (val * 16) + c - '0';
else if (c >= 'a' && c <= 'f') val = (val * 16) + c - 'a' + 10;
else if (c >= 'A' && c <= 'F') val = (val * 16) + c - 'A' + 10;
else return val * sign;
}
}
// check for character
if (str[0] == '\'') return sign * str[1];
// assume decimal
decimal = -1;
total = 0;
while (1)
{
c = *str++;
if (c == '.')
{
decimal = total;
continue;
}
if (c <'0' || c > '9') break;
val = val*10 + c - '0';
total++;
}
if(decimal == -1) return val * sign;
while (total > decimal)
{
val /= 10;
total--;
}
return val * sign;
}
void strtovec( float *vec, const char *str )
{
char *pstr, *pfront, buffer[MAX_QPATH];
int j;
strlcpy( buffer, str, MAX_QPATH );
pstr = pfront = buffer;
for ( j = 0; j < 3; j++ )
{
vec[j] = strtofloat( pfront );
// valid separator is space or ,
while( *pstr && (*pstr != ' ' || *pstr != ',' ))
pstr++;
if (!*pstr) break;
pstr++;
pfront = pstr;
}
if (j < 2) memset( vec, 0, sizeof(vec3_t));
}
/*
============
strlchr
find one charcster in string
============
*/
char *strlchr(const char *s, char c)
{
int len = strlength(s);
s += len;
while(len--) if(*--s == c) return (char *)s;
return 0;
}
int strlcasecmp(const char *s1, const char *s2, int n)
{
int c1, c2;
while (1)
{
c1 = *s1++;
c2 = *s2++;
if (!n--) return 0; // strings are equal until end point
if (c1 != c2)
{
if (c1 >= 'a' && c1 <= 'z') c1 -= ('a' - 'A');
if (c2 >= 'a' && c2 <= 'z') c2 -= ('a' - 'A');
if (c1 != c2) return -1; // strings not equal
}
if (!c1) return 0; // strings are equal
}
return -1;
}
int strlcmp (const char *s1, const char *s2, int n)
{
while (1)
{
if (!n--) return 0;
if (*s1 != *s2) return -1; // strings not equal
if (!*s1) return 0; // strings are equal
s1++, s2++;
}
return -1;
}
/*
====================
timestamp
@ -107,30 +371,37 @@ const char* tstamp( int format )
return timestamp;
}
/*
============
va
strcasestr
does a varargs printf into a temp buffer, so I don't need to have
varargs versions of all text functions.
FIXME: make this buffer size safe someday
search case - insensitive for string2 in string
============
*/
char *_va(const char *format, ...)
char *strcasestr( const char *string, const char *string2 )
{
va_list argptr;
static char string[8][1024], *s;
static int stringindex = 0;
int c, len;
s = string[stringindex];
stringindex = (stringindex + 1) & 7;
va_start (argptr, format);
vsprintf (s, format, argptr);
va_end (argptr);
return s;
if (!string || !string2) return NULL;
c = caselower( *string2 );
len = strlength( string2 );
while (string)
{
for ( ; *string && caselower( *string ) != c; string++ );
if (*string)
{
if(!strlcasecmp( string, string2, len ))
break;
string++;
}
else return NULL;
}
return (char *)string;
}
int vslprintf(char *buffer, size_t buffersize, const char *format, va_list args)
{
int result;
@ -155,4 +426,27 @@ int slprintf(char *buffer, size_t buffersize, const char *format, ...)
va_end (args);
return result;
}
/*
============
va
does a varargs printf into a temp buffer, so I don't need to have
varargs versions of all text functions.
FIXME: make this buffer size safe someday
============
*/
char *_va(const char *format, ...)
{
va_list argptr;
static char string[8][1024], *s;
static int stringindex = 0;
s = string[stringindex];
stringindex = (stringindex + 1) & 7;
va_start (argptr, format);
vslprintf (s, sizeof (string[0]), format, argptr);
va_end (argptr);
return s;
}