lots of type fixes; types.h is now a convenience wrapper on top of the standard uintN_t routines
This was SVN commit r334.
This commit is contained in:
parent
3856c2ab1e
commit
3abf9ac4b5
@ -1,5 +1,4 @@
|
||||
// switch off warnings before including stl files
|
||||
#pragma warning(disable : 4786) // identifier truncated to 255 chars
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "Types.h"
|
||||
#include "MapReader.h"
|
||||
@ -16,8 +15,6 @@
|
||||
extern CTerrain g_Terrain;
|
||||
extern CLightEnv g_LightEnv;
|
||||
|
||||
#include <set>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
// CMapReader constructor: nothing to do at the minute
|
||||
|
@ -1,5 +1,4 @@
|
||||
// switch off warnings before including stl files
|
||||
#pragma warning(disable : 4786) // identifier truncated to 255 chars
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "Types.h"
|
||||
#include "MapWriter.h"
|
||||
@ -13,9 +12,6 @@
|
||||
extern CTerrain g_Terrain;
|
||||
extern CLightEnv g_LightEnv;
|
||||
|
||||
#include <set>
|
||||
#include <stdio.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CMapWriter constructor: nothing to do at the minute
|
||||
CMapWriter::CMapWriter()
|
||||
|
@ -128,10 +128,10 @@ void CTerrain::CalcNormal(u32 i,u32 j,CVector3D& normal)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GetPatch: return the patch at (x,z) in patch space, or null if the patch is
|
||||
// out of bounds
|
||||
CPatch* CTerrain::GetPatch(int32 x,int32 z)
|
||||
CPatch* CTerrain::GetPatch(int32_t x,int32_t z)
|
||||
{
|
||||
if (x<0 || x>=int32(m_MapSizePatches)) return 0;
|
||||
if (z<0 || z>=int32(m_MapSizePatches)) return 0;
|
||||
if (x<0 || x>=int32_t(m_MapSizePatches)) return 0;
|
||||
if (z<0 || z>=int32_t(m_MapSizePatches)) return 0;
|
||||
return &m_Patches[(z*m_MapSizePatches)+x];
|
||||
}
|
||||
|
||||
@ -139,10 +139,10 @@ CPatch* CTerrain::GetPatch(int32 x,int32 z)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GetPatch: return the tile at (x,z) in tile space, or null if the tile is out
|
||||
// of bounds
|
||||
CMiniPatch* CTerrain::GetTile(int32 x,int32 z)
|
||||
CMiniPatch* CTerrain::GetTile(int32_t x,int32_t z)
|
||||
{
|
||||
if (x<0 || x>=int32(m_MapSize)-1) return 0;
|
||||
if (z<0 || z>=int32(m_MapSize)-1) return 0;
|
||||
if (x<0 || x>=int32_t(m_MapSize)-1) return 0;
|
||||
if (z<0 || z>=int32_t(m_MapSize)-1) return 0;
|
||||
|
||||
CPatch* patch=GetPatch(x/16,z/16);
|
||||
return &patch->m_MiniPatches[z%16][x%16];
|
||||
|
@ -51,10 +51,10 @@ public:
|
||||
|
||||
// get patch at given coordinates, expressed in patch-space; return 0 if
|
||||
// coordinates represent patch off the edge of the map
|
||||
CPatch* GetPatch(int32 x,int32 z);
|
||||
CPatch* GetPatch(int32_t x,int32_t z);
|
||||
// get tile at given coordinates, expressed in tile-space; return 0 if
|
||||
// coordinates represent tile off the edge of the map
|
||||
CMiniPatch* GetTile(int32 x,int32 z);
|
||||
CMiniPatch* GetTile(int32_t x,int32_t z);
|
||||
|
||||
// calculate the position of a given vertex
|
||||
void CalcPosition(u32 i,u32 j,CVector3D& pos);
|
||||
|
@ -418,7 +418,7 @@ private:
|
||||
|
||||
/// Used when reading in XML files
|
||||
// TODO Gee: Used?
|
||||
int16 m_Errors;
|
||||
int16_t m_Errors;
|
||||
|
||||
//@}
|
||||
//--------------------------------------------------------
|
||||
|
@ -216,10 +216,10 @@ void CGUIString::SetValue(const CStr &str)
|
||||
Parser.InputTaskType("start", "$ident[_=_$value]");
|
||||
Parser.InputTaskType("end", "/$ident");
|
||||
|
||||
_long position = 0;
|
||||
_long from=0; // the position in the raw string where the last tag ended
|
||||
_long from_nonraw=0; // like from only in position of the REAL string, with tags.
|
||||
_long curpos = 0;
|
||||
long position = 0;
|
||||
long from=0; // the position in the raw string where the last tag ended
|
||||
long from_nonraw=0; // like from only in position of the REAL string, with tags.
|
||||
long curpos = 0;
|
||||
|
||||
// Current Text Chunk
|
||||
CGUIString::TextChunk CurrentTextChunk;
|
||||
@ -246,8 +246,8 @@ void CGUIString::SetValue(const CStr &str)
|
||||
{
|
||||
// First check if there is another TagStart before a TagEnd,
|
||||
// in that case it's just a regular TagStart and we can continue.
|
||||
_long pos_left = str.Find(curpos+1, TagStart);
|
||||
_long pos_right = str.Find(curpos+1, TagEnd);
|
||||
long pos_left = str.Find(curpos+1, TagStart);
|
||||
long pos_right = str.Find(curpos+1, TagEnd);
|
||||
|
||||
if (pos_right == -1)
|
||||
{
|
||||
@ -428,7 +428,7 @@ void CGUIString::SetValue(const CStr &str)
|
||||
for (position=0, curpos=0;;position = curpos+1)
|
||||
{
|
||||
// Find the next word-delimiter.
|
||||
_long dl = m_RawString.Find(position, ' ');
|
||||
long dl = m_RawString.Find(position, ' ');
|
||||
|
||||
if (dl == -1)
|
||||
break;
|
||||
@ -441,7 +441,7 @@ void CGUIString::SetValue(const CStr &str)
|
||||
for (position=0, curpos=0;;position = curpos+1)
|
||||
{
|
||||
// Find the next word-delimiter.
|
||||
_long dl = m_RawString.Find(position, '-');
|
||||
long dl = m_RawString.Find(position, '-');
|
||||
|
||||
if (dl == -1)
|
||||
break;
|
||||
@ -454,7 +454,7 @@ void CGUIString::SetValue(const CStr &str)
|
||||
for (position=0, curpos=0;;position = curpos+1)
|
||||
{
|
||||
// Find the next word-delimiter.
|
||||
_long dl = m_RawString.Find(position, '\n');
|
||||
long dl = m_RawString.Find(position, '\n');
|
||||
|
||||
if (dl == -1)
|
||||
break;
|
||||
|
@ -228,7 +228,7 @@ public:
|
||||
* Set Width
|
||||
* @param width Width
|
||||
*/
|
||||
void SetWidth(const int16 &width) { m_Width = width; }
|
||||
void SetWidth(const int16_t &width) { m_Width = width; }
|
||||
|
||||
/**
|
||||
* Set X Position
|
||||
|
@ -19,7 +19,7 @@
|
||||
#ifndef __DETECT_H__
|
||||
#define __DETECT_H__
|
||||
|
||||
#include "misc.h"
|
||||
#include "lib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -28,7 +28,7 @@ extern "C" {
|
||||
|
||||
// useful for choosing a video mode. not called by detect().
|
||||
// if we fail, outputs are unchanged (assumed initialized to defaults)
|
||||
extern int get_cur_resolution(int& xres, int& yres);
|
||||
extern int get_cur_vmode(int* xres, int* yres, int* bpp, int* freq);
|
||||
|
||||
// useful for determining aspect ratio. not called by detect().
|
||||
// if we fail, outputs are unchanged (assumed initialized to defaults)
|
||||
|
@ -36,7 +36,7 @@
|
||||
// - call atexit (our exit handler would be called before its handler,
|
||||
// so we may have shut down something important already).
|
||||
|
||||
const int MAX_EXIT_FUNCS = 64;
|
||||
static const int MAX_EXIT_FUNCS = 32;
|
||||
|
||||
|
||||
static struct ExitFunc
|
||||
@ -111,3 +111,284 @@ void lib_init()
|
||||
{
|
||||
atexit(call_exit_funcs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
u32 fnv_hash(const void* buf, const size_t len)
|
||||
{
|
||||
u32 h = 0x811c9dc5;
|
||||
// give distinct values for different length 0 buffers.
|
||||
// value taken from FNV; it has no special significance.
|
||||
|
||||
const u8* p = (const u8*)buf;
|
||||
|
||||
// expected case: string
|
||||
if(!len)
|
||||
{
|
||||
while(*p)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x01000193;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_left = len;
|
||||
while(bytes_left != 0)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x01000193;
|
||||
|
||||
bytes_left--;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
u64 fnv_hash64(const void* buf, const size_t len)
|
||||
{
|
||||
u64 h = 0xCBF29CE484222325ull;
|
||||
// give distinct values for different length 0 buffers.
|
||||
// value taken from FNV; it has no special significance.
|
||||
|
||||
const u8* p = (const u8*)buf;
|
||||
|
||||
// expected case: string
|
||||
if(!len)
|
||||
{
|
||||
while(*p)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x100000001B3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_left = len;
|
||||
while(bytes_left != 0)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x100000001B3;
|
||||
|
||||
bytes_left--;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool is_pow2(const long n)
|
||||
{
|
||||
return (n != 0) && !(n & (n-1));
|
||||
}
|
||||
|
||||
|
||||
// return -1 if not an integral power of 2,
|
||||
// otherwise the base2 logarithm
|
||||
|
||||
int ilog2(const int n)
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
|
||||
__asm
|
||||
{
|
||||
mov ecx, [n]
|
||||
or eax, -1 // return value
|
||||
lea edx, [ecx-1]
|
||||
test ecx, edx // power of 2?
|
||||
jnz $ret
|
||||
bsf eax, ecx
|
||||
$ret:
|
||||
mov [n], eax
|
||||
}
|
||||
|
||||
return n;
|
||||
|
||||
#else
|
||||
|
||||
if(n || n & (n-1))
|
||||
return -1;
|
||||
|
||||
int i = 1, j = 0;
|
||||
for(; i != n; i += i, j++)
|
||||
;
|
||||
return j;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int ilog2(const float x)
|
||||
{
|
||||
u32 i = (u32&)x;
|
||||
u32 exp = (i >> 23) & 0xff;
|
||||
return (int)exp - 127;
|
||||
}
|
||||
|
||||
|
||||
uintptr_t round_up(const uintptr_t n, const uintptr_t multiple)
|
||||
{
|
||||
assert(multiple != 0);
|
||||
const uintptr_t padded = n + multiple-1;
|
||||
const uintptr_t remainder = padded % multiple;
|
||||
const uintptr_t result = padded - remainder;
|
||||
assert(n <= result && result < n+multiple);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
u16 addusw(u16 x, u16 y)
|
||||
{
|
||||
u32 t = x;
|
||||
return (u16)MIN(t+y, 0xffff);
|
||||
}
|
||||
|
||||
|
||||
u16 subusw(u16 x, u16 y)
|
||||
{
|
||||
long t = x;
|
||||
return (u16)(MAX(t-y, 0));
|
||||
}
|
||||
|
||||
|
||||
// provide fminf for non-C99 compilers
|
||||
#ifndef HAVE_C99
|
||||
|
||||
float fminf(float a, float b)
|
||||
{
|
||||
return (a < b)? a : b;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
long round(double x)
|
||||
{
|
||||
return (long)(x + 0.5);
|
||||
}
|
||||
|
||||
|
||||
// input in [0, 1); convert to u8 range
|
||||
u8 fp_to_u8(double in)
|
||||
{
|
||||
if(!(0 <= in && in < 1.0))
|
||||
{
|
||||
debug_warn("clampf not in [0,1)");
|
||||
return 255;
|
||||
}
|
||||
|
||||
int l = round(in * 255.0);
|
||||
assert((unsigned int)l <= 255);
|
||||
return (u8)l;
|
||||
}
|
||||
|
||||
|
||||
// input in [0, 1); convert to u16 range
|
||||
u16 fp_to_u16(double in)
|
||||
{
|
||||
if(!(0 <= in && in < 1.0))
|
||||
{
|
||||
debug_warn("clampf not in [0,1)");
|
||||
return 65535;
|
||||
}
|
||||
|
||||
long l = round(in * 65535.0);
|
||||
assert((unsigned long)l <= 65535);
|
||||
return (u16)l;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// big endian!
|
||||
void base32(const int len, const u8* in, u8* out)
|
||||
{
|
||||
int bits = 0;
|
||||
u32 pool = 0;
|
||||
|
||||
static u8 tbl[33] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
if(bits < 5)
|
||||
{
|
||||
pool <<= 8;
|
||||
pool |= *in++;
|
||||
bits += 8;
|
||||
}
|
||||
|
||||
bits -= 5;
|
||||
int c = (pool >> bits) & 31;
|
||||
*out++ = tbl[c];
|
||||
}
|
||||
}
|
||||
/*
|
||||
#ifndef _WIN32
|
||||
|
||||
char *_itoa(int value, char *out, int radix)
|
||||
{
|
||||
return _ltoa(value, out, radix);
|
||||
}
|
||||
|
||||
static const char digits[]="0123456789abcdef";
|
||||
|
||||
char *_ultoa(unsigned long int value, char *out, int radix)
|
||||
{
|
||||
char buf[21];
|
||||
char *p=buf+21;
|
||||
|
||||
do
|
||||
{
|
||||
*(--p)=digits[value % radix];
|
||||
value /= radix;
|
||||
}
|
||||
while (value);
|
||||
|
||||
memcpy(out, p, (buf+21)-p);
|
||||
out[(buf+21)-p]=0;
|
||||
return out;
|
||||
}
|
||||
|
||||
char *_ltoa(long val, char *out, int radix)
|
||||
{
|
||||
char buf[21];
|
||||
char *p=buf+21;
|
||||
bool sign=val < 0;
|
||||
if (sign) val=-val;
|
||||
|
||||
do
|
||||
{
|
||||
*(--p)=digits[val % radix];
|
||||
val /= radix;
|
||||
}
|
||||
while (val);
|
||||
|
||||
if (sign) *(--p) = '-';
|
||||
|
||||
memcpy(out, p, (buf+21)-p);
|
||||
out[(buf+21)-p]=0;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
||||
|
115
source/lib/lib.h
115
source/lib/lib.h
@ -20,19 +20,12 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "misc.h"
|
||||
#include "posix.h"
|
||||
#include "types.h"
|
||||
|
||||
#include "sysdep/sysdep.h"
|
||||
|
||||
|
||||
// yikes! avoid template warning spew on VC6
|
||||
#if _MSC_VER <= 1200
|
||||
#pragma warning(disable:4786)
|
||||
#endif
|
||||
|
||||
|
||||
// tell STL not to generate exceptions, if compiling without exceptions
|
||||
// (usually done for performance reasons).
|
||||
#ifdef CONFIG_DISABLE_EXCEPTIONS
|
||||
@ -45,14 +38,16 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#define STMT(STMT_code__) do { STMT_code__; } while(0)
|
||||
|
||||
// must not be used before main entered! (i.e. not from NLS constructors / functions)
|
||||
#define ONCE(ONCE_code__)\
|
||||
STMT(\
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;\
|
||||
/* static pthread_mutex_t ONCE_mutex__ = PTHREAD_MUTEX_INITIALIZER;\
|
||||
if(pthread_mutex_trylock(&ONCE_mutex__) == 0)\*/\
|
||||
static bool ONCE_done__ = false;\
|
||||
if(pthread_mutex_trylock(&(mutex)) == 0 && !ONCE_done__)\
|
||||
if(!ONCE_done__)\
|
||||
{\
|
||||
ONCE_done__ = true;\
|
||||
ONCE_code__;\
|
||||
@ -191,7 +186,105 @@ extern int atexit2(void* func, uintptr_t arg, CallConvention cc = CC_CDECL_1);
|
||||
// no parameters, cdecl (CC_CDECL_0)
|
||||
extern int atexit2(void* func);
|
||||
|
||||
#include "posix.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
extern u32 fnv_hash(const void* buf, const size_t len = 0);
|
||||
extern u64 fnv_hash64(const void* buf, const size_t len);
|
||||
|
||||
// hash (currently FNV) of a filename
|
||||
typedef u32 FnHash;
|
||||
|
||||
|
||||
#ifndef min
|
||||
inline int min(int a, int b)
|
||||
{
|
||||
return (a < b)? a : b;
|
||||
}
|
||||
|
||||
inline int max(int a, int b)
|
||||
{
|
||||
return (a > b)? a : b;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern u16 addusw(u16 x, u16 y);
|
||||
extern u16 subusw(u16 x, u16 y);
|
||||
|
||||
|
||||
|
||||
|
||||
static inline u16 read_le16(const void* p)
|
||||
{
|
||||
#ifdef BIG_ENDIAN
|
||||
const u8* _p = (const u8*)p;
|
||||
return (u16)_p[0] | (u16)_p[1] << 8;
|
||||
#else
|
||||
return *(u16*)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline u32 read_le32(const void* p)
|
||||
{
|
||||
#ifdef BIG_ENDIAN
|
||||
u32 t = 0;
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
t <<= 8;
|
||||
t |= *((const u8*)p)++;
|
||||
}
|
||||
return t;
|
||||
#else
|
||||
return *(u32*)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
extern bool is_pow2(long n);
|
||||
|
||||
|
||||
// return -1 if not an integral power of 2,
|
||||
// otherwise the base2 logarithm
|
||||
extern int ilog2(const int n);
|
||||
|
||||
|
||||
extern uintptr_t round_up(uintptr_t val, uintptr_t multiple);
|
||||
|
||||
|
||||
// provide fminf for non-C99 compilers
|
||||
#ifndef HAVE_C99
|
||||
extern float fminf(float, float);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
extern long round(double);
|
||||
extern u16 fp_to_u16(double in);
|
||||
|
||||
// big endian!
|
||||
extern void base32(const int len, const u8* in, u8* out);
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
char *_itoa(int, char *, int radix);
|
||||
char *_ultoa(unsigned long int, char*, int radix);
|
||||
char *_ltoa(long, char *, int radix);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -21,271 +21,3 @@
|
||||
#include "lib.h"
|
||||
#include "misc.h"
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
u32 fnv_hash(const void* buf, const size_t len)
|
||||
{
|
||||
u32 h = 0x811c9dc5;
|
||||
// give distinct values for different length 0 buffers.
|
||||
// value taken from FNV; it has no special significance.
|
||||
|
||||
const u8* p = (const u8*)buf;
|
||||
|
||||
// expected case: string
|
||||
if(!len)
|
||||
{
|
||||
while(*p)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x01000193;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_left = len;
|
||||
while(bytes_left != 0)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x01000193;
|
||||
|
||||
bytes_left--;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
u64 fnv_hash64(const void* buf, const size_t len)
|
||||
{
|
||||
u64 h = 0xCBF29CE484222325ull;
|
||||
// give distinct values for different length 0 buffers.
|
||||
// value taken from FNV; it has no special significance.
|
||||
|
||||
const u8* p = (const u8*)buf;
|
||||
|
||||
// expected case: string
|
||||
if(!len)
|
||||
{
|
||||
while(*p)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x100000001B3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bytes_left = len;
|
||||
while(bytes_left != 0)
|
||||
{
|
||||
h ^= *p++;
|
||||
h *= 0x100000001B3;
|
||||
|
||||
bytes_left--;
|
||||
}
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool is_pow2(const long n)
|
||||
{
|
||||
return (n != 0) && !(n & (n-1));
|
||||
}
|
||||
|
||||
|
||||
// return -1 if not an integral power of 2,
|
||||
// otherwise the base2 logarithm
|
||||
|
||||
int ilog2(const int n)
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
|
||||
__asm
|
||||
{
|
||||
mov ecx, [n]
|
||||
or eax, -1 // return value
|
||||
lea edx, [ecx-1]
|
||||
test ecx, edx // power of 2?
|
||||
jnz $ret
|
||||
bsf eax, ecx
|
||||
$ret:
|
||||
mov [n], eax
|
||||
}
|
||||
|
||||
return n;
|
||||
|
||||
#else
|
||||
|
||||
if(n || n & (n-1))
|
||||
return -1;
|
||||
|
||||
int i = 1, j = 0;
|
||||
for(; i != n; i += i, j++)
|
||||
;
|
||||
return j;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int ilog2(const float x)
|
||||
{
|
||||
u32 i = (u32&)x;
|
||||
u32 exp = (i >> 23) & 0xff;
|
||||
return (int)exp - 127;
|
||||
}
|
||||
|
||||
|
||||
uintptr_t round_up(uintptr_t val, uintptr_t multiple)
|
||||
{
|
||||
val += multiple-1;
|
||||
val -= val % multiple;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
u16 addusw(u16 x, u16 y)
|
||||
{
|
||||
u32 t = x;
|
||||
return (u16)MIN(t+y, 0xffff);
|
||||
}
|
||||
|
||||
|
||||
u16 subusw(u16 x, u16 y)
|
||||
{
|
||||
long t = x;
|
||||
return (u16)(MAX(t-y, 0));
|
||||
}
|
||||
|
||||
|
||||
// provide fminf for non-C99 compilers
|
||||
#ifndef HAVE_C99
|
||||
|
||||
float fminf(float a, float b)
|
||||
{
|
||||
return (a < b)? a : b;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
long round(double x)
|
||||
{
|
||||
return (long)(x + 0.5);
|
||||
}
|
||||
|
||||
|
||||
// input in [0, 1); convert to u8 range
|
||||
u8 fp_to_u8(double in)
|
||||
{
|
||||
if(!(0 <= in && in < 1.0))
|
||||
{
|
||||
debug_warn("clampf not in [0,1)");
|
||||
return 255;
|
||||
}
|
||||
|
||||
int l = round(in * 255.0);
|
||||
assert((unsigned int)l <= 255);
|
||||
return (u8)l;
|
||||
}
|
||||
|
||||
|
||||
// input in [0, 1); convert to u16 range
|
||||
u16 fp_to_u16(double in)
|
||||
{
|
||||
if(!(0 <= in && in < 1.0))
|
||||
{
|
||||
debug_warn("clampf not in [0,1)");
|
||||
return 65535;
|
||||
}
|
||||
|
||||
long l = round(in * 65535.0);
|
||||
assert((unsigned long)l <= 65535);
|
||||
return (u16)l;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// big endian!
|
||||
void base32(const int len, const u8* in, u8* out)
|
||||
{
|
||||
int bits = 0;
|
||||
u32 pool = 0;
|
||||
|
||||
static u8 tbl[33] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
if(bits < 5)
|
||||
{
|
||||
pool <<= 8;
|
||||
pool |= *in++;
|
||||
bits += 8;
|
||||
}
|
||||
|
||||
bits -= 5;
|
||||
int c = (pool >> bits) & 31;
|
||||
*out++ = tbl[c];
|
||||
}
|
||||
}
|
||||
/*
|
||||
#ifndef _WIN32
|
||||
|
||||
char *_itoa(int value, char *out, int radix)
|
||||
{
|
||||
return _ltoa(value, out, radix);
|
||||
}
|
||||
|
||||
static const char digits[]="0123456789abcdef";
|
||||
|
||||
char *_ultoa(unsigned long int value, char *out, int radix)
|
||||
{
|
||||
char buf[21];
|
||||
char *p=buf+21;
|
||||
|
||||
do
|
||||
{
|
||||
*(--p)=digits[value % radix];
|
||||
value /= radix;
|
||||
}
|
||||
while (value);
|
||||
|
||||
memcpy(out, p, (buf+21)-p);
|
||||
out[(buf+21)-p]=0;
|
||||
return out;
|
||||
}
|
||||
|
||||
char *_ltoa(long val, char *out, int radix)
|
||||
{
|
||||
char buf[21];
|
||||
char *p=buf+21;
|
||||
bool sign=val < 0;
|
||||
if (sign) val=-val;
|
||||
|
||||
do
|
||||
{
|
||||
*(--p)=digits[val % radix];
|
||||
val /= radix;
|
||||
}
|
||||
while (val);
|
||||
|
||||
if (sign) *(--p) = '-';
|
||||
|
||||
memcpy(out, p, (buf+21)-p);
|
||||
out[(buf+21)-p]=0;
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
@ -19,102 +19,6 @@
|
||||
#ifndef __MISC_H__
|
||||
#define __MISC_H__
|
||||
|
||||
#include "types.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// FNV1-A hash - good for strings.
|
||||
// if len = 0 (default), treat buf as a C-string;
|
||||
// otherwise, hash <len> bytes of buf.
|
||||
extern u32 fnv_hash(const void* buf, const size_t len = 0);
|
||||
extern u64 fnv_hash64(const void* buf, const size_t len);
|
||||
|
||||
// hash (currently FNV) of a filename
|
||||
typedef u32 FnHash;
|
||||
|
||||
|
||||
#ifndef min
|
||||
inline int min(int a, int b)
|
||||
{
|
||||
return (a < b)? a : b;
|
||||
}
|
||||
|
||||
inline int max(int a, int b)
|
||||
{
|
||||
return (a > b)? a : b;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern u16 addusw(u16 x, u16 y);
|
||||
extern u16 subusw(u16 x, u16 y);
|
||||
|
||||
|
||||
|
||||
|
||||
static inline u16 read_le16(const void* p)
|
||||
{
|
||||
#ifdef BIG_ENDIAN
|
||||
const u8* _p = (const u8*)p;
|
||||
return (u16)_p[0] | (u16)_p[1] << 8;
|
||||
#else
|
||||
return *(u16*)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline u32 read_le32(const void* p)
|
||||
{
|
||||
#ifdef BIG_ENDIAN
|
||||
u32 t = 0;
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
t <<= 8;
|
||||
t |= *((const u8*)p)++;
|
||||
}
|
||||
return t;
|
||||
#else
|
||||
return *(u32*)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
extern bool is_pow2(long n);
|
||||
|
||||
|
||||
// return -1 if not an integral power of 2,
|
||||
// otherwise the base2 logarithm
|
||||
extern int ilog2(const int n);
|
||||
|
||||
|
||||
extern uintptr_t round_up(uintptr_t val, uintptr_t multiple);
|
||||
|
||||
|
||||
// provide fminf for non-C99 compilers
|
||||
#ifndef HAVE_C99
|
||||
extern float fminf(float, float);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
extern long round(double);
|
||||
extern u16 fp_to_u16(double in);
|
||||
|
||||
// big endian!
|
||||
extern void base32(const int len, const u8* in, u8* out);
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
char *_itoa(int, char *, int radix);
|
||||
char *_ultoa(unsigned long int, char*, int radix);
|
||||
char *_ltoa(long, char *, int radix);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <math.h>
|
||||
@ -8,19 +7,21 @@
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <deque>
|
||||
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#pragma warning(disable:4996)
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4996) // function is deprecated
|
||||
#pragma warning(disable:4786) // identifier truncated to 255 chars
|
||||
#endif
|
@ -753,7 +753,7 @@ struct Free
|
||||
};
|
||||
|
||||
// free all allocated IOs, so they aren't seen as resource leaks.
|
||||
static void io_cleanup(void)
|
||||
static void io_shutdown(void)
|
||||
{
|
||||
std::for_each(all_ios.begin(), all_ios.end(), Free());
|
||||
}
|
||||
@ -761,7 +761,7 @@ static void io_cleanup(void)
|
||||
|
||||
static Handle io_alloc()
|
||||
{
|
||||
ONCE(atexit(io_cleanup));
|
||||
ONCE(atexit(io_shutdown));
|
||||
/*
|
||||
// grab from freelist
|
||||
if(!free_ios.empty())
|
||||
|
@ -21,13 +21,8 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "lib.h"
|
||||
#include "mem.h"
|
||||
#include "font.h"
|
||||
#include "h_mgr.h"
|
||||
#include "vfs.h"
|
||||
#include "tex.h"
|
||||
#include "res.h"
|
||||
#include "ogl.h"
|
||||
#include "misc.h"
|
||||
|
||||
/*
|
||||
|
||||
@ -108,7 +103,7 @@ int build_font(const char* in_ttf, const char* out_fnt, const char* out_raw, int
|
||||
|
||||
struct Font
|
||||
{
|
||||
Handle ht;
|
||||
Handle ht; // handle to font texture
|
||||
uint list_base;
|
||||
};
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "lib.h"
|
||||
#include "misc.h"
|
||||
#include "h_mgr.h"
|
||||
#include "mem.h"
|
||||
|
||||
@ -235,7 +234,7 @@ static HDATA* h_data(const Handle h, const H_Type type)
|
||||
|
||||
|
||||
|
||||
static void cleanup(void)
|
||||
void h_mgr_shutdown(void)
|
||||
{
|
||||
// close open handles
|
||||
for(i32 i = 0; i < last_in_use; i++)
|
||||
@ -372,7 +371,7 @@ int h_free(Handle& h, H_Type type)
|
||||
// any further params are passed to type's init routine
|
||||
Handle h_alloc(H_Type type, const char* fn, uint flags, ...)
|
||||
{
|
||||
ONCE(atexit2(cleanup));
|
||||
ONCE(atexit2(h_mgr_shutdown));
|
||||
|
||||
Handle err;
|
||||
|
||||
|
@ -19,16 +19,15 @@
|
||||
#ifndef H_MGR_H__
|
||||
#define H_MGR_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h> // type init routines get va_list of args
|
||||
|
||||
#include "../types.h"
|
||||
#include "lib.h"
|
||||
|
||||
|
||||
// handle type (for 'type safety' - can't use a texture handle as a sound)
|
||||
|
||||
|
||||
//
|
||||
// rationale: we could use the destructor passed to h_alloc to identify
|
||||
// the handle, but it's good to have a list of all types, and we avoid having
|
||||
@ -184,10 +183,6 @@ extern int h_reload(const char* fn);
|
||||
|
||||
extern int res_cur_scope;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // #ifndef H_MGR_H__
|
||||
|
||||
|
@ -3,14 +3,8 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "lib.h"
|
||||
#include "types.h"
|
||||
#include "mem.h"
|
||||
#include "res.h"
|
||||
#include "h_mgr.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@ -23,7 +17,7 @@ static void heap_free(void* const p, const size_t size, const uintptr_t ctx)
|
||||
}
|
||||
|
||||
|
||||
static void* heap_alloc(const size_t size, const int align, uintptr_t& ctx, MEM_DTOR& dtor)
|
||||
static void* heap_alloc(const size_t size, const size_t align, uintptr_t& ctx, MEM_DTOR& dtor)
|
||||
{
|
||||
u8* org_p = (u8*)malloc(size+align-1);
|
||||
u8* p = (u8*)round_up((uintptr_t)org_p, align);
|
||||
@ -55,7 +49,7 @@ static void pool_free(void* const p, const size_t size, const uintptr_t ctx)
|
||||
}
|
||||
|
||||
|
||||
static void* pool_alloc(const size_t size, const uint align, uintptr_t& ctx, MEM_DTOR& dtor)
|
||||
static void* pool_alloc(const size_t size, const size_t align, uintptr_t& ctx, MEM_DTOR& dtor)
|
||||
{
|
||||
if(!pool)
|
||||
{
|
||||
@ -208,7 +202,7 @@ Handle mem_assign(void* p, size_t size, uint flags /* = 0 */, MEM_DTOR dtor /* =
|
||||
{
|
||||
// we've already allocated that pointer - returns its handle
|
||||
Handle hm = find_alloc(p);
|
||||
if(hm)
|
||||
if(hm > 0)
|
||||
return hm;
|
||||
|
||||
if(!p || !size)
|
||||
@ -233,7 +227,7 @@ Handle mem_assign(void* p, size_t size, uint flags /* = 0 */, MEM_DTOR dtor /* =
|
||||
}
|
||||
|
||||
|
||||
void* mem_alloc(size_t size, const uint align, uint flags, Handle* phm)
|
||||
void* mem_alloc(size_t size, const size_t align, uint flags, Handle* phm)
|
||||
{
|
||||
if(phm)
|
||||
*phm = 0;
|
||||
|
@ -19,7 +19,7 @@ enum
|
||||
MEM_ZERO = 0x1000
|
||||
};
|
||||
|
||||
extern void* mem_alloc(size_t size, uint align = 1, uint flags = 0, Handle* ph = 0);
|
||||
extern void* mem_alloc(size_t size, size_t align = 1, uint flags = 0, Handle* ph = 0);
|
||||
|
||||
#define mem_free(p) mem_free_p((void*&)p)
|
||||
extern int mem_free_p(void*& p);
|
||||
|
@ -21,12 +21,8 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "lib.h"
|
||||
#include "vfs.h"
|
||||
#include "tex.h"
|
||||
#include "mem.h"
|
||||
#include "res.h"
|
||||
#include "ogl.h"
|
||||
#include "h_mgr.h"
|
||||
#include "misc.h"
|
||||
|
||||
|
||||
#define NO_JP2
|
||||
@ -37,15 +33,17 @@
|
||||
#include <jasper/jasper.h>
|
||||
#endif
|
||||
|
||||
|
||||
// libpng includes windows.h - prevent that, and define what it needs.
|
||||
#define _WINDOWS_
|
||||
#define WINAPI __stdcall
|
||||
#define WINAPIV __cdecl
|
||||
|
||||
#ifndef NO_PNG
|
||||
# include <libpng10/png.h>
|
||||
# ifdef _MSC_VER
|
||||
# pragma comment(lib, "libpng10.lib")
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// filled by loader funcs => declare here
|
||||
@ -469,7 +467,7 @@ struct MemRange
|
||||
};
|
||||
|
||||
|
||||
static void png_read_fn(png_struct* png_ptr, u8* data, png_size_t length)
|
||||
static void png_read_fn(png_struct* const png_ptr, u8* const data, const png_size_t length)
|
||||
{
|
||||
MemRange* const mr = (MemRange*)png_ptr->io_ptr;
|
||||
if(mr->size < length)
|
||||
@ -477,7 +475,7 @@ static void png_read_fn(png_struct* png_ptr, u8* data, png_size_t length)
|
||||
|
||||
memcpy(data, mr->p, length);
|
||||
mr->p += length;
|
||||
mr->size -= length; // > 0 due to test above
|
||||
mr->size -= length; // >= 0 due to test above
|
||||
}
|
||||
|
||||
|
||||
@ -512,7 +510,8 @@ fail:
|
||||
goto ret;
|
||||
}
|
||||
|
||||
u8** rows;
|
||||
const u8** rows;
|
||||
// freed in cleanup code; need scoping on VC6 due to goto
|
||||
|
||||
{
|
||||
|
||||
@ -524,7 +523,7 @@ fail:
|
||||
int prec, color_type;
|
||||
png_get_IHDR(png_ptr, info_ptr, &w, &h, &prec, &color_type, 0, 0, 0);
|
||||
|
||||
size_t pitch = png_get_rowbytes(png_ptr, info_ptr);
|
||||
const size_t pitch = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
const u32 fmts[8] = { 0, ~0, GL_RGB, ~0, GL_LUMINANCE_ALPHA, ~0, GL_RGBA, ~0 };
|
||||
const u32 fmt = color_type < 8? fmts[color_type] : ~0;
|
||||
@ -542,26 +541,25 @@ fail:
|
||||
}
|
||||
|
||||
// allocate mem for image - rows point into buffer (sequential)
|
||||
rows = (u8**)malloc((h+1)*sizeof(void*));
|
||||
rows = (const u8**)malloc(h*sizeof(void*));
|
||||
if(!rows)
|
||||
goto fail;
|
||||
size_t img_size = pitch * (h+1);
|
||||
const size_t img_size = pitch * h;
|
||||
Handle img_hm;
|
||||
u8* img = (u8*)mem_alloc(img_size, 64*KB, 0, &img_hm);
|
||||
const u8* img = (const u8*)mem_alloc(img_size, 64*KB, 0, &img_hm);
|
||||
if(!img)
|
||||
goto fail;
|
||||
u8* pos = img;
|
||||
for(u32 i = 0; i < h+1; i++)
|
||||
const u8* pos = img;
|
||||
for(size_t i = 0; i < h; i++)
|
||||
{
|
||||
rows[i] = pos;
|
||||
pos += pitch;
|
||||
}
|
||||
|
||||
png_read_image(png_ptr, rows);
|
||||
png_read_image(png_ptr, (png_bytepp)rows);
|
||||
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
|
||||
|
||||
mem_free_h(t->hm);
|
||||
|
||||
t->w = w;
|
||||
|
@ -19,9 +19,7 @@
|
||||
#ifndef __TEX_H__
|
||||
#define __TEX_H__
|
||||
|
||||
#include "types.h"
|
||||
#include "h_mgr.h"
|
||||
#include "misc.h"
|
||||
|
||||
// load and return a handle to the texture given in <fn>.
|
||||
// supports RAW, BMP, JP2, PNG, TGA, DDS
|
||||
@ -33,7 +31,7 @@ extern int tex_id(Handle ht);
|
||||
extern int tex_info(Handle ht, int* w, int* h, int *fmt, int *bpp, void** p);
|
||||
|
||||
extern int tex_filter; // GL values; default: GL_LINEAR
|
||||
extern uint tex_bpp; // 16 or 32; default: 32
|
||||
extern unsigned int tex_bpp; // 16 or 32; default: 32
|
||||
|
||||
// upload the specified texture to OpenGL. Texture filter and internal format
|
||||
// may be specified to override the global defaults.
|
||||
|
@ -20,11 +20,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "lib.h"
|
||||
#include "file.h"
|
||||
#include "zip.h"
|
||||
#include "misc.h"
|
||||
#include "vfs.h"
|
||||
#include "mem.h"
|
||||
#include "res.h"
|
||||
#include "adts.h"
|
||||
|
||||
|
||||
@ -183,10 +179,10 @@ ok:
|
||||
// this allows multiple search paths without having to check each one
|
||||
// when opening a file (slow).
|
||||
//
|
||||
// one Loc is allocated for each archive or directory mounted.
|
||||
// therefore, files only /point/ to a (possibly shared) Loc.
|
||||
// one FileLoc is allocated for each archive or directory mounted.
|
||||
// therefore, files only /point/ to a (possibly shared) FileLoc.
|
||||
// if a file's location changes (e.g. after mounting a higher-priority
|
||||
// directory), the VFS entry will point to the new Loc; the priority
|
||||
// directory), the VFS entry will point to the new FileLoc; the priority
|
||||
// of both locations is unchanged.
|
||||
//
|
||||
// allocate via mnt_create, passing the location. do not free!
|
||||
@ -197,122 +193,130 @@ ok:
|
||||
|
||||
|
||||
// not many instances => don't worry about struct size / alignment.
|
||||
struct Loc
|
||||
struct FileLoc
|
||||
{
|
||||
Handle archive;
|
||||
|
||||
std::string dir;
|
||||
|
||||
uint pri;
|
||||
|
||||
Loc() {}
|
||||
Loc(Handle _archive, const char* _dir, uint _pri)
|
||||
FileLoc() {}
|
||||
FileLoc(Handle _archive, const char* _dir, uint _pri)
|
||||
: archive(_archive), dir(_dir), pri(_pri) {}
|
||||
};
|
||||
|
||||
|
||||
struct TreeDir;
|
||||
// rationale for separate file / subdir containers:
|
||||
// problems:
|
||||
// - more code for insertion (oh well);
|
||||
// - makes ordered output of all dirents difficult
|
||||
// (but dirs and files are usually displayed separately)
|
||||
// advantages:
|
||||
// - simplifies lookup code: it can just check if a path is there,
|
||||
// no need to check if the entry is actually a directory
|
||||
// - storing Dir objects directly in the map means less
|
||||
// memory allocations / no need to free them.
|
||||
//
|
||||
// *_add guard against a subdir and file of the same name.
|
||||
|
||||
typedef std::map<std::string, TreeDir*> SubDirs;
|
||||
typedef SubDirs::iterator SubDirIt;
|
||||
|
||||
typedef std::map<std::string, const Loc*> Files;
|
||||
typedef std::map<const std::string, FileLoc*> Files;
|
||||
typedef Files::iterator FileIt;
|
||||
// note: priority is accessed by following the Loc pointer.
|
||||
// notes:
|
||||
// - FileLoc is allocated and owned by caller (the mount code)
|
||||
// - priority is accessed by following the FileLoc pointer.
|
||||
// keeping a copy in the map would lead to better cache coherency,
|
||||
// but it's a bit more clumsy (map filename to struct {pri, Loc*}).
|
||||
// but it's a bit more clumsy (map filename to struct {pri, FileLoc*}).
|
||||
// revisit if file lookup open is too slow (unlikely).
|
||||
|
||||
struct TreeDir
|
||||
struct Dir;
|
||||
typedef std::pair<const std::string, Dir> SubDir;
|
||||
typedef std::map<const std::string, Dir> SubDirs;
|
||||
typedef SubDirs::iterator SubDirIt;
|
||||
|
||||
struct Dir
|
||||
{
|
||||
std::string v_name;
|
||||
int file_add(const char* name, const FileLoc* loc);
|
||||
FileLoc* file_find(const char* name);
|
||||
|
||||
void* watch;
|
||||
int subdir_add(const char* name);
|
||||
Dir* subdir_find(const char* name);
|
||||
|
||||
void clearR();
|
||||
|
||||
SubDirs subdirs;
|
||||
Files files;
|
||||
};
|
||||
|
||||
|
||||
int file_add(const char* const fn, const uint pri, const Loc* const loc)
|
||||
int Dir::subdir_add(const char* const fn)
|
||||
{
|
||||
std::string _fn(fn);
|
||||
|
||||
typedef std::pair<std::string, const Loc*> Ent;
|
||||
Ent ent = std::make_pair(_fn, loc);
|
||||
std::pair<FileIt, bool> ret;
|
||||
ret = files.insert(ent);
|
||||
// file already in dir
|
||||
if(!ret.second)
|
||||
if(file_find(fn) || subdir_find(fn))
|
||||
{
|
||||
FileIt it = ret.first;
|
||||
const Loc*& old_loc = it->second;
|
||||
debug_warn("dir_add: file or subdirectory of same name already exists");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// new Loc is of higher priority; replace pointer
|
||||
if(old_loc->pri <= loc->pri)
|
||||
subdirs[fn];
|
||||
// side effect: maps <fn> to a newly constructed Dir()
|
||||
// non-const => cannot be optimized away.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Dir* Dir::subdir_find(const char* const fn)
|
||||
{
|
||||
SubDirIt it = subdirs.find(fn);
|
||||
if(it == subdirs.end())
|
||||
return 0;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
|
||||
int Dir::file_add(const char* const fn, const FileLoc* const loc)
|
||||
{
|
||||
if(subdir_find(fn))
|
||||
{
|
||||
debug_warn("dir_add: file of same name already exists");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// default pointer ctor sets it to 0 =>
|
||||
// if fn wasn't already in the container, old_loc is 0.
|
||||
const FileLoc*& old_loc = files[fn];
|
||||
// old loc exists and is higher priority - keep it.
|
||||
if(old_loc && old_loc->pri > loc->pri)
|
||||
return 1;
|
||||
|
||||
old_loc = loc;
|
||||
return 0;
|
||||
}
|
||||
// new Loc is of lower priority; keep old pointer
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Loc* file_find(const char* fn)
|
||||
FileLoc* Dir::file_find(const char* const fn)
|
||||
{
|
||||
std::string _fn(fn);
|
||||
FileIt it = files.find(_fn);
|
||||
FileIt it = files.find(fn);
|
||||
if(it == files.end())
|
||||
return 0;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
TreeDir* subdir_add(const char* name)
|
||||
|
||||
void Dir::clearR()
|
||||
{
|
||||
TreeDir* vdir = new TreeDir;
|
||||
const std::string _name(name);
|
||||
vdir->v_name = _name;
|
||||
|
||||
std::pair<std::string, TreeDir*> item = std::make_pair(_name, vdir);
|
||||
std::pair<SubDirIt, bool> res;
|
||||
res = subdirs.insert(item);
|
||||
// already in container
|
||||
if(!res.second)
|
||||
debug_warn("already in subdir");
|
||||
|
||||
SubDirIt it = res.first;
|
||||
return it->second;
|
||||
SubDirIt it;
|
||||
for(it = subdirs.begin(); it != subdirs.end(); ++it)
|
||||
{
|
||||
Dir& subdir = it->second;
|
||||
subdir.clearR();
|
||||
}
|
||||
|
||||
TreeDir* subdir_find(const char* name)
|
||||
{
|
||||
const std::string _name(name);
|
||||
SubDirIt it = subdirs.find(_name);
|
||||
if(it == subdirs.end())
|
||||
return 0;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void subdir_clear()
|
||||
{
|
||||
for(SubDirIt it = subdirs.begin(); it != subdirs.end(); ++it)
|
||||
delete(it->second);
|
||||
subdirs.clear();
|
||||
files.clear();
|
||||
}
|
||||
|
||||
friend void tree_clearR(TreeDir*);
|
||||
|
||||
SubDirs subdirs; // can't make private; needed for iterator
|
||||
Files files;
|
||||
|
||||
|
||||
private:;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
static TreeDir vfs_root;
|
||||
static Dir vfs_root;
|
||||
|
||||
|
||||
enum LookupFlags
|
||||
@ -324,7 +328,7 @@ enum LookupFlags
|
||||
|
||||
// starts in VFS root directory (path = "").
|
||||
// path doesn't need to, and shouldn't, start with '/'.
|
||||
static int tree_lookup(const char* path, const Loc** const loc = 0, TreeDir** const dir = 0, LookupFlags flags = LF_DEFAULT)
|
||||
static int tree_lookup(const char* path, const FileLoc** const loc = 0, Dir** const dir = 0, LookupFlags flags = LF_DEFAULT)
|
||||
{
|
||||
CHECK_PATH(path);
|
||||
|
||||
@ -337,22 +341,40 @@ static int tree_lookup(const char* path, const Loc** const loc = 0, TreeDir** co
|
||||
|
||||
const bool create_missing_components = flags & LF_CREATE_MISSING_COMPONENTS;
|
||||
|
||||
TreeDir* cur_dir = &vfs_root;
|
||||
Dir* cur_dir = &vfs_root;
|
||||
|
||||
// for each path component:
|
||||
for(;;)
|
||||
{
|
||||
char* slash = strchr(cur_component, '/');
|
||||
// we have followed all path components.
|
||||
// cur_component is the filename or ""
|
||||
// done, cur_component is the filename or "" if <path> is a directory
|
||||
if(!slash)
|
||||
{
|
||||
break;
|
||||
*slash = 0; // 0-terminate cur_component
|
||||
const char* subdir_name = cur_component;
|
||||
|
||||
// create <subdir_name>
|
||||
// (note: no-op if it already exists
|
||||
if(create_missing_components)
|
||||
cur_dir->subdir_add(subdir_name);
|
||||
|
||||
// switch to <subdir_name>
|
||||
Dir* subdir = cur_dir->subdir_find(subdir_name);
|
||||
if(!subdir)
|
||||
return ERR_PATH_NOT_FOUND;
|
||||
|
||||
// next component
|
||||
cur_dir = subdir;
|
||||
cur_component = slash+1;
|
||||
}
|
||||
|
||||
// we have followed all path components.
|
||||
|
||||
// caller wants pointer to file location returned
|
||||
if(loc)
|
||||
{
|
||||
const char* fn = cur_component;
|
||||
*loc = cur_dir->file_find(fn);
|
||||
|
||||
// user wanted its loc, but it's not found - fail
|
||||
*loc = cur_dir->file_find(cur_component);
|
||||
// .. but the file doesn't exist
|
||||
if(!*loc)
|
||||
return ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
@ -361,52 +383,20 @@ static int tree_lookup(const char* path, const Loc** const loc = 0, TreeDir** co
|
||||
*dir = cur_dir;
|
||||
return 0;
|
||||
}
|
||||
// cur_component is a subdirectory name; change to it
|
||||
else
|
||||
{
|
||||
const char* subdir_name = cur_component;
|
||||
*slash = 0;
|
||||
|
||||
TreeDir* subdir = cur_dir->subdir_find(subdir_name);
|
||||
if(!subdir)
|
||||
{
|
||||
if(create_missing_components)
|
||||
subdir = cur_dir->subdir_add(subdir_name);
|
||||
else
|
||||
return ERR_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
cur_dir = subdir;
|
||||
cur_component = slash+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void tree_clearR(TreeDir* const dir)
|
||||
{
|
||||
SubDirIt it;
|
||||
for(it = dir->subdirs.begin(); it != dir->subdirs.end(); ++it)
|
||||
{
|
||||
TreeDir* subdir = it->second;
|
||||
tree_clearR(subdir);
|
||||
}
|
||||
|
||||
dir->files.clear();
|
||||
dir->subdir_clear();
|
||||
}
|
||||
|
||||
|
||||
static inline void tree_clear()
|
||||
{
|
||||
tree_clearR(&vfs_root);
|
||||
vfs_root.clearR();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct FileCBParams
|
||||
{
|
||||
TreeDir* dir;
|
||||
const Loc* loc;
|
||||
Dir* const dir;
|
||||
const FileLoc* loc;
|
||||
};
|
||||
|
||||
// called for each OS dir ent.
|
||||
@ -423,58 +413,58 @@ struct FileCBParams
|
||||
static int add_dirent_cb(const char* const fn, const uint flags, const ssize_t size, const uintptr_t user)
|
||||
{
|
||||
const FileCBParams* const params = (FileCBParams*)user;
|
||||
TreeDir* const cur_dir = params->dir;
|
||||
const Loc* const cur_loc = params->loc;
|
||||
Dir* const cur_dir = params->dir;
|
||||
const FileLoc* const cur_loc = params->loc;
|
||||
|
||||
int err;
|
||||
|
||||
// directory
|
||||
if(flags & LOC_DIR)
|
||||
cur_dir->subdir_add(fn);
|
||||
err = cur_dir->subdir_add(fn);
|
||||
// file
|
||||
else
|
||||
CHECK_ERR(cur_dir->file_add(fn, cur_loc->pri, cur_loc));
|
||||
err = cur_dir->file_add(fn, cur_loc);
|
||||
|
||||
if(err < 0)
|
||||
return -EEXIST;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int tree_add_dirR(TreeDir* const vdir, const char* const f_path, const Loc* const loc)
|
||||
static int tree_add_dirR(Dir* const dir, const char* const f_path, const FileLoc* const loc)
|
||||
{
|
||||
CHECK_PATH(f_path);
|
||||
|
||||
// add watch
|
||||
if(!vdir->watch)
|
||||
vdir->watch = 0;
|
||||
|
||||
// add files and subdirs to vdir
|
||||
const FileCBParams params = { vdir, loc };
|
||||
const FileCBParams params = { dir, loc };
|
||||
file_enum(f_path, add_dirent_cb, (uintptr_t)¶ms);
|
||||
|
||||
for(SubDirIt it = vdir->subdirs.begin(); it != vdir->subdirs.end(); ++it)
|
||||
for(SubDirIt it = dir->subdirs.begin(); it != dir->subdirs.end(); ++it)
|
||||
{
|
||||
TreeDir* const vsubdir = it->second;
|
||||
Dir* const subdir = &it->second;
|
||||
const char* const subdir_name_c = (it->first).c_str();
|
||||
|
||||
char f_subdir_path[VFS_MAX_PATH];
|
||||
const char* const v_subdir_name_c = vsubdir->v_name.c_str();
|
||||
CHECK_ERR(path_append(f_subdir_path, f_path, v_subdir_name_c));
|
||||
CHECK_ERR(path_append(f_subdir_path, f_path, subdir_name_c));
|
||||
|
||||
tree_add_dirR(vsubdir, f_subdir_path, loc);
|
||||
tree_add_dirR(subdir, f_subdir_path, loc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int tree_add_loc(TreeDir* const vdir, const Loc* const loc)
|
||||
static int tree_add_loc(Dir* const dir, const FileLoc* const loc)
|
||||
{
|
||||
if(loc->archive > 0)
|
||||
{
|
||||
FileCBParams params = { vdir, loc };
|
||||
FileCBParams params = { dir, loc };
|
||||
return zip_enum(loc->archive, add_dirent_cb, (uintptr_t)¶ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* f_path_c = loc->dir.c_str();
|
||||
return tree_add_dirR(vdir, f_path_c, loc);
|
||||
return tree_add_dirR(dir, f_path_c, loc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -489,7 +479,7 @@ static int tree_add_loc(TreeDir* const vdir, const Loc* const loc)
|
||||
// container must not invalidate iterators after insertion!
|
||||
// (we keep and pass around pointers to Mount.archive_locs elements)
|
||||
// see below.
|
||||
typedef std::list<Loc> Locs;
|
||||
typedef std::list<FileLoc> Locs;
|
||||
typedef Locs::iterator LocIt;
|
||||
|
||||
|
||||
@ -505,14 +495,14 @@ struct Mount
|
||||
uint pri;
|
||||
|
||||
// storage for all Locs ensuing from this mounting.
|
||||
// the VFS tree only holds pointers to Loc, which is why the
|
||||
// the VFS tree only holds pointers to FileLoc, which is why the
|
||||
// Locs container must not invalidate its contents after adding,
|
||||
// and also why the VFS tree must be rebuilt after unmounting something.
|
||||
Loc dir_loc;
|
||||
FileLoc dir_loc;
|
||||
Locs archive_locs;
|
||||
// if not is_single_archive, contains one Loc for every archive
|
||||
// if not is_single_archive, contains one FileLoc for every archive
|
||||
// in the directory (but not its children - see remount()).
|
||||
// otherwise, contains exactly one Loc for the single archive.
|
||||
// otherwise, contains exactly one FileLoc for the single archive.
|
||||
|
||||
// is f_name an archive filename? if not, it's a directory.
|
||||
bool is_single_archive;
|
||||
@ -546,7 +536,7 @@ struct ArchiveCBParams
|
||||
// because Locs are created const.
|
||||
uint pri;
|
||||
|
||||
// will add one Loc to this container for
|
||||
// will add one FileLoc to this container for
|
||||
// every archive successfully opened.
|
||||
Locs* archive_locs;
|
||||
};
|
||||
@ -573,7 +563,7 @@ static int archive_cb(const char* const fn, const uint flags, const ssize_t size
|
||||
// just try to open the file.
|
||||
const Handle archive = zip_archive_open(f_path);
|
||||
if(archive > 0)
|
||||
archive_locs->push_back(Loc(archive, "", pri));
|
||||
archive_locs->push_back(FileLoc(archive, "", pri));
|
||||
|
||||
// only add archive to list; don't add its files into the VFS yet,
|
||||
// to simplify debugging (we see which files are in which archive)
|
||||
@ -592,11 +582,11 @@ static int remount(Mount& m)
|
||||
const char* const v_path = m.v_path.c_str();
|
||||
const char* const f_name = m.f_name.c_str();
|
||||
const uint pri = m.pri;
|
||||
Loc& dir_loc = m.dir_loc;
|
||||
FileLoc& dir_loc = m.dir_loc;
|
||||
Locs& archive_locs = m.archive_locs;
|
||||
|
||||
TreeDir* vdir;
|
||||
CHECK_ERR(tree_lookup(v_path, 0, &vdir, LF_CREATE_MISSING_COMPONENTS));
|
||||
Dir* dir;
|
||||
CHECK_ERR(tree_lookup(v_path, 0, &dir, LF_CREATE_MISSING_COMPONENTS));
|
||||
|
||||
// check if target is a single Zip archive
|
||||
// order doesn't matter; can't have both an archive and dir
|
||||
@ -604,9 +594,9 @@ static int remount(Mount& m)
|
||||
if(archive > 0)
|
||||
{
|
||||
m.is_single_archive = true;
|
||||
archive_locs.push_back(Loc(archive, "", pri));
|
||||
const Loc* loc = &archive_locs.front();
|
||||
return tree_add_loc(vdir, loc);
|
||||
archive_locs.push_back(FileLoc(archive, "", pri));
|
||||
const FileLoc* loc = &archive_locs.front();
|
||||
return tree_add_loc(dir, loc);
|
||||
}
|
||||
|
||||
// enumerate all archives
|
||||
@ -615,13 +605,13 @@ static int remount(Mount& m)
|
||||
|
||||
for(LocIt it = archive_locs.begin(); it != archive_locs.end(); ++it)
|
||||
{
|
||||
const Loc* const loc = &*it;
|
||||
tree_add_loc(vdir, loc);
|
||||
const FileLoc* const loc = &*it;
|
||||
tree_add_loc(dir, loc);
|
||||
}
|
||||
|
||||
|
||||
dir_loc.dir = f_name;
|
||||
err = tree_add_loc(vdir, &dir_loc);
|
||||
err = tree_add_loc(dir, &dir_loc);
|
||||
if(err < 0)
|
||||
err = err;
|
||||
|
||||
@ -633,7 +623,7 @@ static int unmount(Mount& m)
|
||||
{
|
||||
for(LocIt it = m.archive_locs.begin(); it != m.archive_locs.end(); ++it)
|
||||
{
|
||||
Loc& loc = *it;
|
||||
FileLoc& loc = *it;
|
||||
zip_archive_close(loc.archive);
|
||||
}
|
||||
|
||||
@ -649,7 +639,7 @@ static inline void remount_all()
|
||||
{ std::for_each(mounts.begin(), mounts.end(), remount); }
|
||||
|
||||
|
||||
static void cleanup(void)
|
||||
void vfs_shutdown(void)
|
||||
{
|
||||
tree_clear();
|
||||
unmount_all();
|
||||
@ -658,7 +648,7 @@ static void cleanup(void)
|
||||
|
||||
int vfs_mount(const char* const vfs_mount_point, const char* const name, const uint pri)
|
||||
{
|
||||
ONCE(atexit2(cleanup));
|
||||
ONCE(atexit2(vfs_shutdown));
|
||||
|
||||
// make sure it's not already mounted, i.e. in mounts
|
||||
for(MountIt it = mounts.begin(); it != mounts.end(); ++it)
|
||||
@ -715,22 +705,14 @@ int vfs_unmount(const char* name)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// directory
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OLD
|
||||
// rationale for n-archives per PATH entry:
|
||||
// We need to be able to unmount specific paths (e.g. when switching mods).
|
||||
// Don't want to remount everything (slow), or specify a mod tag when mounting
|
||||
// (not this module's job). Instead, we include all archives in one path entry;
|
||||
// the game keeps track of what path(s) it mounted for a mod,
|
||||
// and unmounts those when needed.
|
||||
|
||||
|
||||
int vfs_realpath(const char* fn, char* full_path)
|
||||
{
|
||||
const Loc* loc;
|
||||
const FileLoc* loc;
|
||||
CHECK_ERR(tree_lookup(fn, &loc));
|
||||
|
||||
if(loc->archive > 0)
|
||||
@ -751,7 +733,7 @@ int vfs_realpath(const char* fn, char* full_path)
|
||||
|
||||
int vfs_stat(const char* fn, struct stat* s)
|
||||
{
|
||||
const Loc* loc;
|
||||
const FileLoc* loc;
|
||||
CHECK_ERR(tree_lookup(fn, &loc));
|
||||
|
||||
if(loc->archive > 0)
|
||||
@ -766,32 +748,37 @@ int vfs_stat(const char* fn, struct stat* s)
|
||||
|
||||
struct VDir
|
||||
{
|
||||
TreeDir* dir;
|
||||
FileIt it;
|
||||
// we need to cache the complete contents of the directory:
|
||||
//
|
||||
SubDirs* subdirs;
|
||||
SubDirIt subdir_it;
|
||||
Files* files;
|
||||
FileIt file_it;
|
||||
};
|
||||
|
||||
H_TYPE_DEFINE(VDir);
|
||||
|
||||
|
||||
|
||||
static void VDir_init(VDir* vd, va_list args)
|
||||
{
|
||||
}
|
||||
|
||||
static void VDir_dtor(VDir* vd)
|
||||
{
|
||||
// remove reference to TreeDir, unlock it for further use
|
||||
delete vd->subdirs;
|
||||
delete vd->files;
|
||||
}
|
||||
|
||||
static int VDir_reload(VDir* vd, const char* path)
|
||||
{
|
||||
// check if actually reloaded, and why it happened?
|
||||
// hmm, if TreeDir changes while handle is open, we are screwed.
|
||||
// need a lock.
|
||||
|
||||
CHECK_ERR(tree_lookup(path, 0, &vd->dir));
|
||||
Dir* dir;
|
||||
CHECK_ERR(tree_lookup(path, 0, &dir));
|
||||
|
||||
vd->it = vd->dir->files.begin();
|
||||
vd->subdirs = new SubDirs(dir->subdirs);
|
||||
vd->subdir_it = vd->subdirs->begin();
|
||||
vd->files = new Files(dir->files);
|
||||
vd->file_it = vd->files->begin();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -801,35 +788,75 @@ Handle vfs_open_dir(const char* const path)
|
||||
return h_alloc(H_VDir, path, 0);
|
||||
}
|
||||
|
||||
|
||||
int vfs_close_dir(Handle& hd)
|
||||
{
|
||||
return h_free(hd, H_VDir);
|
||||
}
|
||||
|
||||
|
||||
// filter:
|
||||
// 0: any file
|
||||
// ".": file without extension (filename doesn't contain '.')
|
||||
// ".ext": file with extension <ext> (which must not contain '.')
|
||||
// "/": subdirectory
|
||||
int vfs_next_dirent(const Handle hd, vfsDirEnt* ent, const char* const filter)
|
||||
{
|
||||
// make sure filter is valid
|
||||
// interpret filter, decide if they want files or subdirs
|
||||
|
||||
// until no more entries, or one matches filter
|
||||
for(;;)
|
||||
{
|
||||
H_DEREF(hd, VDir, vd);
|
||||
if(vd->it == vd->dir->files.end())
|
||||
return 1;
|
||||
|
||||
const std::string& fn_s = vd->it->first;
|
||||
const char* const fn = fn_s.c_str();
|
||||
|
||||
// interpret filter
|
||||
bool filter_dir = false;
|
||||
bool filter_no_ext = false;
|
||||
if(filter)
|
||||
{
|
||||
char* ext = strrchr(fn, '.');
|
||||
if(!ext || strcmp(ext, filter) != 0)
|
||||
continue;
|
||||
if(filter[0] == '/')
|
||||
{
|
||||
if(filter[1] != '\0')
|
||||
goto invalid_filter;
|
||||
filter_dir = true;
|
||||
}
|
||||
else if(filter[0] == '.')
|
||||
{
|
||||
if(strchr(filter+1, '.'))
|
||||
goto invalid_filter;
|
||||
filter_no_ext = filter[1] == '\0';
|
||||
}
|
||||
else
|
||||
goto invalid_filter;
|
||||
}
|
||||
|
||||
// found matching entry
|
||||
const char* fn;
|
||||
|
||||
// caller wants a subdirectory; return the next one.
|
||||
if(filter_dir)
|
||||
{
|
||||
if(vd->subdir_it == vd->subdirs->end())
|
||||
return -1;
|
||||
fn = vd->subdir_it->first.c_str();
|
||||
++vd->subdir_it;
|
||||
goto have_match;
|
||||
}
|
||||
|
||||
// caller wants a file; loop until one matches or end of list.
|
||||
for(;;)
|
||||
{
|
||||
if(vd->file_it == vd->files->end())
|
||||
return -1;
|
||||
fn = vd->file_it->first.c_str();
|
||||
++vd->file_it;
|
||||
|
||||
char* const ext = strrchr(fn, '.');
|
||||
if(!filter || (filter_no_ext && !ext) || strcmp(ext, filter) == 0)
|
||||
goto have_match;
|
||||
}
|
||||
|
||||
have_match:
|
||||
ent->name = fn;
|
||||
return 0;
|
||||
|
||||
invalid_filter:
|
||||
debug_warn("vfs_next_dirent: invalid filter");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -927,7 +954,7 @@ static int VFile_reload(VFile* vf, const char* path)
|
||||
int err = -1;
|
||||
|
||||
|
||||
const Loc* loc;
|
||||
const FileLoc* loc;
|
||||
CHECK_ERR(tree_lookup(path, &loc));
|
||||
|
||||
if(loc->archive <= 0)
|
||||
|
@ -22,8 +22,6 @@
|
||||
|
||||
#include "lib.h"
|
||||
#include "win_internal.h"
|
||||
#include "misc.h"
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#define lock() win_lock(WAIO_CS)
|
||||
|
@ -51,18 +51,25 @@ static int import_EnumDisplayDevices()
|
||||
|
||||
// useful for choosing a video mode. not called by detect().
|
||||
// if we fail, outputs are unchanged (assumed initialized to defaults)
|
||||
int get_cur_resolution(int& xres, int& yres)
|
||||
int get_cur_vmode(int* xres, int* yres, int* bpp, int* freq)
|
||||
{
|
||||
DEVMODEA dm;
|
||||
DEVMODEW dm;
|
||||
memset(&dm, 0, sizeof(dm));
|
||||
dm.dmSize = sizeof(dm);
|
||||
// dm.dmDriverExtra already set to 0 by memset
|
||||
|
||||
if(!EnumDisplaySettingsA(0, ENUM_CURRENT_SETTINGS, &dm))
|
||||
if(!EnumDisplaySettingsW(0, ENUM_CURRENT_SETTINGS, &dm))
|
||||
return -1;
|
||||
|
||||
xres = dm.dmPelsWidth;
|
||||
yres = dm.dmPelsHeight;
|
||||
if(dm.dmFields & DM_PELSWIDTH && xres)
|
||||
*xres = (int)dm.dmPelsWidth;
|
||||
if(dm.dmFields & DM_PELSHEIGHT && yres)
|
||||
*yres = (int)dm.dmPelsHeight;
|
||||
if(dm.dmFields & DM_BITSPERPEL && bpp)
|
||||
*bpp = (int)dm.dmBitsPerPel;
|
||||
if(dm.dmFields & DM_DISPLAYFREQUENCY && freq)
|
||||
*freq = (int)dm.dmDisplayFrequency;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,16 @@
|
||||
#include "win_internal.h"
|
||||
#include "hrt.h"
|
||||
|
||||
// waio included via lib -> posix -> wposix
|
||||
|
||||
|
||||
static HANDLE mk_handle(intptr_t i)
|
||||
{
|
||||
// passing in -1 (e.g. if _get_osfhandle fails),
|
||||
// is fine, it ends up INVALID_HANDLE_VALUE.
|
||||
return (HANDLE)((char*)0 + i);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -67,6 +77,7 @@ int open(const char* fn, int mode, ...)
|
||||
|
||||
int close(int fd)
|
||||
{
|
||||
assert(3 <= fd && fd < 256);
|
||||
aio_close(fd);
|
||||
return _close(fd);
|
||||
}
|
||||
@ -74,7 +85,7 @@ int close(int fd)
|
||||
|
||||
int ioctl(int fd, int op, int* data)
|
||||
{
|
||||
HANDLE h = (HANDLE)((char*)0 + _get_osfhandle(fd));
|
||||
const HANDLE h = mk_handle(_get_osfhandle(fd));
|
||||
|
||||
switch(op)
|
||||
{
|
||||
@ -212,7 +223,7 @@ int closedir(DIR* dir)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static HANDLE std_h[2] = { (HANDLE)(((char*)0) + 3), (HANDLE)(((char*)0) + 7) };
|
||||
static HANDLE std_h[2] = { (HANDLE)((char*)0 + 3), (HANDLE)((char*)0 + 7) };
|
||||
|
||||
|
||||
__declspec(naked) void _get_console()
|
||||
@ -274,7 +285,7 @@ int pthread_getschedparam(pthread_t thread, int* policy, struct sched_param* par
|
||||
}
|
||||
if(param)
|
||||
{
|
||||
HANDLE hThread = (HANDLE)((char*)0 + thread);
|
||||
const HANDLE hThread = mk_handle((intptr_t)thread);
|
||||
param->sched_priority = GetThreadPriority(hThread);
|
||||
}
|
||||
|
||||
@ -286,8 +297,7 @@ int pthread_setschedparam(pthread_t thread, int policy, const struct sched_param
|
||||
if(policy == SCHED_FIFO)
|
||||
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
|
||||
|
||||
HANDLE hThread = (HANDLE)((char*)0 + thread);
|
||||
|
||||
const HANDLE hThread = mk_handle((intptr_t)thread);
|
||||
SetThreadPriority(hThread, param->sched_priority);
|
||||
return 0;
|
||||
}
|
||||
@ -388,7 +398,7 @@ void* mmap(void* start, unsigned int len, int prot, int flags, int fd, long offs
|
||||
|
||||
DWORD len_hi = (DWORD)((u64)len >> 32), len_lo = (DWORD)len & 0xffffffff;
|
||||
|
||||
HANDLE hFile = (HANDLE)((char*)0 + _get_osfhandle(fd));
|
||||
HANDLE hFile = mk_handle(_get_osfhandle(fd));
|
||||
HANDLE hMap = CreateFileMapping(hFile, &sec, flProtect, len_hi, len_lo, 0);
|
||||
|
||||
void* ptr = MapViewOfFileEx(hMap, dwAccess, len_hi, offset, len_lo, start);
|
||||
|
@ -26,28 +26,51 @@
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define IMP(ret, name, param) extern "C" __declspec(dllimport) ret __stdcall name param;
|
||||
|
||||
// for functions actually implemented in the CRT
|
||||
#ifdef _DLL
|
||||
#define _CRTIMP __declspec(dllimport)
|
||||
#else
|
||||
#define _CRTIMP
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//
|
||||
// <inttypes.h>
|
||||
//
|
||||
|
||||
typedef unsigned short u16_t;
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__LCC__)
|
||||
typedef __int64 int64_t;
|
||||
#elif defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__DMC__)
|
||||
typedef long long int64_t;
|
||||
#else
|
||||
#error "port int64_t"
|
||||
#endif
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__LCC__)
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#elif defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__DMC__)
|
||||
typedef unsigned long long uint64_t;
|
||||
#else
|
||||
#error "port uint64_t"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# ifndef _UINTPTR_T_DEFINED
|
||||
# define _UINTPTR_T_DEFINED
|
||||
# define uintptr_t unsigned int
|
||||
# endif // _UINTPTR_T_DEFINED
|
||||
# ifndef _INTPTR_T_DEFINED
|
||||
# define _INTPTR_T_DEFINED
|
||||
# define intptr_t signed int
|
||||
# endif // _INTPTR_T_DEFINED
|
||||
#else // _MSC_VER
|
||||
#include <stdint.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
//
|
||||
@ -225,11 +248,6 @@ extern int usleep(useconds_t us);
|
||||
|
||||
extern long sysconf(int name);
|
||||
|
||||
#ifndef _WINSOCKAPI_
|
||||
|
||||
IMP(int, gethostname, (char* name, size_t namelen))
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// <stdlib.h>
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "sdl.h"
|
||||
#include "lib.h"
|
||||
#include "win_internal.h"
|
||||
#include "misc.h"
|
||||
|
||||
#include <SDL_vkeys.h>
|
||||
|
||||
|
@ -46,7 +46,7 @@ static int wsock_shutdown()
|
||||
}
|
||||
|
||||
|
||||
u16_t htons(u16_t s)
|
||||
uint16_t htons(uint16_t s)
|
||||
{
|
||||
return (s >> 8) | ((s & 0xff) << 8);
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
#ifndef WSOCK_H__
|
||||
#define WSOCK_H__
|
||||
|
||||
#define IMP(ret, name, param) extern "C" __declspec(dllimport) ret __stdcall name param;
|
||||
|
||||
IMP(int, gethostname, (char* name, size_t namelen))
|
||||
|
||||
|
||||
//
|
||||
// <sys/socket.h>
|
||||
@ -9,10 +13,7 @@
|
||||
typedef unsigned long socklen_t;
|
||||
typedef unsigned short sa_family_t;
|
||||
|
||||
//#ifndef _WINSOCKAPI_
|
||||
|
||||
// Win32 values - do not change
|
||||
|
||||
#define SOCK_STREAM 1
|
||||
#define SOCK_DGRAM 2
|
||||
#define AF_INET 2
|
||||
@ -178,7 +179,7 @@ struct addrinfo
|
||||
// <arpa/inet.h>
|
||||
//
|
||||
|
||||
extern u16_t htons(u16_t hostshort);
|
||||
extern uint16_t htons(uint16_t hostshort);
|
||||
#define ntohs htons
|
||||
IMP(unsigned long, htonl, (unsigned long hostlong))
|
||||
|
||||
@ -194,7 +195,7 @@ IMP(ssize_t, send, (int, const void*, size_t, int))
|
||||
IMP(ssize_t, sendto, (int, const void*, size_t, int, const struct sockaddr*, socklen_t))
|
||||
IMP(ssize_t, recvfrom, (int, void*, size_t, int, struct sockaddr*, socklen_t*))
|
||||
|
||||
//#endif /* _WINSOCKAPI_ */
|
||||
|
||||
#undef IMP
|
||||
|
||||
#endif // #ifndef WSOCK_H__
|
@ -24,15 +24,21 @@
|
||||
|
||||
// useful for choosing a video mode. not called by detect().
|
||||
// if we fail, outputs are unchanged (assumed initialized to defaults)
|
||||
int get_cur_resolution(int& xres, int& yres)
|
||||
int get_cur_vmode(int* xres, int* yres, int* bpp, int* freq)
|
||||
{
|
||||
Display* disp = XOpenDisplay(0);
|
||||
if(!disp)
|
||||
return -1;
|
||||
|
||||
int screen = XDefaultScreen(disp);
|
||||
xres = XDisplayWidth (disp, screen);
|
||||
yres = XDisplayHeight(disp, screen);
|
||||
if(xres)
|
||||
*xres = XDisplayWidth (disp, screen);
|
||||
if(yres)
|
||||
*yres = XDisplayHeight(disp, screen);
|
||||
if(bpp)
|
||||
*bpp = 0;
|
||||
if(freq)
|
||||
*freq = 0;
|
||||
XCloseDisplay(disp);
|
||||
return 0;
|
||||
}
|
||||
|
@ -17,10 +17,8 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "timer.h"
|
||||
#include "types.h"
|
||||
#include "misc.h"
|
||||
#include "lib.h"
|
||||
#include "timer.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "sysdep/win/hrt.h"
|
||||
|
@ -1,50 +1,32 @@
|
||||
// convenience type (shorter defs than stdint uintN_t)
|
||||
|
||||
#ifndef __TYPES_H__
|
||||
#define __TYPES_H__
|
||||
|
||||
#include "posix.h"
|
||||
|
||||
// defines instead of typedefs so we can #undef conflicting decls
|
||||
|
||||
|
||||
#define ulong unsigned long
|
||||
|
||||
#define uint unsigned int
|
||||
|
||||
#define i8 signed char
|
||||
#define i16 short
|
||||
#define i32 long
|
||||
#define i8 int8_t
|
||||
#define i16 int16_t
|
||||
#define i32 int32_t
|
||||
#define i64 int64_t
|
||||
|
||||
#define u8 unsigned char
|
||||
#define u16 unsigned short
|
||||
#define u32 unsigned long // long to match Win32 DWORD
|
||||
#define u8 uint8_t
|
||||
#define u16 uint16_t
|
||||
#define u32 uint32_t
|
||||
#define u64 uint64_t
|
||||
|
||||
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__LCC__)
|
||||
#define i64 __int64
|
||||
#define u64 unsigned __int64
|
||||
#elif defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__DMC__)
|
||||
#define i64 long long
|
||||
#define u64 unsigned long long
|
||||
#else
|
||||
#error "TODO: port u64"
|
||||
|
||||
// the standard only guarantees 16 bits.
|
||||
// we use this for memory offsets and ranges, so it better be big enough.
|
||||
#if defined(SIZE_MAX) && SIZE_MAX < 32
|
||||
#error "check size_t and SIZE_MAX - too small?"
|
||||
#endif
|
||||
|
||||
|
||||
#define int8 i8
|
||||
#define int16 i16
|
||||
#define int32 i32
|
||||
|
||||
#include <stddef.h>
|
||||
#ifdef _MSC_VER
|
||||
# ifndef _UINTPTR_T_DEFINED
|
||||
# define _UINTPTR_T_DEFINED
|
||||
# define uintptr_t u32
|
||||
# endif // _UINTPTR_T_DEFINED
|
||||
# ifndef _INTPTR_T_DEFINED
|
||||
# define _INTPTR_T_DEFINED
|
||||
# define intptr_t i32
|
||||
# endif // _INTPTR_T_DEFINED
|
||||
#else // !_MSC_VER
|
||||
# include <stdint.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
#endif // #ifndef __TYPES_H__
|
||||
|
@ -109,14 +109,15 @@ static int write_sys_info()
|
||||
// .. graphics card
|
||||
fprintf(f, "%s\n", gfx_card);
|
||||
fprintf(f, "%s\n", gfx_drv_ver);
|
||||
fprintf(f, "%dx%d:%d@%d\n", g_xres, g_yres, g_bpp, g_freq);
|
||||
// .. network name / ips
|
||||
char hostname[100]; // possibly nodename != hostname
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
fprintf(f, "%s\n", hostname);
|
||||
hostent* h = gethostbyname(hostname);
|
||||
if(h)
|
||||
hostent* host = gethostbyname(hostname);
|
||||
if(host)
|
||||
{
|
||||
struct in_addr** ips = (struct in_addr**)h->h_addr_list;
|
||||
struct in_addr** ips = (struct in_addr**)host->h_addr_list;
|
||||
for(int i = 0; ips && ips[i]; i++)
|
||||
fprintf(f, "%s ", inet_ntoa(*ips[i]));
|
||||
fprintf(f, "\n");
|
||||
@ -228,7 +229,7 @@ void RenderTerrain()
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SubmitModelRecursive: recurse down given model, submitting it and all it's descendents to the
|
||||
// SubmitModelRecursive: recurse down given model, submitting it and all its descendents to the
|
||||
// renderer
|
||||
void SubmitModelRecursive(CModel* model)
|
||||
{
|
||||
@ -433,6 +434,7 @@ int main(int argc, char* argv[])
|
||||
_control87(_PC_24, _MCW_PC);
|
||||
#endif
|
||||
|
||||
|
||||
detect();
|
||||
|
||||
// init SDL
|
||||
@ -476,7 +478,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// preferred video mode = current desktop settings
|
||||
// (command line params may override these)
|
||||
get_cur_resolution(g_xres, g_yres);
|
||||
get_cur_vmode(&g_xres, &g_yres, &g_bpp, &g_freq);
|
||||
|
||||
for(int a = 1; a < argc; a++)
|
||||
if(!strncmp(argv[a], "xres", 4))
|
||||
@ -514,9 +516,6 @@ int main(int argc, char* argv[])
|
||||
vfs_mount("", "mods/official/", 0);
|
||||
//// dir_add_watch("mods\\official", false);
|
||||
|
||||
|
||||
//Handle xx = tex_load("art/textures/skins/structural/null.png");
|
||||
|
||||
#ifndef NO_GUI
|
||||
// GUI uses VFS, so this must come after VFS init.
|
||||
g_GUI.Initialize();
|
||||
@ -639,10 +638,6 @@ if(!g_MapFile)
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO MT: Move this to atexit() code? Capture original gamma ramp at initialization and restore it?
|
||||
|
||||
SDL_SetGamma( 1.0f, 1.0f, 1.0f );
|
||||
|
||||
#ifndef NO_GUI
|
||||
g_GUI.Destroy();
|
||||
delete CGUI::GetSingletonPtr(); // again, we should have all singleton deletes somewhere
|
||||
@ -665,5 +660,6 @@ if(!g_MapFile)
|
||||
// destroy renderer
|
||||
delete CRenderer::GetSingletonPtr();
|
||||
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -47,13 +47,13 @@ TDD at http://forums.wildfiregames.com/0ad
|
||||
// Includes / Compiler directives
|
||||
//--------------------------------------------------------
|
||||
|
||||
#include "stdlib.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Prometheus.h"
|
||||
#include "Singleton.h"
|
||||
#include "CStr.h"
|
||||
#include "LogFile.h"
|
||||
#include "posix.h"
|
||||
#include "misc.h"
|
||||
#include "lib.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
@ -49,7 +49,7 @@ CRect::CRect(const CPos &pos, const CSize &size) :
|
||||
{
|
||||
}
|
||||
|
||||
CRect::CRect(const int32 &_l, const int32 &_t, const int32 &_r, const int32 &_b) :
|
||||
CRect::CRect(const int32_t &_l, const int32_t &_t, const int32_t &_r, const int32_t &_b) :
|
||||
left(_l), top(_t), right(_r), bottom(_b)
|
||||
{
|
||||
}
|
||||
@ -180,12 +180,12 @@ void CRect::operator -=(const CSize& a)
|
||||
bottom -= a.cy;
|
||||
}
|
||||
|
||||
int32 CRect::GetWidth() const
|
||||
int32_t CRect::GetWidth() const
|
||||
{
|
||||
return right-left;
|
||||
}
|
||||
|
||||
int32 CRect::GetHeight() const
|
||||
int32_t CRect::GetHeight() const
|
||||
{
|
||||
return bottom-top;
|
||||
}
|
||||
@ -224,7 +224,7 @@ CPos::CPos() : x(0), y(0)
|
||||
{
|
||||
}
|
||||
|
||||
CPos::CPos(const int32 &_x, const int32 &_y) : x(_x), y(_y)
|
||||
CPos::CPos(const int32_t &_x, const int32_t &_y) : x(_x), y(_y)
|
||||
{
|
||||
}
|
||||
|
||||
@ -325,7 +325,7 @@ CSize::CSize(const CPos &pos) : cx(pos.x), cy(pos.y)
|
||||
{
|
||||
}
|
||||
|
||||
CSize::CSize(const int32 &_cx, const int32 &_cy) : cx(_cx), cy(_cy)
|
||||
CSize::CSize(const int32_t &_cx, const int32_t &_cy) : cx(_cx), cy(_cy)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ by Rich Cross, rich@0ad.wildfiregames.com
|
||||
#ifndef COVERLAY_H
|
||||
#define COVERLAY_H
|
||||
|
||||
#include "types.h"
|
||||
#include "lib.h"
|
||||
|
||||
struct CColor
|
||||
{
|
||||
@ -60,7 +60,7 @@ public:
|
||||
CRect(const CSize &size);
|
||||
CRect(const CPos &upperleft, const CPos &bottomright);
|
||||
CRect(const CPos &pos, const CSize &size);
|
||||
CRect(const int32 &_l, const int32 &_t, const int32 &_r, const int32 &_b);
|
||||
CRect(const int32_t &_l, const int32_t &_t, const int32_t &_r, const int32_t &_b);
|
||||
|
||||
// Operators
|
||||
void operator = (const CRect& a);
|
||||
@ -86,12 +86,12 @@ public:
|
||||
/**
|
||||
* @return Width of Rectangle
|
||||
*/
|
||||
int32 GetWidth() const;
|
||||
int32_t GetWidth() const;
|
||||
|
||||
/**
|
||||
* @return Height of Rectangle
|
||||
*/
|
||||
int32 GetHeight() const;
|
||||
int32_t GetHeight() const;
|
||||
|
||||
/**
|
||||
* Get Size
|
||||
@ -128,7 +128,7 @@ public:
|
||||
/**
|
||||
* Dimensions
|
||||
*/
|
||||
int32 left, top, right, bottom;
|
||||
int32_t left, top, right, bottom;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -142,7 +142,7 @@ class CPos
|
||||
{
|
||||
public:
|
||||
CPos();
|
||||
CPos(const int32 &_x, const int32 &_y);
|
||||
CPos(const int32_t &_x, const int32_t &_y);
|
||||
|
||||
// Operators
|
||||
void operator = (const CPos& a);
|
||||
@ -165,7 +165,7 @@ public:
|
||||
/**
|
||||
* Position
|
||||
*/
|
||||
int32 x, y;
|
||||
int32_t x, y;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -183,7 +183,7 @@ public:
|
||||
CSize();
|
||||
CSize(const CRect &rect);
|
||||
CSize(const CPos &pos);
|
||||
CSize(const int32 &_cx, const int32 &_cy);
|
||||
CSize(const int32_t &_cx, const int32_t &_cy);
|
||||
|
||||
// Operators
|
||||
void operator = (const CSize& a);
|
||||
@ -206,7 +206,7 @@ public:
|
||||
/**
|
||||
* Size
|
||||
*/
|
||||
int32 cx, cy;
|
||||
int32_t cx, cy;
|
||||
};
|
||||
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#define _TEMPLATE_SINGLETON
|
||||
|
||||
#include <assert.h>
|
||||
#include "types.h" // uintptr_t - not otherwise defined by VC6
|
||||
#include "lib.h"
|
||||
|
||||
|
||||
template<typename T>
|
||||
|
@ -66,8 +66,8 @@ CLocker usage 2:
|
||||
// Includes / Compiler directives
|
||||
//--------------------------------------------------------
|
||||
|
||||
#include "posix.h"
|
||||
#include "misc.h"
|
||||
#include "lib.h"
|
||||
|
||||
#ifdef DEBUG_LOCKS
|
||||
|
||||
#define LOCK_MUTEX(_mutex) STMT( \
|
||||
|
@ -1,4 +1,4 @@
|
||||
#pragma warning(disable:4786)
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <set>
|
||||
|
@ -49,7 +49,7 @@ CGenericProperty::operator void *()
|
||||
return( toVoid() );
|
||||
}
|
||||
|
||||
CGenericProperty& CGenericProperty::operator=( int32 value )
|
||||
CGenericProperty& CGenericProperty::operator=( int32_t value )
|
||||
{
|
||||
if( m_type & PROP_TYPELOCKED )
|
||||
{
|
||||
|
@ -41,15 +41,13 @@ int mouse_x=50, mouse_y=50;
|
||||
|
||||
void terr_init()
|
||||
{
|
||||
int xres,yres;
|
||||
get_cur_resolution(xres,yres);
|
||||
g_Renderer.Open(xres,yres,32);
|
||||
g_Renderer.Open(g_xres,g_yres,g_bpp);
|
||||
|
||||
SViewPort vp;
|
||||
vp.m_X=0;
|
||||
vp.m_Y=0;
|
||||
vp.m_Width=xres;
|
||||
vp.m_Height=yres;
|
||||
vp.m_Width=g_xres;
|
||||
vp.m_Height=g_yres;
|
||||
g_Camera.SetViewPort(&vp);
|
||||
|
||||
InitResources ();
|
||||
|
Loading…
Reference in New Issue
Block a user