This commit is contained in:
romkazvo
2023-08-07 19:29:24 +08:00
commit 34d6c5d489
4832 changed files with 1389451 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2004.
// -------------------------------------------------------------------------
// File name: ApplicationHelper.cpp
// Version: v1.00
// Created: 02/12/2004 by MartinM
// Compilers: Visual Studio.NET
// Description: Helper class for simple application creation
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ApplicationHelper.h" // CApplicationHelper
CApplicationHelper::CApplicationHelper()
{
}
CApplicationHelper::~CApplicationHelper()
{
}
void CApplicationHelper::ParseArguments( const char *inszCommandLine, ICmdlineArgumentSink *pEarlyCommands, ICmdlineArgumentSink *pConsoleCommands )
{
assert(inszCommandLine);
// int iArgNo=0;
char *src=(char *)inszCommandLine;
char Arg[1024];
while(*src)
{
char *dst=Arg;
while(*src<=' ' && *src!=0)
src++; // jump over whitespace
if(*src=='\"')
{
src++;
while(*src!='\"' && *src!=0)
*dst++=*src++;
if(*src=='\"')
src++;
}
else
{
while(*src!=' ' && *src!=0)
*dst++=*src++;
}
*dst=0;
if(*Arg!=0)
{
// if(iArgNo!=0) // ignore .exe name
{
if(Arg[0]=='-')
{
if(pEarlyCommands)
pEarlyCommands->ReturnArgument(&Arg[1]);
}
else
{
if(pConsoleCommands)
pConsoleCommands->ReturnArgument(Arg);
}
}
// iArgNo++;
}
}
}

View File

@@ -0,0 +1,50 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2004.
// -------------------------------------------------------------------------
// File name: ApplicationHelper.h
// Version: v1.00
// Created: 02/12/2004 by MartinM
// Compilers: Visual Studio.NET
// Description: Helper class for simple application creation
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#pragma once
class CApplicationHelper
{
public:
//! destructor
CApplicationHelper();
//! constructor
virtual ~CApplicationHelper();
// ----------------------------------------------------------------------
//! Sink for ParseArguments()
struct ICmdlineArgumentSink
{
//! used for early command e.g. "-DEVMODE", "-IP:123.22.23.1", "-MOD:CS"
//! or for console command e.g. "map mp_airstrip", "name test"
//! \param inszArgument must not be 0
virtual void ReturnArgument( const char *inszArgument )=0;
};
// ----------------------------------------------------------------------
//! to parse the command-line in a consistent way (you have to implement CApplicationHelper::ICommandlineArgumentSink)
//! arguments bigger than 1024 chars are not handles correctly
//! \param inszCommandLine must not be 0, e.g. -DEVMODE -IP:123.22.23.1 -MOD:CS "g_gametype ASSAULT" "start_server mp_airstrip"
//! \param pEarlyCommands 0 or pointer to the sink for early commands e.g. "-DEVMODE", "-IP:123.22.23.1", "-MOD:CS"
//! \param pConsoleCommands 0 or pointer to the sink for console commands e.g. "map mp_airstrip", "name test"
static void ParseArguments( const char *inszCommandLine, ICmdlineArgumentSink *pEarlyCommands,
ICmdlineArgumentSink *pConsoleCommands );
private: // ---------------------------------------------------------------
};

1077
CrySystem/CPUDetect.cpp Normal file

File diff suppressed because it is too large Load Diff

163
CrySystem/CPUDetect.h Normal file
View File

@@ -0,0 +1,163 @@
/*=============================================================================
CPUDetect.cpp : CPU detection.
Copyright 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#ifndef __CPUDETECT_H__
#define __CPUDETECT_H__
//-------------------------------------------------------
/// Cpu class
//-------------------------------------------------------
#define MAX_CPU 32
/// Cpu Features
#define CFI_FPUEMULATION 1
#define CFI_MMX 2
#define CFI_3DNOW 4
#define CFI_SSE 8
#define CFI_SSE2 0x10
/// Type of Cpu Vendor.
enum ECpuVendor
{
eCVendor_Unknown,
eCVendor_Intel,
eCVendor_Cyrix,
eCVendor_AMD,
eCVendor_Centaur,
eCVendor_NexGen,
eCVendor_UMC,
eCVendor_M68K
};
/// Type of Cpu Model.
enum ECpuModel
{
eCpu_Unknown,
eCpu_8086,
eCpu_80286,
eCpu_80386,
eCpu_80486,
eCpu_Pentium,
eCpu_PentiumPro,
eCpu_Pentium2,
eCpu_Pentium3,
eCpu_Pentium4,
eCpu_Pentium2Xeon,
eCpu_Pentium3Xeon,
eCpu_Celeron,
eCpu_CeleronA,
eCpu_Am5x86,
eCpu_AmK5,
eCpu_AmK6,
eCpu_AmK6_2,
eCpu_AmK6_3,
eCpu_AmK6_3D,
eCpu_AmAthlon,
eCpu_AmDuron,
eCpu_CyrixMediaGX,
eCpu_Cyrix6x86,
eCpu_CyrixGXm,
eCpu_Cyrix6x86MX,
eCpu_CenWinChip,
eCpu_CenWinChip2,
};
struct SCpu
{
ECpuVendor meVendor;
ECpuModel meModel;
unsigned long mFeatures;
bool mbSerialPresent;
char mSerialNumber[30];
int mFamily;
int mModel;
int mStepping;
char mVendor[64];
char mCpuType[64];
char mFpuType[64];
int mSpeed;
double m_SecondsPerCycle;
};
class CCpuFeatures
{
private:
int m_NumSystemProcessors;
int m_NumAvailProcessors;
bool m_bOS_ISSE;
bool m_bOS_ISSE_EXCEPTIONS;
public:
SCpu m_Cpu[MAX_CPU];
public:
CCpuFeatures()
{
m_NumSystemProcessors = 0;
m_NumAvailProcessors = 0;
m_bOS_ISSE = 0;
m_bOS_ISSE_EXCEPTIONS = 0;
}
void Detect(void);
bool hasSSE() { return (m_Cpu[0].mFeatures & CFI_SSE) != 0; }
bool hasSSE2() { return (m_Cpu[0].mFeatures & CFI_SSE2) != 0; }
bool has3DNow() { return (m_Cpu[0].mFeatures & CFI_3DNOW) != 0; }
bool hasMMX() { return (m_Cpu[0].mFeatures & CFI_MMX) != 0; }
};
#if defined(WIN64) || defined(LINUX64)
inline bool IsAMD64()
{
#ifdef _AMD64_
return true;
#else
#error not supported here
#endif
}
#else
inline bool
IsAMD64()
{
#if defined(LINUX32)
return false;
#else
_asm
{
// make sure cpuid is available
pushfd // save EFLAGS
pop eax // store EFLAGS in EAX
mov ebx, eax // save in EBX for later testing
xor eax, 00200000h // toggle bit 21
push eax // push to stack
popfd // save changed EAX to EFLAGS
pushfd // push EFLAGS to TOS
pop eax // store EFLAGS in EAX
cmp eax, ebx // see if bit 21 has changed
mov eax, 0 // clear eax to return "false"
jz QUIT // if no change, no CPUID
// perform AMD64 detection
mov eax, 0x80000001 // load argument "Processor Signature and AMD Features" to call cpuid
cpuid // call cpuid
mov eax, edx // edx contains "AMD Feature Support" flags
shr eax, 29 // test bit 29 (support for "Long Mode")
and eax, 0x00000001 // mask out bit for proper return value
QUIT:
}
#endif
}
#endif // WIN32
#endif

View File

@@ -0,0 +1,97 @@
#include "stdafx.h"
#include <ILog.h>
#include <Stream.h>
#include "System.h"
#include "zlib/zlib.h"
#if defined(LINUX)
# include <sys/io.h>
#else
# include <io.h>
#endif
#if defined(LINUX)
#include "ILog.h"
#endif
#include <fcntl.h>
#define USE_COMPRESSION
bool CSystem::WriteCompressedFile(char *filename, void *data, unsigned int bitlen)
{
FILE *pFile = fxopen(filename, "wb+");
if (!pFile)
return false;
#ifdef USE_COMPRESSION
gzFile f = gzdopen(fileno(pFile), "wb9");
gzwrite(f, &bitlen, sizeof(int));
gzwrite(f, data, BITS2BYTES(bitlen));
gzclose(f);
#else
fwrite(&bitlen, sizeof(int), 1, pFile);
fwrite(data, BITS2BYTES(bitlen), 1, pFile);
fclose(pFile);
#endif
return true;
};
unsigned int CSystem::GetCompressedFileSize(char *filename)
{
FILE *pFile=fxopen(filename, "rb");
if (!pFile)
return 0;
fseek(pFile,0,SEEK_END);
long nLen=ftell(pFile);
fseek(pFile,0,SEEK_SET);
if (nLen<=0)
{
// gzread works incorrectly if the filesize is 0
fclose(pFile);
return (0);
}
fclose(pFile);
pFile=fxopen(filename, "rb");
if (!pFile)
return 0;
unsigned int bitlen;
gzFile f = gzdopen(fileno(pFile), "rb9");
gzread(f, &bitlen, sizeof(int));
gzclose(f);
fclose(pFile);
return bitlen;
}
unsigned int CSystem::ReadCompressedFile(char *filename, void *data, unsigned int maxbitlen)
{
FILE * pFile=fxopen(filename, "rb");
if (!pFile)
return 0;
/*
fseek(pFile,0,SEEK_END);
long nLen=ftell(pFile);
fseek(pFile,0,SEEK_SET);
*/
unsigned int bitlen;
#ifdef USE_COMPRESSION
gzFile f = gzdopen(fileno(pFile), "rb9");
gzread(f, &bitlen, sizeof(int));
assert(bitlen<=maxbitlen); // FIXME: nicer if caller doesn't need to know buffer size in advance
gzread(f, data, BITS2BYTES(bitlen));
gzclose(f);
fclose(pFile);
#else
fread(pFile, &bitlen, sizeof(int));
assert(bitlen<=maxbitlen); // FIXME: nicer if caller doesn't need to know buffer size in advance
fread(pFile, data, BITS2BYTES(bitlen));
fclose(pFile);
#endif
return bitlen;
};

89
CrySystem/CritSection.h Normal file
View File

@@ -0,0 +1,89 @@
#ifndef _CRIT_SECTION_CRY_SYSTEM_HDR_
#define _CRIT_SECTION_CRY_SYSTEM_HDR_
#if defined(LINUX)
#include "WinBase.h"
#endif
/////////////////////////////////////////////////////////////////////////////////////
// Safe critical section robot: when constructing, it's locking the section, when
// destructing, it's unlocking it
/////////////////////////////////////////////////////////////////////////////////////
template <class T>
class CAutoLock
{
T& m_csThis; // the critical section that is to be locked on construction and unlocked on destruction
public:
// on construction, we lock the critical section
CAutoLock(T& csThis):
m_csThis(csThis)
{
csThis.Lock();
}
// on destruction, we unlock it
~CAutoLock()
{
m_csThis.Unlock();
}
};
template <class T>
class CAutoUnlock
{
T& m_csThis; // the critical section that is to be locked on construction and unlocked on destruction
public:
// on construction, we lock the critical section
CAutoUnlock (T& csThis):
m_csThis(csThis)
{
csThis.Unlock();
}
// on destruction, we unlock it
~CAutoUnlock()
{
m_csThis.Lock();
}
};
/////////////////////////////////////////////////////////////////////////////////////
// Abstraction of critical section synchronization object. Auto-constructs/destructs
// the embedded critical section
/////////////////////////////////////////////////////////////////////////////////////
class CCritSection
{
//this is a mutex implementation under linux too since semaphores provide additional functionality not provided by the windows compendent
CRITICAL_SECTION csThis;
public:
CCritSection()
{
InitializeCriticalSection (&csThis);
}
~CCritSection()
{
DeleteCriticalSection (&csThis);
}
void Lock ()
{
EnterCriticalSection(&csThis);
}
void Unlock ()
{
LeaveCriticalSection(&csThis);
}
// the lock and unlock facilities are disabled for explicit use,
// the client functions should use auto-lockers and auto-unlockers
private:
CCritSection (const CCritSection &);
friend class CAutoLock<CCritSection>;
friend class CAutoUnlock<CCritSection>;
};
#define AUTO_LOCK(csLock) CAutoLock<CCritSection> __AL__##csLock(csLock)
#define AUTO_LOCK_THIS() CAutoLock<CCritSection> __AL__this(*this)
#define AUTO_UNLOCK(csUnlock) CAutoUnlock<CCritSection> __AUl__##csUnlock(csUnlock)
#define AUTO_UNLOCK_THIS() CAutoUnlock<CCritSection> __AUl__##thisUnlock(*this)
#endif

View File

@@ -0,0 +1,498 @@
// CryMemoryManager.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <new.h>
#include <ISystem.h>
#include "platform.h"
#undef USE_NEWPOOL
#include <CryMemoryManager.h>
//////////////////////////////////////////////////////////////////////////
// Some globals for fast profiling.
//////////////////////////////////////////////////////////////////////////
size_t g_TotalAllocatedMemory = 0;
size_t g_ScriptAllocatedMemory = 0;
int g_nPrecaution = 0; // will cause delayed crash, will make engine extremally unstable.
//#if !defined(LINUX)
extern ISystem* g_System;
extern bool g_bProfilerEnabled;
//////////////////////////////////////////////////////////////////////////
// Undefine malloc for memory manager itself..
#undef malloc
#undef realloc
#undef free
#ifndef _XBOX
#define GLOBALPOOLSIZE (32*1025*1025+16)
#define EXTRAPOOLSIZE (32*1025*1025+16) // how much to allocate if we allow the pool to be exceeded
// currently biggest allocation happends during hires screenshot creation
#else // _XBOX
#ifndef _DEBUG
#define GLOBALPOOLSIZE (8*1025*1025+16)
#define EXTRAPOOLSIZE (8*1025*1025+16)
#else // _DEBUG
#define GLOBALPOOLSIZE (0)
#define EXTRAPOOLSIZE (0)
#endif // _DEBUG
#endif // _XBOX
#define MAXPOOLS 128
void *poolbufs[MAXPOOLS];
int poolsizes[MAXPOOLS];
int numpools = 0;
#if defined(WIN32) || defined(LINUX)
#if defined(WIN64) || defined(LINUX64)
// non-512 doesn't work for some reason: an infinite loop (recursion with stack overflow) occurs
#define BUCKETQUANT 512 // wouter: affects performance of bucket allocator, modify with care!
#else
#define BUCKETQUANT 512*2
#endif
#else
#define BUCKETQUANT 256 // save some memory overhead with tiny speed cost on consoles
#endif
/*
PoolContext *AllocPool(PoolContext *pCtx, int size)
{
// TODO: replace "malloc" with however we obtain memory on other platforms
void *buf = VirtualAlloc(NULL,size,MEM_COMMIT,PAGE_READWRITE);
if(!buf)
{
CryError( "<CrySystem> (AllocPool) malloc() Failed" );
};
bpool(pCtx, buf, size);
if (numpools==MAXPOOLS)
{
CryError( "<CrySystem> (AllocPool) Maximum number of memory pools reached." );
}
poolsizes[numpools] = size;
poolbufs[numpools++] = buf;
return pCtx;
};
*/
//static PoolContext globalpool;
//static PoolContext *g_pool = AllocPool(InitPoolContext(&globalpool), GLOBALPOOLSIZE);
static unsigned int biggestalloc = 0;
/*
#define MAXSTAT 1000
static int stats[MAXSTAT];
void addstat(int size) { if(size<0 || size>=MAXSTAT) size = MAXSTAT-1; stats[size]++; };
void printstats() { for(int i = 0; i<MAXSTAT; i++) if(stats[i]) { char buf[100]; sprintf(buf, "bucket %d -> %d\n", i, stats[i]); ::OutputDebugString(buf); }; };
int clearstats() { for(int i = 0; i<MAXSTAT; i++) stats[i] = 0; return 0; };
static int foo = clearstats();
*/
class PageBucketAllocator
{
/*
Generic allocator that combines bucket allocation with reference counted 1 size object pages.
manages to perform well along each axis:
- very fast for small objects: only a few instructions in the general case for alloc/dealloc,
up to several orders of magnitude faster than traditional best fit allocators
- low per object memory overhead: 0 bytes overhead on small objects, small overhead for
pages that are partially in use (still significantly lower than other allocators).
- almost no fragmentation, reuse of pages is close to optimal
- very good cache locality (page aligned, same size objects)
*/
enum { PAGESIZE = 4096 };
enum { PAGEMASK = (~(PAGESIZE-1)) };
//enum { PAGESATONCE = 64 };
enum { PAGESATONCE = 32 };
enum { PAGEBLOCKSIZE = PAGESIZE*PAGESATONCE };
enum { PTRSIZE = sizeof(char *) };
enum { MAXBUCKETS = BUCKETQUANT/4+1 }; // meaning up to size 512 on 32bit pointer systems
enum { MAXREUSESIZE = MAXBUCKETS*PTRSIZE-PTRSIZE };
int bucket(int s) { return (s+PTRSIZE-1)>>PTRBITS; };
int *ppage(void *p) { return (int *)(((INT_PTR)p)&PAGEMASK); };
enum { PTRBITS = PTRSIZE==2 ? 1 : PTRSIZE==4 ? 2 : 3 };
void *reuse[MAXBUCKETS];
void **pages;
//! Total allocated size.
void putinbuckets(char *start, char *end, int bsize)
{
int size = bsize*PTRSIZE;
for(end -= size; start<=end; start += size)
{
*((void **)start) = reuse[bsize];
reuse[bsize] = start;
};
};
void newpageblocks()
{
char *b = (char *)::malloc(PAGEBLOCKSIZE); // if we could get page aligned memory here, that would be even better
char *first = ((char *)ppage(b))+PAGESIZE;
for(int i = 0; i<PAGESATONCE-1; i++)
{
void **p = (void **)(first+i*PAGESIZE);
*p = pages;
pages = p;
};
//if(b-first+PAGESIZE>BUCKETQUANT) bpool(g_pool, first+PAGEBLOCKSIZE-PAGESIZE, b-first+PAGESIZE);
};
void *newpage(unsigned int bsize)
{
if(!pages) newpageblocks();
void **page = pages;
pages = (void **)*pages;
*page = 0;
putinbuckets((char *)(page+1), ((char *)page)+PAGESIZE, bsize);
return alloc(bsize*PTRSIZE);
};
void freepage(int *page, int bsize) // worst case if very large amounts of objects get deallocated in random order from when they were allocated
{
for(void **r = &reuse[bsize]; *r; )
{
if(page == ppage(*r)) *r = *((void **)*r);
else r = (void **)*r;
};
void **p = (void **)page;
*p = pages;
pages = p;
};
public:
PageBucketAllocator()
{
pages = NULL;
for(int i = 0; i<MAXBUCKETS; i++) reuse[i] = NULL;
};
void *alloc(unsigned int size)
{
if(size>biggestalloc)
{
biggestalloc = size;
};
if(size>MAXREUSESIZE) return ::malloc(size);
size = bucket(size);
void **r = (void **)reuse[size];
if(!r) return newpage(size);
reuse[size] = *r;
int *page = ppage(r);
(*page)++;
return (void *)r;
};
void dealloc(void *p, unsigned int size)
{
if(size>MAXREUSESIZE)
{
::free(p);
//brel(g_pool, p);
}
else
{
size = bucket(size);
*((void **)p) = reuse[size];
reuse[size] = p;
int *page = ppage(p);
if(!--(*page)) freepage(page, size);
};
};
void stats()
{
int totalwaste = 0;
char buf[100];
for(int i = 0; i<MAXBUCKETS; i++)
{
int n = 0;
for(void **r = (void **)reuse[i]; r; r = (void **)*r) n++;
if(n)
{
int waste = i*4*n/1024;
totalwaste += waste;
sprintf(buf, "bucket %d -> %d (%d k)\n", i*4, n, waste);
::OutputDebugString(buf);
};
};
sprintf(buf, "totalwaste %d k\n", totalwaste);
::OutputDebugString(buf);
};
};
PageBucketAllocator g_GlobPageBucketAllocator;
CRYMEMORYMANAGER_API void *CryMalloc(size_t size)
{
if (!g_bProfilerEnabled)
{
g_TotalAllocatedMemory += size+sizeof(int);
int *p = (int *)g_GlobPageBucketAllocator.alloc(size+sizeof(int));
*p++ = size; // stores 2 sizes for big objects!
return p;
}
else
{
FUNCTION_PROFILER_FAST( g_System,PROFILE_SYSTEM,g_bProfilerEnabled );
g_TotalAllocatedMemory += size+sizeof(int);
int *p = (int *)g_GlobPageBucketAllocator.alloc(size+sizeof(int));
*p++ = size; // stores 2 sizes for big objects!
return p;
}
}
CRYMEMORYMANAGER_API void CryFree(void *p)
{
if (!g_bProfilerEnabled)
{
if (p != NULL)
{
unsigned int *t = (unsigned int *)p;
unsigned int size = *--t;
#ifdef MINIMALDEBUG
if (size>=100000000)
{
CryError( "\001[CRYMANAGER ERROR](CryFree): illegal size 0x%X - block header was corrupted",size);
}
#endif
size += sizeof(int);
#ifdef GARBAGEMEMORY //FIXME: *disabling* memset caused random crash???
memset(t, 0xBA, size);
#endif
g_TotalAllocatedMemory -= size;
g_GlobPageBucketAllocator.dealloc(t, size);
}
}
else
{
// With profiler.
if (p != NULL)
{
FUNCTION_PROFILER_FAST( g_System,PROFILE_SYSTEM,g_bProfilerEnabled );
unsigned int *t = (unsigned int *)p;
unsigned int size = *--t;
#ifdef MINIMALDEBUG
if (size>=100000000)
{
CryError( "\001[CRYMANAGER ERROR](CryFree): illegal size 0x%X - block header was corrupted",size);
}
#endif
size += sizeof(int);
#ifdef GARBAGEMEMORY //FIXME: *disabling* memset caused random crash???
memset(t, 0xBA, size);
#endif
g_TotalAllocatedMemory -= size;
g_GlobPageBucketAllocator.dealloc(t, size);
}
}
}
CRYMEMORYMANAGER_API void CryFreeSize(void *p, size_t size)
{
g_ScriptAllocatedMemory -= size;
g_TotalAllocatedMemory -= size;
if (!g_bProfilerEnabled)
{
if (p != NULL)
{
#ifdef MINIMALDEBUG
if (size>=100000000)
{
CryError("[CRYMANAGER ERROR](CryFreeSize): illegal size 0x%X - block header was corrupted",size );
}
#endif
#ifdef GARBAGEMEMORY //FIXME: idem
memset(p, 0xBB, size);
#endif
g_GlobPageBucketAllocator.dealloc(p, size);
}
}
else
{
// With profiler.
if (p != NULL)
{
FUNCTION_PROFILER_FAST( g_System,PROFILE_SYSTEM,g_bProfilerEnabled );
#ifdef MINIMALDEBUG
if (size>=100000000)
{
CryError("[CRYMANAGER ERROR](CryFreeSize): illegal size 0x%X - block header was corrupted",size );
}
#endif
#ifdef GARBAGEMEMORY //FIXME: idem
memset(p, 0xBB, size);
#endif
g_GlobPageBucketAllocator.dealloc(p, size);
}
}
}
CRYMEMORYMANAGER_API void *CryRealloc(void *memblock, size_t size)
{
if (!g_bProfilerEnabled)
{
// Without profiler.
if(memblock==NULL)
return CryMalloc(size);
else
{
void *np = CryMalloc(size);
size_t oldsize = ((int *)memblock)[-1];
memcpy(np, memblock, size>oldsize ? oldsize : size);
CryFree(memblock);
return np;
}
}
else
{
// With Profiler.
FUNCTION_PROFILER_FAST( g_System,PROFILE_SYSTEM,g_bProfilerEnabled );
if(memblock==NULL)
return CryMalloc(size);
else
{
void *np = CryMalloc(size);
size_t oldsize = ((int *)memblock)[-1];
memcpy(np, memblock, size>oldsize ? oldsize : size);
CryFree(memblock);
return np;
}
}
}
CRYMEMORYMANAGER_API void *CryReallocSize(void *memblock, size_t oldsize, size_t size)
{
g_ScriptAllocatedMemory += size; // -old size done in CryFreeSize
g_TotalAllocatedMemory += size;
if (!g_bProfilerEnabled)
{
if(memblock==NULL)
{
return (char*)g_GlobPageBucketAllocator.alloc(size) + g_nPrecaution;
}
else
{
void *np = (char*)g_GlobPageBucketAllocator.alloc(size) + g_nPrecaution;
memcpy(np, memblock, size>oldsize ? oldsize : size);
CryFreeSize(memblock, oldsize);
return np;
}
}
else
{
FUNCTION_PROFILER_FAST( g_System,PROFILE_SYSTEM,g_bProfilerEnabled );
if(memblock==NULL)
{
return (char*)g_GlobPageBucketAllocator.alloc(size) + g_nPrecaution;
}
else
{
void *np = (char*)g_GlobPageBucketAllocator.alloc(size) + g_nPrecaution;
memcpy(np, memblock, size>oldsize ? oldsize : size);
CryFreeSize(memblock, oldsize);
return np;
}
}
}
CRYMEMORYMANAGER_API void CryFlushAll() // releases/resets ALL memory... this is useful for restarting the game
{
/*
InitPoolContext(g_pool);
for(int i = 0; i<numpools; i++)
bpool(g_pool, poolbufs[i], poolsizes[i]);
*/
new (&g_GlobPageBucketAllocator) PageBucketAllocator();
g_ScriptAllocatedMemory = 0;
g_TotalAllocatedMemory = 0;
};
/* MarcoK: This is never used anywhere ... commented out (LINUX port)
extern "C" CRYMEMORYMANAGER_API void CryFreeMemoryPools() // releases/resets ALL memory... this is useful for restarting the game
{
for(int i = 0; i<numpools; i++)
{
void *pBuf = poolbufs[i];
VirtualFree( pBuf,0,MEM_RELEASE );
}
numpools = 0;
g_ScriptAllocatedMemory = 0;
g_TotalAllocatedMemory = 0;
};
*/
//////////////////////////////////////////////////////////////////////////
// Returns ammount of memory allocated with CryMalloc/CryFree functions.
//////////////////////////////////////////////////////////////////////////
CRYMEMORYMANAGER_API int CryMemoryGetAllocatedSize()
{
return g_TotalAllocatedMemory;
}
//////////////////////////////////////////////////////////////////////////
CRYMEMORYMANAGER_API int CryMemoryGetAllocatedInScriptSize()
{
return g_ScriptAllocatedMemory;
}
//////////////////////////////////////////////////////////////////////////
CRYMEMORYMANAGER_API int CryMemoryGetPoolSize()
{
int totalsize = 0;
for(int i = 0; i<numpools; i++)
totalsize += poolsizes[i];
return totalsize;
}
//////////////////////////////////////////////////////////////////////////
CRYMEMORYMANAGER_API int CryStats(char *buf)
{
long curalloc=0, totfree=0, maxfree=0, nget=0, nrel=0;
//bstats(g_pool, &curalloc, &totfree, &maxfree, &nget, &nrel);
if(buf)
{
int poolsize = CryMemoryGetPoolSize();
int scriptalloc = CryMemoryGetAllocatedInScriptSize();
sprintf(buf, "Memory Allocated = %d K, totfree = %d K , maxfree = %d K, nmalloc = %d, nfree = %d, biggestalloc = %d, Pool Size = %d K, Lua Allocated = %d K",
curalloc/1024, totfree/1024, maxfree/1024, nget, nrel, biggestalloc,poolsize/1024,scriptalloc/1024);
//printstats();
g_GlobPageBucketAllocator.stats();
};
return curalloc/1024;
}
/*
extern "C" void debug(int n)
{
char buf[100];
sprintf(buf, "BESTFIT: %d\n", n);
::OutputDebugString(buf);
};
*/// CryMemoryManager.cpp : Defines the entry point for the DLL application.
//#endif //LINUX

1867
CrySystem/CryPak.cpp Normal file

File diff suppressed because it is too large Load Diff

626
CrySystem/CryPak.h Normal file
View File

@@ -0,0 +1,626 @@
//////////////////////////////////////////////////////////////////////
//
// Crytek CryENGINE Source code
//
// File:CryPak.h
//
// History:
// -Feb 2,2001:Created by Honich Andrey
// -June 12, 2003: Taken over by Sergiy Migdalskiy.
// Got rid of unzip usage, now using ZipDir for much more effective
// memory usage (~3-6 times less memory, and no allocator overhead)
// to keep the directory of the zip file; better overall effectiveness and
// more readable and manageable code, made the connection to Streaming Engine
//
//////////////////////////////////////////////////////////////////////
#ifndef CRYPAK_H
#define CRYPAK_H
#include <ICryPak.h>
#include "IMiniLog.h"
#include "ZipDir.h"
#include "MTSafeAllocator.h"
#include "CritSection.h"
#include "StlUtils.h"
#include "PakVars.h"
extern CMTSafeHeap* g_pSmallHeap;
extern CMTSafeHeap* g_pBigHeap;
// this is the header in the cache of the file data
struct CCachedFileData: public _reference_target_MT_novtbl<CCachedFileData>
{
CCachedFileData (class CCryPak* pPak, ZipDir::Cache*pZip, ZipDir::FileEntry* pFileEntry);
~CCachedFileData();
// return the data in the file, or NULL if error
// by default, if bRefreshCache is true, and the data isn't in the cache already,m
// the cache is refreshed. Otherwise, it returns whatever cache is (NULL if the data isn't cached yet)
void* GetData(bool bRefreshCache = true);
ZipDir::Cache* GetZip(){return m_pZip;}
ZipDir::FileEntry* GetFileEntry() {return m_pFileEntry;}
// the memory needs to be allocated out of a MT-safe heap here
void * __cdecl operator new (size_t size) { return g_pSmallHeap->Alloc(size, "CCachedFileData::new"); }
void __cdecl operator delete (void *p) { g_pSmallHeap->Free(p); };
unsigned GetFileDataOffset()
{
if (m_pFileEntry->nFileDataOffset == m_pFileEntry->INVALID_DATA_OFFSET)
m_pZip->Refresh (m_pFileEntry);
return m_pFileEntry->nFileDataOffset;
}
unsigned sizeofThis()const
{
return sizeof(*this) + (m_pFileData&&m_pFileEntry?m_pFileEntry->desc.lSizeUncompressed:0);
}
protected:
void* m_pFileData;
volatile LONG m_nRefCounter;
// the zip file in which this file is opened
ZipDir::CachePtr m_pZip;
// the file entry : if this is NULL, the entry is free and all the other fields are meaningless
ZipDir::FileEntry* m_pFileEntry;
class CCryPak* m_pPak;
friend struct CCachedFileDataOrder;
};
TYPEDEF_AUTOPTR(CCachedFileData);
typedef CCachedFileData_AutoPtr CCachedFileDataPtr;
// the cached data pointers are sorted by the FileEntries
struct CCachedFileDataOrder
{
bool operator () (const CCachedFileData* left, const CCachedFileData* right)const
{
return left->m_pFileEntry < right->m_pFileEntry;
}
};
// an (inside zip) emultated open file
struct CZipPseudoFile
{
CZipPseudoFile()
{
Construct();
}
enum
{
_O_COMMIT_FLUSH_MODE = 1 << 31,
_O_DIRECT_OPERATION = 1 << 30
};
// this object must be constructed before usage
// nFlags is a combination of _O_... flags
void Construct(CCachedFileData* pFileData = NULL, unsigned nFlags = 0)
{
m_pFileData = pFileData;
m_nFlags = nFlags;
m_nCurSeek = 0;
if ((nFlags & _O_DIRECT_OPERATION)&&pFileData&&pFileData->GetFileEntry()->nMethod == ZipFile::METHOD_STORE)
{
m_fDirect = fopen (pFileData->GetZip()->GetFilePath(), "rb"); // "rb" is the only supported mode
FSeek(0,SEEK_SET); // the user assumes offset 0 right after opening the file
}
else
m_fDirect = NULL;
}
// this object needs to be freed manually when the CryPak shuts down..
void Destruct()
{
assert ((bool)m_pFileData);
// mark it free, and deallocate the pseudofile memory
m_pFileData = NULL;
if (m_fDirect)
fclose (m_fDirect);
}
CCachedFileData* GetFile() {return m_pFileData;}
long FTell() {return m_nCurSeek;}
unsigned GetFileSize()
{
return GetFile()?GetFile()->GetFileEntry()->desc.lSizeUncompressed:0;
}
int FSeek (long nOffset, int nMode);
size_t FRead (void* pDest, size_t nSize, size_t nCount, FILE* hFile);
int FEof();
int FScanfv (const char* szFormat, va_list args);
char* FGets(char* pBuf, int n);
int Getc();
int Ungetc(int c);
FILETIME GetModificationTime()
{
return m_pFileData->GetFileEntry()->GetModificationTime();
}
const char* GetArchivePath()
{
return m_pFileData->GetZip()->GetFilePath();
}
protected:
long m_nCurSeek;
CCachedFileDataPtr m_pFileData;
// nFlags is a combination of _O_... flags
unsigned m_nFlags;
FILE* m_fDirect;
};
struct CIStringOrder
{
bool operator () (const string& left, const string& right) const
{
return stricmp(left.c_str(), right.c_str()) < 0;
}
};
class CCryPakFindData: public _reference_target_t
{
public:
// the directory wildcard must already be adjusted
CCryPakFindData (class CCryPak*pPak, const char* szDir);
bool empty() const;
bool Fetch(_finddata_t* pfd);
void Scan(CCryPak*pPak, const char* szDir);
size_t sizeofThis()const;
protected:
void ScanFS(CCryPak*pPak, const char* szDir);
void ScanZips(CCryPak*pPak, const char* szDir);
struct FileDesc
{
unsigned nAttrib;
unsigned nSize;
time_t tAccess;
time_t tCreate;
time_t tWrite;
FileDesc (struct _finddata_t* fd);
FileDesc (struct __finddata64_t* fd);
FileDesc (ZipDir::FileEntry* fe);
// default initialization is as a directory entry
FileDesc ();
};
typedef std::map<string, FileDesc, CIStringOrder> FileMap;
FileMap m_mapFiles;
};
TYPEDEF_AUTOPTR(CCryPakFindData);
//////////////////////////////////////////////////////////////////////
class CCryPak : public ICryPak
{
// the array of pseudo-files : emulated files in the virtual zip file system
// the handle to the file is its index inside this array.
// some of the entries can be free. The entries need to be destructed manually
typedef std::vector<CZipPseudoFile> ZipPseudoFileArray;
ZipPseudoFileArray m_arrOpenFiles;
// the array of file datas; they are relatively self-contained and can
// read and cache the file data on-demand. It's up to the clients
// to use caching or access the zips directly
CCritSection m_csCachedFiles;
typedef CMTSafeAllocator<CCachedFileData*> CachedFileDataAllocator;
typedef std::set<CCachedFileData*,CCachedFileDataOrder, CachedFileDataAllocator > CachedFileDataSet;
CachedFileDataSet m_setCachedFiles;
// The F* emulation functions critical sectio: protects all F* functions
// that don't have a chance to be called recursively (to avoid deadlocks)
CCritSection m_csMain;
// open zip cache objects that can be reused. They're self-[un]registered
// they're sorted by the path and
typedef std::vector<ICryArchive*> ArchiveArray;
ArchiveArray m_arrArchives;
// the array of opened caches - they get destructed by themselves (these are auto-pointers, see the ZipDir::Cache documentation)
struct PackDesc
{
string strBindRoot; // the zip binding root WITH the trailing native slash
//string strFileName; // the zip file name (no path)
const char* GetFullPath()const {return pZip->GetFilePath();}
ICryArchive_AutoPtr pArchive;
ZipDir::CachePtr pZip;
size_t sizeofThis()
{
return strBindRoot.capacity() + pZip->GetSize();
}
};
typedef std::vector<PackDesc > ZipArray;
CCritSection m_csZips;
ZipArray m_arrZips;
friend class CCryPakFindData;
typedef std::set<CCryPakFindData_AutoPtr> CryPakFindDataSet;
CryPakFindDataSet m_setFindData;
IMiniLog *m_pLog;
// the root: "C:\MasterCD\"
string m_strMasterCDRoot;
// this is the list of MOD subdirectories that will be prepended to the actual relative file path
// they all have trailing forward slash. "" means the root dir
std::vector<string> m_arrMods;
//////////////////////////////////////////////////////////////////////////
// Opened files collector.
//////////////////////////////////////////////////////////////////////////
bool m_bRememberOpenedFiles;
typedef std::set<string,stl::less_stricmp<string> > RecordedFilesSet;
RecordedFilesSet m_recordedFilesSet;
const PakVars* m_pPakVars;
bool InitPack(const char *szBasePath, unsigned nFlags = FLAGS_PATH_REAL);
public:
// given the source relative path, constructs the full path to the file according to the flags
const char* AdjustFileName (const char *src, char dst[g_nMaxPath], unsigned nFlags,bool *bFoundInPak=NULL);
// this is the start of indexation of pseudofiles:
// to the actual index , this offset is added to get the valid handle
enum {g_nPseudoFileIdxOffset = 1};
// this defines which slash will be kept internally
enum {g_cNativeSlash = '\\', g_cNonNativeSlash = '/'};
// makes the path lower-case and removes the duplicate and non native slashes
// may make some other fool-proof stuff
// may NOT write beyond the string buffer (may not make it longer)
// returns: the pointer to the ending terminator \0
static char* BeautifyPath(char* dst);
CCryPak(IMiniLog* pLog,PakVars* pPakVars = NULL);
~CCryPak();
const PakVars* GetPakVars()const {return m_pPakVars;}
public:
PakInfo* GetPakInfo();
void FreePakInfo (PakInfo*);
//! adds a mod to the list of mods
void AddMod(const char* szMod);
//! removes a mod from the list of mods
void RemoveMod(const char* szMod);
//! Puts the memory statistics into the given sizer object
//! According to the specifications in interface ICrySizer
void GetMemoryStatistics(ICrySizer *pSizer);
// open the physical archive file - creates if it doesn't exist
// returns NULL if it's invalid or can't open the file
virtual ICryArchive* OpenArchive (const char* szPath, unsigned nFlags = 0);
// returns the path to the archive in which the file was opened
virtual const char* GetFileArchivePath (FILE* f);
CCritSection& GetCachedFileLock() {return m_csCachedFiles;}
void Register (CCachedFileData* p)
{
// actually, registration may only happen when the set is already locked, but for generality..
AUTO_LOCK(m_csCachedFiles);
m_setCachedFiles.insert (p);
}
void Unregister (CCachedFileData* p)
{
AUTO_LOCK(m_csCachedFiles);
m_setCachedFiles.erase (p);
}
// ICryPak interface
virtual bool Init (const char *szBasePath);
virtual void Release();
virtual bool OpenPack(const char *pName, unsigned nFlags = 0);
virtual bool OpenPack(const char* szBindRoot, const char *pName, unsigned nFlags = 0);
virtual bool OpenPackCommon(const char* szBindRoot, const char *pName, unsigned nFlags = 0);
// after this call, the file will be unlocked and closed, and its contents won't be used to search for files
virtual bool ClosePack(const char* pName, unsigned nFlags = 0);
virtual bool OpenPacks(const char *pWildcard, unsigned nFlags = 0);
virtual bool OpenPacks(const char* szBindRoot, const char *pWildcard, unsigned nFlags = 0);
bool OpenPacksCommon(const char* szDir, char *cWork, unsigned nFlags);
// closes pack files by the path and wildcard
virtual bool ClosePacks(const char* pWildcard, unsigned nFlags = 0);
// returns the file modification time
virtual FILETIME GetModificationTime(FILE* f);
// this function gets the file data for the given file, if found.
// The file data object may be created in this function,
// and it's important that the autoptr is returned: another thread may release the existing
// cached data before the function returns
// the path must be absolute normalized lower-case with forward-slashes
CCachedFileDataPtr GetFileData(const char* szName);
// tests if the given file path refers to an existing file inside registered (opened) packs
// the path must be absolute normalized lower-case with forward-slashes
bool HasFileEntry (const char* szPath);
virtual FILE *FOpen(const char *pName, const char *mode, unsigned nFlags);
virtual FILE *FOpen(const char *pName, const char *mode,char *szFileGamePath,int nLen);
virtual size_t FRead(void *data, size_t length, size_t elems, FILE *handle);
virtual size_t FWrite(void *data, size_t length, size_t elems, FILE *handle);
virtual int FSeek(FILE *handle, long seek, int mode);
virtual long FTell(FILE *handle);
virtual int FFlush(FILE *handle);
virtual int FClose(FILE *handle);
virtual intptr_t FindFirst(const char *pDir, struct _finddata_t *fd);
virtual int FindNext(intptr_t handle, struct _finddata_t *fd);
virtual int FindClose(intptr_t handle);
virtual int FEof(FILE *handle);
virtual int FScanf(FILE *, const char *, ...);
virtual char *FGets(char *, int, FILE *);
virtual int Getc(FILE *);
virtual int Ungetc(int c, FILE *);
virtual int FPrintf(FILE *handle, const char *format, ...);
unsigned FGetSize(FILE* f);
// virtual bool IsOutOfDate(const char * szFileName, const char * szMasterFile);
//virtual FILETIME GetFileTime(const char * szFileName);
// creates a directory
virtual bool MakeDir (const char* szPath);
// returns the current game directory, with trailing slash (or empty string if it's right in MasterCD)
// this is used to support Resource Compiler which doesn't have access to this interface:
// in case all the contents is located in a subdirectory of MasterCD, this string is the subdirectory name with slash
//virtual const char* GetGameDir();
void Register (ICryArchive* pArchive);
void Unregister (ICryArchive* pArchive);
ICryArchive* FindArchive (const char* szFullPath);
// compresses the raw data into raw data. The buffer for compressed data itself with the heap passed. Uses method 8 (deflate)
// returns one of the Z_* errors (Z_OK upon success)
// MT-safe
int RawCompress (const void* pUncompressed, unsigned long* pDestSize, void* pCompressed, unsigned long nSrcSize, int nLevel = -1);
// Uncompresses raw (without wrapping) data that is compressed with method 8 (deflated) in the Zip file
// returns one of the Z_* errors (Z_OK upon success)
// This function just mimics the standard uncompress (with modification taken from unzReadCurrentFile)
// with 2 differences: there are no 16-bit checks, and
// it initializes the inflation to start without waiting for compression method byte, as this is the
// way it's stored into zip file
int RawUncompress (void* pUncompressed, unsigned long* pDestSize, const void* pCompressed, unsigned long nSrcSize) ;
//////////////////////////////////////////////////////////////////////////
// Files opening recorder.
//////////////////////////////////////////////////////////////////////////
void RecordFileOpen( bool bEnable );
void RecordFile( const char *szFilename );
void EnumerateRecordedFiles( RecordedFilesEnumCallback enumCallback );
void OnMissingFile (const char* szPath);
// missing file -> count of missing files
typedef CMTSafeAllocator<std::pair<string, unsigned> > MissingFileMapAllocator;
typedef std::map<string, unsigned, std::less<string>, MissingFileMapAllocator > MissingFileMap;
MissingFileMap m_mapMissingFiles;
};
struct CryArchiveSortByName
{
bool operator () (const ICryArchive* left, const ICryArchive* right)const
{
return stricmp(left->GetFullPath(), right->GetFullPath()) < 0;
}
bool operator () (const char* left, const ICryArchive* right)const
{
return stricmp(left, right->GetFullPath()) < 0;
}
bool operator () (const ICryArchive* left, const char* right)const
{
return stricmp(left->GetFullPath(), right) < 0;
}
};
template <class Cache>
class TCryArchive: public ICryArchive
{
public:
TCryArchive (CCryPak*pPak, const string& strBindRoot, Cache* pCache, unsigned nFlags = 0):
m_pCache(pCache),
m_strBindRoot (strBindRoot),
m_pPak(pPak),
m_nFlags (nFlags)
{
pPak->Register(this);
}
~TCryArchive()
{
m_pPak->Unregister (this);
}
// finds the file; you don't have to close the returned handle
Handle FindFile (const char* szRelativePath)
{
char szFullPath[CCryPak::g_nMaxPath];
const char*pPath = AdjustPath (szRelativePath, szFullPath);
if (!pPath)
return NULL;
return m_pCache->FindFile(pPath);
}
// returns the size of the file (unpacked) by the handle
unsigned GetFileSize (Handle h)
{
assert (m_pCache->IsOwnerOf((ZipDir::FileEntry*)h));
return ((ZipDir::FileEntry*)h)->desc.lSizeUncompressed;
}
// reads the file into the preallocated buffer (must be at least the size of GetFileSize())
int ReadFile (Handle h, void* pBuffer)
{
assert (m_pCache->IsOwnerOf((ZipDir::FileEntry*)h));
return m_pCache->ReadFile ((ZipDir::FileEntry*)h, NULL, pBuffer);
}
// returns the full path to the archive file
const char* GetFullPath() const
{
return m_pCache->GetFilePath();
}
unsigned GetFlags() const {return m_nFlags;}
bool SetFlags(unsigned nFlagsToSet)
{
if (nFlagsToSet & FLAGS_RELATIVE_PATHS_ONLY)
m_nFlags |= FLAGS_RELATIVE_PATHS_ONLY;
if (nFlagsToSet & ~(FLAGS_RELATIVE_PATHS_ONLY))
{
// we don't support changing of any other flags
return false;
}
return true;
}
bool ResetFlags (unsigned nFlagsToReset)
{
if (nFlagsToReset & FLAGS_RELATIVE_PATHS_ONLY)
m_nFlags &= ~FLAGS_RELATIVE_PATHS_ONLY;
if (nFlagsToReset & ~(FLAGS_RELATIVE_PATHS_ONLY))
{
// we don't support changing of any other flags
return false;
}
return true;
}
Cache* GetCache() {return m_pCache;}
protected:
// returns the pointer to the relative file path to be passed
// to the underlying Cache pointer. Uses the given buffer to construct the path.
// returns NULL if the file path is invalid
const char* AdjustPath (const char* szRelativePath, char szFullPathBuf[CCryPak::g_nMaxPath])
{
if (!szRelativePath[0])
return NULL;
if (m_nFlags & FLAGS_RELATIVE_PATHS_ONLY)
return szRelativePath;
if (szRelativePath[1] == ':' || (m_nFlags & FLAGS_ABSOLUTE_PATHS))
{
// make the normalized full path and try to match it against the binding root of this object
const char* szFullPath = m_pPak->AdjustFileName (szRelativePath, szFullPathBuf, m_nFlags & FLAGS_IGNORE_MODS ? ICryPak::FLAGS_PATH_REAL : 0);
size_t nPathLen = strlen(szFullPath);
if (nPathLen <= m_strBindRoot.length())
return NULL;
// you should access exactly the file under the directly in which the zip is situated
if (szFullPath[m_strBindRoot.length()] != '/' && szFullPath[m_strBindRoot.length()] != '\\')
return NULL;
#if defined(LINUX)
if (comparePathNames(szFullPath, m_strBindRoot.c_str(), m_strBindRoot.length()))
#else
if (memicmp(szFullPath, m_strBindRoot.c_str(), m_strBindRoot.length()))
#endif
return NULL; // the roots don't match
return szFullPath + m_strBindRoot.length() + 1;
}
return szRelativePath;
}
protected:
_smart_ptr<Cache> m_pCache;
// the binding root may be empty string - in this case, the absolute path binding won't work
string m_strBindRoot;
CCryPak* m_pPak;
unsigned m_nFlags;
};
class CryArchiveRW: public TCryArchive<ZipDir::CacheRW>
{
public:
CryArchiveRW (CCryPak*pPak, const string& strBindRoot, ZipDir::CacheRW* pCache, unsigned nFlags = 0):
TCryArchive<ZipDir::CacheRW>(pPak, strBindRoot, pCache, nFlags)
{
}
~CryArchiveRW()
{
}
// Adds a new file to the zip or update an existing one
// adds a directory (creates several nested directories if needed)
// compression methods supported are 0 (store) and 8 (deflate) , compression level is 0..9 or -1 for default (like in zlib)
int UpdateFile (const char* szRelativePath, void* pUncompressed, unsigned nSize, unsigned nCompressionMethod = 0, int nCompressionLevel = -1);
// deletes the file from the archive
int RemoveFile (const char* szRelativePath);
// deletes the directory, with all its descendants (files and subdirs)
int RemoveDir (const char* szRelativePath);
int RemoveAll();
enum {gClassId = 1};
unsigned GetClassId()const {return gClassId;}
};
class CryArchive: public TCryArchive<ZipDir::Cache>
{
public:
CryArchive (CCryPak* pPak, const string& strBindRoot, ZipDir::Cache* pCache, unsigned nFlags):
TCryArchive<ZipDir::Cache>(pPak, strBindRoot, pCache, nFlags)
{ }
~CryArchive(){}
// Adds a new file to the zip or update an existing one
// adds a directory (creates several nested directories if needed)
// compression methods supported are METHOD_STORE == 0 (store) and
// METHOD_DEFLATE == METHOD_COMPRESS == 8 (deflate) , compression
// level is LEVEL_FASTEST == 0 till LEVEL_BEST == 9 or LEVEL_DEFAULT == -1
// for default (like in zlib)
int UpdateFile (const char* szRelativePath, void* pUncompressed, unsigned nSize, unsigned nCompressionMethod = 0, int nCompressionLevel = -1) {return ZipDir::ZD_ERROR_INVALID_CALL;}
// deletes the file from the archive
int RemoveFile (const char* szRelativePath) {return ZipDir::ZD_ERROR_INVALID_CALL;}
int RemoveAll();
// deletes the directory, with all its descendants (files and subdirs)
int RemoveDir (const char* szRelativePath) {return ZipDir::ZD_ERROR_INVALID_CALL;}
enum {gClassId = 2};
unsigned GetClassId()const {return gClassId;}
};
#endif

169
CrySystem/CrySizerImpl.cpp Normal file
View File

@@ -0,0 +1,169 @@
#include "stdafx.h"
#include <ITimer.h>
#include <CrySizer.h>
#include "CrySizerImpl.h"
CrySizerImpl::CrySizerImpl()
{
// to avoid reallocations during walk through the memory tree, reserve the space for the names
clear();
}
CrySizerImpl::~CrySizerImpl()
{
}
void CrySizerImpl::Push (const char* szComponentName)
{
m_stackNames.push_back (getNameIndex(getCurrentName(), szComponentName));
// if the depth is too deep, something is wrong, perhaps an infinite loop
assert (m_stackNames.size() < 128);
}
void CrySizerImpl::PushSubcomponent (const char* szSubcomponentName)
{
Push (szSubcomponentName);
}
void CrySizerImpl::Pop ()
{
if (!m_stackNames.empty())
m_stackNames.pop_back();
else
assert (0);
}
// returns the index of the current name on the top of the name stack
size_t CrySizerImpl::getCurrentName()const
{
assert(!m_stackNames.empty());
return m_stackNames.empty()?0:m_stackNames.back();
}
// searches for the name in the name array; adds the name if it's not there and returns the index
size_t CrySizerImpl::getNameIndex (size_t nParent, const char* szComponentName)
{
NameArray::const_iterator it = m_arrNames.begin(), itEnd = it + m_arrNames.size();
for (; it != itEnd; ++it)
#if defined(LINUX)
if (!strcasecmp(it->strName.c_str(), szComponentName) && it->nParent == nParent)
#else
if (!strcmp(it->strName.c_str(), szComponentName) && it->nParent == nParent)
#endif
return it-m_arrNames.begin();
size_t nNewName = m_arrNames.size();
m_arrNames.resize(nNewName+1);
m_arrNames[nNewName].assign(szComponentName, nParent);
m_arrNames[nParent].arrChildren.push_back(nParent);
return nNewName;
}
// adds an object identified by the unique pointer (it needs not be
// the actual object position in the memory, though it would be nice,
// but it must be unique throughout the system and unchanging for this object)
// RETURNS: true if the object has actually been added (for the first time)
// and calculated
bool CrySizerImpl::AddObject (const void* pIdentifier, size_t sizeBytes)
{
if (!pIdentifier || !sizeBytes)
return false; // we don't add the NULL objects
//return true;
Object NewObject(pIdentifier, sizeBytes, getCurrentName());
// check if the last object was the same
if (NewObject == m_LastObject)
{
assert (m_LastObject.nSize == sizeBytes);
return false;
}
ObjectSet& rSet = m_setObjects[getHash(pIdentifier)];
ObjectSet::iterator it = rSet.find (NewObject);
if (it == rSet.end())
{
// there's no such object in the map, add it
rSet.insert (NewObject);
ComponentName& CompName = m_arrNames[getCurrentName()];
++CompName.numObjects;
CompName.sizeObjects += sizeBytes;
return true;
}
else
{
// there's such object in the map, don't add it
if (sizeBytes != it->nSize)
{
// if the following assert fails:
assert (0);
// .. it means we have one object that's added two times with different sizes; that's screws up the whole idea
// we assume there are two different objects that are for some reason assigned the same id
Object *pObj = const_cast<Object*>(&(*it));
pObj->nSize += sizeBytes; // anyway it's an invalid situation
ComponentName& CompName = m_arrNames[getCurrentName()];
CompName.sizeObjects += sizeBytes;
return true; // yes we added the object, though there were an error condition
}
return false;
}
}
// finalizes data collection, should be called after all objects have been added
void CrySizerImpl::end()
{
// clean up the totals of each name
size_t i;
for (i = 0; i < m_arrNames.size(); ++i)
{
assert (i == 0 || (m_arrNames[i].nParent < i && m_arrNames[i].nParent >=0));
m_arrNames[i].sizeObjectsTotal = m_arrNames[i].sizeObjects;
}
// add the component's size to the total size of the parent.
// for every component, all their children are put after them in the name array
// we don't include the root because it doesn't belong to any other parent (nowhere further to add)
for (i = m_arrNames.size() - 1; i > 0; --i)
{
// the parent's total size is increased by the _total_ size (already calculated) of this object
m_arrNames[m_arrNames[i].nParent].sizeObjectsTotal += m_arrNames[i].sizeObjectsTotal;
}
}
void CrySizerImpl::clear()
{
for (unsigned i = 0 ; i < g_nHashSize; ++i)
m_setObjects[i].clear();
m_arrNames.clear();
m_arrNames.push_back("TOTAL"); // the default name, with index 0
m_stackNames.clear();
m_stackNames.push_back(0);
m_LastObject.pId = NULL;
}
// hash function for an address; returns value 0..1<<g_nHashSize
unsigned CrySizerImpl::getHash (const void* pId)
{
//return (((unsigned)pId) >> 4) & (g_nHashSize-1);
// pseudorandomizing transform
ldiv_t _Qrem = ldiv(((UINT_PTR)pId >> 2), 127773);
_Qrem.rem = 16807 * _Qrem.rem - 2836 * _Qrem.quot;
if (_Qrem.rem < 0)
_Qrem.rem += 2147483647; // 0x7FFFFFFF
return ((unsigned)_Qrem.rem) & (g_nHashSize-1);
}

144
CrySystem/CrySizerImpl.h Normal file
View File

@@ -0,0 +1,144 @@
//////////////////////////////////////////////////////////////////////
//
// CryEngine Source code
//
// File:CrySizerImpl.h
// Implementation of the ICrySizer interface, which is used to
// calculate the memory usage by the subsystems and components, to help
// the artists keep the memory budged low.
//
// History:
// December 03, 2002 : Created by Sergiy Migdalskiy <sergiy@crytek.de>
//
//////////////////////////////////////////////////////////////////////
#ifndef _CRY_SYSTEM_CRY_SIZER_CLASS_IMPLEMENTATION_HDR_
#define _CRY_SYSTEM_CRY_SIZER_CLASS_IMPLEMENTATION_HDR_
// prerequisities
//////////////////////////////////////////////////////////////////////////
// implementation of interface ICrySizer
// ICrySizer is passed to all subsystems and has a lot of helper functions that
// are compiled in the appropriate subsystems. CrySizerImpl is created in CrySystem
// and is passed to all the other subsystems
class CrySizerImpl: public ICrySizer
{
public:
CrySizerImpl();
~CrySizerImpl();
// adds an object identified by the unique pointer (it needs not be
// the actual object position in the memory, though it would be nice,
// but it must be unique throughout the system and unchanging for this object)
// RETURNS: true if the object has actually been added (for the first time)
// and calculated
virtual bool AddObject (const void* pIdentifier, size_t nSizeBytes);
// finalizes data collection, should be called after all objects have been added
void end();
void clear();
protected:
// these functions must operate on the component name stack
// they are to be only accessible from within class CrySizerComponentNameHelper
// which should be used through macro SIZER_COMPONENT_NAME
virtual void Push (const char* szComponentName);
virtual void PushSubcomponent (const char* szSubcomponentName);
virtual void Pop ();
// searches for the name in the name array; adds the name if it's not there and returns the index
size_t getNameIndex (size_t nParent, const char* szComponentName);
// returns the index of the current name on the top of the name stack
size_t getCurrentName()const;
protected:
friend class CrySizerStatsBuilder;
// the stack of subsystem names; the indices in the name array are kept, not the names themselves
typedef std::vector<size_t> NameStack;
NameStack m_stackNames;
// the array of names; each name ever pushed on the stack is present here
struct ComponentName
{
ComponentName (){}
ComponentName (const char* szName, size_t parent = 0):
strName (szName),
nParent (parent),
numObjects(0),
sizeObjects (0),
sizeObjectsTotal (0)
{
}
void assign (const char* szName, size_t parent = 0)
{
strName = szName;
nParent = parent;
numObjects = 0;
sizeObjects = 0;
sizeObjectsTotal = 0;
arrChildren.clear();
}
// the component name, not including the parents' names
string strName;
// the index of the parent, 0 being the root
size_t nParent;
// the number of objects within this component
size_t numObjects;
// the size of the objects belonging to this component, in bytes
size_t sizeObjects;
// the total size of all objects; gets filled by the end() method of the CrySizerImpl
size_t sizeObjectsTotal;
// the children components
std::vector<size_t> arrChildren;
};
typedef std::vector<ComponentName> NameArray;
NameArray m_arrNames;
// the set of objects and their sizes: the key is the object address/id,
// the value is the size of the object and its name (the index of the name actually)
struct Object
{
const void * pId; // unique pointer identifying the object in memory
size_t nSize; // the size of the object in bytes
size_t nName; // the index of the name in the name array
Object ()
{clear();}
Object (const void* id, size_t size = 0, size_t name = 0):
pId(id), nSize(size), nName(name) {}
// the objects are sorted by their Id
bool operator < (const Object& right)const {return (UINT_PTR)pId < (UINT_PTR)right.pId;}
bool operator < (const void* right)const {return (UINT_PTR)pId < (UINT_PTR)right;}
//friend bool operator < (const void* left, const Object& right);
bool operator == (const Object& right) const {return pId == right.pId;}
void clear()
{
pId = NULL;
nSize = 0;
nName = 0;
}
};
typedef std::set <Object> ObjectSet;
// 2^g_nHashPower == the number of subsets comprising the hash
enum {g_nHashPower = 7};
// hash size (number of subsets)
enum {g_nHashSize = 1 << g_nHashPower};
// hash function for an address; returns value 0..1<<g_nHashSize
unsigned getHash (const void* pId);
ObjectSet m_setObjects[g_nHashSize];
// the last object inserted; this is a small optimization for our template implementaiton
// that often can add two times the same object
Object m_LastObject;
};
#endif

363
CrySystem/CrySizerStats.cpp Normal file
View File

@@ -0,0 +1,363 @@
#include "stdafx.h"
#include "ILog.h"
#include "ITimer.h"
#include "ISystem.h"
#include "IConsole.h"
#include "IRenderer.h"
#include "Font.h"
#include "CrySizerImpl.h"
#include "CrySizerStats.h"
CrySizerStatsBuilder::CrySizerStatsBuilder (CrySizerImpl* pSizer, int nMinSubcomponentBytes):
m_pSizer (pSizer),
m_nMinSubcomponentBytes (nMinSubcomponentBytes < 0 || nMinSubcomponentBytes > 0x10000000 ? 0 : nMinSubcomponentBytes)
{
}
// creates the map of names from old (in the sizer Impl) to new (in the Stats)
void CrySizerStatsBuilder::processNames()
{
size_t numCompNames = m_pSizer->m_arrNames.size();
m_pStats->m_arrComponents.reserve (numCompNames);
m_pStats->m_arrComponents.clear();
m_mapNames.resize (numCompNames, -1);
// add all root objects
addNameSubtree(0,0);
}
//////////////////////////////////////////////////////////////////////////
// given the name in the old system, adds the subtree of names to the
// name map and components. In case all the subtree is empty, returns false and
// adds nothing
size_t CrySizerStatsBuilder::addNameSubtree (unsigned nDepth, size_t nName)
{
assert (nName < m_pSizer->m_arrNames.size());
CrySizerImpl::ComponentName& rCompName = m_pSizer->m_arrNames[nName];
size_t sizeObjectsTotal = rCompName.sizeObjectsTotal;
if (sizeObjectsTotal <= m_nMinSubcomponentBytes)
return sizeObjectsTotal; // the subtree didn't pass
// the index of the component in the stats object (sorted by the depth-first traverse order)
size_t nNewName = m_pStats->m_arrComponents.size();
m_pStats->m_arrComponents.resize (nNewName+1);
Component& rNewComp = m_pStats->m_arrComponents[nNewName];
rNewComp.strName = rCompName.strName;
rNewComp.nDepth = nDepth;
rNewComp.numObjects = rCompName.numObjects;
rNewComp.sizeBytes = rCompName.sizeObjects;
rNewComp.sizeBytesTotal = sizeObjectsTotal;
m_mapNames[nName] = nNewName;
// find the immediate children and sort them by their total size
typedef std::map<size_t,size_t> UintUintMap;
UintUintMap mapSizeName; // total size -> child index (name in old indexation)
for (size_t i = nName + 1; i < m_pSizer->m_arrNames.size(); ++i)
{
CrySizerImpl::ComponentName& rChild = m_pSizer->m_arrNames[i];
if (rChild.nParent == nName && rChild.sizeObjectsTotal > m_nMinSubcomponentBytes)
mapSizeName.insert (UintUintMap::value_type(rChild.sizeObjectsTotal,i));
}
// add the sorted components
/*
for (unsigned i = nName + 1; i < m_pSizer->m_arrNames.size(); ++i)
if (m_pSizer->m_arrNames[i].nParent == nName)
addNameSubtree(nDepth+1,i);
*/
for (UintUintMap::reverse_iterator it = mapSizeName.rbegin(); it != mapSizeName.rend(); ++it)
{
addNameSubtree(nDepth + 1, it->second);
}
return sizeObjectsTotal;
}
//////////////////////////////////////////////////////////////////////////
// creates the statistics out of the given CrySizerImpl into the given CrySizerStats
// Maps the old to new names according to the depth-walk tree rule
void CrySizerStatsBuilder::build (CrySizerStats* pStats)
{
m_pStats = pStats;
m_mapNames.clear();
processNames();
m_pSizer->clear();
pStats->refresh();
pStats->m_nAgeFrames = 0;
}
//////////////////////////////////////////////////////////////////////////
// constructs the statistics based on the given cry sizer
CrySizerStats::CrySizerStats (CrySizerImpl* pCrySizer)
{
CrySizerStatsBuilder builder (pCrySizer);
builder.build(this);
}
CrySizerStats::CrySizerStats ()
{
}
// if there is already such name in the map, then just returns the index
// of the compoentn in the component array; otherwise adds an entry to themap
// and to the component array nad returns its index
CrySizerStatsBuilder::Component& CrySizerStatsBuilder::mapName (unsigned nName)
{
assert (m_mapNames[nName] != -1);
return m_pStats->m_arrComponents[m_mapNames[nName]];
/*
IdToIdMap::iterator it = m_mapNames.find (nName);
if (it == m_mapNames.end())
{
unsigned nNewName = m_arrComponents.size();
m_mapNames.insert (IdToIdMap::value_type(nName, nNewName));
m_arrComponents.resize(nNewName + 1);
m_arrComponents[nNewName].strName.swap(m_pSizer->m_arrNames[nName]);
return m_arrComponents.back();
}
else
{
assert (it->second < m_arrComponents.size());
return m_arrComponents[it->second];
}
*/
}
// refreshes the statistics built after the component array is built
void CrySizerStats::refresh()
{
m_nMaxNameLength = 0;
for (size_t i = 0; i < m_arrComponents.size(); ++i)
{
size_t nLength = m_arrComponents[i].strName.length()+m_arrComponents[i].nDepth;
if (nLength > m_nMaxNameLength)
m_nMaxNameLength = nLength;
}
}
bool CrySizerStats::Component::GenericOrder::operator () (const Component& left, const Component& right)const
{
return left.strName < right.strName;
}
CrySizerStatsRenderer::CrySizerStatsRenderer (ISystem* pSystem, CrySizerStats* pStats, unsigned nMaxSubcomponentDepth, int nMinSubcomponentBytes):
m_pStats(pStats),
m_pRenderer(pSystem->GetIRenderer()),
m_pLog (pSystem->GetILog()),
m_pFont (pSystem->GetIConsole()->GetFont()),
m_nMinSubcomponentBytes (nMinSubcomponentBytes < 0 || nMinSubcomponentBytes > 0x10000000 ? 0x8000 : nMinSubcomponentBytes),
m_nMaxSubcomponentDepth (nMaxSubcomponentDepth)
{
}
void CrySizerStatsRenderer::render(bool bRefreshMark)
{
if (!m_pStats->size())
return;
int x,y,dx,dy;
m_pRenderer->GetViewport(&x,&y,&dx,&dy);
// left coordinate of the text
unsigned nNameWidth = (unsigned)(m_pStats->getMaxNameLength()+1);
if (nNameWidth < 25)
nNameWidth = 25;
float fCharScaleX = 0.375f, fCharScaleY = 0.5f;
float fCharSizeX = m_pFont->m_charsize*fCharScaleX, fCharSizeY = m_pFont->m_charsize*fCharScaleY;
float fLeft = 0;
float fTop = 48;
float fVStep = 10;
#ifdef _XBOX
fTop = 20;
#endif
m_pRenderer->WriteXY (m_pFont, (int)fLeft, (int)(fTop), fCharScaleX, fCharScaleY, 0.9f,0.85f,1,0.85f,
"%-*s TOTAL partial count",nNameWidth,bRefreshMark?"Memory usage (refresh*)":"Memory usage (refresh )");
m_pRenderer->WriteXY (m_pFont, (int)fLeft, (int)(fTop + fVStep*0.25f), fCharScaleX, fCharScaleY, 0.85f,0.9f,1,0.85f,
"%*s _____ _______ _____",nNameWidth,"");
unsigned nSubgroupDepth = 1;
// different colors used to paint the statistics subgroups
// a new statistic subgroup starts with a new subtree of depth <= specified
float fGray = 0;//0.45f;
float fLightGray = 0.5f;//0.8f;
float fColors[] =
{
fLightGray,fLightGray,fGray, 1,
1,1,1,1,
fGray,1,1,1,
1,fGray,1,1,
1,1,fGray,1,
fGray,fLightGray,1,1,
fGray,1,fGray,1,
1,fGray,fGray,1
};
float*pColor = fColors;
for (unsigned i = 0; i < m_pStats->size(); ++i)
{
const Component& rComp = (*m_pStats)[i];
if (rComp.nDepth <= nSubgroupDepth)
{
//switch the color
pColor += 4;
if (pColor >= fColors + sizeof(fColors)/sizeof(fColors[0]))
pColor = fColors;
fTop += fVStep*(0.333333f + (nSubgroupDepth - rComp.nDepth) * 0.15f);
}
if (rComp.sizeBytesTotal <= m_nMinSubcomponentBytes || rComp.nDepth > m_nMaxSubcomponentDepth)
continue;
fTop += fVStep;
//m_pRenderer->WriteXY(m_pFont, (int)fLeft+fCharSizeX*(nNameWidth-rComp.strName.length()), (int)fTop, fCharScale, fCharScale, 1,1,1,1,
// "%s:%7.3f",rComp.strName.c_str(), rComp.getSizeMBytes());
char szDepth[32] = " ..............................";
if (rComp.nDepth < sizeof(szDepth))
szDepth[rComp.nDepth] = '\0';
char szSize[32];
if (rComp.sizeBytes > 0)
{
if (rComp.sizeBytesTotal > rComp.sizeBytes)
sprintf (szSize, "%7.3f %7.3f", rComp.getTotalSizeMBytes(), rComp.getSizeMBytes());
else
sprintf (szSize, " %7.3f", rComp.getSizeMBytes());
}
else
{
assert (rComp.sizeBytesTotal > 0);
sprintf (szSize, "%7.3f ", rComp.getTotalSizeMBytes());
}
char szCount[16];
#ifdef _DEBUG
if (rComp.numObjects)
sprintf (szCount, "%8u", rComp.numObjects);
else
#endif
szCount[0] = '\0';
m_pRenderer->WriteXY(m_pFont, (int)fLeft, (int)(fTop), fCharScaleX, fCharScaleY, pColor[0],pColor[1],pColor[2],pColor[3],
"%s%-*s:%s%s",szDepth, nNameWidth-rComp.nDepth,rComp.strName.c_str(), szSize, szCount);
}
fTop += 0.25f*fVStep;
m_pRenderer->WriteXY(m_pFont, (int)fLeft, (int)(fTop), fCharScaleX, fCharScaleY, fLightGray,fLightGray,fLightGray,1,
"%-*s %s",nNameWidth,"___________________________", "________________");
fTop += fVStep;
const char* szOverheadNames[CrySizerStats::g_numTimers] =
{
".Collection",
".Transformation",
".Cleanup"
};
bool bOverheadsHeaderPrinted = false;
for (unsigned i = 0; i < CrySizerStats::g_numTimers; ++i)
{
float fTime = m_pStats->getTime(i);
if (fTime < 20)
continue;
// print the header
if (!bOverheadsHeaderPrinted)
{
m_pRenderer->WriteXY(m_pFont, (int)fLeft, (int)(fTop), fCharScaleX, fCharScaleY, fLightGray,fLightGray,fLightGray,1,
"%-*s",nNameWidth,"Overheads");
fTop += fVStep;
bOverheadsHeaderPrinted = true;
}
m_pRenderer->WriteXY(m_pFont, (int)fLeft, (int)(fTop), fCharScaleX, fCharScaleY, fLightGray,fLightGray,fLightGray,1,
"%-*s:%7.1f ms",nNameWidth,szOverheadNames[i], fTime);
fTop += fVStep;
}
}
void CrySizerStatsRenderer::dump()
{
if (!m_pStats->size())
return;
unsigned nNameWidth = (unsigned)(m_pStats->getMaxNameLength()+1);
// left coordinate of the text
m_pLog->LogToFile ("Memory Statistics:");
m_pLog->LogToFile("%-*s TOTAL partial count",nNameWidth,"");
unsigned nSubgroupDepth = 1;
// different colors used to paint the statistics subgroups
// a new statistic subgroup starts with a new subtree of depth <= specified
for (unsigned i = 0; i < m_pStats->size(); ++i)
{
const Component& rComp = (*m_pStats)[i];
if (rComp.sizeBytesTotal <= m_nMinSubcomponentBytes || rComp.nDepth > m_nMaxSubcomponentDepth)
continue;
char szDepth[32] = " ..............................";
if (rComp.nDepth < sizeof(szDepth))
szDepth[rComp.nDepth] = '\0';
char szSize[32];
if (rComp.sizeBytes > 0)
{
if (rComp.sizeBytesTotal > rComp.sizeBytes)
sprintf (szSize, "%7.3f %7.3f", rComp.getTotalSizeMBytes(), rComp.getSizeMBytes());
else
sprintf (szSize, " %7.3f", rComp.getSizeMBytes());
}
else
{
assert (rComp.sizeBytesTotal > 0);
sprintf (szSize, "%7.3f ", rComp.getTotalSizeMBytes());
}
char szCount[16];
if (rComp.numObjects)
sprintf (szCount, "%8u", rComp.numObjects);
else
szCount[0] = '\0';
m_pLog->LogToFile ("%s%-*s:%s%s",szDepth, nNameWidth-rComp.nDepth,rComp.strName.c_str(), szSize, szCount);
}
}
void CrySizerStats::startTimer(unsigned nTimer, ITimer* pTimer)
{
assert (nTimer < g_numTimers);
m_fTime[nTimer] = pTimer->GetAsyncCurTime();
}
void CrySizerStats::stopTimer(unsigned nTimer, ITimer* pTimer)
{
assert (nTimer < g_numTimers);
m_fTime[nTimer] = 1000*(pTimer->GetAsyncCurTime() - m_fTime[nTimer]);
}

183
CrySystem/CrySizerStats.h Normal file
View File

@@ -0,0 +1,183 @@
//////////////////////////////////////////////////////////////////////
//
// CryEngine Source code
//
// File:CrySizerStats.h
// Declaration of the CrySizerStats class, which is used to
// calculate the memory usage by the subsystems and components, to help
// the artists keep the memory budged low.
//
//
// History:
// December 03, 2002 : Created by Sergiy Migdalskiy <sergiy@crytek.de>
//
//////////////////////////////////////////////////////////////////////
#ifndef _CRY_SYSTEM_CRY_SIZER_STATS_HDR_
#define _CRY_SYSTEM_CRY_SIZER_STATS_HDR_
class CrySizerImpl;
//////////////////////////////////////////////////////////////////////////
// This class holds only the necessary statistics data, which can be carried
// over a few frames without significant impact on memory usage
// CrySizerImpl is an implementation of ICrySizer, which is used to collect
// those data; it must be destructed immediately after constructing the Stats
// object to avoid excessive memory usage.
class CrySizerStats
{
public:
// constructs the statistics based on the given cry sizer
CrySizerStats (CrySizerImpl* pCrySizer);
CrySizerStats ();
// this structure describes one component of the memory size statistics
struct Component
{
Component() {clear();}
Component (const string& name, unsigned size = 0, unsigned num = 0):
strName(name), sizeBytes(size), numObjects(num), nDepth(0) {}
void clear()
{
strName = "";
sizeBytes = 0;
numObjects = 0;
nDepth = 0;
}
// the name of the component, as it appeared in the push() call
string strName;
// the total size, in bytes, of objects in the component
size_t sizeBytes;
// the total size including the subcomponents
size_t sizeBytesTotal;
// the number of objects allocated
size_t numObjects;
unsigned nDepth;
float getSizeMBytes() const {return sizeBytes / float(1<<20);}
float getTotalSizeMBytes () const {return sizeBytesTotal / float(1<<20);}
struct NameOrder
{
bool operator () (const Component& left, const Component& right)const {return left.strName < right.strName;}
};
struct SizeOrder
{
bool operator () (const Component& left, const Component& right)const {return left.sizeBytes < right.sizeBytes;}
};
struct GenericOrder
{
bool operator () (const Component& left, const Component& right)const;
};
};
// returns the number of different subsystems/components used
unsigned numComponents()const {return (unsigned)m_arrComponents.size();}
// returns the name of the i-th component
const Component& getComponent(unsigned nComponent)const {return m_arrComponents[nComponent];}
unsigned size() const {return numComponents();}
const Component& operator [] (unsigned i) const {return getComponent(i);}
const Component& operator [] ( signed i) const {return getComponent(i);}
size_t getMaxNameLength()const {return m_nMaxNameLength;}
enum {g_numTimers = 3};
void startTimer(unsigned nTimer, ITimer*pTimer);
void stopTimer(unsigned nTimer, ITimer*pTimer);
float getTime(unsigned nTimer)const {assert (nTimer < g_numTimers);return m_fTime[nTimer];}
int getAgeFrames() const {return m_nAgeFrames;}
void incAgeFrames() {++m_nAgeFrames;}
protected:
// refreshes the statistics built after the component array is built
void refresh();
protected:
// the names of the components
typedef std::vector<Component> ComponentArray;
ComponentArray m_arrComponents;
// the maximum length of the component name, in characters
size_t m_nMaxNameLength;
// the timer that counts the time spent on statistics gathering
float m_fTime[g_numTimers];
// the age of the statistics, in frames
int m_nAgeFrames;
friend class CrySizerStatsBuilder;
};
//////////////////////////////////////////////////////////////////////////
// this is the constructor for the CrySizerStats
class CrySizerStatsBuilder
{
public:
CrySizerStatsBuilder (CrySizerImpl* pSizer, int nMinSubcomponentBytes = 0);
void build (CrySizerStats* pStats);
protected:
typedef CrySizerStats::Component Component;
// if there is already such name in the map, then just returns the index
// of the compoentn in the component array; otherwise adds an entry to themap
// and to the component array nad returns its index
Component& mapName (unsigned nName);
// creates the map of names from old to new, and initializes the components themselves
void processNames();
// given the name in the old system, adds the subtree of names to the
// name map and components. In case all the subtree is empty, returns 0 and
// adds nothing. Otherwise, returns the total size of objects belonging to the
// subtree
size_t addNameSubtree (unsigned nDepth, size_t nName);
protected:
CrySizerStats* m_pStats;
CrySizerImpl* m_pSizer;
// this is the mapping from the old names into the new componentn indices
typedef std::vector<size_t> IdToIdMap;
// from old to new
IdToIdMap m_mapNames;
// this is the threshold: if the total number of bytes in the subcomponent
// is less than this, the subcomponent isn't shown
unsigned m_nMinSubcomponentBytes;
};
//////////////////////////////////////////////////////////////////////////
// Renders the given usage stats; gets created upon every rendering
class CrySizerStatsRenderer
{
public:
CrySizerStatsRenderer (ISystem* pSystem, CrySizerStats* pStats, unsigned nMaxDepth = 2, int nMinSubcomponentBytes = -1);
void render(bool bRefreshMark = false);
// dumps it to log
void dump ();
protected:
typedef CrySizerStats::Component Component;
IRenderer* m_pRenderer;
ILog* m_pLog;
CrySizerStats* m_pStats;
class CXFont* m_pFont;
// this is the threshold: if the total number of bytes in the subcomponent
// is less than this, the subcomponent isn't shown
unsigned m_nMinSubcomponentBytes;
// the max depth of the branch to output
unsigned m_nMaxSubcomponentDepth;
};
#endif

BIN
CrySystem/CrySystem.aps Normal file

Binary file not shown.

267
CrySystem/CrySystem.rc Normal file
View File

@@ -0,0 +1,267 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_CRITICAL_ERROR, DIALOG
BEGIN
LEFTMARGIN, 5
RIGHTMARGIN, 260
BOTTOMMARGIN, 296
END
IDD_ABOUTBOX, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 103
TOPMARGIN, 7
BOTTOMMARGIN, 88
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_CRITICAL_ERROR DIALOGEX 0, 0, 267, 303
STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP |
WS_VISIBLE | WS_CAPTION
CAPTION "Critical Exception"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "&Abort",IDB_EXIT,210,282,50,14
EDITTEXT IDC_CALLSTACK,10,95,245,102,ES_MULTILINE |
ES_AUTOVSCROLL | WS_VSCROLL | WS_HSCROLL
EDITTEXT IDC_EXCEPTION_CODE,10,25,50,12,ES_AUTOHSCROLL |
ES_READONLY
LTEXT "Call Stack Trace",IDC_STATIC,13,85,54,8
LTEXT "Code",IDC_STATIC,10,15,18,8
LTEXT "Address:",IDC_STATIC,66,15,28,8
EDITTEXT IDC_EXCEPTION_ADDRESS,65,25,75,12,ES_AUTOHSCROLL |
ES_READONLY
LTEXT "Description",IDC_STATIC,10,40,36,8
GROUPBOX "Exception Info",IDC_STATIC,5,5,255,200
EDITTEXT IDC_EXCEPTION_MODULE,145,25,110,12,ES_AUTOHSCROLL |
ES_READONLY
LTEXT "Module",IDC_STATIC,145,15,24,8
EDITTEXT IDC_EXCEPTION_DESC,10,50,245,30,ES_MULTILINE |
ES_AUTOHSCROLL | ES_READONLY
PUSHBUTTON "&Send in Mail",IDB_MAIL,128,282,65,14
EDITTEXT IDC_ERROR_TEXT,5,220,255,45,ES_MULTILINE |
ES_AUTOHSCROLL | ES_WANTRETURN
LTEXT "Enter error description here:",IDC_STATIC,5,210,88,8
DEFPUSHBUTTON "&Save Document",IDB_SAVE,58,282,65,14
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,5,274,255,1
END
IDD_EXCEPTION DIALOG 0, 0, 138, 52
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE |
WS_CAPTION | WS_SYSMENU
CAPTION "Exception"
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Exception Intercepted\r\nRetrieving Info...",IDC_STATIC,
33,18,71,19
END
IDD_ABOUTBOX DIALOGEX 0, 0, 110, 95
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
WS_SYSMENU
CAPTION "About"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,53,74,50,14
LTEXT "Lua Debugger Version 1.0\n(C) 2002 Crytek\n\nWritten by\nAlberto Demichelis\nTim Schr<68>der",
IDC_STATIC,7,7,96,53
END
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_TREE_VIEW BITMAP "LuaDebugger\\res\\TreeView.bmp"
IDC_LUADBG BITMAP "luadebugger\\res\\toolbar1.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_LUADBG ICON "LuaDebugger\\LUADBG.ico"
IDI_SMALL ICON "LuaDebugger\\small.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDC_LUADBG MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Reload", ID_FILE_RELOAD
END
POPUP "&Debug"
BEGIN
MENUITEM "&Set Breakpoint\tF9", ID_DEBUG_TOGGLEBREAKPOINT
MENUITEM "&Step Over\tF10", ID_DEBUG_STEPOVER
MENUITEM "&Step Into\tF11", ID_DEBUG_STEPINTO
MENUITEM SEPARATOR
MENUITEM "&Run\tF5", ID_DEBUG_RUN
MENUITEM SEPARATOR
MENUITEM "&Disable Debugging", 40014
END
POPUP "&Help"
BEGIN
MENUITEM "&About", 109
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Toolbar
//
IDC_LUADBG TOOLBAR 16, 15
BEGIN
BUTTON ID_DEBUG_RUN
BUTTON ID_DEBUG_BREAK
BUTTON IDM_EXIT
SEPARATOR
BUTTON ID_DEBUG_STEPINTO
BUTTON ID_DEBUG_STEPOVER
BUTTON ID_DEBUG_TOGGLEBREAKPOINT
BUTTON ID_BUTTON40071
SEPARATOR
BUTTON IDM_ABOUT
END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_LUADGB_ACCEL ACCELERATORS
BEGIN
VK_F5, ID_DEBUG_RUN, VIRTKEY, NOINVERT
VK_F11, ID_DEBUG_STEPINTO, VIRTKEY, NOINVERT
VK_F10, ID_DEBUG_STEPOVER, VIRTKEY, NOINVERT
VK_F9, ID_DEBUG_TOGGLEBREAKPOINT, VIRTKEY, NOINVERT
VK_F5, ID_DEBUG_DISABLE, VIRTKEY, SHIFT, NOINVERT
END
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,3,1395
PRODUCTVERSION 1,1,3,1395
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Crytek Studios"
VALUE "FileDescription", "CrySyste Dynamic Link Library"
VALUE "FileVersion", "1, 1, 3, 1395"
VALUE "InternalName", "CrySystem"
VALUE "LegalCopyright", "Copyright Crytek (C) 2003"
VALUE "OriginalFilename", "CrySystem.dll"
VALUE "ProductName", " CrySystem Dynamic Link Library"
VALUE "ProductVersion", "1, 1, 3, 1395"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

1587
CrySystem/CrySystem.vcproj Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = "relative:CrySystem"
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = ""
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
}

View File

@@ -0,0 +1,604 @@
<?xml version="1.0" encoding = "windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.00"
Name="CrySystem_XBox"
ProjectGUID="{9F9FB6F5-D971-4887-B0AD-5C368DDAD90B}"
SccProjectName="&quot;$/Game01/CrySystem&quot;, JPKBAAAA"
SccAuxPath=""
SccLocalPath="."
SccProvider="MSSCCI:Microsoft Visual SourceSafe"
Keyword="XboxProj">
<Platforms>
<Platform
Name="Xbox"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Xbox"
OutputDirectory="Debug_XBox"
IntermediateDirectory="Debug_XBox"
ConfigurationType="4">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\CryCommon"
PreprocessorDefinitions="_DEBUG;_XBOX;_LIB"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
BufferSecurityCheck="TRUE"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="3"
AssemblerListingLocation=".\Debug_XBox/"
ObjectFile=".\Debug_XBox/"
ProgramDataBaseFileName=".\Debug_XBox/"
DebugInformationFormat="3"
CompileAs="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/CrySystem.lib"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
</Configuration>
<Configuration
Name="Release|Xbox"
OutputDirectory="Release_XBox"
IntermediateDirectory="Release_XBox"
ConfigurationType="4">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\CryCommon"
PreprocessorDefinitions="_RELEASE;NDEBUG;_XBOX;_LIB"
UsePrecompiledHeader="3"
DebugInformationFormat="2"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/CrySystem.lib"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
</Configuration>
<Configuration
Name="Profile|Xbox"
OutputDirectory="Profile"
IntermediateDirectory="Profile"
ConfigurationType="4">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\CryCommon"
PreprocessorDefinitions="NDEBUG;_XBOX;_LIB"
StringPooling="TRUE"
BufferSecurityCheck="FALSE"
UsePrecompiledHeader="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/CrySystem.lib"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
</Configuration>
</Configurations>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
<File
RelativePath="CompressedFile.cpp">
</File>
<File
RelativePath="CryPak.cpp">
</File>
<File
RelativePath="CrySizerImpl.cpp">
</File>
<File
RelativePath="CrySizerStats.cpp">
</File>
<File
RelativePath="DebugCallStack.cpp">
</File>
<File
RelativePath="DllMain.cpp">
</File>
<File
RelativePath="FrameProfileSystem.cpp">
</File>
<File
RelativePath="Log.cpp">
</File>
<File
RelativePath="Mailer.cpp">
</File>
<File
RelativePath="MusicLoad.cpp">
</File>
<File
RelativePath="RefReadStream.cpp">
</File>
<File
RelativePath="RefReadStream.h">
</File>
<File
RelativePath="RefReadStreamProxy.cpp">
</File>
<File
RelativePath="RefReadStreamProxy.h">
</File>
<File
RelativePath="RefStreamEngine.cpp">
</File>
<File
RelativePath="RefStreamEngine.h">
</File>
<File
RelativePath="ScriptBinding.cpp">
</File>
<File
RelativePath="ScriptObjectAnimation.cpp">
</File>
<File
RelativePath="ScriptObjectAnimation.h">
</File>
<File
RelativePath="ScriptObjectEntity.cpp">
</File>
<File
RelativePath="ScriptObjectEntity.h">
</File>
<File
RelativePath="ScriptObjectMovie.cpp">
</File>
<File
RelativePath="ScriptObjectMovie.h">
</File>
<File
RelativePath="ScriptObjectParticle.cpp">
</File>
<File
RelativePath="ScriptObjectParticle.h">
</File>
<File
RelativePath="ScriptObjectScript.cpp">
</File>
<File
RelativePath="ScriptObjectScript.h">
</File>
<File
RelativePath="ScriptObjectSound.cpp">
</File>
<File
RelativePath="ScriptObjectSound.h">
</File>
<File
RelativePath="ScriptObjectSystem.cpp">
</File>
<File
RelativePath="ScriptObjectSystem.h">
</File>
<File
RelativePath="ScriptSink.cpp">
</File>
<File
RelativePath="StdAfx.cpp">
<FileConfiguration
Name="Debug|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
<FileConfiguration
Name="Profile|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
</File>
<File
RelativePath="System.cpp">
</File>
<File
RelativePath="Timer.cpp">
</File>
<File
RelativePath="XConsole.cpp">
</File>
<File
RelativePath="XConsoleVariable.cpp">
</File>
<File
RelativePath="ini_vars.cpp">
</File>
<File
RelativePath="unzip.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc">
<File
RelativePath="CryPak.h">
</File>
<File
RelativePath="CrySizerImpl.h">
</File>
<File
RelativePath="CrySizerStats.h">
</File>
<File
RelativePath="DebugCallStack.h">
</File>
<File
RelativePath="Log.h">
</File>
<File
RelativePath="Mailer.h">
</File>
<File
RelativePath="ScriptSink.h">
</File>
<File
RelativePath="StdAfx.h">
</File>
<File
RelativePath="System.h">
</File>
<File
RelativePath="Timer.h">
</File>
<File
RelativePath="XConsole.h">
</File>
<File
RelativePath="XConsoleVariable.h">
</File>
<File
RelativePath="ini_vars.h">
</File>
<File
RelativePath="resource.h">
</File>
<File
RelativePath="unzip.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
<File
RelativePath="CrySystem.rc">
</File>
<File
RelativePath="LuaDebugger\LUADBG.ico">
</File>
<File
RelativePath="LuaDebugger\res\TreeView.bmp">
</File>
<File
RelativePath="LuaDebugger\small.ico">
</File>
<File
RelativePath="LuaDebugger\res\toolbar1.bmp">
</File>
</Filter>
<Filter
Name="MemoryManager"
Filter="">
<File
RelativePath="CryMemoryManager.cpp">
</File>
<File
RelativePath="bget.c">
<FileConfiguration
Name="Debug|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
<FileConfiguration
Name="Profile|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
</File>
<File
RelativePath="bget.h">
</File>
</Filter>
<Filter
Name="LuaDebugger"
Filter="">
<File
RelativePath="LuaDebugger\AboutWnd.h">
</File>
<File
RelativePath="LuaDebugger\FileTree.cpp">
<FileConfiguration
Name="Debug|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
<FileConfiguration
Name="Profile|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
</File>
<File
RelativePath="LuaDebugger\FileTree.h">
</File>
<File
RelativePath="LuaDebugger\LUADBG.cpp">
<FileConfiguration
Name="Debug|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
<FileConfiguration
Name="Profile|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
</File>
<File
RelativePath="LuaDebugger\LUADBG.h">
</File>
<File
RelativePath="LuaDebugger\LuaDbgInterface.cpp">
<FileConfiguration
Name="Debug|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
<FileConfiguration
Name="Profile|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
</File>
<File
RelativePath="LuaDebugger\LuaDbgInterface.h">
</File>
<File
RelativePath="LuaDebugger\_TinyBrowseFolder.h">
</File>
<File
RelativePath="LuaDebugger\_TinyCaptionWindow.h">
</File>
<File
RelativePath="LuaDebugger\_TinyCoolEdit.h">
</File>
<File
RelativePath="LuaDebugger\_TinyFileEnum.h">
</File>
<File
RelativePath="LuaDebugger\_TinyImageList.h">
</File>
<File
RelativePath="LuaDebugger\_TinyMain.h">
</File>
<File
RelativePath="LuaDebugger\_TinyRegistry.h">
</File>
<File
RelativePath="LuaDebugger\_TinySplitter.h">
</File>
<File
RelativePath="LuaDebugger\_TinyStatusBar.h">
</File>
<File
RelativePath="LuaDebugger\_TinyTreeList.h">
</File>
<File
RelativePath="LuaDebugger\_TinyWindow.h">
</File>
</Filter>
<Filter
Name="XML"
Filter="">
<File
RelativePath="XML\XMLDOMDocumentImpl.cpp">
</File>
<File
RelativePath="XML\XMLDOMDocumentImpl.h">
</File>
<File
RelativePath="XML\XMLDOMNodeImpl.cpp">
</File>
<File
RelativePath="XML\XMLDOMNodeImpl.h">
</File>
<File
RelativePath="XML\XMLDOMNodeListImpl.cpp">
</File>
<File
RelativePath="XML\XMLDOMNodeListImpl.h">
</File>
<File
RelativePath="XML\_XMLDOMParserImpl.cpp">
</File>
<File
RelativePath="XML\_XMLDOMParserImpl.h">
</File>
<File
RelativePath="XML\xml.cpp">
</File>
<File
RelativePath="XML\xml.h">
</File>
<Filter
Name="expat"
Filter="">
<File
RelativePath="XML\Expat\ascii.h">
</File>
<File
RelativePath="XML\Expat\asciitab.h">
</File>
<File
RelativePath="XML\Expat\config.h">
</File>
<File
RelativePath="XML\Expat\expat.h">
</File>
<File
RelativePath="XML\Expat\iasciitab.h">
</File>
<File
RelativePath="XML\Expat\latin1tab.h">
</File>
<File
RelativePath="XML\Expat\nametab.h">
</File>
<File
RelativePath="XML\Expat\utf8tab.h">
</File>
<File
RelativePath="XML\Expat\winconfig.h">
</File>
<File
RelativePath="XML\Expat\xmlparse.c">
<FileConfiguration
Name="Debug|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
</File>
<File
RelativePath="XML\Expat\xmlrole.c">
<FileConfiguration
Name="Debug|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
</File>
<File
RelativePath="XML\Expat\xmlrole.h">
</File>
<File
RelativePath="XML\Expat\xmltok.c">
<FileConfiguration
Name="Debug|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Xbox">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
</File>
<File
RelativePath="XML\Expat\xmltok.h">
</File>
<File
RelativePath="XML\Expat\xmltok_impl.c">
<FileConfiguration
Name="Debug|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
</File>
<File
RelativePath="XML\Expat\xmltok_impl.h">
</File>
<File
RelativePath="XML\Expat\xmltok_ns.c">
<FileConfiguration
Name="Debug|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Xbox"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"/>
</FileConfiguration>
</File>
</Filter>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,10 @@
""
{
"FILE_VERSION" = "9237"
"ENLISTMENT_CHOICE" = "NEVER"
"PROJECT_FILE_RELATIVE_PATH" = ""
"NUMBER_OF_EXCLUDED_FILES" = "0"
"ORIGINAL_PROJECT_FILE_PATH" = "file:F:\\Crytek\\CrySystem\\CrySystem_XBox.vcproj"
"NUMBER_OF_NESTED_PROJECTS" = "0"
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
}

14
CrySystem/CryWaterMark.h Normal file
View File

@@ -0,0 +1,14 @@
// Header for adding a watermark to an exe, which can then be set
// by the external CryWaterMark program. To use, simply write:
//
// WATERMARKDATA(__blah);
//
// anywhere in the global scope in the program
#define NUMMARKWORDS 10
#define WATERMARKDATA(name) int name[] = { 0xDEBEFECA, 0xFABECEDA, 0xADABAFBE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// (the name is such that you can have multiple watermarks in one exe, don't use
// names like "watermark" just incase you accidentally give out an exe with
// debug information).

871
CrySystem/DataProbe.cpp Normal file
View File

@@ -0,0 +1,871 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2001-2004.
// -------------------------------------------------------------------------
// File name: DataProbe.cpp
// Version: v1.00
// Created: 19/1/2004 by Timur.
// Compilers: Visual Studio.NET 2003
// Description: This is authentication functions, this code is not for public release!!
// -------------------------------------------------------------------------
// History:
//
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Timur.
// This is authentication functions, this code is not for public release!!
//////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#if defined(LINUX)
#include <CryLibrary.h>
#endif
#include "DataProbe.h"
#include "zlib\zlib.h"
#include "ISystem.h"
#include "CryFile.h"
#include "md5.h"
//#define FARCRY_EXE_CRC_CHECK
#if !defined(LINUX)
extern HMODULE gDLLHandle;
#endif
// embedd searchable string.
//#pragma comment( exestr, "CScriptObjectEntity:...." )
#define TEST_NAME_END 28
const char test_name[] = "Cannot find attached entity.\0....";
// Check Up to 1 Mb of data.
#define MAX_PROBE_SIZE uint64(1000000)
//#define XOR_VALUE_64 0xB1A72C931C38E5F2
#define ADLER_32_BASE 65521L /* largest prime smaller than 65536 */
#define ADLER_32_NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
#define ADLER_32 SpecialFunc1
#define CRC_32 SpecialFunc2
#define CRC_64 SpecialFunc3
/* ========================================================================= */
static unsigned int ADLER_32( unsigned int adler, const char *buf, unsigned int len)
{
unsigned int s1 = adler & 0xFFFF;
unsigned int s2 = (adler >> 16) & 0xFFFF;
int k;
if (!buf)
return 1L;
while (len > 0) {
k = len < ADLER_32_NMAX ? len : ADLER_32_NMAX;
len -= k;
while (k >= 16)
{
DO16(buf);
buf += 16;
k -= 16;
}
if (k != 0) do {
s1 += *buf++;
s2 += s1;
} while (--k);
s1 %= ADLER_32_BASE;
s2 %= ADLER_32_BASE;
}
return (s2 << 16) | s1;
}
#define AUTODIN_IIREV 0xEDB88320
#define POLY64REV 0xd800000000000000ULL
//////////////////////////////////////////////////////////////////////////
// Calculate CRC32 of buffer.
//////////////////////////////////////////////////////////////////////////
static unsigned int CRC_32( const char *buf,unsigned int len )
{
static unsigned int Table[256];
static int init = 0;
unsigned int code = 0xFFFFFFFF;
if (!init) {
int i;
init = 1;
for (i = 0; i <= 255; i++) {
int j;
unsigned int part = i;
for (j = 0; j < 8; j++) {
if (part & 1)
part = (part >> 1) ^ AUTODIN_IIREV;
else
part >>= 1;
}
Table[i] = part;
}
}
while (len--)
{
unsigned int temp1 = code >> 8;
unsigned int temp2 = Table[(code ^ (unsigned int )*buf) & 0xff];
code = temp1 ^ temp2;
buf += 1;
}
return code;
}
//////////////////////////////////////////////////////////////////////////
// Calculate CRC64 of buffer.
//////////////////////////////////////////////////////////////////////////
static uint64 CRC_64( const char *buf,unsigned int len )
{
static uint64 Table[256];
uint64 code = 0;
static int init = 0;
if (!init) {
int i;
init = 1;
for (i = 0; i <= 255; i++) {
int j;
uint64 part = i;
for (j = 0; j < 8; j++) {
if (part & 1)
part = (part >> 1) ^ POLY64REV;
else
part >>= 1;
}
Table[i] = part;
}
}
while (len--)
{
uint64 temp1 = code >> 8;
uint64 temp2 = Table[(code ^ (uint64)*buf) & 0xff];
code = temp1 ^ temp2;
buf += 1;
}
return code;
}
/*
void encipher(unsigned int *src,unsigned int *trg,int len,unsigned int *key )
{
unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3;
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3];
while (nlen--) {
register unsigned int y=v[0],z=v[1],n=32,sum=0;
while(n-->0) { sum += delta; y += (z << 4)+a ^ z+sum ^ (z >> 5)+b; z += (y << 4)+c ^ y+sum ^ (y >> 5)+d; }
w[0]=y; w[1]=z;
v+=2,w+=2;
}
}
void decipher(unsigned int *src,unsigned int *trg,int len,unsigned int *key )
{
unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3;
register unsigned delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3];
while (nlen--) {
register unsigned int y=v[0],z=v[1],sum=0xC6EF3720,n=32;
while(n-->0) { z -= (y << 4)+c ^ y+sum ^ (y >> 5)+d; y -= (z << 4)+a ^ z+sum ^ (z >> 5)+b; sum -= delta; }
w[0]=y; w[1]=z;
v+=2,w+=2;
}
}
*/
// src and trg can be the same pointer (in place encryption)
// len must be in bytes and must be multiple of 8 byts (64bits).
// key is 128bit: int key[4] = {n1,n2,n3,n4};
// void encipher(unsigned int *const v,unsigned int *const w,const unsigned int *const k )
#define TEA_ENCODE( src,trg,len,key ) {\
register unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3; \
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3]; \
while (nlen--) {\
register unsigned int y=v[0],z=v[1],n=32,sum=0; \
while(n-->0) { sum += delta; y += (z << 4)+a ^ z+sum ^ (z >> 5)+b; z += (y << 4)+c ^ y+sum ^ (y >> 5)+d; } \
w[0]=y; w[1]=z; v+=2,w+=2; }}
// src and trg can be the same pointer (in place decryption)
// len must be in bytes and must be multiple of 8 byts (64bits).
// key is 128bit: int key[4] = {n1,n2,n3,n4};
// void decipher(unsigned int *const v,unsigned int *const w,const unsigned int *const k)
#define TEA_DECODE( src,trg,len,key ) {\
register unsigned int *v = (src), *w = (trg), *k = (key), nlen = (len) >> 3; \
register unsigned int delta=0x9E3779B9,a=k[0],b=k[1],c=k[2],d=k[3]; \
while (nlen--) { \
register unsigned int y=v[0],z=v[1],sum=0xC6EF3720,n=32; \
while(n-->0) { z -= (y << 4)+c ^ y+sum ^ (y >> 5)+d; y -= (z << 4)+a ^ z+sum ^ (z >> 5)+b; sum -= delta; } \
w[0]=y; w[1]=z; v+=2,w+=2; }}
//////////////////////////////////////////////////////////////////////////
// CDataProbe implementation.
//////////////////////////////////////////////////////////////////////////
CDataProbe::CDataProbe()
{
if (test_name[0]) // Make sure string is linked.
m_pRandAlloc = 0;
m_pRandAlloc = 0;
// Add current module. must be CrySystem.dll
SModuleInfo module;
module.filename = string("CrySystem")+string(".dll");
module.handle = (void*)test_name;
#if !defined(LINUX)
module.handle = gDLLHandle;
m_loadedModules.push_back(module);
#endif
#ifdef WIN32
char sPath[_MAX_PATH];
char dir[_MAX_DIR];
char drive[_MAX_DRIVE];
GetModuleFileName( GetModuleHandle(NULL),sPath,sizeof(sPath) );
_splitpath( sPath,drive,dir,NULL,NULL);
_makepath( sPath,drive,dir,NULL,NULL);
m_sBinPath = sPath;
#endif
}
CDataProbe::~CDataProbe()
{
}
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::GetDataCode( char *pBuf,int nSize,SDataProbeContext &ctx )
{
uint64 nCode = ((uint64)rand()) | (((uint64)rand())<<16) | (((uint64)rand())<<32) | (((uint64)rand())<<48);
nCode = 0; //@TODO: Comment out this later, 0 only for debugging.
// Hash readed data with choosen algorithm, store result into 64bit nCode.
switch ((ctx.nCodeInfo) & 7)
{
case DATAPROBE_CRC32:
{
nCode = CRC_32( pBuf,nSize );
nCode = nCode | ((~nCode) << 32);
}
break;
case DATAPROBE_CRC64:
{
nCode = CRC_64( pBuf,nSize );
}
break;
case DATAPROBE_ADLER32:
{
unsigned int code = ADLER_32(0L, 0, 0);
nCode = ADLER_32( 1,pBuf,ctx.nSize );
nCode = nCode | ((~nCode) << 32);
}
break;
case DATAPROBE_PURE_CRC32:
{
ctx.nCode = CRC_32( pBuf,nSize );
return true;
}
break;
case DATAPROBE_MD5:
{
char md5[16];
GetMD5( (char*)pBuf,nSize,md5 );
nCode = *((uint64*)md5);
return true;
}
break;
default:
{
nCode = CRC_32( pBuf,nSize );
nCode = nCode | ((~nCode) << 32);
}
}
// scramble code not to look like crc or alike.
int tkey[4] = {2985634234,378634893,387681212,436851212};
TEA_ENCODE( (unsigned int*)&nCode,(unsigned int*)&nCode,8,(unsigned int*)tkey );
ctx.nCode = nCode;
return true;
}
//////////////////////////////////////////////////////////////////////////
uint32 CDataProbe::GetHash( const char *sString )
{
return CRC_32( sString,strlen(sString) );
}
//////////////////////////////////////////////////////////////////////////
uint32 CDataProbe::GetHash( const void *buffer,int len )
{
return CRC_32( (const char*)buffer,len );
}
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::GetCode( SDataProbeContext &ctx )
{
if (ctx.nSize <= 0)
return false;
if (ctx.pBuffer)
{
return GetDataCode( (char*)ctx.pBuffer,ctx.nSize,ctx );
}
// Try to open file and hash it.
FILE *file = fopen( ctx.sFilename.c_str(),"rb" );
if (file)
{
fseek( file,0,SEEK_END );
unsigned int nFileSize = ftell(file);
if (ctx.nOffset >= nFileSize)
{
fclose(file);
return false;
}
ctx.nSize = min( ctx.nSize,nFileSize-ctx.nOffset );
if (fseek( file,ctx.nOffset,SEEK_SET ) != 0)
{
fclose( file );
return false;
}
char *pBuf = (char*)malloc( ctx.nSize );
if (fread( pBuf,ctx.nSize,1,file ) != 1)
{
free( pBuf );
fclose(file);
return false;
}
// Hash readed data with choosen algorithm, store result into 64bit nCode.
bool bOk = GetDataCode( pBuf,ctx.nSize,ctx );
free( pBuf );
fclose(file);
return bOk;
}
else
{
// Real file on disk not found... so check against one in the pak.
// Try to open file and hash it.
CCryFile cryfile;
if (cryfile.Open( ctx.sFilename.c_str(),"rb" ))
{
unsigned int nFileSize = cryfile.GetLength();
if (ctx.nOffset >= nFileSize)
{
return false;
}
ctx.nSize = min( ctx.nSize,nFileSize-ctx.nOffset );
if (cryfile.Seek( ctx.nOffset,SEEK_SET ) != 0)
{
return false;
}
char *pBuf = (char*)malloc( ctx.nSize );
if (cryfile.Read( pBuf,ctx.nSize ) != ctx.nSize)
{
free( pBuf );
return false;
}
// Hash readed data with choosen algorithm, store result into 64bit nCode.
bool bOk = GetDataCode( pBuf,ctx.nSize,ctx );
free( pBuf );
return bOk;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////
inline int64 GetRandom( int64 nRange )
{
return (int64(nRange) * int64(rand())) / RAND_MAX;
}
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::GetRandomFileProbe( SDataProbeContext &ctx,bool bAtEnd )
{
// Try to open file and hash it.
FILE *file = fopen( ctx.sFilename.c_str(),"rb" );
if (file)
{
fseek( file,0,SEEK_END );
int64 nFileSize = ftell(file);
// Choose any random size.
int64 nOffset = 0;
int64 nSize = GetRandom( MAX_PROBE_SIZE ) + 100;
if (bAtEnd)
{
// Prefare probe near the file end.
nSize = min( nSize,nFileSize-1 );
// Choose offset.
nOffset = nFileSize - nSize - GetRandom( 1000 );
}
else
{
nOffset = GetRandom( nFileSize - nSize );
if (nFileSize < MAX_PROBE_SIZE)
{
// Choose small random offset from both sides.
int nOffset1 = 0;
int nOffset2 = 0;
do {
nOffset1 = GetRandom( 1000 );
nOffset2 = GetRandom( 1000 );
} while (nOffset1+nOffset2 >= nFileSize+1);
nOffset = nOffset1;
nSize = nFileSize - nOffset2 - nOffset1;
}
}
if (nOffset < 0)
nOffset = 0;
if (nSize < 0)
nSize = nFileSize;
ctx.nSize = nSize;
ctx.nOffset = nOffset;
fclose(file);
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
void CDataProbe::RandSeed( uint32 seed )
{
m_rand.Seed( seed );
}
uint32 CDataProbe::GetRand()
{
return m_rand.Rand();
}
float CDataProbe::GetRand( float fMin,float fMax )
{
return m_rand.Rand( fMin,fMax );
}
//////////////////////////////////////////////////////////////////////////
// Timur.
// This is FarCry.exe authentication function, this code is not for public release!!
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::CheckLoader( void *pFunc )
{
const char *sKey = "Timur Davidenko";
typedef void (*AuthFunction)( void *data );
AuthFunction pCheckFunc = (AuthFunction)pFunc;
unsigned int data1[8];
unsigned int data2[8];
memcpy( data1,sKey,8 );
#ifdef FARCRY_EXE_CRC_CHECK
// Comment out after alpha master.
if (!CheckLoaderFC())
{
int *p = 0;
*p = 1;
return false;
}
#endif // FARCRY_EXE_CRC_CHECK
// data1 is filled with 32 bytes of random data.
// It is then encrypted with key1 and send to supplied check function.
// Function is supposed to uncrypt the data, and encrypt it again with key2.
// when function returns we should be able to uncrypt the data with key2 and compare with original.
// if it fails, we possibly running from the not authorized loader.
// set of keys (one for farcry.exe second for dedicated server).
int keys[6][4] = {
{1873613783,235688123,812763783,1745863682},
{1897178562,734896899,156436554,902793442},
{1178362782,223786232,371615531,90884141},
{89158165, 1389745433,971685123,785741042},
{389623487,373673863,657846392,378467832},
{1982697467,3278962783,278963782,287678311},
};
m_rand.Seed( GetTickCount() );
// Data assumed to be 32 bytes (8 ints).
for (int i = 0; i < 8; i++)
{
data1[i] = m_rand.Rand();
}
//////////////////////////////////////////////////////////////////////////
// First try... key0,key1
//////////////////////////////////////////////////////////////////////////
TEA_ENCODE( data1,data2,32,(unsigned int*)keys[0] );
pCheckFunc( data2 );
TEA_DECODE( data2,data2,32,(unsigned int*)keys[1] );
// Now check data1 and data2.
if (memcmp( data1,data2,32 ) == 0)
{
// Authentication passed.
return true;
}
//////////////////////////////////////////////////////////////////////////
// Second try... key2,key3
//////////////////////////////////////////////////////////////////////////
TEA_ENCODE( data1,data2,32,(unsigned int*)keys[2] );
pCheckFunc( data2 );
TEA_DECODE( data2,data2,32,(unsigned int*)keys[3] );
// Now check data1 and data2.
if (memcmp( data1,data2,32 ) == 0)
{
// Authentication passed.
return true;
}
//////////////////////////////////////////////////////////////////////////
// Third try... key4,key5
//////////////////////////////////////////////////////////////////////////
TEA_ENCODE( data1,data2,32,(unsigned int*)keys[4] );
pCheckFunc( data2 );
TEA_DECODE( data2,data2,32,(unsigned int*)keys[5] );
// Now check data1 and data2.
if (memcmp( data1,data2,32 ) == 0)
{
// Authentication passed.
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::CheckLoaderFC()
{
#ifdef FARCRY_EXE_CRC_CHECK
// Open exe file.
CCryFile file;
// crysystem.dll
string fsysname = string("c")+"r"+"y"+"s"+"y"+"s"+"t"+"e"+"m"+"."+"d"+"l"+"l";
// farcry.exe
string fcname = string("f")+"a"+"r"+"c"+"r"+"y"+"."+"e"+"x"+"e";
if (!file.Open( (m_sBinPath + fsysname).c_str(),"rb" ))
return false;
int nLen = file.GetLength();
char *pBuffer = new char[nLen+16];
file.Read( pBuffer,nLen );
// find embedded string.
int nStrLen = strlen(test_name)+1;
CryLogAlways( "Len=%d",nStrLen );
//nStrLen = TEST_NAME_END;
unsigned int nStoredCode = 0;
memcpy( &nStoredCode,test_name+nStrLen,sizeof(nStoredCode) );
bool bFound = false;
unsigned int nCode = 0;
for (int i = 0; i < nLen-nStrLen-32; i++)
{
if (memcmp(pBuffer+i,test_name,nStrLen) == 0)
{
// Found!
// Read code.
memcpy( &nStoredCode,pBuffer+i+nStrLen,sizeof(nCode) );
bFound = true;
break;
}
}
if (!bFound)
return false;
// Now compare code to the farcry.exe.
SDataProbeContext ctx;
ctx.nCodeInfo = DATAPROBE_PURE_CRC32;
ctx.sFilename = m_sBinPath + fcname;
ctx.nSize = 10000000;
if (!GetCode(ctx))
return false;
unsigned int nCurrentCode = ctx.nCode; // Invert of CRC32
nCurrentCode = ~nCurrentCode; // Invert of CRC32
// Codes must match.
if (nCurrentCode != nStoredCode)
return false;
delete []pBuffer;
#endif // FARCRY_EXE_CRC_CHECK
CryLogComment( "Init Loader" );
return true;
}
//////////////////////////////////////////////////////////////////////////
int CDataProbe::Compress( void *dest,unsigned int &destLen,const void *source, unsigned int sourceLen,int level )
{
unsigned long dlen = destLen;
int res = ::compress2( (Bytef*)dest,&dlen,(const Bytef*)source,sourceLen,level );
destLen = dlen;
return res;
}
//////////////////////////////////////////////////////////////////////////
int CDataProbe::Uncompress( void *dest,unsigned int &destLen,const void *source, unsigned int sourceLen )
{
unsigned long dlen = destLen;
int res = ::uncompress( (Bytef*)dest,&dlen,(const Bytef*)source,sourceLen );
destLen = dlen;
return res;
}
void CDataProbe::RandomAlloc()
{
#ifndef _DEBUG
RandSeed( GetTickCount() );
m_pRandAlloc = malloc( (GetRand() & 0xFFF) ); // do a random allocation to make debugging harder.
#endif
}
#if !defined(LINUX)
//////////////////////////////////////////////////////////////////////////
// Get address of executable code RAM for loaded DLL or EXE.
//////////////////////////////////////////////////////////////////////////
static void GetModuleCodeAddress( void *base,void **pCodeStartAddress,int *nCodeSize )
{
const IMAGE_DOS_HEADER *dos_head = (IMAGE_DOS_HEADER*)base;
assert(base);
assert(pCodeStartAddress);
assert(nCodeSize);
*pCodeStartAddress = 0;
*nCodeSize = 0;
#include <pshpack1.h> // no padding.
const struct PEHeader
{
DWORD signature;
IMAGE_FILE_HEADER _head;
IMAGE_OPTIONAL_HEADER opt_head;
IMAGE_SECTION_HEADER *section_header; // actual number in NumberOfSections
}
*header;
#include <poppack.h>
if (dos_head->e_magic != IMAGE_DOS_SIGNATURE)
{
// Wrong pointer, not to PE header.
return;
}
// verify DOS-EXE-Header
// after end of DOS-EXE-Header: offset to PE-Header
header = (PEHeader*)(const void *)((char *)dos_head + dos_head->e_lfanew);
if (IsBadReadPtr(header, sizeof(*header))) // start of PE-Header
{
// (no PE header, probably DOS executable)
return;
}
/*
CryLog( "[CodeModule] base: %x",base );
CryLog( "[CodeModule] base of code: %x",header->opt_head.BaseOfCode );
CryLog( "[CodeModule] size of code: %x",header->opt_head.SizeOfCode );
*/
void *pCodeAddress = (char*)base + header->opt_head.BaseOfCode;
if (IsBadReadPtr(pCodeAddress, header->opt_head.SizeOfCode ))
{
// Something wrong..., cant read code memory, skip it.
return;
}
*pCodeStartAddress = pCodeAddress;
*nCodeSize = header->opt_head.SizeOfCode;
/*
{
int sect;
const IMAGE_SECTION_HEADER *section_header;
for (sect = 0, section_header = header->section_header; sect < header->_head.NumberOfSections; sect++, section_header++)
{
}
}
*/
}
#endif //LINUX
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::GetRandomModuleProbe( SDataProbeContext &ctx )
{
#ifndef WIN32
return false; // Not WIN32
#else // WIN32
if (!ctx.pModuleBaseAddress)
{
// Try to find module handle from filename.
HMODULE hModule = GetModuleHandle( ctx.sFilename.c_str() );
if (!hModule)
return false;
ctx.pModuleBaseAddress = hModule;
}
void *pCodeAddress = 0;
int nCodeSize = 0;
// Get code sections pointers.
GetModuleCodeAddress( ctx.pModuleBaseAddress,&pCodeAddress,&nCodeSize );
if (!pCodeAddress || nCodeSize == 0)
return false;
// Choose small random offset from both sides.
int nOffset1 = 0;
int nOffset2 = 0;
do {
nOffset1 = GetRandom( 1000 );
nOffset2 = GetRandom( 1000 );
} while (nOffset1+nOffset2 >= nCodeSize+1);
ctx.pBuffer = pCodeAddress;
ctx.nOffset = nOffset1;
ctx.nSize = nCodeSize - nOffset1 - nOffset2;
if (IsBadReadPtr( (char*)pCodeAddress+nOffset1,ctx.nSize))
{
// Something wrong..., cant read code memory, skip it.
return false;
}
/*
//////////////////////////////////////////////////////////////////////////
// Write this to file....
CryLog( "[CodeModule] %s, base: %x",ctx.sFilename.c_str(),ctx.pModuleBaseAddress );
char *pBuf = (char*)malloc(ctx.nSize + 128);
memset(pBuf,0,ctx.nSize+64);
memcpy(pBuf,(char*)ctx.pBuffer+ctx.nOffset,ctx.nSize);
FILE *file;
if (!GetISystem()->IsDedicated())
file = fopen( (ctx.sFilename+".client_code").c_str(),"wb" );
else
file = fopen( (ctx.sFilename+".server_code").c_str(),"wb" );
fwrite( pBuf,ctx.nSize,1,file );
fclose(file);
unsigned int nCode = CRC_32( pBuf,ctx.nSize );
CryLog( "Code CRC32=%u, offset=%d,size=%d",nCode,ctx.nOffset,ctx.nSize );
free(pBuf);
//////////////////////////////////////////////////////////////////////////
*/
return true;
#endif //WIN32
}
//////////////////////////////////////////////////////////////////////////
bool CDataProbe::GetModuleProbe( SDataProbeContext &ctx )
{
#ifndef WIN32
return false; // Not WIN32
#else // WIN32
if (!ctx.pModuleBaseAddress)
{
// Try to find module handle from filename.
HMODULE hModule = GetModuleHandle( ctx.sFilename.c_str() );
if (!hModule)
return false;
ctx.pModuleBaseAddress = hModule;
}
void *pCodeAddress = 0;
int nCodeSize = 0;
// Get code sections pointers.
GetModuleCodeAddress( ctx.pModuleBaseAddress,&pCodeAddress,&nCodeSize );
if (!pCodeAddress || nCodeSize == 0)
return false;
ctx.pBuffer = pCodeAddress;
if (IsBadReadPtr( (char*)pCodeAddress+ctx.nOffset,ctx.nSize))
{
// Something wrong..., cant read code memory, skip it.
return false;
}
/*
//////////////////////////////////////////////////////////////////////////
// Write this to file....
CryLog( "[CodeModule] %s, base: %x",ctx.sFilename.c_str(),ctx.pModuleBaseAddress );
char *pBuf = (char*)malloc(ctx.nSize + 128);
memset(pBuf,0,ctx.nSize+64);
memcpy(pBuf,(char*)ctx.pBuffer+ctx.nOffset,ctx.nSize);
FILE *file;
if (!GetISystem()->IsDedicated())
file = fopen( (ctx.sFilename+".client_code").c_str(),"wb" );
else
file = fopen( (ctx.sFilename+".server_code").c_str(),"wb" );
fwrite( pBuf,ctx.nSize,1,file );
fclose(file);
unsigned int nCode = CRC_32( pBuf,ctx.nSize );
CryLog( "Code CRC32=%u, offset=%d,size=%d",nCode,ctx.nOffset,ctx.nSize );
free(pBuf);
//////////////////////////////////////////////////////////////////////////
*/
return true;
#endif //WIN32
}
//////////////////////////////////////////////////////////////////////////
int CDataProbe::GetLoadedModules( SModuleInfo **pModules )
{
*pModules = 0;
int numModules = m_loadedModules.size();
if (numModules > 0)
{
*pModules = &m_loadedModules[0];
}
return numModules;
}
//////////////////////////////////////////////////////////////////////////
void CDataProbe::AddModule( SModuleInfo &moduleInfo )
{
m_loadedModules.push_back(moduleInfo);
}
//////////////////////////////////////////////////////////////////////////
void CDataProbe::AESDecryptBuffer( const char *pSrcBuffer,int nSrcSize,char *pDestBuffer,int &nDestSize,const char *sKey )
{
nDestSize = nSrcSize;
memcpy( pDestBuffer,pSrcBuffer,nSrcSize );
}
//////////////////////////////////////////////////////////////////////////
void CDataProbe::GetMD5( const char *pSrcBuffer,int nSrcSize,char signatureMD5[16] )
{
//#if !defined(LINUX)
struct MD5Context md5c;
MD5Init(&md5c);
MD5Update(&md5c, (unsigned char*)pSrcBuffer,nSrcSize );
MD5Final( (unsigned char*)signatureMD5, &md5c);
//#endif
}

91
CrySystem/DataProbe.h Normal file
View File

@@ -0,0 +1,91 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2001-2004.
// -------------------------------------------------------------------------
// File name: DataProbe.h
// Version: v1.00
// Created: 19/1/2004 by Timur.
// Compilers: Visual Studio.NET 2003
// Description:
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#ifndef __DataProbe_h__
#define __DataProbe_h__
#pragma once
#include <IDataProbe.h>
#include "RandGen.h"
enum EDataProbeCodeInfo
{
DATAPROBE_CRC32 = 0,
DATAPROBE_CRC64 = 1,
DATAPROBE_ADLER32 = 2,
DATAPROBE_PURE_CRC32 = 3,
DATAPROBE_MD5 = 4,
};
//////////////////////////////////////////////////////////////////////////
// Timur.
// This is authentication functions, this code is not for public release!!
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// CDataProbe implementation.
//////////////////////////////////////////////////////////////////////////
class CDataProbe : public IDataProbe
{
public:
CDataProbe();
virtual ~CDataProbe();
virtual bool Dummy1( SDataProbeContext &ctx ) { return false; };
virtual int Dummy2( void *pBuf,int aa,SDataProbeContext &ctx ) { return 2322; };
virtual bool Dummy3( SDataProbeContext &ctx ) { return false; };
virtual uint32 GetHash( const char *sString );
// Hash of any buffer.
virtual uint32 GetHash( const void *buffer,int len );
virtual void RandomAlloc();
virtual bool GetCode( SDataProbeContext &ctx );
virtual bool GetRandomFileProbe( SDataProbeContext &ctx,bool bAtEnd );
virtual bool GetRandomModuleProbe( SDataProbeContext &ctx );
virtual bool GetModuleProbe( SDataProbeContext &ctx );
virtual int GetLoadedModules( SModuleInfo **pModules );
virtual void AddModule( SModuleInfo &moduleInfo );
virtual void RandSeed( uint32 seed );
virtual uint32 GetRand();
virtual float GetRand( float fMin,float fMax );
//////////////////////////////////////////////////////////////////////////
// Compress block of data with zlib.
virtual int Compress( void *dest,unsigned int &destLen,const void *source, unsigned int sourceLen,int level=6 );
// Uncompress block of data with zlib.
virtual int Uncompress( void *dest,unsigned int &destLen,const void *source, unsigned int sourceLen );
void GetMD5( const char *pSrcBuffer,int nSrcSize,char signatureMD5[16] );
void AESDecryptBuffer( const char *pSrcBuffer,int nSrcSize,char *pDestBuffer,int &nDestSize,const char *sKey );
// Local from system.
bool CheckLoader( void *pFunc );
private:
bool GetDataCode( char* pBuffer,int nSize,SDataProbeContext &ctx );
bool CheckLoaderFC();
CSysPseudoRandGen m_rand;
void *m_pRandAlloc;
std::vector<SModuleInfo> m_loadedModules;
string m_sBinPath;
};
#endif // __DataProbe_h__

View File

@@ -0,0 +1,768 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: debugcallstack.cpp
// Version: v1.00
// Created: 1/10/2002 by Timur.
// Compilers: Visual Studio.NET
// Description:
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "DebugCallStack.h"
#ifdef WIN32
#include <ISystem.h>
#include <ILog.h>
#include "Mailer.h"
#include "System.h"
#include <Process.h>
#include <imagehlp.h>
#include <time.h>
#include <crtdbg.h>
#include "Resource.h"
#pragma comment(lib, "version.lib")
//! Needs one external of DLL handle.
extern HMODULE gDLLHandle;
#ifndef WIN98
//#pragma comment( lib, "imagehlp" )
#pragma comment( lib, "dbghelp" )
#endif
#define MAX_PATH_LENGTH 1024
#define MAX_SYMBOL_LENGTH 512
static HWND hwndException = 0;
static int PrintException( EXCEPTION_POINTERS* pex );
void PutVersion( char *str );
//=============================================================================
LONG __stdcall UnhandledExceptionHandler( EXCEPTION_POINTERS *pex )
{
DebugCallStack::instance()->handleException( pex );
return EXCEPTION_EXECUTE_HANDLER;
}
//=============================================================================
// Class Statics
//=============================================================================
DebugCallStack* DebugCallStack::m_instance = 0;
// Return single instance of class.
DebugCallStack* DebugCallStack::instance()
{
if (!m_instance) {
m_instance = new DebugCallStack;
}
return m_instance;
}
//------------------------------------------------------------------------------------------------------------------------
// Sets up the symbols forfunctions in the debug file.
//------------------------------------------------------------------------------------------------------------------------
DebugCallStack::DebugCallStack()
{
prevExceptionHandler = 0;
m_pSystem = 0;
m_symbols = false;
}
DebugCallStack::~DebugCallStack()
{
}
bool DebugCallStack::initSymbols()
{
#ifndef WIN98
if (m_symbols) return true;
char fullpath[MAX_PATH_LENGTH+1];
char pathname[MAX_PATH_LENGTH+1];
char fname[MAX_PATH_LENGTH+1];
char directory[MAX_PATH_LENGTH+1];
char drive[10];
HANDLE process;
// SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_UNDNAME|SYMOPT_LOAD_LINES|SYMOPT_OMAP_FIND_NEAREST|SYMOPT_INCLUDE_32BIT_MODULES);
SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_UNDNAME|SYMOPT_LOAD_LINES|SYMOPT_OMAP_FIND_NEAREST);
process = GetCurrentProcess();
// Get module file name.
GetModuleFileName( NULL, fullpath, MAX_PATH_LENGTH );
// Convert it into search path for symbols.
strcpy( pathname,fullpath );
_splitpath( pathname, drive, directory, fname, NULL );
sprintf( pathname, "%s%s", drive,directory );
// Append the current directory to build a search path forSymInit
strcat( pathname, ";.;" );
int result = 0;
m_symbols = false;
result = SymInitialize( process,pathname,TRUE );
if (result) {
//HMODULE hMod = GetModuleHandle( "imagehlp" );
//SymGetLineFromAddrPtr = (SymGetLineFromAddrFunction)GetProcAddress( hMod,"SymGetLineFromAddr" );
char pdb[MAX_PATH_LENGTH+1];
char res_pdb[MAX_PATH_LENGTH+1];
sprintf( pdb, "%s.pdb",fname );
sprintf( pathname, "%s%s", drive,directory );
if (SearchTreeForFile( pathname,pdb,res_pdb )) {
m_symbols = true;
}
/*
if (SymLoadModule( process,NULL,fullpath,NULL,0,0 ))
{
//You could load dll/lib information ifyou wish here...
// if(::SymLoadModule(process, NULL, GLibDLLName, NULL, 0, 0))
{
m_symbols = true;
}
} else {
SymCleanup( process );
}
*/
} else {
result = SymInitialize( process,pathname,FALSE );
if (!result)
{
CryWarning( VALIDATOR_MODULE_SYSTEM,VALIDATOR_WARNING,"SymInitialize faield" );
}
}
#else
return false;
#endif
//return m_symbols;
return result != 0;
}
void DebugCallStack::doneSymbols()
{
#ifndef WIN98
if (m_symbols) {
SymCleanup( GetCurrentProcess() );
}
m_symbols = false;
#endif
}
void DebugCallStack::getCallStack( std::vector<string> &functions )
{
functions = m_functions;
}
void DebugCallStack::updateCallStack()
{
if (initSymbols())
{
m_functions.clear();
// (Not used) Rise exception to call updateCallStack(exc) method.
//riseException();
//updateCallStack(GetExceptionInformation())
CONTEXT context;
memset( &context,0,sizeof(context) );
context.ContextFlags = CONTEXT_FULL;
if (GetThreadContext( GetCurrentThread(), &context ) )
{
#ifndef WIN64
FillStackTrace( context.Eip,context.Esp,context.Ebp,&context );
#else
FillStackTrace( context.Rip,context.Rsp,context.Rbp,&context );
#endif
}
doneSymbols();
}
}
//------------------------------------------------------------------------------------------------------------------------
int DebugCallStack::updateCallStack( void *exception_pointer )
{
static int callCount = 0;
if (callCount > 0)
{
if (prevExceptionHandler)
{
// uninstall our exception handler.
SetUnhandledExceptionFilter( (LPTOP_LEVEL_EXCEPTION_FILTER)prevExceptionHandler );
}
// Immidiate termination of process.
abort();
}
callCount++;
EXCEPTION_POINTERS *pex = (EXCEPTION_POINTERS*)exception_pointer;
HANDLE process = GetCurrentProcess();
//! Find source line at exception address.
//m_excLine = lookupFunctionName( (void*)pex->ExceptionRecord->ExceptionAddress,true );
//! Find Name of .DLL from Exception address.
strcpy( m_excModule,"<Unknown>" );
#if !defined(WIN98) && !defined(WIN64)
if (m_symbols) {
DWORD dwAddr = SymGetModuleBase( process,(DWORD)pex->ExceptionRecord->ExceptionAddress );
if (dwAddr) {
char szBuff[MAX_PATH_LENGTH];
if (GetModuleFileName( (HINSTANCE)dwAddr,szBuff,MAX_PATH_LENGTH )) {
strcpy( m_excModule,szBuff );
string path,fname,ext;
char fdir[_MAX_PATH];
char fdrive[_MAX_PATH];
char file[_MAX_PATH];
char fext[_MAX_PATH];
_splitpath( m_excModule,fdrive,fdir,file,fext );
_makepath( fdir,NULL,NULL,file,fext );
strcpy(m_excModule,fdir);
}
}
}
// Fill stack trace info.
FillStackTrace( pex->ContextRecord->Eip,pex->ContextRecord->Esp,pex->ContextRecord->Ebp,pex->ContextRecord );
#endif
return EXCEPTION_CONTINUE_EXECUTION;
}
//////////////////////////////////////////////////////////////////////////
void DebugCallStack::FillStackTrace( DWORD64 eip,DWORD64 esp,DWORD64 ebp,PCONTEXT pContext )
{
HANDLE hThread = GetCurrentThread();
HANDLE hProcess = GetCurrentProcess();
int count;
STACKFRAME64 stack_frame;
BOOL b_ret=TRUE; //Setup stack frame
memset(&stack_frame, 0, sizeof(stack_frame));
stack_frame.AddrPC.Mode = AddrModeFlat;
stack_frame.AddrPC.Offset = eip;
stack_frame.AddrStack.Mode = AddrModeFlat;
stack_frame.AddrStack.Offset = esp;
stack_frame.AddrFrame.Mode = AddrModeFlat;
stack_frame.AddrFrame.Offset = 0;
stack_frame.AddrFrame.Offset = ebp;
m_functions.clear();
PCONTEXT pContextRecord = NULL;
CONTEXT CpuContext;
if (pContext)
{
pContextRecord = &CpuContext;
CpuContext = *pContext;
}
//While there are still functions on the stack..
for(count=0; count < MAX_DEBUG_STACK_ENTRIES && b_ret==TRUE; count++)
{
b_ret = StackWalk64( IMAGE_FILE_MACHINE_I386, hProcess, hThread, &stack_frame, pContextRecord,
NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL);
if (m_symbols)
{
string funcName = LookupFunctionName( (void*)stack_frame.AddrPC.Offset,true );
if (funcName.empty()) {
funcName = "<Unknown Function>";
}
m_functions.push_back( funcName );
} else {
DWORD p = stack_frame.AddrPC.Offset;
char str[80];
sprintf( str,"function=0x%X",p );
m_functions.push_back( str );
}
}
}
//------------------------------------------------------------------------------------------------------------------------
string DebugCallStack::LookupFunctionName( void *pointer,bool fileInfo )
{
string symName = "";
#ifndef WIN98
HANDLE process = GetCurrentProcess();
char symbolBuf[sizeof(SYMBOL_INFO)+MAX_SYMBOL_LENGTH];
memset( symbolBuf, 0, sizeof(symbolBuf));
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)symbolBuf;
DWORD displacement = 0;
DWORD64 displacement64 = 0;
pSymbol->SizeOfStruct = sizeof(symbolBuf);
pSymbol->MaxNameLen = MAX_SYMBOL_LENGTH;
if (SymFromAddr( process,(DWORD64)pointer,&displacement64,pSymbol ))
{
symName = string(pSymbol->Name) + "()";
if (fileInfo)
{
// Lookup Line in source file.
IMAGEHLP_LINE64 lineImg;
memset( &lineImg,0,sizeof(lineImg) );
lineImg.SizeOfStruct = sizeof(lineImg);
if (SymGetLineFromAddr64( process,(DWORD_PTR)pointer, &displacement, &lineImg ))
{
char lineNum[1024];
itoa( lineImg.LineNumber,lineNum,10 );
string path;
char file[1024];
char fname[1024];
char fext[1024];
_splitpath( lineImg.FileName,NULL,NULL,fname,fext );
_makepath( file,NULL,NULL,fname,fext );
string fileName = file;
/*
string finfo = string("[" ) + fileName + ", line:" + lineNum + "]";
//symName += string(" --- [" ) + fileName + ", line:" + lineNum + "]";
//char finfo[1024];
//sprintf( finfo,"[%s,line:%d]",fileName.
char temp[4096];
sprintf( temp,"%30s --- %s",finfo.c_str(),symName.c_str() );
symName = temp;
*/
symName += string(" [" ) + fileName + ":" + lineNum + "]";
}
}
}
#endif
CryLogAlways( symName.c_str() );
return symName;
}
void DebugCallStack::registerErrorCallback( ErrorCallback callBack ) {
m_errorCallbacks.push_back( callBack );
}
void DebugCallStack::unregisterErrorCallback( ErrorCallback callBack ) {
m_errorCallbacks.remove( callBack );
}
void DebugCallStack::installErrorHandler( ISystem *pSystem )
{
m_pSystem = pSystem;
prevExceptionHandler = (void*)SetUnhandledExceptionFilter( UnhandledExceptionHandler );
// Crash.
//PrintException( 0 );
}
//////////////////////////////////////////////////////////////////////////
int DebugCallStack::handleException( void *exception_pointer )
{
EXCEPTION_POINTERS *pex = (EXCEPTION_POINTERS*)exception_pointer;
int ret = 0;
static bool firstTime = true;
// uninstall our exception handler.
SetUnhandledExceptionFilter( (LPTOP_LEVEL_EXCEPTION_FILTER)prevExceptionHandler );
if (!firstTime)
{
CryLogAlways( "Critical Exception! Called Multiple Times!" );
// Exception called more then once.
exit(1);
}
firstTime = false;
hwndException = CreateDialog( gDLLHandle,MAKEINTRESOURCE(IDD_EXCEPTION),NULL,NULL );
if (initSymbols())
{
CryLogAlways( "<CRITICAL ERROR>" );
char excCode[80];
char excAddr[80];
sprintf( excAddr,"0x%04X:0x%p",pex->ContextRecord->SegCs,pex->ExceptionRecord->ExceptionAddress );
sprintf( excCode,"0x%08X",pex->ExceptionRecord->ExceptionCode );
CryLogAlways( "Exception: %s, at Address: %s",excCode,excAddr );
// Rise exception to call updateCallStack method.
updateCallStack( exception_pointer );
//! Print exception dialog.
ret = PrintException( pex );
doneSymbols();
//exit(0);
}
/*
if (ret == IDB_DEBUG)
{
//SetUnhandledExceptionFilter( (LPTOP_LEVEL_EXCEPTION_FILTER)prevExceptionHandler );
//SetUnhandledExceptionFilter( (LPTOP_LEVEL_EXCEPTION_FILTER)prevExceptionHandler );
DebugActiveProcess( GetCurrentProcessId() );
DebugBreak();
}
*/
if (pex->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
{
// This is non continuable exception. abort application now.
exit(1);
}
//typedef long (__stdcall *ExceptionFunc)(EXCEPTION_POINTERS*);
//ExceptionFunc prevFunc = (ExceptionFunc)prevExceptionHandler;
//return prevFunc( (EXCEPTION_POINTERS*)exception_pointer );
if (ret == IDB_EXIT)
{
// Immidiate exit.
exit(1);
} else {
}
// Continue;
return EXCEPTION_CONTINUE_EXECUTION;
}
void DebugCallStack::dumpCallStack( std::vector<string> &funcs )
{
CryLogAlways( "=============================================================================" );
int len = (int)funcs.size();
for (int i = 0; i < len; i++) {
const char* str = funcs[i].c_str();
CryLogAlways( "%2d) %s",len-i,str );
}
// Call all error callbacks.
for (std::list<DebugCallStack::ErrorCallback>::iterator it = m_errorCallbacks.begin(); it != m_errorCallbacks.end(); ++it)
{
DebugCallStack::ErrorCallback callback = *it;
string desc,data;
callback( desc.c_str(),data.c_str() );
CryLogAlways( "%s",(const char*)desc.c_str() );
CryLogAlways( "%s",(const char*)data.c_str() );
}
CryLogAlways( "=============================================================================" );
}
//////////////////////////////////////////////////////////////////////////
void DebugCallStack::LogCallstack()
{
updateCallStack(); // is updating m_functions
CryLogAlways( "=============================================================================" );
int len = (int)m_functions.size();
for (int i = 0; i < len; i++) {
const char* str = m_functions[i].c_str();
CryLogAlways( "%2d) %s",len-i,str );
}
CryLogAlways( "=============================================================================" );
}
static const char* TranslateExceptionCode( DWORD dwExcept )
{
switch (dwExcept)
{
case EXCEPTION_ACCESS_VIOLATION : return "EXCEPTION_ACCESS_VIOLATION"; break ;
case EXCEPTION_DATATYPE_MISALIGNMENT : return "EXCEPTION_DATATYPE_MISALIGNMENT"; break ;
case EXCEPTION_BREAKPOINT: return "EXCEPTION_BREAKPOINT"; break ;
case EXCEPTION_SINGLE_STEP: return "EXCEPTION_SINGLE_STEP"; break ;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; break ;
case EXCEPTION_FLT_DENORMAL_OPERAND : return "EXCEPTION_FLT_DENORMAL_OPERAND"; break ;
case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "EXCEPTION_FLT_DIVIDE_BY_ZERO"; break ;
case EXCEPTION_FLT_INEXACT_RESULT: return "EXCEPTION_FLT_INEXACT_RESULT"; break ;
case EXCEPTION_FLT_INVALID_OPERATION: return "EXCEPTION_FLT_INVALID_OPERATION"; break ;
case EXCEPTION_FLT_OVERFLOW: return "EXCEPTION_FLT_OVERFLOW"; break ;
case EXCEPTION_FLT_STACK_CHECK: return "EXCEPTION_FLT_STACK_CHECK"; break ;
case EXCEPTION_FLT_UNDERFLOW: return "EXCEPTION_FLT_UNDERFLOW"; break ;
case EXCEPTION_INT_DIVIDE_BY_ZERO: return "EXCEPTION_INT_DIVIDE_BY_ZERO";break ;
case EXCEPTION_INT_OVERFLOW:return "EXCEPTION_INT_OVERFLOW";break ;
case EXCEPTION_PRIV_INSTRUCTION: return "EXCEPTION_PRIV_INSTRUCTION"; break ;
case EXCEPTION_IN_PAGE_ERROR: return "EXCEPTION_IN_PAGE_ERROR"; break ;
case EXCEPTION_ILLEGAL_INSTRUCTION: return "EXCEPTION_ILLEGAL_INSTRUCTION"; break ;
case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "EXCEPTION_NONCONTINUABLE_EXCEPTION"; break ;
case EXCEPTION_STACK_OVERFLOW: return "EXCEPTION_STACK_OVERFLOW"; break ;
case EXCEPTION_INVALID_DISPOSITION: return "EXCEPTION_INVALID_DISPOSITION"; break ;
case EXCEPTION_GUARD_PAGE: return "EXCEPTION_GUARD_PAGE"; break ;
case EXCEPTION_INVALID_HANDLE: return "EXCEPTION_INVALID_HANDLE"; break ;
default:
return "Unknown";
break;
}
}
BOOL CALLBACK ExceptionDialogProc(HWND hwndDlg, unsigned int message, WPARAM wParam, LPARAM lParam)
{
static EXCEPTION_POINTERS *pex;
static char errorString[32768] = "";
switch (message)
{
case WM_INITDIALOG:
{
pex = (EXCEPTION_POINTERS*)lParam;
HWND h;
if (pex->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) {
// Disable continue button for non continuable exceptions.
//h = GetDlgItem( hwndDlg,IDB_CONTINUE );
//if (h) EnableWindow( h,FALSE );
}
// Time and Version.
char versionbuf[1024];
strcpy( versionbuf,"" );
PutVersion( versionbuf );
strcat( errorString,versionbuf );
strcat( errorString,"\n" );
//! Get call stack functions.
DebugCallStack *cs = DebugCallStack::instance();
std::vector<string> funcs;
cs->getCallStack( funcs );
// Init dialog.
int iswrite = 0;
DWORD accessAddr = 0;
char excCode[80];
char excAddr[80];
sprintf( excAddr,"0x%04X:0x%p",pex->ContextRecord->SegCs,pex->ExceptionRecord->ExceptionAddress );
sprintf( excCode,"0x%08X",pex->ExceptionRecord->ExceptionCode );
string moduleName = DebugCallStack::instance()->getExceptionModule();
const char *excModule = moduleName.c_str();
char desc[1024];
char excDesc[1024];
const char *excName = TranslateExceptionCode(pex->ExceptionRecord->ExceptionCode);
if (pex->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
if (pex->ExceptionRecord->NumberParameters > 1) {
int iswrite = pex->ExceptionRecord->ExceptionInformation[0];
accessAddr = pex->ExceptionRecord->ExceptionInformation[1];
if (iswrite) {
sprintf( desc,"Attempt to write data to address 0x%08X\r\nThe memory could not be \"written\"",accessAddr );
} else {
sprintf( desc,"Attempt to read from address 0x%08X\r\nThe memory could not be \"read\"",accessAddr );
}
}
}
sprintf( excDesc,"%s\r\n%s",excName,desc );
CryLogAlways( "Exception Code: %s",excCode );
CryLogAlways( "Exception Addr: %s",excAddr );
CryLogAlways( "Exception Module: %s",excModule );
CryLogAlways( "Exception Description: %s",desc );
DebugCallStack::instance()->dumpCallStack( funcs );
char errs[32768];
sprintf( errs,"Exception Code: %s\nException Addr: %s\nException Module: %s\nException Description: %s, %s\n",
excCode,excAddr,excModule,excName,desc );
// Level Info.
//char szLevel[1024];
//const char *szLevelName = GetIEditor()->GetGameEngine()->GetLevelName();
//const char *szMissionName = GetIEditor()->GetGameEngine()->GetMissionName();
//sprintf( szLevel,"Level %s, Mission %s\n",szLevelName,szMissionName );
//strcat( errs,szLevel );
strcat( errs,"\nCall Stack Trace:\n" );
h = GetDlgItem( hwndDlg,IDC_EXCEPTION_DESC );
if (h) SendMessage( h,EM_REPLACESEL,FALSE, (LONG_PTR)excDesc );
h = GetDlgItem( hwndDlg,IDC_EXCEPTION_CODE );
if (h) SendMessage( h,EM_REPLACESEL,FALSE, (LONG_PTR)excCode );
h = GetDlgItem( hwndDlg,IDC_EXCEPTION_MODULE );
if (h) SendMessage( h,EM_REPLACESEL,FALSE, (LONG_PTR)excModule );
h = GetDlgItem( hwndDlg,IDC_EXCEPTION_ADDRESS );
if (h) SendMessage( h,EM_REPLACESEL,FALSE, (LONG_PTR)excAddr );
// Fill call stack.
HWND callStack = GetDlgItem( hwndDlg,IDC_CALLSTACK );
if (callStack) {
char str[32768];
strcpy( str,"" );
for (unsigned int i = 0; i < funcs.size(); i++) {
char temp[4096];
sprintf( temp,"%2d) %s",funcs.size()-i,(const char*)funcs[i].c_str() );
strcat( str,temp );
strcat( str,"\r\n" );
strcat( errs,temp );
strcat( errs,"\n" );
}
// Call all error callbacks.
for (std::list<DebugCallStack::ErrorCallback>::iterator it = cs->m_errorCallbacks.begin(); it != cs->m_errorCallbacks.end(); ++it) {
DebugCallStack::ErrorCallback callback = *it;
string desc,data;
callback( desc.c_str(),data.c_str() );
CryLogAlways( "%s",(const char*)desc.c_str() );
CryLogAlways( "%s",(const char*)data.c_str() );
strcat( str,"======================================================\r\n" );
strcat( str,(const char*)desc.c_str() );
strcat( str,"\r\n" );
strcat( str,(const char*)data.c_str() );
strcat( str,"\r\n" );
strcat( errs,(const char*)desc.c_str() );
strcat( errs,"\n" );
strcat( errs,(const char*)data.c_str() );
strcat( errs,"\n" );
}
SendMessage( callStack,WM_SETTEXT,FALSE, (LPARAM)str );
}
strcat( errorString,errs );
FILE *f = fopen( "error.log","wt" );
if (f) {
fwrite( errorString,strlen(errorString),1,f );
fclose(f);
}
if (hwndException)
DestroyWindow( hwndException );
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDB_MAIL:
{
HWND h = GetDlgItem( hwndDlg,IDC_ERROR_TEXT );
if (h) {
char errs[4096];
strcpy( errs,"" );
SendMessage( h,WM_GETTEXT,(WPARAM)sizeof(errs),(LPARAM)errs );
strcat( errorString,"\nError Description:\n" );
strcat( errorString,errs );
}
char dir[1024];
GetCurrentDirectory( 1024,dir );
std::vector<const char*> emails;
std::vector<const char*> files;
emails.push_back( "timur@crytek.de" );
emails.push_back( "xtest@crytek.de" );
emails.push_back( "xcode@crytek.de" );
///files.push_back( string(dir)+"\\error.log" );
files.push_back( DebugCallStack::instance()->GetSystem()->GetILog()->GetFileName() );
if (CMailer::SendMessage( "Critical Exception",errorString,emails,files,true ))
{
MessageBox( NULL,"Mail Successfully Sent","Send Mail",MB_OK );
}
else
{
MessageBox( NULL,"Mail has not been sent","Send Mail",MB_OK|MB_ICONWARNING );
}
}
break;
case IDB_SAVE:
{
int res = MessageBox( NULL,"Warning!\r\nEditor has crashed and is now in unstable state,\r\nand may crash again during saving of document.\r\nProceed with Save?","Save Level",MB_YESNO|MB_ICONEXCLAMATION );
if (res == IDYES)
{
// Make one additional backup.
CSystem *pSystem = (CSystem*)DebugCallStack::instance()->GetSystem();
if (pSystem && pSystem->GetUserCallback())
pSystem->GetUserCallback()->OnSaveDocument();
MessageBox( NULL,"Level has been sucessfully saved!\r\nPress Ok to terminate Editor.","Save",MB_OK );
}
}
break;
case IDB_EXIT:
// Fall through.
//case IDB_CONTINUE:
EndDialog(hwndDlg, wParam);
return TRUE;
}
}
return FALSE;
}
static int PrintException( EXCEPTION_POINTERS* pex)
{
#ifdef WIN64
// NOTE: AMD64: implement
return 0;
#else
return DialogBoxParam( gDLLHandle,MAKEINTRESOURCE(IDD_CRITICAL_ERROR),NULL,ExceptionDialogProc,(LPARAM)pex );
#endif
}
static void PutVersion( char *str )
{
char exe[_MAX_PATH];
DWORD dwHandle;
unsigned int len;
char ver[1024*8];
GetModuleFileName( NULL, exe, _MAX_PATH );
int fv[4],pv[4];
int verSize = GetFileVersionInfoSize( exe,&dwHandle );
if (verSize > 0)
{
GetFileVersionInfo( exe,dwHandle,1024*8,ver );
VS_FIXEDFILEINFO *vinfo;
VerQueryValue( ver,"\\",(void**)&vinfo,&len );
fv[0] = vinfo->dwFileVersionLS & 0xFFFF;
fv[1] = vinfo->dwFileVersionLS >> 16;
fv[2] = vinfo->dwFileVersionMS & 0xFFFF;
fv[3] = vinfo->dwFileVersionMS >> 16;
pv[0] = vinfo->dwProductVersionLS & 0xFFFF;
pv[1] = vinfo->dwProductVersionLS >> 16;
pv[2] = vinfo->dwProductVersionMS & 0xFFFF;
pv[3] = vinfo->dwProductVersionMS >> 16;
}
//! Get time.
time_t ltime;
time( &ltime );
tm *today = localtime( &ltime );
char s[1024];
//! Use strftime to build a customized time string.
strftime( s,128,"Logged at %#c\n", today );
strcat( str,s );
sprintf( s,"FileVersion: %d.%d.%d.%d\n",fv[3],fv[2],fv[1],fv[0] );
strcat( str,s );
sprintf( s,"ProductVersion: %d.%d.%d.%d\n",pv[3],pv[2],pv[1],pv[0] );
strcat( str,s );
}
#endif //WIN32

View File

@@ -0,0 +1,93 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2001.
// -------------------------------------------------------------------------
// File name: DebugCallStack.h
// Version: v1.00
// Created: 3/12/2001 by Timur.
// Compilers: Visual C++ 6.0
// Description:
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#ifndef __DebugCallStack_h__
#define __DebugCallStack_h__
#if _MSC_VER > 1000
#pragma once
#endif
#ifdef WIN32
//! Limits the maximal number of functions in call stack.
const int MAX_DEBUG_STACK_ENTRIES = 32;
struct ISystem;
//!============================================================================
//!
//! DebugCallStack class, capture call stack information from symbol files.
//!
//!============================================================================
class DebugCallStack
{
public:
// Returns single instance of DebugStack
static DebugCallStack* instance();
ISystem* GetSystem() { return m_pSystem; };
//! Dumps Current Call Stack to log.
void LogCallstack();
void updateCallStack();
//! Get current call stack information.
void getCallStack( std::vector<string> &functions );
void installErrorHandler( ISystem *pSystem );
int handleException( void *exception_pointer );
void dumpCallStack( std::vector<string> &functions );
//! Return name of module where exception happened.
const char* getExceptionModule() { return m_excModule; }
const char* getExceptionLine() { return m_excLine; }
typedef void (*ErrorCallback)( const char* description,const char* value );
void registerErrorCallback( ErrorCallback call );
void unregisterErrorCallback( ErrorCallback call );
std::list<ErrorCallback> m_errorCallbacks;
public:
DebugCallStack();
virtual ~DebugCallStack();
bool initSymbols();
void doneSymbols();
string LookupFunctionName( void *adderss,bool fileInfo );
int updateCallStack( void *exception_pointer );
void FillStackTrace( DWORD64 eip,DWORD64 esp,DWORD64 ebp,PCONTEXT pContext=NULL );
static int unhandledExceptionHandler( void *exception_pointer );
std::vector<string> m_functions;
static DebugCallStack* m_instance;
char m_excLine[256];
char m_excModule[128];
void *prevExceptionHandler;
bool m_symbols;
ISystem *m_pSystem;
};
#endif //WIN32
#endif // __DebugCallStack_h__

85
CrySystem/DllMain.cpp Normal file
View File

@@ -0,0 +1,85 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: dllmain.cpp
// Version: v1.00
// Created: 1/10/2002 by Timur.
// Compilers: Visual Studio.NET
// Description:
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "System.h"
#include "DebugCallStack.h"
#ifdef WIN32
#include <windows.h>
// For lua debugger
HMODULE gDLLHandle = NULL;
#ifdef USING_CRY_MEMORY_MANAGER
//#if !defined(LINUX)
_ACCESS_POOL
//#endif
#endif
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
gDLLHandle = (HMODULE)hModule;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#endif //WIN32
extern "C"
{
CRYSYSTEM_API ISystem* CreateSystemInterface( SSystemInitParams &initParams )
{
CSystem *pSystem = NULL;
if (!initParams.pSystem)
{
pSystem = new CSystem;
}
else
{
pSystem = (CSystem*)initParams.pSystem;
}
#ifndef _DEBUG
#ifdef WIN32
// Install exception handler in Release modes.
DebugCallStack::instance()->installErrorHandler( pSystem );
#endif
#endif
if (!pSystem->Init( initParams ))
{
delete pSystem;
return 0;
}
return pSystem;
}
};

View File

@@ -0,0 +1,94 @@
#include "stdafx.h"
#include "DownloadManager.h"
#include "HTTPDownloader.h"
//#ifndef LINUX
//-------------------------------------------------------------------------------------------------
CDownloadManager::CDownloadManager()
: m_pSystem(0)
{
}
//-------------------------------------------------------------------------------------------------
CDownloadManager::~CDownloadManager()
{
}
//-------------------------------------------------------------------------------------------------
void CDownloadManager::Create(ISystem *pSystem)
{
m_pSystem = pSystem;
}
//-------------------------------------------------------------------------------------------------
CHTTPDownloader *CDownloadManager::CreateDownload()
{
CHTTPDownloader *pDL = new CHTTPDownloader;
m_lDownloadList.push_back(pDL);
pDL->Create(m_pSystem, this);
return pDL;
}
//-------------------------------------------------------------------------------------------------
void CDownloadManager::RemoveDownload(CHTTPDownloader *pDownload)
{
std::list<CHTTPDownloader *>::iterator it = std::find(m_lDownloadList.begin(), m_lDownloadList.end(), pDownload);
if (it != m_lDownloadList.end())
{
m_lDownloadList.erase(it);
}
}
//-------------------------------------------------------------------------------------------------
void CDownloadManager::Update()
{
std::list<CHTTPDownloader *>::iterator it = m_lDownloadList.begin();
while(it != m_lDownloadList.end())
{
CHTTPDownloader *pDL = *it;
switch (pDL->GetState())
{
case HTTP_STATE_NONE:
case HTTP_STATE_WORKING:
++it;
continue;
case HTTP_STATE_COMPLETE:
pDL->OnComplete();
break;
case HTTP_STATE_ERROR:
pDL->OnError();
break;
case HTTP_STATE_CANCELED:
pDL->OnCancel();
break;
}
it = m_lDownloadList.erase(it);
pDL->Release();
}
}
//-------------------------------------------------------------------------------------------------
void CDownloadManager::Release()
{
for (std::list<CHTTPDownloader *>::iterator it = m_lDownloadList.begin(); it != m_lDownloadList.end();)
{
CHTTPDownloader *pDL = *it;
it = m_lDownloadList.erase(it);
pDL->Release();
}
delete this;
}
//#endif //LINUX

View File

@@ -0,0 +1,27 @@
#pragma once
//#ifndef LINUX
class CHTTPDownloader;
class CDownloadManager
{
public:
CDownloadManager();
virtual ~CDownloadManager();
void Create(ISystem *pSystem);
CHTTPDownloader *CreateDownload();
void RemoveDownload(CHTTPDownloader *pDownload);
void Update();
void Release();
private:
ISystem *m_pSystem;
std::list<CHTTPDownloader *> m_lDownloadList;
};
//#endif //LINUX

187
CrySystem/DxDiag.h Normal file
View File

@@ -0,0 +1,187 @@
/*==========================================================================;
*
* Copyright (C) Microsoft Corporation. All Rights Reserved.
*
* File: dxdiag.h
* Content: DirectX Diagnostic Tool include file
*
****************************************************************************/
#ifndef _DXDIAG_H_
#define _DXDIAG_H_
#include <ole2.h> // for DECLARE_INTERFACE_ and HRESULT
// This identifier is passed to IDxDiagProvider::Initialize in order to ensure that an
// application was built against the correct header files. This number is
// incremented whenever a header (or other) change would require applications
// to be rebuilt. If the version doesn't match, IDxDiagProvider::Initialize will fail.
// (The number itself has no meaning.)
#define DXDIAG_DX9_SDK_VERSION 111
#ifdef __cplusplus
extern "C" {
#endif
/****************************************************************************
*
* DxDiag Errors
*
****************************************************************************/
#define DXDIAG_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL) // HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
/****************************************************************************
*
* DxDiag CLSIDs
*
****************************************************************************/
// {A65B8071-3BFE-4213-9A5B-491DA4461CA7}
DEFINE_GUID(CLSID_DxDiagProvider,
0xA65B8071, 0x3BFE, 0x4213, 0x9A, 0x5B, 0x49, 0x1D, 0xA4, 0x46, 0x1C, 0xA7);
/****************************************************************************
*
* DxDiag Interface IIDs
*
****************************************************************************/
// {9C6B4CB0-23F8-49CC-A3ED-45A55000A6D2}
DEFINE_GUID(IID_IDxDiagProvider,
0x9C6B4CB0, 0x23F8, 0x49CC, 0xA3, 0xED, 0x45, 0xA5, 0x50, 0x00, 0xA6, 0xD2);
// {0x7D0F462F-0x4064-0x4862-BC7F-933E5058C10F}
DEFINE_GUID(IID_IDxDiagContainer,
0x7D0F462F, 0x4064, 0x4862, 0xBC, 0x7F, 0x93, 0x3E, 0x50, 0x58, 0xC1, 0x0F);
/****************************************************************************
*
* DxDiag Interface Pointer definitions
*
****************************************************************************/
typedef struct IDxDiagProvider *LPDXDIAGPROVIDER, *PDXDIAGPROVIDER;
typedef struct IDxDiagContainer *LPDXDIAGCONTAINER, *PDXDIAGCONTAINER;
/****************************************************************************
*
* DxDiag Structures
*
****************************************************************************/
typedef struct _DXDIAG_INIT_PARAMS
{
DWORD dwSize; // Size of this structure.
DWORD dwDxDiagHeaderVersion; // Pass in DXDIAG_DX9_SDK_VERSION. This verifies
// the header and dll are correctly matched.
BOOL bAllowWHQLChecks; // If true, allow dxdiag to check if drivers are
// digital signed as logo'd by WHQL which may
// connect via internet to update WHQL certificates.
VOID* pReserved; // Reserved. Must be NULL.
} DXDIAG_INIT_PARAMS;
/****************************************************************************
*
* DxDiag Application Interfaces
*
****************************************************************************/
//
// COM definition for IDxDiagProvider
//
#undef INTERFACE // External COM Implementation
#define INTERFACE IDxDiagProvider
DECLARE_INTERFACE_(IDxDiagProvider,IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID *ppvObj) PURE;
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
STDMETHOD_(ULONG,Release) (THIS) PURE;
/*** IDxDiagProvider methods ***/
STDMETHOD(Initialize) (THIS_ DXDIAG_INIT_PARAMS* pParams) PURE;
STDMETHOD(GetRootContainer) (THIS_ IDxDiagContainer **ppInstance) PURE;
};
//
// COM definition for IDxDiagContainer
//
#undef INTERFACE // External COM Implementation
#define INTERFACE IDxDiagContainer
DECLARE_INTERFACE_(IDxDiagContainer,IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID *ppvObj) PURE;
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
STDMETHOD_(ULONG,Release) (THIS) PURE;
/*** IDxDiagContainer methods ***/
STDMETHOD(GetNumberOfChildContainers) (THIS_ DWORD *pdwCount) PURE;
STDMETHOD(EnumChildContainerNames) (THIS_ DWORD dwIndex, LPWSTR pwszContainer, DWORD cchContainer) PURE;
STDMETHOD(GetChildContainer) (THIS_ LPCWSTR pwszContainer, IDxDiagContainer **ppInstance) PURE;
STDMETHOD(GetNumberOfProps) (THIS_ DWORD *pdwCount) PURE;
STDMETHOD(EnumPropNames) (THIS_ DWORD dwIndex, LPWSTR pwszPropName, DWORD cchPropName) PURE;
STDMETHOD(GetProp) (THIS_ LPCWSTR pwszPropName, VARIANT *pvarProp) PURE;
};
/****************************************************************************
*
* DxDiag application interface macros
*
****************************************************************************/
#if !defined(__cplusplus) || defined(CINTERFACE)
#define IDxDiagProvider_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
#define IDxDiagProvider_AddRef(p) (p)->lpVtbl->AddRef(p)
#define IDxDiagProvider_Release(p) (p)->lpVtbl->Release(p)
#define IDxDiagProvider_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
#define IDxDiagProvider_GetRootContainer(p,a) (p)->lpVtbl->GetRootContainer(p,a)
#define IDxDiagContainer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
#define IDxDiagContainer_AddRef(p) (p)->lpVtbl->AddRef(p)
#define IDxDiagContainer_Release(p) (p)->lpVtbl->Release(p)
#define IDxDiagContainer_GetNumberOfChildContainers(p,a) (p)->lpVtbl->GetNumberOfChildContainers(p,a)
#define IDxDiagContainer_EnumChildContainerNames(p,a,b,c) (p)->lpVtbl->EnumChildContainerNames(p,a,b,c)
#define IDxDiagContainer_GetChildContainer(p,a,b) (p)->lpVtbl->GetChildContainer(p,a,b)
#define IDxDiagContainer_GetNumberOfProps(p,a) (p)->lpVtbl->GetNumberOfProps(p,a)
#define IDxDiagContainer_EnumProps(p,a,b) (p)->lpVtbl->EnumProps(p,a,b,c)
#define IDxDiagContainer_GetProp(p,a,b) (p)->lpVtbl->GetProp(p,a,b)
#else /* C++ */
#define IDxDiagProvider_QueryInterface(p,a,b) (p)->QueryInterface(p,a,b)
#define IDxDiagProvider_AddRef(p) (p)->AddRef(p)
#define IDxDiagProvider_Release(p) (p)->Release(p)
#define IDxDiagProvider_Initialize(p,a,b) (p)->Initialize(p,a,b)
#define IDxDiagProvider_GetRootContainer(p,a) (p)->GetRootContainer(p,a)
#define IDxDiagContainer_QueryInterface(p,a,b) (p)->QueryInterface(p,a,b)
#define IDxDiagContainer_AddRef(p) (p)->AddRef(p)
#define IDxDiagContainer_Release(p) (p)->Release(p)
#define IDxDiagContainer_GetNumberOfChildContainers(p,a) (p)->GetNumberOfChildContainers(p,a)
#define IDxDiagContainer_EnumChildContainerNames(p,a,b,c) (p)->EnumChildContainerNames(p,a,b,c)
#define IDxDiagContainer_GetChildContainer(p,a,b) (p)->GetChildContainer(p,a,b)
#define IDxDiagContainer_GetNumberOfProps(p,a) (p)->GetNumberOfProps(p,a)
#define IDxDiagContainer_EnumProps(p,a,b) (p)->EnumProps(p,a,b,c)
#define IDxDiagContainer_GetProp(p,a,b) (p)->GetProp(p,a,b)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _DXDIAG_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,896 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: FrameProfileSystem.cpp
// Version: v1.00
// Created: 24/6/2003 by Timur,Sergey,Wouter.
// Compilers: Visual Studio.NET
// Description:
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "FrameProfileSystem.h"
#include <ILog.h>
#include <IRenderer.h>
#include <IInput.h>
#include <StlUtils.h>
#if defined(LINUX)
#include "platform.h"
#endif
bool g_bProfilerEnabled = false;
#ifdef USE_FRAME_PROFILER
#define MAX_SMOOTH_FRAMES 40
#define MAX_PEAK_PROFILERS 20
//! Peak tolerance in milliseconds.
#define PEAK_TOLERANCE 10.0f
//////////////////////////////////////////////////////////////////////////
// CFrameProfilerTimer static variable.
//////////////////////////////////////////////////////////////////////////
int64 CFrameProfilerTimer::g_nTicksPerSecond = 1000000000;
double CFrameProfilerTimer::g_fSecondsPerTick = 1e-9;
double CFrameProfilerTimer::g_fMilliSecondsPerTick = 1e-6;
unsigned CFrameProfilerTimer::g_nCPUHerz = 1000000000;
//////////////////////////////////////////////////////////////////////////
// CFrameProfilerTimer implementation.
//////////////////////////////////////////////////////////////////////////
void CFrameProfilerTimer::Init() // called once
{
#ifdef WIN32
QueryPerformanceFrequency ((LARGE_INTEGER*)&g_nTicksPerSecond);
#endif //WIN32
#ifdef GAMECUBE
g_nTicksPerSecond = OS_CORE_CLOCK; //its a simple define on GC: 486.000.000
g_nCPUHerz = OS_CORE_CLOCK;
#endif
g_fSecondsPerTick = 1.0 / (double)g_nTicksPerSecond;
g_fMilliSecondsPerTick = 1000.0 / (double)g_nTicksPerSecond;
#ifdef WIN32
HKEY hKey;
DWORD dwSize = sizeof(g_nCPUHerz);
if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey)
&&ERROR_SUCCESS == RegQueryValueEx (hKey, "~MHz", NULL, NULL, (LPBYTE)&g_nCPUHerz, &dwSize))
{
g_nCPUHerz *= 1000000;
g_fSecondsPerTick = 1.0/(double)g_nCPUHerz;
g_fMilliSecondsPerTick = 1000.0/(double)g_nCPUHerz;
}
else
g_nCPUHerz = 1000000000;
#endif //WIN32
#ifdef _XBOX
//@FIXME: Hack for XBOX
g_nCPUHerz = 800*1000*1000; // 800 Mhz
g_fSecondsPerTick = 1.0/(double)g_nCPUHerz;
g_fMilliSecondsPerTick = 1000.0/(double)g_nCPUHerz;
#endif //XBOX
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfilerTimer::GetTicks(int64* pnTime)
{
#if defined(LINUX)
*pnTime = ::GetTicks();
#else
#ifdef WIN64
*pnTime = __rdtsc();
#elif defined(_CPU_X86)
__asm {
mov ebx, pnTime
rdtsc
mov [ebx], eax
mov [ebx+4], edx
}
#elif defined(GAMECUBE)
//#error Please provide a precise value or zero for pnTime
//I know it looks strange, but this are the cycles!
pnTime = (s64*)(OSGetTime()*12);
#elif defined(WIN32)
QueryPerformanceCounter((LARGE_INTEGER*)pnTime);
#endif
#endif
}
//////////////////////////////////////////////////////////////////////////
float CFrameProfilerTimer::TicksToSeconds (int64 nTime)
{
return float(g_fSecondsPerTick * nTime);
}
//////////////////////////////////////////////////////////////////////////
float CFrameProfilerTimer::TicksToMilliseconds (int64 nTime)
{
return float(g_fMilliSecondsPerTick * nTime);
}
//////////////////////////////////////////////////////////////////////////
// FrameProfilerSystem Implementation.
//////////////////////////////////////////////////////////////////////////
// these functions will let you use both string or const char* in the maps TraceMap and SampleMap just by switching
inline const char* toCStr(const char* p){ return p;}
inline const char* toCStr (const string& str){ return str.c_str();}
//////////////////////////////////////////////////////////////////////////
CFrameProfileSystem::CFrameProfileSystem()
: m_nCurSample(-1)
{
#ifdef WIN32
hPsapiModule = NULL;
pfGetProcessMemoryInfo = NULL;
m_bNoPsapiDll = false;
#endif
// Allocate space for 256 profilers.
m_profilers.reserve( 256 );
m_pCurrentProfileSection = 0;
m_pCurrentCustomSection = 0;
m_bEnabled = false;
m_totalProfileTime = 0;
m_frameStartTime = 0;
m_frameTime = 0;
m_frameLostTime = 0;
m_pRenderer = 0;
m_displayQuantity = SELF_TIME;
m_bCollect = false;
m_bDisplay = false;
m_bDisplayMemoryInfo = false;
m_bLogMemoryInfo = false;
m_smoothFrame = 0;
m_smoothMaxFrames = MAX_SMOOTH_FRAMES;
m_peakTolerance = PEAK_TOLERANCE;
m_pGraphProfiler = 0;
m_timeGraphCurrentPos = 0;
m_bCollectionPaused = false;
m_bDrawGraph = false;
m_selectedRow = -1;
m_selectedCol = -1;
m_bEnableHistograms = false;
m_histogramsMaxPos = 200;
m_histogramsHeight = 16;
m_histogramsCurrPos = 0;
m_bSubsystemFilterEnabled = false;
m_subsystemFilter = PROFILE_RENDERER;
m_histogramScale = 100;
m_bDisplayedProfilersValid = false;
m_bNetworkProfiling = false;
//m_pProfilers = &m_netTrafficProfilers;
m_pProfilers = &m_profilers;
m_nLastPageFaultCount = 0;
m_nPagesFaultsLastFrame = 0;
m_bPageFaultsGraph = false;
m_nPagesFaultsPerSec = 0;
//////////////////////////////////////////////////////////////////////////
// Initialize subsystems list.
memset( m_subsystems,0,sizeof(m_subsystems) );
m_subsystems[PROFILE_RENDERER].name = "Renderer";
m_subsystems[PROFILE_3DENGINE].name = "3DEngine";
m_subsystems[PROFILE_ANIMATION].name = "Animation";
m_subsystems[PROFILE_AI].name = "AI";
m_subsystems[PROFILE_ENTITY].name = "Entity";
m_subsystems[PROFILE_PHYSICS].name = "Physics";
m_subsystems[PROFILE_SOUND].name = "Sound";
m_subsystems[PROFILE_GAME].name = "Game";
m_subsystems[PROFILE_EDITOR].name = "Editor";
m_subsystems[PROFILE_NETWORK].name = "Network";
m_subsystems[PROFILE_SYSTEM].name = "System";
};
//////////////////////////////////////////////////////////////////////////
CFrameProfileSystem::~CFrameProfileSystem()
{
// Delete graphs for all frame profilers.
#ifdef WIN32
if (hPsapiModule)
::FreeLibrary( hPsapiModule );
#endif
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::Init( ISystem *pSystem )
{
m_pSystem = pSystem;
CFrameProfilerTimer::Init();
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::Done()
{
for (int i = 0; i < (int)m_profilers.size(); i++)
{
SAFE_DELETE( m_profilers[i]->m_pGraph );
SAFE_DELETE( m_profilers[i]->m_pOfflineHistory );
}
for (int i = 0; i < (int)m_netTrafficProfilers.size(); i++)
{
SAFE_DELETE( m_netTrafficProfilers[i]->m_pGraph );
SAFE_DELETE( m_netTrafficProfilers[i]->m_pOfflineHistory );
}
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::SetProfiling(bool on, bool display, char *prefix, ISystem *pSystem)
{
Enable( on,display );
m_pPrefix = prefix;
if(on && m_nCurSample<0)
{
m_nCurSample = 0;
pSystem->GetILog()->Log("\001Profiling data started (%s), prefix = \"%s\"", display ? "display only" : "tracing", prefix);
m_frameTimeOfflineHistory.m_selfTime.reserve(1000);
m_frameTimeOfflineHistory.m_count.reserve(1000);
}
else if(!on && m_nCurSample>=0)
{
pSystem->GetILog()->Log("\001Profiling data finished");
{
#ifdef WIN32
// find the "frameprofileXX" filename for the file
char outfilename[32] = "frameprofile.dat";
// while there is such file already
for (int i = 0; (GetFileAttributes (outfilename) != INVALID_FILE_ATTRIBUTES) && i < 1000; ++i)
sprintf (outfilename, "frameprofile%02d.dat", i);
FILE *f = fopen(outfilename, "wb");
if(!f)
{
pSystem->GetILog()->Log("\001Could not write profiling data to file!");
}
else
{
int i;
// Find out how many profilers was active.
int numProf = 0;
for (i = 0; i < (int)m_pProfilers->size(); i++)
{
CFrameProfiler *pProfiler = (*m_pProfilers)[i];
if (pProfiler->m_pOfflineHistory)
numProf++;
}
fwrite("FPROFDAT", 8, 1, f); // magic header, for what its worth
int version = 2; // bump this if any of the format below changes
fwrite(&version, sizeof(int), 1, f);
int numSamples = m_nCurSample;
fwrite(&numSamples, sizeof(int), 1, f); // number of samples per group (everything little endian)
int mapsize = numProf+1; // Plus 1 global.
fwrite(&mapsize, sizeof(int), 1, f);
// Write global profiler.
fwrite( "__frametime",strlen("__frametime")+1,1, f);
int len = (int)m_frameTimeOfflineHistory.m_selfTime.size();
assert( len == numSamples );
for(i = 0; i<len; i++)
{
fwrite( &m_frameTimeOfflineHistory.m_selfTime[i], 1, sizeof(int), f);
fwrite( &m_frameTimeOfflineHistory.m_count[i], 1, sizeof(short), f);
};
// Write other profilers.
for (i = 0; i < (int)m_pProfilers->size(); i++)
{
CFrameProfiler *pProfiler = (*m_pProfilers)[i];
if (!pProfiler->m_pOfflineHistory)
continue;
const char *name = pProfiler->m_name;
//int slen = strlen(name)+1;
fwrite(name, strlen(name)+1,1,f);
len = (int)pProfiler->m_pOfflineHistory->m_selfTime.size();
assert( len == numSamples );
for(int i = 0; i<len; i++)
{
fwrite( &pProfiler->m_pOfflineHistory->m_selfTime[i], 1, sizeof(int), f);
fwrite( &pProfiler->m_pOfflineHistory->m_count[i], 1, sizeof(short), f);
};
// Delete offline data, from profiler.
SAFE_DELETE( pProfiler->m_pOfflineHistory );
};
fclose(f);
pSystem->GetILog()->Log("\001Profiling data saved to file '%s'",outfilename);
};
#endif
};
m_frameTimeOfflineHistory.m_selfTime.clear();
m_frameTimeOfflineHistory.m_count.clear();
m_nCurSample = -1;
};
};
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::Enable( bool bCollect,bool bDisplay )
{
if (m_bEnabled != bCollect)
{
Reset();
}
m_bEnabled = bCollect;
m_bDisplay = bDisplay;
m_bDisplayedProfilersValid = false;
}
void CFrameProfileSystem::EnableHistograms( bool bEnableHistograms )
{
if (m_bEnableHistograms != bEnableHistograms)
{
}
m_bEnableHistograms = bEnableHistograms;
m_bDisplayedProfilersValid = false;
}
//////////////////////////////////////////////////////////////////////////
CFrameProfiler* CFrameProfileSystem::GetProfiler( int index ) const
{
assert( index >= 0 && index < (int)m_profilers.size() );
return m_profilers[index];
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::Reset()
{
m_pCurrentProfileSection = 0;
m_pCurrentCustomSection = 0;
m_totalProfileTime = 0;
m_frameStartTime = 0;
m_frameTime = 0;
m_frameLostTime = 0;
m_smoothFrame = 0;
m_bCollectionPaused = false;
int i;
// Iterate over all profilers update thier history and reset them.
for (i = 0; i < (int)m_profilers.size(); i++)
{
CFrameProfiler *pProfiler = m_profilers[i];
// Reset profiler.
pProfiler->m_totalTimeHistory.Clear();
pProfiler->m_selfTimeHistory.Clear();
pProfiler->m_countHistory.Clear();
pProfiler->m_sumTotalTime = 0;
pProfiler->m_sumSelfTime = 0;
pProfiler->m_totalTime = 0;
pProfiler->m_selfTime = 0;
pProfiler->m_count = 0;
pProfiler->m_displayedValue = 0;
pProfiler->m_displayedCurrentValue = 0;
pProfiler->m_variance = 0;
}
// Iterate over all profilers update thier history and reset them.
for (i = 0; i < (int)m_netTrafficProfilers.size(); i++)
{
CFrameProfiler *pProfiler = m_netTrafficProfilers[i];
// Reset profiler.
pProfiler->m_totalTimeHistory.Clear();
pProfiler->m_selfTimeHistory.Clear();
pProfiler->m_countHistory.Clear();
pProfiler->m_sumTotalTime = 0;
pProfiler->m_sumSelfTime = 0;
pProfiler->m_totalTime = 0;
pProfiler->m_selfTime = 0;
pProfiler->m_count = 0;
}
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::AddFrameProfiler( CFrameProfiler *pProfiler )
{
if (pProfiler->m_subsystem == PROFILE_NETWORK_TRAFFIC)
{
m_netTrafficProfilers.push_back( pProfiler );
}
else
{
m_profilers.push_back( pProfiler );
}
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::StartProfilerSection( CFrameProfilerSection *pSection )
{
if (!m_bCollect)
return;
pSection->m_excludeTime = 0;
pSection->m_pParent = m_pCurrentProfileSection;
m_pCurrentProfileSection = pSection;
CFrameProfilerTimer::GetTicks( &pSection->m_startTime );
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::EndProfilerSection( CFrameProfilerSection *pSection )
{
if (!m_bCollect)
return;
int64 endTime;
CFrameProfilerTimer::GetTicks( &endTime );
int64 totalTime = endTime - pSection->m_startTime;
int64 selfTime = totalTime - pSection->m_excludeTime;
CFrameProfiler *pProfiler = pSection->m_pFrameProfiler;
pProfiler->m_count++;
pProfiler->m_selfTime += selfTime;
pProfiler->m_totalTime += totalTime;
m_pCurrentProfileSection = pSection->m_pParent;
if (m_pCurrentProfileSection)
{
// If we have parent, add this counter total time to parent exclude time.
m_pCurrentProfileSection->m_pFrameProfiler->m_bHaveChildren = true;
m_pCurrentProfileSection->m_excludeTime += totalTime;
pProfiler->m_pParent = m_pCurrentProfileSection->m_pFrameProfiler;
}
else
pProfiler->m_pParent = 0;
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::StartCustomSection( CCustomProfilerSection *pSection )
{
if (!m_bNetworkProfiling)
return;
pSection->m_excludeValue = 0;
pSection->m_pParent = m_pCurrentCustomSection;
m_pCurrentCustomSection = pSection;
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::EndCustomSection( CCustomProfilerSection *pSection )
{
if (!m_bNetworkProfiling || m_bCollectionPaused)
return;
int total = *pSection->m_pValue;
int self = total - pSection->m_excludeValue;
CFrameProfiler *pProfiler = pSection->m_pFrameProfiler;
pProfiler->m_count++;
pProfiler->m_selfTime += self;
pProfiler->m_totalTime += total;
m_pCurrentCustomSection = pSection->m_pParent;
if (m_pCurrentCustomSection)
{
// If we have parent, add this counter total time to parent exclude time.
m_pCurrentCustomSection->m_pFrameProfiler->m_bHaveChildren = true;
m_pCurrentCustomSection->m_excludeValue += total;
pProfiler->m_pParent = m_pCurrentCustomSection->m_pFrameProfiler;
}
else
pProfiler->m_pParent = 0;
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::StartFrame()
{
m_bCollect = m_bEnabled && !m_bCollectionPaused;
if (m_bCollect)
{
m_pCurrentProfileSection = 0;
m_pCurrentCustomSection = 0;
CFrameProfilerTimer::GetTicks(&m_frameStartTime);
}
g_bProfilerEnabled = m_bCollect;
/*
if (m_displayQuantity == SUBSYSTEM_INFO)
{
for (int i = 0; i < PROFILE_LAST_SUBSYSTEM; i++)
{
//m_subsystems[i].selfTime = 0;
}
}
*/
}
//////////////////////////////////////////////////////////////////////////
float CFrameProfileSystem::TranslateToDisplayValue( int64 val )
{
if (m_bNetworkProfiling)
return (float)val;
else
return CFrameProfilerTimer::TicksToMilliseconds(val);
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::EndFrame()
{
if (!m_bEnabled && !m_bNetworkProfiling)
return;
#ifdef WIN32
bool bPaused = false;
if (GetISystem()->GetIInput())
{
bPaused = (GetISystem()->GetIInput()->GetKeyState(XKEY_SCROLLLOCK) & 1);
}
// Will pause or resume collection.
if (bPaused != m_bCollectionPaused)
{
if (bPaused)
{
// Must be paused.
m_pSystem->GetIInput()->SetMouseExclusive( false );
}
else
{
// Must be resumed.
m_pSystem->GetIInput()->SetMouseExclusive( true );
}
}
if (m_bCollectionPaused != bPaused)
{
m_bDisplayedProfilersValid = false;
}
m_bCollectionPaused = bPaused;
#endif
if (m_bCollectionPaused || (!m_bCollect && !m_bNetworkProfiling))
return;
FUNCTION_PROFILER( m_pSystem,PROFILE_SYSTEM );
int64 endTime;
CFrameProfilerTimer::GetTicks(&endTime);
m_frameTime = endTime - m_frameStartTime;
m_totalProfileTime += m_frameTime;
//////////////////////////////////////////////////////////////////////////
// Lets see how many page faults we got.
//////////////////////////////////////////////////////////////////////////
#if defined(WIN32) && !defined(WIN64)
// PSAPI is not supported on window9x
// so, don't use it
if (!m_bNoPsapiDll)
{
// Load psapi dll.
if (!pfGetProcessMemoryInfo)
{
hPsapiModule = ::LoadLibrary( "psapi.dll" );
if (hPsapiModule)
{
pfGetProcessMemoryInfo = (FUNC_GetProcessMemoryInfo)(::GetProcAddress(hPsapiModule,"GetProcessMemoryInfo" ));
}
else
m_bNoPsapiDll = true;
}
if (pfGetProcessMemoryInfo)
{
PROCESS_MEMORY_COUNTERS pc;
pfGetProcessMemoryInfo( GetCurrentProcess(),&pc,sizeof(pc) );
m_nPagesFaultsLastFrame = pc.PageFaultCount - m_nLastPageFaultCount;
m_nLastPageFaultCount = pc.PageFaultCount;
static float fLastPFTime = 0;
static int nPFCounter = 0;
nPFCounter += m_nPagesFaultsLastFrame;
float fCurr = CFrameProfilerTimer::TicksToMilliseconds(endTime);
if ((fCurr - fLastPFTime) >= 1000)
{
fLastPFTime = fCurr;
m_nPagesFaultsPerSec = nPFCounter;
nPFCounter = 0;
}
}
}
#endif
//////////////////////////////////////////////////////////////////////////
int64 selfAccountedTime = 0;
//float times_to_reach_90_percent = 0.8f;
float times_to_reach_90_percent = 0.8f;
if (m_displayQuantity == PEAK_TIME || m_displayQuantity == COUNT_INFO+1)
{
//m_smoothMaxFrames = 60*5;
times_to_reach_90_percent = 1.0f;
}
float dt = CFrameProfilerTimer::TicksToSeconds(m_frameTime);
float smoothFactor = (float)pow( 0.1, dt/double(times_to_reach_90_percent) );
m_frameTimeHistory.Add( CFrameProfilerTimer::TicksToMilliseconds(m_frameTime) );
m_frameTimeLostHistory.Add( CFrameProfilerTimer::TicksToMilliseconds(m_frameLostTime) );
// Iterate over all profilers update thier history and reset them.
for (int i = 0; i < (int)m_pProfilers->size(); i++)
{
CFrameProfiler *pProfiler = (*m_pProfilers)[i];
// Skip this profiler if its filtered out.
if (m_bSubsystemFilterEnabled && pProfiler->m_subsystem != m_subsystemFilter)
continue;
selfAccountedTime += pProfiler->m_selfTime;
pProfiler->m_sumTotalTime += pProfiler->m_totalTime;
pProfiler->m_sumSelfTime += pProfiler->m_selfTime;
bool bEnablePeaks = true;
float aveValue;
float currentValue;
float variance;
switch (m_displayQuantity)
{
case SELF_TIME:
case PEAK_TIME:
case COUNT_INFO:
currentValue = TranslateToDisplayValue(pProfiler->m_selfTime);
aveValue = pProfiler->m_selfTimeHistory.GetAverage();
variance = (currentValue - aveValue) * (currentValue - aveValue);
break;
case TOTAL_TIME:
currentValue = TranslateToDisplayValue(pProfiler->m_totalTime);
aveValue = pProfiler->m_totalTimeHistory.GetAverage();
variance = (currentValue - aveValue) * (currentValue - aveValue);
break;
case SELF_TIME_EXTENDED:
currentValue = TranslateToDisplayValue(pProfiler->m_selfTime);
aveValue = pProfiler->m_selfTimeHistory.GetAverage();
variance = (currentValue - aveValue) * (currentValue - aveValue);
bEnablePeaks = false;
break;
case TOTAL_TIME_EXTENDED:
currentValue = TranslateToDisplayValue(pProfiler->m_totalTime);
aveValue = pProfiler->m_totalTimeHistory.GetAverage();
variance = (currentValue - aveValue) * (currentValue - aveValue);
bEnablePeaks = false;
break;
case SUBSYSTEM_INFO:
currentValue = (float)pProfiler->m_count;
aveValue = pProfiler->m_selfTimeHistory.GetAverage();
variance = (currentValue - aveValue) * (currentValue - aveValue);
if (pProfiler->m_subsystem < PROFILE_LAST_SUBSYSTEM)
m_subsystems[pProfiler->m_subsystem].selfTime += aveValue;
break;
case COUNT_INFO+1:
// Standart Deviation.
aveValue = pProfiler->m_selfTimeHistory.GetStdDeviation();
aveValue *= 100.0f;
currentValue = aveValue;
variance = 0;
break;
};
//////////////////////////////////////////////////////////////////////////
// Records Peaks.
if (bEnablePeaks)
{
float prevValue = pProfiler->m_selfTimeHistory.GetLast();
float peakValue = TranslateToDisplayValue(pProfiler->m_selfTime);
if ((peakValue-prevValue) > m_peakTolerance)
{
SPeakRecord peak;
peak.pProfiler = pProfiler;
peak.peakValue = peakValue;
peak.avarageValue = pProfiler->m_selfTimeHistory.GetAverage();
peak.count = pProfiler->m_count;
peak.pageFaults = m_nPagesFaultsLastFrame;
peak.when = CFrameProfilerTimer::TicksToSeconds(m_totalProfileTime);
AddPeak( peak );
// Call peak callbacks.
if (!m_peakCallbacks.empty())
{
for (int i = 0; i < (int)m_peakCallbacks.size(); i++)
{
m_peakCallbacks[i]->OnFrameProfilerPeak( pProfiler,peakValue );
}
}
}
}
//////////////////////////////////////////////////////////////////////////
pProfiler->m_totalTimeHistory.Add( TranslateToDisplayValue(pProfiler->m_totalTime) );
pProfiler->m_selfTimeHistory.Add( TranslateToDisplayValue(pProfiler->m_selfTime) );
pProfiler->m_countHistory.Add( pProfiler->m_count );
pProfiler->m_displayedCurrentValue = aveValue;
//if (m_smoothFrame < m_smoothMaxFrames)
{
pProfiler->m_displayedValue = pProfiler->m_displayedValue*smoothFactor + aveValue*(1.0f - smoothFactor);
pProfiler->m_variance = pProfiler->m_variance*smoothFactor + variance*(1.0f - smoothFactor);
}
//else
{
//pProfiler->m_displayedValue = value;
//pProfiler->m_variance = variance;
}
if (m_bEnableHistograms)
{
if (!pProfiler->m_pGraph)
{
// Create graph.
pProfiler->m_pGraph = new CFrameProfilerGraph;
}
// Update values in histogram graph.
if (m_histogramsMaxPos != pProfiler->m_pGraph->m_data.size())
{
pProfiler->m_pGraph->m_width = m_histogramsMaxPos;
pProfiler->m_pGraph->m_height = m_histogramsHeight;
pProfiler->m_pGraph->m_data.resize( m_histogramsMaxPos );
}
float millis;
if (m_displayQuantity == TOTAL_TIME || m_displayQuantity == TOTAL_TIME_EXTENDED)
millis = m_histogramScale * pProfiler->m_totalTimeHistory.GetLast();
else
millis = m_histogramScale * pProfiler->m_selfTimeHistory.GetLast();
if (millis < 0) millis = 0;
if (millis > 255) millis = 255;
pProfiler->m_pGraph->m_data[m_histogramsCurrPos] = 255-FtoI(millis); // must use ftoi.
}
if (m_nCurSample >= 0)
{
UpdateOfflineHistory( pProfiler );
}
// Reset profiler.
pProfiler->m_totalTime = 0;
pProfiler->m_selfTime = 0;
pProfiler->m_count = 0;
}
if (m_smoothFrame >= m_smoothMaxFrames)
{
m_smoothFrame = 0;
}
else
{
m_smoothFrame++;
}
m_frameLostTime = m_frameTime - selfAccountedTime;
if (m_nCurSample >= 0)
{
// Keep offline global time history.
m_frameTimeOfflineHistory.m_selfTime.push_back( FtoI(CFrameProfilerTimer::TicksToMilliseconds(m_frameTime)*1000) );
m_frameTimeOfflineHistory.m_count.push_back(1);
m_nCurSample++;
}
//AdvanceFrame( m_pSystem );
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::UpdateOfflineHistory( CFrameProfiler *pProfiler )
{
if (!pProfiler->m_pOfflineHistory)
{
pProfiler->m_pOfflineHistory = new CFrameProfilerOfflineHistory;
pProfiler->m_pOfflineHistory->m_count.reserve( 1000+m_nCurSample*2 );
pProfiler->m_pOfflineHistory->m_selfTime.reserve( 1000+m_nCurSample*2 );
}
int prevCont = (int)pProfiler->m_pOfflineHistory->m_selfTime.size();
int newCount = m_nCurSample+1;
pProfiler->m_pOfflineHistory->m_selfTime.resize( newCount );
pProfiler->m_pOfflineHistory->m_count.resize( newCount );
unsigned int micros = FtoI(CFrameProfilerTimer::TicksToMilliseconds(pProfiler->m_selfTime)*1000);
unsigned short count = pProfiler->m_count;
for (int i = prevCont; i < newCount; i++)
{
pProfiler->m_pOfflineHistory->m_selfTime[i] = micros;
pProfiler->m_pOfflineHistory->m_count[i] = count;
}
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::AddPeak( SPeakRecord &peak )
{
// Add peak.
if (m_peaks.size() > MAX_PEAK_PROFILERS)
m_peaks.pop_back();
if(m_pSystem->IsDedicated())
m_pSystem->GetILog()->Log("Peak: name:'%s' val:%.2f avg:%.2f cnt:%d",peak.pProfiler->m_name,peak.peakValue,peak.avarageValue,peak.count);
/*
// Check to see if this function is already a peak.
for (int i = 0; i < (int)m_peaks.size(); i++)
{
if (m_peaks[i].pProfiler == peak.pProfiler)
{
m_peaks.erase( m_peaks.begin()+i );
break;
}
}
*/
m_peaks.insert( m_peaks.begin(),peak );
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::SetDisplayQuantity( EDisplayQuantity quantity )
{
m_displayQuantity = quantity;
m_bDisplayedProfilersValid = false;
if (m_displayQuantity == SELF_TIME_EXTENDED || m_displayQuantity == TOTAL_TIME_EXTENDED)
EnableHistograms(true);
else
EnableHistograms(false);
};
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::SetSubsystemFilter( bool bFilterSubsystem,EProfiledSubsystem subsystem )
{
m_bSubsystemFilterEnabled = bFilterSubsystem;
m_subsystemFilter = subsystem;
m_bDisplayedProfilersValid = false;
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::SetSubsystemFilter( const char *szFilterName )
{
bool bFound = false;
for (int i = 0; i < PROFILE_LAST_SUBSYSTEM; i++)
{
if (!m_subsystems[i].name)
continue;
if (stricmp(m_subsystems[i].name,szFilterName) == 0)
{
SetSubsystemFilter( true,(EProfiledSubsystem)i );
bFound = true;
break;
}
}
if (!bFound)
SetSubsystemFilter( false,PROFILE_ANY );
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::AddPeaksListener( IFrameProfilePeakCallback *pPeakCallback )
{
// Only add one time.
stl::push_back_unique( m_peakCallbacks,pPeakCallback );
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::RemovePeaksListener( IFrameProfilePeakCallback *pPeakCallback )
{
stl::find_and_erase( m_peakCallbacks,pPeakCallback );
}
//////////////////////////////////////////////////////////////////////////
void CFrameProfileSystem::EnableMemoryProfile( bool bEnable )
{
if (bEnable != m_bDisplayMemoryInfo)
m_bLogMemoryInfo = true;
m_bDisplayMemoryInfo = bEnable;
}
#endif

View File

@@ -0,0 +1,331 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: frameprofilesystem.h
// Version: v1.00
// Created: 24/6/2003 by Timur,Sergey,Wouter.
// Compilers: Visual Studio.NET
// Description:
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#ifndef __frameprofilesystem_h__
#define __frameprofilesystem_h__
#pragma once
#include "platform.h"
#include "FrameProfiler.h"
#if !defined (LINUX)
# include <Psapi.h>
#endif
#ifdef USE_FRAME_PROFILER
//////////////////////////////////////////////////////////////////////////
// Frame Profile Timer, provides precise timer for frame profiler.
//////////////////////////////////////////////////////////////////////////
class CFrameProfilerTimer
{
public:
static void Init(); // called once
static void GetTicks( int64* nTime);
static int64 GetTicks() { int64 nTime; GetTicks(&nTime); return nTime; }
static float TicksToSeconds( int64 nTime );
static float TicksToMilliseconds( int64 nTime );
protected:
static int64 g_nTicksPerSecond;
static double g_fSecondsPerTick;
static double g_fMilliSecondsPerTick;
// CPU speed, in Herz
static unsigned g_nCPUHerz;
};
//////////////////////////////////////////////////////////////////////////
//! the system which does the gathering of stats
class CFrameProfileSystem : public IFrameProfileSystem
{
public:
int m_nCurSample;
char *m_pPrefix;
bool m_bEnabled;
//! True when collection must be paused.
bool m_bCollectionPaused;
//! If set profiling data will be collected.
bool m_bCollect;
//! If set profiling data will be displayed.
bool m_bDisplay;
//! True if network profiling is enabled.
bool m_bNetworkProfiling;
//! If set memory info by modules will be displayed.
bool m_bDisplayMemoryInfo;
//! Put memory info also in the log.
bool m_bLogMemoryInfo;
ISystem *m_pSystem;
IRenderer *m_pRenderer;
struct SPeakRecord
{
CFrameProfiler *pProfiler;
float peakValue;
float avarageValue;
float variance;
int pageFaults; // Number of page faults at this frame.
int count; // Number of times called for peak.
float when; // when it added.
};
struct SProfilerDisplayInfo
{
float x,y; // Position where this profiler rendered.
int averageCount;
int level; // child level.
CFrameProfiler *pProfiler;
};
struct SSubSystemInfo
{
const char *name;
float selfTime;
};
EDisplayQuantity m_displayQuantity;
int m_smoothFrame;
int m_smoothMaxFrames;
//! When profiling frame started.
int64 m_frameStartTime;
//! Total time of profiling.
int64 m_totalProfileTime;
//! Frame time from the last frame.
int64 m_frameTime;
//! Frame time not accounted by registered profilers.
int64 m_frameLostTime;
//! Frame profiler.
CFrameProfilerSection *m_pCurrentProfileSection;
CCustomProfilerSection *m_pCurrentCustomSection;
typedef std::vector<CFrameProfiler*> Profilers;
//! Array of all registered profilers.
Profilers m_profilers;
//! Network profilers, they are not in regular list.
Profilers m_netTrafficProfilers;
//! Currently active profilers array.
Profilers *m_pProfilers;
float m_peakTolerance;
//! List of several latest peaks.
std::vector<SPeakRecord> m_peaks;
std::vector<SProfilerDisplayInfo> m_displayedProfilers;
bool m_bDisplayedProfilersValid;
EProfiledSubsystem m_subsystemFilter;
bool m_bSubsystemFilterEnabled;
//////////////////////////////////////////////////////////////////////////
//! Smooth frame time in milliseconds.
CFrameProfilerSamplesHistory<float,32> m_frameTimeHistory;
CFrameProfilerSamplesHistory<float,32> m_frameTimeLostHistory;
//////////////////////////////////////////////////////////////////////////
// Graphs.
//////////////////////////////////////////////////////////////////////////
bool m_bDrawGraph;
std::vector<unsigned char> m_timeGraph;
std::vector<unsigned char> m_timeGraph2;
int m_timeGraphCurrentPos;
CFrameProfiler* m_pGraphProfiler;
//////////////////////////////////////////////////////////////////////////
// Histograms.
//////////////////////////////////////////////////////////////////////////
bool m_bEnableHistograms;
int m_histogramsCurrPos;
int m_histogramsMaxPos;
int m_histogramsHeight;
float m_histogramScale;
//////////////////////////////////////////////////////////////////////////
// Selection/Render.
//////////////////////////////////////////////////////////////////////////
int m_selectedRow,m_selectedCol;
float ROW_SIZE,COL_SIZE;
float m_baseY;
float m_mouseX,m_mouseY;
#ifdef WIN32
HMODULE hPsapiModule;
typedef BOOL (WINAPI *FUNC_GetProcessMemoryInfo)( HANDLE,PPROCESS_MEMORY_COUNTERS,DWORD );
FUNC_GetProcessMemoryInfo pfGetProcessMemoryInfo;
bool m_bNoPsapiDll;
#endif
int m_nPagesFaultsLastFrame;
int m_nPagesFaultsPerSec;
int64 m_nLastPageFaultCount;
bool m_bPageFaultsGraph;
//////////////////////////////////////////////////////////////////////////
// Subsystems.
//////////////////////////////////////////////////////////////////////////
SSubSystemInfo m_subsystems[PROFILE_LAST_SUBSYSTEM];
CFrameProfilerOfflineHistory m_frameTimeOfflineHistory;
//////////////////////////////////////////////////////////////////////////
// Peak callbacks.
//////////////////////////////////////////////////////////////////////////
std::vector<IFrameProfilePeakCallback*> m_peakCallbacks;
public:
//////////////////////////////////////////////////////////////////////////
// Methods.
//////////////////////////////////////////////////////////////////////////
CFrameProfileSystem();
~CFrameProfileSystem();
void Init( ISystem *pSystem );
void Done();
void SetProfiling(bool on, bool display, char *prefix, ISystem *pSystem);
//////////////////////////////////////////////////////////////////////////
// IFrameProfileSystem interface implementation.
//////////////////////////////////////////////////////////////////////////
//! Reset all profiling data.
void Reset();
//! Add new frame profiler.
//! Profile System will not delete those pointers, client must take care of memory managment issues.
void AddFrameProfiler( CFrameProfiler *pProfiler );
//! Must be called at the start of the frame.
void StartFrame();
//! Must be called at the end of the frame.
void EndFrame();
//! Get number of registered frame profilers.
int GetProfilerCount() const { return (int)m_profilers.size(); };
//! Get frame profiler at specified index.
//! @param index must be 0 <= index < GetProfileCount()
CFrameProfiler* GetProfiler( int index ) const;
//////////////////////////////////////////////////////////////////////////
// Adds a value to profiler.
virtual void StartCustomSection( CCustomProfilerSection *pSection );
virtual void EndCustomSection( CCustomProfilerSection *pSection );
//////////////////////////////////////////////////////////////////////////
// Peak callbacks.
//////////////////////////////////////////////////////////////////////////
virtual void AddPeaksListener( IFrameProfilePeakCallback *pPeakCallback );
virtual void RemovePeaksListener( IFrameProfilePeakCallback *pPeakCallback );
//////////////////////////////////////////////////////////////////////////
//! Starts profiling a new section.
void StartProfilerSection( CFrameProfilerSection *pSection );
//! Ends profiling a section.
void EndProfilerSection( CFrameProfilerSection *pSection );
//! Enable/Diable profile samples gathering.
void Enable( bool bCollect,bool bDisplay );
void EnableMemoryProfile( bool bEnable );
void SetSubsystemFilter( bool bFilterSubsystem,EProfiledSubsystem subsystem );
void EnableHistograms( bool bEnableHistograms );
bool IsEnabled() const { return m_bEnabled; };
bool IsProfiling() const { return m_bCollect; }
void SetDisplayQuantity( EDisplayQuantity quantity );
void AddPeak( SPeakRecord &peak );
void SetHistogramScale( float fScale ) { m_histogramScale = fScale; }
void SetDrawGraph( bool bDrawGraph ) { m_bDrawGraph = bDrawGraph; };
void SetNetworkProfiler( bool bNet ) { m_bNetworkProfiling = bNet; };
void SetPeakTolerance( float fPeakTimeMillis ) { m_peakTolerance = fPeakTimeMillis; }
void SetPageFaultsGraph( bool bEnabled ) { m_bPageFaultsGraph = bEnabled; };
void SetSubsystemFilter( const char *sFilterName );
void UpdateOfflineHistory( CFrameProfiler *pProfiler );
//////////////////////////////////////////////////////////////////////////
// Rendering.
//////////////////////////////////////////////////////////////////////////
void Render();
void RenderMemoryInfo();
void RenderProfiler( CFrameProfiler *pProfiler,int level,float col,float row,bool bExtended,bool bSelected );
void RenderProfilerHeader( float col,float row,bool bExtended );
void RenderProfilers( float col,float row,bool bExtended );
void RenderPeaks();
void RenderSubSystems( float col,float row );
void RenderHistograms();
void CalcDisplayedProfilers();
void DrawGraph();
void DrawLabel( float raw,float column, float* fColor,float glow,const char* szText,float fScale=1.0f);
void DrawRect( float x1,float y1,float x2,float y2,float *fColor );
CFrameProfiler* GetSelectedProfiler();
// Recursively add frame profiler and childs to displayed list.
void AddDisplayedProfiler( CFrameProfiler *pProfiler,int level );
//////////////////////////////////////////////////////////////////////////
float TranslateToDisplayValue( int64 val );
};
#else
// Dummy Frame profile Timer interface.
class CFrameProfilerTimer
{
public:
static float TicksToSeconds( int64 nTime ){return 0.0f;}
};
// Dummy Frame profile system interface.
struct CFrameProfileSystem : public IFrameProfileSystem
{
//! Reset all profiling data.
virtual void Reset() {};
//! Add new frame profiler.
//! Profile System will not delete those pointers, client must take care of memory managment issues.
virtual void AddFrameProfiler( class CFrameProfiler *pProfiler ) {};
//! Must be called at the start of the frame.
virtual void StartFrame() {};
//! Must be called at the end of the frame.
virtual void EndFrame() {};
//! Here the new methods needed to enable profiling to go off.
virtual int GetProfilerCount() const {return 0;}
virtual CFrameProfiler* GetProfiler( int index ) const {return NULL;}
virtual void Enable( bool bCollect,bool bDisplay ){}
virtual void SetSubsystemFilter( bool bFilterSubsystem,EProfiledSubsystem subsystem ){}
virtual void SetSubsystemFilter( const char *sFilterName ){}
virtual bool IsEnabled() const {return 0;}
virtual bool IsProfiling() const {return 0;}
virtual void SetDisplayQuantity( EDisplayQuantity quantity ){}
virtual void StartCustomSection( CCustomProfilerSection *pSection ){}
virtual void EndCustomSection( CCustomProfilerSection *pSection ){}
virtual void AddPeaksListener( IFrameProfilePeakCallback *pPeakCallback ){}
virtual void RemovePeaksListener( IFrameProfilePeakCallback *pPeakCallback ){}
void Init( ISystem *pSystem ){}
void Done(){}
void Render(){}
void SetHistogramScale( float fScale ){}
void SetDrawGraph( bool bDrawGraph ){}
void SetNetworkProfiler( bool bNet ){}
void SetPeakTolerance( float fPeakTimeMillis ){}
void SetPageFaultsGraph( bool bEnabled ){}
void EnableMemoryProfile( bool bEnable ){}
};
#endif // USE_FRAME_PROFILER
#endif // __frameprofilesystem_h__

View File

@@ -0,0 +1,353 @@
#include "stdafx.h"
#include "HTTPDownloader.h"
#include "DownloadManager.h"
#include <ILog.h>
//#ifndef LINUX
_DECLARE_SCRIPTABLEEX(CHTTPDownloader)
//-------------------------------------------------------------------------------------------------
CHTTPDownloader::CHTTPDownloader()
#if defined(LINUX)
: m_hThread(INVALID_HANDLE_VALUE),
#else
: m_hThread(NULL),
#endif
m_hINET(0),
m_hUrl(0),
m_iFileSize(0),
m_pBuffer(0),
m_iState(HTTP_STATE_NONE),
m_pSystem(0),
m_pParent(0)
{
}
//-------------------------------------------------------------------------------------------------
CHTTPDownloader::~CHTTPDownloader()
{
}
//-------------------------------------------------------------------------------------------------
void CHTTPDownloader::InitializeTemplate(IScriptSystem *pSS)
{
_ScriptableEx<CHTTPDownloader>::InitializeTemplate(pSS);
REG_FUNC(CHTTPDownloader, Download);
REG_FUNC(CHTTPDownloader, Cancel);
REG_FUNC(CHTTPDownloader, Release);
REG_FUNC(CHTTPDownloader, GetURL);
REG_FUNC(CHTTPDownloader, GetFileName);
REG_FUNC(CHTTPDownloader, GetFileSize);
}
//-------------------------------------------------------------------------------------------------
int CHTTPDownloader::Create(ISystem *pISystem, CDownloadManager *pParent)
{
m_pSystem = pISystem;
m_pParent = pParent;
Init(m_pSystem->GetIScriptSystem(), this);
return 1;
}
//-------------------------------------------------------------------------------------------------
int CHTTPDownloader::Download(const char *szURL, const char *szDestination)
{
m_szURL = szURL;
m_szDstFile = szDestination;
m_bContinue = 1;
CreateThread();
return 1;
}
//-------------------------------------------------------------------------------------------------
void CHTTPDownloader::Cancel()
{
m_bContinue = 0;
}
//-------------------------------------------------------------------------------------------------
DWORD CHTTPDownloader::DownloadProc(CHTTPDownloader *_this)
{
_this->DoDownload();
return 0;
}
//-------------------------------------------------------------------------------------------------
void CHTTPDownloader::CreateThread()
{
DWORD dwThreadId = 0;
m_hThread = ::CreateThread(0, 0, (LPTHREAD_START_ROUTINE)DownloadProc, this, 0, &dwThreadId);
}
//-------------------------------------------------------------------------------------------------
DWORD CHTTPDownloader::DoDownload()
{
m_iState = HTTP_STATE_WORKING;
m_hINET = InternetOpen("", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0);
if (!m_hINET)
{
m_iState = HTTP_STATE_ERROR;
return 1;
}
if (!m_bContinue)
{
m_iState = HTTP_STATE_CANCELED;
return 1;
}
DWORD dwFlags = INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI | INTERNET_FLAG_RELOAD;
m_hUrl = InternetOpenUrl(m_hINET, m_szURL.c_str(), 0, 0, dwFlags, 0);
if (!m_hUrl)
{
m_iState = HTTP_STATE_ERROR;
return 1;
}
if (!m_bContinue)
{
m_iState = HTTP_STATE_CANCELED;
return 1;
}
char szBuffer[64] = {0};
DWORD dwSize = 64;
int bQuery = HttpQueryInfo(m_hUrl, HTTP_QUERY_CONTENT_LENGTH, szBuffer, &dwSize, 0);
if (bQuery)
{
m_iFileSize = atoi(szBuffer);
}
else
{
m_iFileSize = -1;
}
if (!m_bContinue)
{
m_iState = HTTP_STATE_CANCELED;
return 1;
}
PrepareBuffer();
FILE *hFile = fopen(m_szDstFile.c_str(), "wb");
if (!hFile)
{
m_iState = HTTP_STATE_ERROR;
return 1;
}
DWORD dwRead = 0;
while (InternetReadFile(m_hUrl, m_pBuffer, HTTP_BUFFER_SIZE, &dwRead))
{
if (dwRead)
{
fwrite(m_pBuffer, 1, dwRead, hFile);
}
else
{
fclose(hFile);
m_iState = HTTP_STATE_COMPLETE;
return 1;
}
if (!m_bContinue)
{
fclose(hFile);
m_iState = HTTP_STATE_CANCELED;
return 1;
}
Sleep(5);
}
fclose(hFile);
m_iState = HTTP_STATE_ERROR;
return 1;
}
//-------------------------------------------------------------------------------------------------
void CHTTPDownloader::PrepareBuffer()
{
if (!m_pBuffer)
{
m_pBuffer = new unsigned char[HTTP_BUFFER_SIZE];
}
}
//-------------------------------------------------------------------------------------------------
void CHTTPDownloader::Release()
{
m_bContinue = 0;
if (m_hUrl)
{
InternetCloseHandle(m_hUrl);
}
if (m_hINET)
{
InternetSetStatusCallback(m_hINET, 0);
InternetCloseHandle(m_hINET);
}
if (m_pBuffer)
{
delete[] m_pBuffer;
m_pBuffer = 0;
}
m_hINET = 0;
m_hUrl = 0;
m_iFileSize = 0;
m_szURL.clear();
m_szDstFile.clear();
WaitForSingleObject(m_hThread, 5); // wait five milliseconds for the thread to finish
CloseHandle(m_hThread);
m_hThread = 0;
m_pParent->RemoveDownload(this);
delete this;
}
//-------------------------------------------------------------------------------------------------
void CHTTPDownloader::OnError()
{
m_pSystem->GetILog()->Log("\004 DOWNLOAD ERROR: %s", CHTTPDownloader::GetURL().c_str());
IScriptObject *pScriptObject = GetScriptObject();
HSCRIPTFUNCTION pScriptFunction = 0;
if (!pScriptObject->GetValue("OnError", pScriptFunction))
{
return;
}
m_pScriptSystem->BeginCall(pScriptFunction);
m_pScriptSystem->PushFuncParam(pScriptObject);
m_pScriptSystem->EndCall();
}
//-------------------------------------------------------------------------------------------------
void CHTTPDownloader::OnComplete()
{
m_pSystem->GetILog()->Log("\004 DOWNLOAD COMPLETE: %s", CHTTPDownloader::GetURL().c_str());
IScriptObject *pScriptObject = GetScriptObject();
HSCRIPTFUNCTION pScriptFunction = 0;
if (!pScriptObject->GetValue("OnComplete", pScriptFunction))
{
return;
}
m_pScriptSystem->BeginCall(pScriptFunction);
m_pScriptSystem->PushFuncParam(pScriptObject);
m_pScriptSystem->EndCall();
}
//-------------------------------------------------------------------------------------------------
void CHTTPDownloader::OnCancel()
{
m_pSystem->GetILog()->Log("\004 DOWNLOAD CANCELED: %s", CHTTPDownloader::GetURL().c_str());
IScriptObject *pScriptObject = GetScriptObject();
HSCRIPTFUNCTION pScriptFunction = 0;
if (!pScriptObject->GetValue("OnCancel", pScriptFunction))
{
return;
}
m_pScriptSystem->BeginCall(pScriptFunction);
m_pScriptSystem->PushFuncParam(pScriptObject);
m_pScriptSystem->EndCall();
}
//-------------------------------------------------------------------------------------------------
// Script Functions
//-------------------------------------------------------------------------------------------------
int CHTTPDownloader::Download(IFunctionHandler *pH)
{
CHECK_PARAMETERS(2);
char *szURL = 0;
char *szFileName = 0;
pH->GetParam(1, szURL);
pH->GetParam(2, szFileName);
if (szURL && szFileName)
{
CHTTPDownloader::Download(szURL, szFileName);
}
return pH->EndFunction();
}
//-------------------------------------------------------------------------------------------------
int CHTTPDownloader::Cancel(IFunctionHandler *pH)
{
CHTTPDownloader::Cancel();
return pH->EndFunction();
}
//-------------------------------------------------------------------------------------------------
int CHTTPDownloader::Release(IFunctionHandler *pH)
{
CHTTPDownloader::Release();
return pH->EndFunction();
}
//-------------------------------------------------------------------------------------------------
int CHTTPDownloader::GetURL(IFunctionHandler *pH)
{
return pH->EndFunction(CHTTPDownloader::GetURL().c_str());
}
//-------------------------------------------------------------------------------------------------
int CHTTPDownloader::GetFileSize(IFunctionHandler *pH)
{
return pH->EndFunction(CHTTPDownloader::GetFileSize());
}
//-------------------------------------------------------------------------------------------------
int CHTTPDownloader::GetFileName(IFunctionHandler *pH)
{
return pH->EndFunction(CHTTPDownloader::GetDstFileName().c_str());
}
//#endif //LINUX

View File

@@ -0,0 +1,83 @@
#pragma once
#if !defined(LINUX)
#include <wininet.h>
#include <dbghelp.h>
#endif
#include <IScriptSystem.h>
#include <_ScriptableEx.h>
#define HTTP_BUFFER_SIZE (16384)
enum
{
HTTP_STATE_WORKING = 0,
HTTP_STATE_COMPLETE,
HTTP_STATE_CANCELED,
HTTP_STATE_ERROR,
HTTP_STATE_NONE,
};
class CDownloadManager;
class CHTTPDownloader:
public _ScriptableEx<CHTTPDownloader>
{
public:
CHTTPDownloader();
virtual ~CHTTPDownloader();
static
void InitializeTemplate(IScriptSystem *pSS);
int Create(ISystem *pISystem, CDownloadManager *pParent);
int Download(const char *szURL, const char *szDestination);
void Cancel();
int GetState() { return m_iState; };
int GetFileSize() const { return m_iFileSize; };
const string& GetURL() const { return m_szURL; };
const string& GetDstFileName() const { return m_szDstFile; };
void Release();
int Download(IFunctionHandler *pH);
int Cancel(IFunctionHandler *pH);
int Release(IFunctionHandler *pH);
int GetURL(IFunctionHandler *pH);
int GetFileSize(IFunctionHandler *pH);
int GetFileName(IFunctionHandler *pH);
void OnError();
void OnComplete();
void OnCancel();
private:
static
DWORD DownloadProc(CHTTPDownloader *_this);
void CreateThread();
DWORD DoDownload();
void PrepareBuffer();
string m_szURL;
string m_szDstFile;
THREAD_HANDLE m_hThread;
HINTERNET m_hINET;
HINTERNET m_hUrl;
unsigned char *m_pBuffer;
int m_iFileSize;
volatile int m_iState;
volatile bool m_bContinue;
ISystem *m_pSystem;
CDownloadManager *m_pParent;
};
//#endif //LINUX

678
CrySystem/Log.cpp Normal file
View File

@@ -0,0 +1,678 @@
//////////////////////////////////////////////////////////////////////
//
// Crytek CryENGINE Source code
//
// File:Log.cpp
// Description:Log related functions
//
// History:
// -Feb 2,2001:Created by Marco Corbetta
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "log.h"
//this should not be included here
#include <IConsole.h>
#include <ISystem.h>
#include <IStreamEngine.h>
#include "System.h"
#ifdef _WIN32
#include <time.h>
#endif
//#define RETURN return
#define RETURN
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
CLog::CLog( ISystem *pSystem )
{
memset(m_szFilename,0,MAX_FILENAME_SIZE);
memset(m_szTemp,0,MAX_TEMP_LENGTH_SIZE);
m_pSystem=pSystem;
m_pLogVerbosity = 0;
m_pLogFileVerbosity = 0;
m_pLogIncludeTime = 0;
}
//////////////////////////////////////////////////////////////////////
CLog::~CLog()
{
Done();
}
void CLog::Done()
{
//# These console vars are released when script system shutdown.
m_pLogVerbosity = 0;
m_pLogFileVerbosity = 0;
m_pLogWarningsOnly = 0;
m_pLogColoredText = 0;
m_pLogIncludeTime = 0;
}
//////////////////////////////////////////////////////////////////////////
void CLog::EnableVerbosity( bool bEnable )
{
RETURN;
if (bEnable)
{
if (!m_pLogVerbosity)
{
if (m_pSystem->GetIConsole())
{
#if defined(DEBUG) || (defined(LINUX) && !defined(NDEBUG))
m_pLogVerbosity = m_pSystem->GetIConsole()->CreateVariable("log_Verbosity","5",VF_DUMPTODISK);
#else
m_pLogVerbosity = m_pSystem->GetIConsole()->CreateVariable("log_Verbosity","3",VF_DUMPTODISK);
#endif
m_pLogFileVerbosity = m_pSystem->GetIConsole()->CreateVariable("log_FileVerbosity","3",VF_DUMPTODISK);
}
}
}
else
{
m_pLogIncludeTime = 0; // otherwise may not work in debug mode.
if (m_pSystem->GetIConsole())
{
m_pSystem->GetIConsole()->UnregisterVariable("log_Verbosity",true);
m_pSystem->GetIConsole()->UnregisterVariable("log_FileVerbosity",true);
}
m_pLogVerbosity = 0;
m_pLogFileVerbosity = 0;
}
}
//////////////////////////////////////////////////////////////////////////
void CLog::SetVerbosity( int verbosity )
{
RETURN;
EnableVerbosity(true);
if (m_pLogVerbosity)
m_pLogVerbosity->Set(verbosity);
}
//////////////////////////////////////////////////////////////////////////
void CLog::LogWarning(const char *szFormat,...)
{
va_list ArgList;
char szBuffer[MAX_WARNING_LENGTH];
va_start(ArgList, szFormat);
vsprintf(szBuffer, szFormat, ArgList);
va_end(ArgList);
m_pSystem->Warning( VALIDATOR_MODULE_SYSTEM,VALIDATOR_WARNING,0,NULL,"%s",szBuffer );
}
//////////////////////////////////////////////////////////////////////////
void CLog::LogError(const char *szFormat,...)
{
va_list ArgList;
char szBuffer[MAX_WARNING_LENGTH];
va_start(ArgList, szFormat);
vsprintf(szBuffer, szFormat, ArgList);
va_end(ArgList);
m_pSystem->Warning( VALIDATOR_MODULE_SYSTEM,VALIDATOR_ERROR,0,NULL,"%s",szBuffer );
}
//////////////////////////////////////////////////////////////////////////
void CLog::Log(const char *szFormat,...)
{
if (m_pLogVerbosity && !m_pLogVerbosity->GetIVal())
{
if (m_pLogFileVerbosity && !m_pLogFileVerbosity->GetIVal())
{
return;
}
}
RETURN;
va_list arg;
va_start(arg, szFormat);
LogV (eMessage, szFormat, arg);
va_end(arg);
}
//will log the text both to file and console
//////////////////////////////////////////////////////////////////////
void CLog::LogV( const ELogType type, const char* szFormat, va_list args )
{
RETURN;
if (!szFormat)
return;
bool bfile = false, bconsole = false;
const char* szCommand = szFormat;
if (type != eAlways && type != eWarningAlways && type != eErrorAlways && type != eInput)
{
szCommand = CheckAgainstVerbosity(szFormat, bfile, bconsole);
if (!bfile && !bconsole)
return;
}
else
{
bfile = true;
if (type == eInput)
{
const unsigned char nMaxVerbosity = 8;
int nLogFileVerbosity = m_pLogFileVerbosity ? m_pLogFileVerbosity->GetIVal() : nMaxVerbosity;
if (nLogFileVerbosity == 0)
bfile = 0;
}
bconsole = true; // console always true.
}
char szBuffer[MAX_WARNING_LENGTH+32];
char *szString = szBuffer;
switch(type)
{
case eWarningAlways:
strcpy( szString,"$6" ); // yellow color.
szString += 2;
break;
case eErrorAlways:
strcpy( szString,"$4" ); // red color.
szString += 2;
break;
case eWarning:
strcpy( szString,"[WARNING]" );
szString += strlen("[WARNING]");
break;
case eError:
strcpy( szString,"[ERROR]" );
szString += strlen("[ERROR]");
break;
}
_vsnprintf( szString, sizeof(szBuffer)-32, szCommand, args );
szBuffer[sizeof(szBuffer)-8]=0;
if (bfile)
LogStringToFile( szString );
if (bconsole)
LogStringToConsole( szString );
// in case of error - update screen and make a sound to wake up artists (in testing)
/*if(strstr(szCommand,"rror"))
{
IConsole *console=m_pSystem->GetIConsole();
IRenderer *renderer=m_pSystem->GetIRenderer();
if(console)
if(renderer)
{
console->Update();
renderer->BeginFrame();
console->Draw();
renderer->Update();
}
///MessageBeep(MB_ICONHAND);
//// Sleep(500);
} */
}
//will log the text both to the end of file and console
//////////////////////////////////////////////////////////////////////
void CLog::LogPlus(const char *szFormat,...)
{
if (m_pLogVerbosity && !m_pLogVerbosity->GetIVal())
{
if (m_pLogFileVerbosity && !m_pLogFileVerbosity->GetIVal())
{
return;
}
}
RETURN;
if (!szFormat)
return;
bool bfile = false, bconsole = false;
const char* szCommand = CheckAgainstVerbosity(szFormat, bfile, bconsole);
if (!bfile && !bconsole)
return;
va_list arglist;
va_start(arglist, szFormat);
_vsnprintf(m_szTemp, sizeof(m_szTemp), szCommand, arglist);
m_szTemp[sizeof(m_szTemp)-8]=0;
va_end(arglist);
if (bfile)
LogToFilePlus(m_szTemp);
if (bconsole)
LogToConsolePlus(m_szTemp);
}
//log to console only
//////////////////////////////////////////////////////////////////////
void CLog::LogStringToConsole( const char *szString,bool bAdd )
{
if (!szString || !szString[0])
return;
if (!m_pSystem)
return;
IConsole *console = m_pSystem->GetIConsole();
if (!console)
return;
char szTemp[MAX_WARNING_LENGTH];
strncpy( szTemp,szString,sizeof(szTemp)-32 ); // leave space for additional text data.
szTemp[sizeof(szTemp)-32] = 0;
size_t len = strlen(szTemp);
const char * mptr=szTemp+len-1;
if (*mptr!='\n')
strcat(szTemp,"\n");
size_t nLen = strlen(szTemp);
assert(nLen<sizeof(szTemp));
//check if Tony wanna output only wanrning or error messages
if (strstr(szTemp,"rror") || strstr(szTemp,"ERROR"))
{ // make error message red
memmove(szTemp+2,szTemp,nLen+1);
nLen+=2;
szTemp[0] = '$';
szTemp[1] = '4';
}
else
{
if (strstr(szTemp,"arning") || strstr(szTemp,"WARNING"))
{ // make error message blue
memmove(szTemp+2,szTemp,nLen+1);
nLen+=2;
szTemp[0] = '$';
szTemp[1] = '6';
}
}
if (bAdd)
console->PrintLinePlus(szTemp);
else
console->PrintLine(szTemp);
}
//log to console only
//////////////////////////////////////////////////////////////////////
void CLog::LogToConsole(const char *szFormat,...)
{
if (m_pLogVerbosity && !m_pLogVerbosity->GetIVal())
{
if (m_pLogFileVerbosity && !m_pLogFileVerbosity->GetIVal())
{
return;
}
}
RETURN;
if (!szFormat)
return;
bool bfile = false, bconsole = false;
const char* szCommand = CheckAgainstVerbosity(szFormat, bfile, bconsole);
if (!bconsole)
return;
va_list arglist;
char szBuffer[MAX_WARNING_LENGTH];
va_start(arglist, szFormat);
_vsnprintf(szBuffer, sizeof(szBuffer), szCommand, arglist);
szBuffer[sizeof(szBuffer)-8]=0;
va_end(arglist);
LogStringToConsole( szBuffer );
}
//////////////////////////////////////////////////////////////////////
void CLog::LogToConsolePlus(const char *szFormat,...)
{
if (m_pLogVerbosity && !m_pLogVerbosity->GetIVal())
{
if (m_pLogFileVerbosity && !m_pLogFileVerbosity->GetIVal())
{
return;
}
}
RETURN;
if (!szFormat)
return;
bool bfile = false, bconsole = false;
const char* szCommand = CheckAgainstVerbosity(szFormat, bfile, bconsole);
if (!bconsole)
return;
va_list arglist;
va_start(arglist, szFormat);
_vsnprintf(m_szTemp, sizeof(m_szTemp), szCommand, arglist);
m_szTemp[sizeof(m_szTemp)-8]=0;
va_end(arglist);
if (!m_pSystem)
return;
LogStringToConsole( m_szTemp,true );
}
//////////////////////////////////////////////////////////////////////
void CLog::LogStringToFile( const char *szString,bool bAdd )
{
if (!szString || !szString[0])
return;
if (!m_pSystem)
return;
IConsole * console = m_pSystem->GetIConsole();
char szTemp[MAX_TEMP_LENGTH_SIZE];
strncpy( szTemp,szString,sizeof(szTemp)-32 ); // leave space for additional text data.
szTemp[sizeof(szTemp)-32] = 0;
size_t len = strlen(szTemp);
const char * mptr=szTemp+len-1;
if (*mptr!='\n')
strcat(szTemp,"\n");
if (szTemp[0] == '$')
strcpy(szTemp, szTemp+2);
#ifdef _WIN32
if (!m_pLogIncludeTime)
{
// put time into begin of the string if requested by cvar
m_pLogIncludeTime = (console && m_pSystem->GetIScriptSystem()) ? console->CreateVariable("log_IncludeTime", "0", 0,
"Toggles timestamping of log entries.\n"
"Usage: log_IncludeTime [0/1]\n"
"Default is 0 (off). Set to 1 to include time in log items.") : 0;
}
if (m_pLogIncludeTime && m_pLogIncludeTime->GetIVal())
{
memmove( szTemp+8, szTemp, strlen(szTemp)+1 );
time_t ltime;
time( &ltime );
struct tm *today = localtime( &ltime );
memset(szTemp, ' ', 8);
strftime( szTemp, 8, "<%M:%S> ", today );
}
#endif
if (bAdd)
{
FILE *fp=fxopen(m_szFilename,"r+t");
if (fp)
{
int p1 = ftell(fp);
fseek(fp,0,SEEK_END);
p1 = ftell(fp);
fseek(fp,-2,SEEK_CUR);
p1 = ftell(fp);
fputs(szTemp,fp);
fclose(fp);
}
}
else
{
if(FILE * fp = fxopen(m_szFilename,"at"))
{
fputs(szTemp,fp);
fclose(fp);
}
}
}
//same as above but to a file
//////////////////////////////////////////////////////////////////////
void CLog::LogToFilePlus(const char *szFormat,...)
{
if (m_pLogVerbosity && !m_pLogVerbosity->GetIVal())
{
if (m_pLogFileVerbosity && !m_pLogFileVerbosity->GetIVal())
{
return;
}
}
RETURN;
if (!m_szFilename[0] || !szFormat)
return;
bool bfile = false, bconsole = false;
const char* szCommand = CheckAgainstVerbosity(szFormat, bfile, bconsole);
if (!bfile)
return;
va_list arglist;
va_start(arglist, szFormat);
_vsnprintf(m_szTemp, sizeof(m_szTemp), szCommand, arglist);
m_szTemp[sizeof(m_szTemp)-8]=0;
va_end(arglist);
LogStringToFile( m_szTemp,true );
}
//log to the file specified in setfilename
//////////////////////////////////////////////////////////////////////
void CLog::LogToFile(const char *szFormat,...)
{
if (m_pLogVerbosity && !m_pLogVerbosity->GetIVal())
{
if (m_pLogFileVerbosity && !m_pLogFileVerbosity->GetIVal())
{
return;
}
}
RETURN;
if (!m_szFilename[0] || !szFormat)
return;
bool bfile = false, bconsole = false;
const char* szCommand = CheckAgainstVerbosity(szFormat, bfile, bconsole);
if (!bfile)
return;
va_list arglist;
va_start(arglist, szFormat);
_vsnprintf(m_szTemp, sizeof(m_szTemp), szCommand, arglist);
m_szTemp[sizeof(m_szTemp)-16]=0;
va_end(arglist);
LogStringToFile( m_szTemp );
}
//set the file used to log to disk
//////////////////////////////////////////////////////////////////////
void CLog::SetFileName(const char *command)
{
RETURN;
if (!command)
return;
strcpy(m_szFilename,command);
#ifndef _XBOX
FILE *fp=fxopen(m_szFilename,"wt");
if (fp)
fclose(fp);
#endif
}
//////////////////////////////////////////////////////////////////////////
const char* CLog::GetFileName()
{
return m_szFilename;
}
//////////////////////////////////////////////////////////////////////
void CLog::UpdateLoadingScreen(const char *szFormat,...)
{
if ((!m_pLogVerbosity) || (m_pLogVerbosity && m_pLogVerbosity->GetIVal()) || ((!m_pLogFileVerbosity) || (m_pLogFileVerbosity && m_pLogFileVerbosity->GetIVal())))
{
RETURN;
if (szFormat)
{
bool bfile = false, bconsole = false;
CheckAgainstVerbosity(szFormat, bfile, bconsole);
if (bconsole || bfile)
{
va_list args;
va_start(args, szFormat);
_vsnprintf(m_szTemp, sizeof(m_szTemp), szFormat, args);
m_szTemp[sizeof(m_szTemp)-8]=0;
va_end(args);
if (bconsole)
LogToConsole(m_szTemp);
if (bfile)
LogToFile(m_szTemp);
if (bconsole)
{
((CSystem*)m_pSystem)->UpdateLoadingScreen();
}
}
}
}
// Take this oportunity to update streaming engine.
GetISystem()->GetStreamEngine()->Update();
}
//////////////////////////////////////////////////////////////////////
void CLog::UpdateLoadingScreenPlus(const char *szFormat,...)
{
if ((!m_pLogVerbosity) || (m_pLogVerbosity && m_pLogVerbosity->GetIVal()) || ((!m_pLogFileVerbosity) || (m_pLogFileVerbosity && m_pLogFileVerbosity->GetIVal())))
{
RETURN;
if (szFormat)
{
bool bfile = false, bconsole = false;
CheckAgainstVerbosity(szFormat, bfile, bconsole);
va_list args;
va_start(args, szFormat);
_vsnprintf(m_szTemp, sizeof(m_szTemp), szFormat, args);
m_szTemp[sizeof(m_szTemp)-8]=0;
va_end(args);
if (bconsole)
LogToConsolePlus(m_szTemp);
if (bfile)
LogToFilePlus(m_szTemp);
if (bconsole)
{
((CSystem*)m_pSystem)->UpdateLoadingScreen();
}
}
}
}
//////////////////////////////////////////////////////////////////////////
int CLog::GetVerbosityLevel()
{
if (m_pLogVerbosity)
return (m_pLogVerbosity->GetIVal());
return (0);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Checks the verbosity of the message and returns NULL if the message must NOT be
// logged, or the pointer to the part of the message that should be logged
// NOTE:
// Normally, this is either the pText pointer itself, or the pText+1, meaning
// the first verbosity character may be cut off)
// This is done in order to avoid modification of const char*, which may cause GPF
// sometimes, or kill the verbosity qualifier in the text that's gonna be passed next time.
const char* CLog::CheckAgainstVerbosity(const char * pText, bool &logtofile, bool &logtoconsole)
{
RETURN;
// the max verbosity (most detailed level)
const unsigned char nMaxVerbosity = 8;
// the current verbosity of the log
int nLogVerbosity = m_pLogVerbosity ? m_pLogVerbosity->GetIVal() : nMaxVerbosity;
int nLogFileVerbosity = m_pLogFileVerbosity ? m_pLogFileVerbosity->GetIVal() : nMaxVerbosity;
nLogFileVerbosity=max(nLogFileVerbosity,nLogVerbosity); // file verbosity depends on usual log_verbosity as well
const char *pStartText;
int textVerbosity;
// Empty string
if (pText[0] == '\0')
{
logtoconsole = false;
logtofile = false;
return 0;
}
if((unsigned char)pText[0]>=' ')
{
// verbosity is not defined in the text
pStartText=pText;
textVerbosity=nMaxVerbosity;
}
else
{
// verbosity is defined in the text
pStartText=pText+1;
textVerbosity=(unsigned char)pText[0];
}
logtoconsole = (nLogVerbosity >= textVerbosity);
logtofile = (nLogFileVerbosity >= textVerbosity);
return pStartText;
}
/*
//////////////////////////////////////////////////////////////////////////
int CLog::CheckVerbosity( const char * pText )
{
RETURN;
// the max verbosity (most detailed level)
const unsigned char nMaxVerbosity = 5;
// set message verbosity for error and warning messages
char sBuff[256];
strncpy(sBuff,pText,255);
sBuff[255]=0;
strlwr(sBuff);
if(strstr(pText,"error"))
return 1;
if(strstr(pText,"warning"))
return 3;
int textVerbosity = (unsigned char)pText[0];
if (textVerbosity > nMaxVerbosity)
{
return nMaxVerbosity;
}
else
return textVerbosity;
}
*/

89
CrySystem/Log.h Normal file
View File

@@ -0,0 +1,89 @@
//////////////////////////////////////////////////////////////////////
//
// Crytek CryENGINE Source code
//
// File:Log.h
//
// History:
// -Feb 2,2001:Created by Marco Corbetta
//
//////////////////////////////////////////////////////////////////////
#ifndef LOG_H
#define LOG_H
#if _MSC_VER > 1000
# pragma once
#endif
#include <ILog.h>
//////////////////////////////////////////////////////////////////////
#define MAX_TEMP_LENGTH_SIZE 2048
#define MAX_FILENAME_SIZE 256
//////////////////////////////////////////////////////////////////////
class CLog:
public ILog
{
public:
CLog( ISystem *pSystem );
~CLog();
// interface ILog -------------------------------------------------
virtual void Release() { delete this; };
virtual void SetFileName(const char *command);
virtual const char* GetFileName();
// void Log(int dwFlags,const char *szCommand,...){}
virtual void Log(const char *command,...);
virtual void LogWarning(const char *command,...);
virtual void LogError(const char *command,...);
virtual void LogPlus(const char *command,...);
virtual void LogToFile (const char *command,...);
virtual void LogToFilePlus(const char *command,...);
virtual void LogToConsole(const char *command,...);
virtual void LogToConsolePlus(const char *command,...);
virtual void UpdateLoadingScreen(const char *command,...);
virtual void UpdateLoadingScreenPlus(const char *command,...);
virtual void EnableVerbosity( bool bEnable );
virtual void SetVerbosity( int verbosity );
virtual int GetVerbosityLevel();
private:
virtual void LogV( const ELogType ineType, const char* szFormat, va_list args );
void LogStringToFile( const char* szString,bool bAdd=false );
void LogStringToConsole( const char* szString,bool bAdd=false );
void Done();
//will format the message into m_szTemp
void FormatMessage(const char *szCommand,...);
ISystem *m_pSystem;
char m_szTemp[MAX_TEMP_LENGTH_SIZE];
char m_szFilename[MAX_FILENAME_SIZE];
ICVar *m_pLogWarningsOnly;
ICVar *m_pLogIncludeTime;
ICVar *m_pLogColoredText;
IConsole *m_pConsole;
public:
// checks the verbosity of the message and returns NULL if the message must NOT be
// logged, or the pointer to the part of the message that should be logged
const char* CheckAgainstVerbosity(const char * pText, bool &logtofile, bool &logtoconsole);
//! Returns verbosity level of this string.
//int CheckVerbosity( const char * pText );
ICVar *m_pLogVerbosity;
ICVar *m_pLogFileVerbosity;
};
#endif

View File

@@ -0,0 +1,28 @@
#ifndef __ABOUT_WND_H__
#define __ABOUT_WND_H__
#pragma once
class CAboutWnd : public _TinyDialog
{
public:
BOOL Create(_TinyWindow *pParent = NULL)
{ return _TinyDialog::Create(MAKEINTRESOURCE(IDD_ABOUTBOX), pParent); };
BOOL DoModal(_TinyWindow *pParent = NULL)
{ return _TinyDialog::DoModal(MAKEINTRESOURCE(IDD_ABOUTBOX), pParent); };
protected:
_BEGIN_DLG_MSG_MAP(_TinyDialog)
_BEGIN_COMMAND_HANDLER()
_COMMAND_HANDLER(IDOK, OnOk)
_END_COMMAND_HANDLER()
_END_DLG_MSG_MAP()
LRESULT OnOk(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
_TinyVerify(EndDialog(hWnd, 0));
return 0;
};
};
#endif

View File

@@ -0,0 +1,2 @@
#include "stdafx.h"
#include "FileTree.h"

View File

@@ -0,0 +1,85 @@
#ifndef __FILE_TREE_H__
#define __FILE_TREE_H__
#pragma once
#include "_TinyMain.h"
#include "_TinyWindow.h"
#include "_TinyFileEnum.h"
#include "_TinyImageList.h"
#include <vector>
#include <string>
#include "..\resource.h"
class CFileTree : public _TinyTreeView {
public:
CFileTree() { m_iID = 0; };
virtual ~CFileTree() { };
BOOL Create(const _TinyRect& rcWnd, _TinyWindow *pParent = NULL, UINT iID = NULL) {
m_iID = iID;
_TinyVerify(_TinyTreeView::Create(iID, WS_CHILD | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT |
WS_VISIBLE, WS_EX_CLIENTEDGE, &rcWnd, pParent));
m_cTreeIcons.CreateFromBitmap(MAKEINTRESOURCE(IDB_TREE_VIEW), 16);
SetImageList(m_cTreeIcons.GetHandle());
return TRUE;
};
void ScanFiles(char *pszRootPath) {
HTREEITEM hRoot = _TinyTreeView::AddItemToTree(pszRootPath, NULL, NULL, 2);
EnumerateScripts(hRoot, pszRootPath);
Expand(hRoot);
};
const char * GetCurItemFileName() {
HTREEITEM hCurSel = NULL;
LPARAM nIdx;
hCurSel = _TinyTreeView::GetSelectedItem();
if (!hCurSel)
return NULL;
nIdx = _TinyTreeView::GetItemUserData(hCurSel);
if ((size_t) nIdx > m_vFileNameTbl.size() - 1)
return NULL;
return m_vFileNameTbl[nIdx].c_str();
};
protected:
_TinyImageList m_cTreeIcons;
INT m_iID;
std::vector<string> m_vFileNameTbl;
void EnumerateScripts(HTREEITEM hRoot, char *pszEnumPath) {
_TinyFileEnum cScripts;
__finddata64_t sCurFile;
char szPath[_MAX_PATH];
char szFullFilePath[_MAX_PATH];
HTREEITEM hItem = NULL;
if (!cScripts.StartEnumeration(pszEnumPath, "*", &sCurFile))
return;
while (cScripts.GetNextFile(&sCurFile)) {
if (_stricmp(sCurFile.name, "..") == 0)
continue;
if (_stricmp(sCurFile.name, ".") == 0)
continue;
sprintf(szFullFilePath, "%s%s", pszEnumPath, sCurFile.name);
m_vFileNameTbl.push_back(szFullFilePath);
if (sCurFile.attrib & _A_SUBDIR) {
hItem = AddItemToTree(sCurFile.name, (LPARAM) m_vFileNameTbl.size() - 1, hRoot, 0);
sprintf(szPath, "%s%s\\", pszEnumPath, sCurFile.name);
EnumerateScripts(hItem, szPath);
} else {
if (strstr(_strlwr(sCurFile.name), ".lua"))
hItem = AddItemToTree(sCurFile.name, (LPARAM) m_vFileNameTbl.size() - 1, hRoot, 1);
}
}
};
};
#endif

View File

@@ -0,0 +1,761 @@
// LUADBG.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "LUADBG.h"
#include "_TinyRegistry.h"
#include "_TinyFileEnum.h"
#include "_TinyBrowseFolder.h"
#include "AboutWnd.h"
#include <ICryPak.h>
#include <direct.h>
#ifndef WIN64
#include "Shlwapi.h"
#pragma comment (lib, "Shlwapi.lib")
#endif
_TINY_DECLARE_APP();
CLUADbg::CLUADbg()
{
m_pIScriptSystem = NULL;
m_pIPak = NULL;
m_pIVariable = NULL;
m_hRoot = NULL;
m_bDisabled = false;
m_pTreeToAdd = NULL;
}
CLUADbg::~CLUADbg()
{
_TinyRegistry cTReg;
_TinyVerify(cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "MainHorzSplitter", m_wndMainHorzSplitter.GetSplitterPos()));
_TinyVerify(cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "SrcEditSplitter", m_wndSrcEditSplitter.GetSplitterPos()));
_TinyVerify(cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "WatchSplitter", m_wndWatchSplitter.GetSplitterPos()));
_TinyVerify(cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "WatchCallstackSplitter", m_wndWatchCallstackSplitter.GetSplitterPos()));
_TinyVerify(cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "Fullscreen", ::IsZoomed(m_hWnd) ? 1 : 0));
}
TBBUTTON tbButtonsAdd [] =
{
{ 0, ID_DEBUG_RUN, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0L, 0 },
{ 1, ID_DEBUG_BREAK, 0, BTNS_BUTTON, { 0 }, 0L, 0 },
{ 2, ID_DEBUG_STOP, 0, BTNS_BUTTON, { 0 }, 0L, 0 },
{ 0, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0L, 0 },
{ 3, ID_DEBUG_STEPINTO, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0L, 0 },
{ 4, ID_DEBUG_STEPOVER, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0L, 0 },
{ 5, ID_DEBUG_TOGGLEBREAKPOINT, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0L, 0 },
{ 6, ID_DEBUG_DISABLE, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0L, 0 },
{ 0, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0L, 0 },
{ 7, IDM_ABOUT, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0L, 0 },
};
//! add a backslash if needed
inline void MyPathAddBackslash( char* szPath )
{
if(szPath[0]==0)
return;
size_t nLen = strlen(szPath);
if (szPath[nLen-1] == '\\')
return;
if (szPath[nLen-1] == '/')
{
szPath[nLen-1] = '\\';
return;
}
szPath[nLen] = '\\';
szPath[nLen+1] = '\0';
}
LRESULT CLUADbg::OnCreate(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
_TinyRect erect;
_TinyRect lrect;
_TinyRect wrect;
_TinyRegistry cTReg;
DWORD dwXOrigin=0,dwYOrigin=0,dwXSize=800,dwYSize=600;
if(cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "XOrigin",dwXOrigin))
{
cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "YOrigin",dwYOrigin);
cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "XSize",dwXSize);
cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "YSize",dwYSize);
}
SetWindowPos(dwXOrigin, dwYOrigin, dwXSize, dwYSize, SWP_NOZORDER | SWP_NOMOVE);
// TODO: Make sure fullscreen flag is loaded and used
// WS_MAXIMIZE
// DWORD dwFullscreen = 0;
// cTReg.ReadNumber("Software\\Tiny\\LuaDebugger\\", "Fullscreen", dwFullscreen);
// if (dwFullscreen == 1)
// ShowWindow(SW_MAXIMIZE);
CenterOnScreen();
GetClientRect(&wrect);
erect=wrect;
erect.top=0;
erect.bottom=32;
m_wToolbar.Create((ULONG_PTR) GetMenu(m_hWnd), WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS, 0, &erect, this); //AMD Port
m_wToolbar.AddButtons(IDC_LUADBG, tbButtonsAdd, 10);
m_wndStatus.Create(0, NULL, this);
// Client area window
_TinyVerify(m_wndClient.Create(NULL, _T(""), WS_CHILD | WS_VISIBLE, 0, &wrect, this));
m_wndClient.NotifyReflection(TRUE);
// Splitter dividing source/file and watch windows
m_wndMainHorzSplitter.Create(&m_wndClient, NULL, NULL, true);
// Divides source and file view
m_wndSrcEditSplitter.Create(&m_wndMainHorzSplitter);
// Divides two watch windows
m_wndWatchSplitter.Create(&m_wndMainHorzSplitter);
// Divides the watch window and the cllstack
m_wndWatchCallstackSplitter.Create(&m_wndWatchSplitter);
// Add all scripts to the file tree
m_wFilesTree.Create(erect, &m_wndSrcEditSplitter, IDC_FILES);
char szRootPath[_MAX_PATH];
_getcwd(szRootPath, _MAX_PATH);
MyPathAddBackslash(szRootPath);
strcat(szRootPath, "SCRIPTS\\");
m_wFilesTree.ScanFiles(szRootPath);
_TinyVerify(m_wScriptWindow.Create(WS_VISIBLE | WS_CHILD | ES_WANTRETURN | WS_HSCROLL | WS_VSCROLL |
ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE, 0, &erect, &m_wndSrcEditSplitter));
m_wScriptWindow.SendMessage(EM_SETEVENTMASK,0,ENM_SCROLL);
m_wndFileViewCaption.Create("Scripts", &m_wFilesTree, &m_wndSrcEditSplitter);
m_wndSourceCaption.Create("Source", &m_wScriptWindow, &m_wndSrcEditSplitter);
m_wndSrcEditSplitter.SetFirstPan(&m_wndFileViewCaption);
m_wndSrcEditSplitter.SetSecondPan(&m_wndSourceCaption);
m_wLocals.Create(IDC_LOCALS,WS_CHILD|TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT|WS_VISIBLE,WS_EX_CLIENTEDGE,&erect, &m_wndWatchSplitter);
m_wWatch.Create(IDC_WATCH,WS_CHILD|WS_VISIBLE|TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT,WS_EX_CLIENTEDGE,&erect, &m_wndWatchSplitter);
m_wCallstack.Create(0,WS_CHILD|WS_VISIBLE|LVS_REPORT,WS_EX_CLIENTEDGE,&erect, &m_wndWatchSplitter);
m_wndLocalsCaption.Create("Locals", &m_wLocals, &m_wndWatchSplitter);
m_wndWatchCaption.Create("Watch", &m_wWatch, &m_wndWatchCallstackSplitter);
m_wndCallstackCaption.Create("Callstack", &m_wCallstack, &m_wndWatchCallstackSplitter);
m_wndWatchSplitter.SetFirstPan(&m_wndWatchCallstackSplitter);
m_wndWatchCallstackSplitter.SetFirstPan(&m_wndWatchCaption);
m_wndWatchCallstackSplitter.SetSecondPan(&m_wndCallstackCaption);
m_wndWatchSplitter.SetSecondPan(&m_wndLocalsCaption);
m_wndMainHorzSplitter.SetFirstPan(&m_wndSrcEditSplitter);
m_wndMainHorzSplitter.SetSecondPan(&m_wndWatchSplitter);
Reshape(wrect.right-wrect.left,wrect.bottom-wrect.top);
// Read splitter window locations from registry
DWORD dwVal;
cTReg.ReadNumber("Software\\Tiny\\LuaDebugger\\", "MainHorzSplitter", dwVal, 150);
m_wndMainHorzSplitter.SetSplitterPos(dwVal);
m_wndMainHorzSplitter.Reshape();
cTReg.ReadNumber("Software\\Tiny\\LuaDebugger\\", "SrcEditSplitter", dwVal, 190);
m_wndSrcEditSplitter.SetSplitterPos(dwVal);
m_wndSrcEditSplitter.Reshape();
cTReg.ReadNumber("Software\\Tiny\\LuaDebugger\\", "WatchSplitter", dwVal, wrect.right / 3 * 2);
m_wndWatchSplitter.SetSplitterPos(dwVal);
m_wndWatchSplitter.Reshape();
cTReg.ReadNumber("Software\\Tiny\\LuaDebugger\\", "WatchCallstackSplitter", dwVal, wrect.right / 3);
m_wndWatchCallstackSplitter.SetSplitterPos(dwVal);
m_wndWatchCallstackSplitter.Reshape();
m_wCallstack.InsertColumn(0, "Function", 108, 0);
m_wCallstack.InsertColumn(1, "Line", 40, 1);
m_wCallstack.InsertColumn(2, "File", 108, 2);
//_TinyVerify(LoadFile("C:\\MASTERCD\\SCRIPTS\\Default\\Entities\\PLAYER\\BasicPlayer.lua"));
//_TinyVerify(LoadFile("C:\\MASTERCD\\SCRIPTS\\Default\\Entities\\PLAYER\\player.lua"));
// _TINY_CHECK_LAST_ERROR
return 0;
}
bool CLUADbg::LoadFile(const char *pszFile, bool bForceReload)
{
FILE *hFile = NULL;
char *pszScript = NULL, *pszFormattedScript = NULL;
UINT iLength, iCmpBufPos, iSrcBufPos, iDestBufPos, iNumChars, iStrStartPos, iCurKWrd, i;
char szCmpBuf[2048];
bool bIsKeyWord;
string strLuaFormatFileName = "@";
char szMasterCD[_MAX_PATH];
// Create lua specific filename and check if we already have that file loaded
_getcwd(szMasterCD, _MAX_PATH);
if (strncmp(szMasterCD, pszFile, strlen(szMasterCD) - 1) == 0)
{
strLuaFormatFileName += &pszFile[strlen(szMasterCD) + 1];
for (i=0; i<strLuaFormatFileName.length(); i++)
if (strLuaFormatFileName[i] == '\\')
strLuaFormatFileName[i] = '/';
std::transform(strLuaFormatFileName.begin(), strLuaFormatFileName.end(),
strLuaFormatFileName.begin(), (int (*) (int)) tolower);
}
else
strLuaFormatFileName += pszFile;
if (bForceReload == false && m_wScriptWindow.GetSourceFile() == strLuaFormatFileName)
return true;
m_wScriptWindow.SetSourceFile(strLuaFormatFileName.c_str());
// hFile = fopen(pszFile, "rb");
hFile = m_pIPak->FOpen(pszFile, "rb");
if (!hFile)
return false;
// set filename in window title
{
char str[_MAX_PATH];
sprintf(str,"Lua Debugger [%s]",pszFile);
SetWindowText(str);
}
// Get file size
// fseek(hFile, 0, SEEK_END);
m_pIPak->FSeek(hFile, 0, SEEK_END);
// iLength = ftell(hFile);
iLength = m_pIPak->FTell(hFile);
// fseek(hFile, 0, SEEK_SET);
m_pIPak->FSeek(hFile, 0, SEEK_SET);
pszScript = new char [iLength + 1];
pszFormattedScript = new char [512 + iLength * 3];
// _TinyVerify(fread(pszScript, iLength, 1, hFile) == 1);
_TinyVerify(m_pIPak->FRead(pszScript, iLength, 1, hFile) == 1);
pszScript[iLength] = '\0';
_TinyAssert(strlen(pszScript) == iLength);
// RTF text, font Courier, green comments and blue keyword
strcpy(pszFormattedScript, "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033" \
"{\\fonttbl{\\f0\\fmodern\\fprq1\\fcharset0 Courier(PS);}{\\f1\\fswiss\\fcharset0 Arial;}}" \
"{\\colortbl ;\\red0\\green0\\blue255;\\red0\\green128\\blue0;\\red160\\green160\\blue160;}\\f0\\fs20");
const char szKeywords[][32] =
{
"function",
"do",
"for",
"end",
"and",
"or",
"not",
"while",
"return",
"if",
"then",
"else",
"elseif",
"self",
"local",
"in",
"nil",
"repeat",
"until",
"break",
};
// Format text with syntax coloring
iDestBufPos = strlen(pszFormattedScript);
iSrcBufPos = 0;
while (pszScript[iSrcBufPos] != '\0')
{
// Scan next token
iNumChars = 1;
iStrStartPos = iSrcBufPos;
while (pszScript[iSrcBufPos] != ' ' &&
pszScript[iSrcBufPos] != '\n' &&
pszScript[iSrcBufPos] != '\r' &&
pszScript[iSrcBufPos] != '\t' &&
pszScript[iSrcBufPos] != '\0' &&
pszScript[iSrcBufPos] != '(' &&
pszScript[iSrcBufPos] != ')' &&
pszScript[iSrcBufPos] != '[' &&
pszScript[iSrcBufPos] != ']' &&
pszScript[iSrcBufPos] != '{' &&
pszScript[iSrcBufPos] != '}' &&
pszScript[iSrcBufPos] != ',' &&
pszScript[iSrcBufPos] != '.' &&
pszScript[iSrcBufPos] != ';' &&
pszScript[iSrcBufPos] != ':' &&
pszScript[iSrcBufPos] != '=' &&
pszScript[iSrcBufPos] != '==' &&
pszScript[iSrcBufPos] != '*' &&
pszScript[iSrcBufPos] != '+' &&
pszScript[iSrcBufPos] != '/' &&
pszScript[iSrcBufPos] != '~' &&
pszScript[iSrcBufPos] != '"')
{
iSrcBufPos++;
iNumChars++;
// Special treatment of '-' to allow parsing of '--'
if (pszScript[iSrcBufPos - 1] == '-' && pszScript[iSrcBufPos] != '-')
break;
}
if (iNumChars == 1)
iSrcBufPos++;
else
iNumChars--;
// Copy token and add escapes
iCmpBufPos = 0;
for (i=iStrStartPos; i<iStrStartPos + iNumChars; i++)
{
_TinyAssert(i - iStrStartPos < sizeof(szCmpBuf));
if (pszScript[i] == '{' || pszScript[i] == '}' || pszScript[i] == '\\')
{
// Add \ to mark it as non-escape character
szCmpBuf[iCmpBufPos++] = '\\';
szCmpBuf[iCmpBufPos++] = pszScript[i];
szCmpBuf[iCmpBufPos] = '\0';
}
else
{
szCmpBuf[iCmpBufPos++] = pszScript[i];
szCmpBuf[iCmpBufPos] = '\0';
}
}
// Comment
if (strncmp(szCmpBuf, "--", 2) == 0)
{
// Green
strcat(pszFormattedScript, "\\cf2 ");
iDestBufPos += 5;
strcpy(&pszFormattedScript[iDestBufPos], szCmpBuf);
iDestBufPos += strlen(szCmpBuf);
// Parse until newline
while (pszScript[iSrcBufPos] != '\n' && pszScript[iSrcBufPos] != '\0')
{
pszFormattedScript[iDestBufPos++] = pszScript[iSrcBufPos++];
}
iSrcBufPos++;
pszFormattedScript[iDestBufPos] = '\0';
// Add newline and restore color
strcat(pszFormattedScript, "\\par\n");
iDestBufPos += 5;
strcat(pszFormattedScript, "\\cf0 ");
iDestBufPos += 5;
continue;
}
// String
if (strncmp(szCmpBuf, "\"", 2) == 0)
{
// Gray
strcat(pszFormattedScript, "\\cf3 ");
iDestBufPos += 5;
strcpy(&pszFormattedScript[iDestBufPos], szCmpBuf);
iDestBufPos += strlen(szCmpBuf);
// Parse until end string / newline
while (pszScript[iSrcBufPos] != '\n' && pszScript[iSrcBufPos] != '\0' && pszScript[iSrcBufPos] != '"')
{
pszFormattedScript[iDestBufPos++] = pszScript[iSrcBufPos++];
}
iSrcBufPos++;
pszFormattedScript[iDestBufPos] = '\0';
// Add literal
strcat(pszFormattedScript, "\"");
iDestBufPos += 1;
// Restore color
strcat(pszFormattedScript, "\\cf0 ");
iDestBufPos += 5;
continue;
}
// Have we parsed a keyword ?
bIsKeyWord = false;
for (iCurKWrd=0; iCurKWrd<sizeof(szKeywords) / sizeof(szKeywords[0]); iCurKWrd++)
{
if (strcmp(szKeywords[iCurKWrd], szCmpBuf) == 0)
{
strcat(pszFormattedScript, "\\cf1 ");
strcat(pszFormattedScript, szKeywords[iCurKWrd]);
strcat(pszFormattedScript, "\\cf0 ");
iDestBufPos += 5 + 5 + strlen(szKeywords[iCurKWrd]);
bIsKeyWord = true;
}
}
if (bIsKeyWord)
continue;
if (strcmp(szCmpBuf, "\n") == 0)
{
// Newline
strcat(pszFormattedScript, "\\par ");
iDestBufPos += 5;
}
else
{
// Anything else, just append
iDestBufPos += strlen(szCmpBuf);
strcat(pszFormattedScript, szCmpBuf);
}
}
if (hFile)
// fclose(hFile);
m_pIPak->FClose(hFile);
if (pszScript)
{
delete [] pszScript;
pszScript = NULL;
}
/*
hFile = fopen("C:\\Debug.txt", "w");
fwrite(pszFormattedScript, 1, strlen(pszFormattedScript), hFile);
fclose(hFile);
*/
m_wScriptWindow.SetText(pszFormattedScript);
if (pszFormattedScript)
{
delete [] pszFormattedScript;
pszFormattedScript = NULL;
}
return true;
}
LRESULT CLUADbg::OnEraseBkGnd(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
return 1;
}
extern bool g_bDone; // From LuaDbgInterface.cpp
LRESULT CLUADbg::OnClose(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
// Quit();
WINDOWINFO wi;
if(::GetWindowInfo(m_hWnd,&wi))
{
_TinyRegistry cTReg;
_TinyVerify(cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "XOrigin", wi.rcWindow.left));
_TinyVerify(cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "YOrigin", wi.rcWindow.top));
_TinyVerify(cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "XSize", wi.rcWindow.right-wi.rcWindow.left));
_TinyVerify(cTReg.WriteNumber("Software\\Tiny\\LuaDebugger\\", "YSize", wi.rcWindow.bottom-wi.rcWindow.top));
}
g_bDone=true;
return 0;
}
LRESULT CLUADbg::OnSize(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
int w=LOWORD(lParam);
int h=HIWORD(lParam);
Reshape(w,h);
return 0;
}
LRESULT CLUADbg::OnAbout(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
CAboutWnd wndAbout;
wndAbout.DoModal(this);
return 0;
}
LRESULT CLUADbg::OnToggleBreakpoint(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
m_wScriptWindow.AddBreakpoint();
return 0;
}
#define TOOLBAR_HEIGHT 28
#define STATUS_BAR_HEIGHT 20
bool CLUADbg::Reshape(int w,int h)
{
/*
int nWatchHeight=(((float)h)*WATCH_HEIGHT_MULTIPLIER);
int nFilesWidth=(((float)h)*FILES_WIDTH_MULTIPLIER);
m_wScriptWindow.SetWindowPos(nFilesWidth,TOOLBAR_HEIGHT,w-nFilesWidth,h-TOOLBAR_HEIGHT-nWatchHeight,SWP_DRAWFRAME);
m_wLocals.SetWindowPos(0,h-nWatchHeight,w/2,nWatchHeight,SWP_DRAWFRAME);
m_wFilesTree.SetWindowPos(nFilesWidth,TOOLBAR_HEIGHT,nFilesWidth,h-TOOLBAR_HEIGHT-nWatchHeight,SWP_DRAWFRAME);
m_wWatch.SetWindowPos(w/2,h-nWatchHeight,w/2,nWatchHeight,SWP_DRAWFRAME);
*/
m_wndClient.Reshape(w, h - TOOLBAR_HEIGHT - STATUS_BAR_HEIGHT);
m_wndClient.SetWindowPos(0, TOOLBAR_HEIGHT, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
m_wndMainHorzSplitter.Reshape(w, h - TOOLBAR_HEIGHT - STATUS_BAR_HEIGHT);
m_wToolbar.SetWindowPos(0,0,w,TOOLBAR_HEIGHT,0);
m_wndStatus.SetWindowPos(0, h - STATUS_BAR_HEIGHT, w, STATUS_BAR_HEIGHT, NULL);
return true;
}
void CLUADbg::PlaceLineMarker(UINT iLine)
{
m_wScriptWindow.SetLineMarker(iLine);
m_wScriptWindow.ScrollToLine(iLine);
}
void CLUADbg::SetStatusBarText(const char *pszText)
{
// TODO: Find out why setting the panel text using the
// dedicated message doesn't work. For some reason the
// text gets drawn once but never again.
// m_wndStatus.SetPanelText(pszText);
m_wndStatus.SetWindowText(pszText);
}
void CLUADbg::GetStackAndLocals()
{
///////////
// Stack //
///////////
{
IScriptObject *pICallstack = m_pIScriptSystem->GetCallsStack();
_SmartScriptObject pIEntry(m_pIScriptSystem, true);
const char *pszText = NULL;
int iItem=0;
m_wCallstack.Clear();
int i;
for (i=pICallstack->Count() - 1; i>=1; i--)
{
pICallstack->GetAt(i, pIEntry);
pIEntry->GetValue("description", pszText);
iItem = m_wCallstack.InsertItem(0, pszText, 0);
pIEntry->GetValue("line", pszText);
m_wCallstack.SetItemText(iItem, 1, pszText);
if (pIEntry->GetValue("sourcefile", pszText))
{
if (_stricmp(pszText, "=C") == 0)
m_wCallstack.SetItemText(iItem, 2, "Native C Function");
else
m_wCallstack.SetItemText(iItem, 2, &pszText[1]);
}
else
m_wCallstack.SetItemText(iItem, 2, "No Source");
}
if (pICallstack->Count() == 0)
iItem = m_wCallstack.InsertItem(0, "No Callstack Available", 0);
pICallstack->Release();
pICallstack = NULL;
}
////////////
// Locals //
////////////
m_wLocals.Clear();
m_pIVariable = m_pIScriptSystem->GetLocalVariables(1);
m_pTreeToAdd = &m_wLocals;
if (m_pIVariable)
{
m_hRoot = NULL;
m_iRecursionLevel = 0;
m_pIVariable->Dump((IScriptObjectDumpSink *) this);
m_pIVariable->Release();
m_pIVariable = NULL;
}
else
m_wLocals.AddItemToTree("No Locals Available");
m_pTreeToAdd = NULL;
///////////
// Watch //
///////////
const char *pszText = NULL;
m_wWatch.Clear();
IScriptObject *pIScriptObj = m_pIScriptSystem->GetLocalVariables(1);
string strWatchVar = "self";
bool bVarFound = false;
pIScriptObj->BeginIteration();
while (pIScriptObj->MoveNext())
{
if (pIScriptObj->GetCurrentKey(pszText))
{
if (strWatchVar == pszText)
{
_SmartScriptObject pIEntry(m_pIScriptSystem, true);
pIScriptObj->GetCurrent(pIEntry);
m_pIVariable = pIEntry;
m_pTreeToAdd = &m_wWatch;
if (m_pIVariable)
{
bVarFound = true;
m_hRoot = NULL;
m_iRecursionLevel = 0;
// Dump only works for tables, in case of values call the sink directly
if (m_pIVariable->GetCurrentType() == svtObject)
m_pIVariable->Dump((IScriptObjectDumpSink *) this);
else
{
m_pIVariable = pIScriptObj; // Value needs to be retrieved from parent table
OnElementFound(pszText, m_pIVariable->GetCurrentType());
}
// No AddRef() !
// m_pIVariable->Release();
m_pIVariable = NULL;
}
m_pTreeToAdd = NULL;
}
}
}
pIScriptObj->EndIteration();
if (!bVarFound)
m_wWatch.AddItemToTree(const_cast<LPSTR>((strWatchVar + " = ?").c_str())); // TODO: Cast...
}
HTREEITEM CLUADbg::AddVariableToTree(const char *sName, ScriptVarType type, HTREEITEM hParent)
{
char szBuf[2048];
char szType[32];
const char *pszContent = NULL;
bool bRetrieved = false;
int iIdx;
if (m_pTreeToAdd == NULL)
{
_TinyAssert(m_pTreeToAdd != NULL);
return 0;
}
switch (type)
{
case svtNull:
strcpy(szType, "[nil]");
break;
case svtString:
strcpy(szType, "[string]");
break;
case svtNumber:
strcpy(szType, "[numeric]");
break;
case svtFunction:
strcpy(szType, "[function]");
break;
case svtObject:
strcpy(szType, "[table]");
break;
case svtUserData:
strcpy(szType, "[user data]");
break;
default:
strcpy(szType, "[unknown]");
break;
}
if (type == svtString || type == svtNumber)
{
if (sName[0] == '[')
{
strcpy(szBuf, &sName[1]);
szBuf[strlen(szBuf) - 1] = '\0';
iIdx = atoi(szBuf);
bRetrieved = m_pIVariable->GetAt(iIdx, pszContent);
}
else
bRetrieved = m_pIVariable->GetValue(sName, pszContent);
if (bRetrieved)
sprintf(szBuf, "%s %s = %s", szType, sName, pszContent);
else
sprintf(szBuf, "%s %s = (Unknown)", szType, sName);
}
else
sprintf(szBuf, "%s %s", szType, sName);
HTREEITEM hNewItem = m_pTreeToAdd->AddItemToTree(szBuf, NULL, hParent);
TreeView_SortChildren(m_pTreeToAdd->m_hWnd, hNewItem, FALSE);
return hNewItem;
}
void CLUADbg::OnElementFound(const char *sName, ScriptVarType type)
{
HTREEITEM hRoot = NULL;
UINT iRecursionLevel = 0;
_SmartScriptObject pTable(m_pIScriptSystem, true);
IScriptObject *pIOldTbl = NULL;
HTREEITEM hOldRoot = NULL;
if(!sName)sName="[table idx]";
hRoot = AddVariableToTree(sName, type, m_hRoot);
if (type == svtObject && m_iRecursionLevel < 5)
{
if (m_pIVariable->GetValue(sName, pTable))
{
pIOldTbl = m_pIVariable;
hOldRoot = m_hRoot;
m_pIVariable = pTable;
m_hRoot = hRoot;
m_iRecursionLevel++;
pTable->Dump((IScriptObjectDumpSink *) this);
m_iRecursionLevel--;
m_pIVariable = pIOldTbl;
m_hRoot = hOldRoot;
}
}
}
void CLUADbg::OnElementFound(int nIdx,ScriptVarType type)
{
char szBuf[32];
sprintf(szBuf, "[%i]", nIdx);
OnElementFound(szBuf, type);
}

View File

@@ -0,0 +1,418 @@
#pragma once
#include "_TinyMain.h"
#include "_TinySplitter.h"
#include "_TinyStatusBar.h"
#include "_TinyCaptionWindow.h"
#include "FileTree.h"
#include <IScriptSystem.h>
#include "..\resource.h"
#include <stdio.h>
#include <list>
#define IDC_SOURCE 666
#define IDC_LOCALS 667
#define IDC_WATCH 668
#define IDC_FILES 669
#define BORDER_SIZE 50
class CSourceEdit : public _TinyWindow
{
public:
CSourceEdit() { m_iLineMarkerPos = 1; };
~CSourceEdit() { };
protected:
_BEGIN_MSG_MAP(CSourceEdit)
_MESSAGE_HANDLER(WM_SIZE,OnSize)
_MESSAGE_HANDLER(WM_PAINT,OnPaint)
_BEGIN_COMMAND_HANDLER()
_BEGIN_CMD_EVENT_FILTER(IDC_SOURCE)
_EVENT_FILTER(EN_VSCROLL,OnScroll)
_EVENT_FILTER(EN_HSCROLL,OnScroll)
_EVENT_FILTER(EN_UPDATE ,OnScroll)
_END_CMD_EVENT_FILTER()
_END_COMMAND_HANDLER()
_END_MSG_MAP()
public:
void SetLineMarker(UINT iLine) { m_iLineMarkerPos = iLine; };
void SetScriptSystem(IScriptSystem *pIScriptSystem) { m_pIScriptSystem = pIScriptSystem; };
BOOL Create(DWORD dwStyle=WS_VISIBLE,DWORD dwExStyle=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL,ULONG nID=0)
{
_TinyRect erect;
erect.left=BORDER_SIZE;
erect.right=pRect->right;
erect.top=0;
erect.bottom=pRect->bottom;
if(!_TinyWindow::Create(NULL,_T("asd"),WS_CHILD|WS_VISIBLE,0,pRect,pParentWnd,nID))
return FALSE;
if(!m_wEditWindow.Create(IDC_SOURCE,WS_VISIBLE|WS_CHILD|ES_WANTRETURN|WS_HSCROLL|WS_VSCROLL|ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_MULTILINE|ES_NOHIDESEL,WS_EX_CLIENTEDGE,&erect,this))
return FALSE;
m_wEditWindow.SetFont((HFONT) GetStockObject(ANSI_FIXED_FONT));
return TRUE;
}
BOOL SetText(char *pszText)
{
EDITSTREAM strm;
char ***pppText = new char **;
*pppText = &pszText;
strm.dwCookie = (DWORD_PTR) pppText;
strm.dwError = 0;
strm.pfnCallback = EditStreamCallback;
m_wEditWindow.SendMessage(EM_LIMITTEXT, 0x7FFFFFF, 0);
return m_wEditWindow.SendMessage(EM_STREAMIN, SF_RTF, (LPARAM) &strm);
};
friend DWORD CALLBACK EditStreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
char ***pppText = reinterpret_cast<char ***> (dwCookie);
char **ppText = *pppText;
LONG iLen = (LONG)strlen(* ppText) /*- 1*/;
*pcb = __min(cb, iLen);
if (*pcb == 0)
{
delete pppText;
return 0;
}
memcpy(pbBuff, (* ppText), *pcb);
*ppText += *pcb;
return 0;
};
void SetSourceFile(const char *pszFileName)
{
m_strSourceFile = pszFileName;
};
const char * GetSourceFile() { return m_strSourceFile.c_str(); };
void AddBreakpoint()
{
// Adds a breakpoint for the current file in the current line
_TinyAssert(m_pIScriptSystem);
HBREAKPOINT hBreakPt = m_pIScriptSystem->AddBreakPoint(m_strSourceFile.c_str(),
m_wEditWindow.LineFromChar(m_wEditWindow.GetSel()));
_TinyVerify(::InvalidateRect(m_wEditWindow.m_hWnd, NULL, FALSE));
}
void ScrollToLine(UINT iLine)
{
m_wEditWindow.ScrollToLine(iLine);
};
private:
LRESULT OnEraseBkGnd(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam){return 1;};
LRESULT OnPaint(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
_TinyRect rect;
PAINTSTRUCT ps;
HDC hDC;
BeginPaint(m_hWnd,&ps);
hDC=::GetDC(m_hWnd);
int w,h;
UINT i;
int iLine;
const char *pszFile = NULL;
/////////////////////////////
GetClientRect(&rect);
w=rect.right-rect.left;
h=rect.bottom-rect.top;
_TinyRect rc(0,0,BORDER_SIZE,h);
::DrawFrameControl(hDC, &rc, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED);
::SetBkMode(hDC,TRANSPARENT);
POINT pt;
m_wEditWindow.GetScrollPos(&pt);
int iFirstLine = m_wEditWindow.GetFirstVisibleLine() + 1;
TEXTMETRIC tm;
m_wEditWindow.GetTextMetrics(&tm);
int iFontY=tm.tmHeight-tm.tmDescent;
int y=-pt.y%iFontY+3;
char sTemp[10];
HRGN hOldRgn=::CreateRectRgn(0,0,0,0);
HRGN hClippedRgn=::CreateRectRgn(0,0,BORDER_SIZE,h - 1);
::GetWindowRgn(m_hWnd,hOldRgn);
::SelectClipRgn(hDC,hClippedRgn);
::SelectObject(hDC, GetStockObject(ANSI_FIXED_FONT));
while(y<h)
{
sprintf(sTemp,"%d",iFirstLine);
::TextOut(hDC,2,y,sTemp,(int)strlen(sTemp));
y+=iFontY;
iFirstLine++;
}
// Draw current line marker
HBRUSH brsh = ::CreateSolidBrush(0x00FFFF00);
::SelectObject(hDC, brsh);
POINT sTriangle[4];
sTriangle[0].x = 36;
sTriangle[0].y = 0;
sTriangle[1].x = 46;
sTriangle[1].y = 5;
sTriangle[2].x = 36;
sTriangle[2].y = 10;
sTriangle[3].x = 36;
sTriangle[3].y = 0;
iFirstLine = m_wEditWindow.GetFirstVisibleLine();
for (i=0; i<4; i++)
sTriangle[i].y += (-pt.y % iFontY + 3) + (m_iLineMarkerPos - iFirstLine - 1) * iFontY + 2;
Polygon(hDC, sTriangle, 4);
// Breakpoints
::DeleteObject(brsh);
brsh = ::CreateSolidBrush(0x0000007F);
::SelectObject(hDC, brsh);
/*
std::list<UINT>::iterator it;
for (it=m_lBreakPoints.begin(); it!=m_lBreakPoints.end(); it++)
{
INT iY = (-pt.y % iFontY + 3) + ((* it) - iFirstLine - 1) * iFontY + 7;
Ellipse(hDC, 41 - 5, iY - 5, 41 + 5, iY + 5);
}
*/
IScriptObject *pIBreakPoints = m_pIScriptSystem->GetBreakPoints();
if (pIBreakPoints)
{
for (i=0; i<(UINT) pIBreakPoints->Count(); i++)
{
_SmartScriptObject pIBreakPt(m_pIScriptSystem, true);
pIBreakPoints->GetAt(i + 1, pIBreakPt);
if (pIBreakPt->GetValue("line", iLine))
{
if (pIBreakPt->GetValue("sourcefile", pszFile))
{
if (pszFile == m_strSourceFile)
{
INT iY = (-pt.y % iFontY + 3) + (iLine - iFirstLine - 1) * iFontY + 7;
Ellipse(hDC, 41 - 5, iY - 5, 41 + 5, iY + 5);
}
}
}
}
pIBreakPoints->Release();
pIBreakPoints = NULL;
}
::DeleteObject(brsh);
::SelectClipRgn(hDC,hOldRgn);
::DeleteObject(hOldRgn);
::DeleteObject(hClippedRgn);
//::DeleteObject(hBrush);
/////////////////////////////
EndPaint(m_hWnd,&ps);
return 0;
}
LRESULT OnSize(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
int w=LOWORD(lParam);
int h=HIWORD(lParam);
_TinyRect erect;
erect.left=BORDER_SIZE;
erect.right=w-BORDER_SIZE;
erect.top=0;
erect.bottom=h;
m_wEditWindow.SetWindowPos(BORDER_SIZE,0,w-BORDER_SIZE,h,0);
return 0;
}
LRESULT OnScroll(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
_TinyRect rect;
GetClientRect(&rect);
rect.top=0;
rect.left=0;
rect.right=BORDER_SIZE;
return InvalidateRect(&rect);
}
protected:
_TinyRichEdit m_wEditWindow;
UINT m_iLineMarkerPos;
IScriptSystem *m_pIScriptSystem;
string m_strSourceFile;
};
class CLUADbg : public _TinyFrameWindow, IScriptObjectDumpSink
{
public:
CLUADbg();
virtual ~CLUADbg();
bool LoadFile(const char *pszFile, bool bForceReload = false);
void PlaceLineMarker(UINT iLine);
void SetStatusBarText(const char *pszText);
void GetStackAndLocals();
void SetSystem(ISystem *pISystem)
{
SetScriptSystem(pISystem->GetIScriptSystem());
m_pIPak = pISystem->GetIPak();
};
IScriptSystem * GetScriptSystem() { return m_pIScriptSystem; };
bool IsUserDisabled() const { return m_bDisabled; };
// For callback use byIScriptObjectDumpSink only, don't call directly
void OnElementFound(const char *sName,ScriptVarType type);
void OnElementFound(int nIdx,ScriptVarType type);
protected:
_BEGIN_MSG_MAP(CMainWindow)
_MESSAGE_HANDLER(WM_CLOSE,OnClose)
_MESSAGE_HANDLER(WM_SIZE,OnSize)
_MESSAGE_HANDLER(WM_CREATE,OnCreate)
_MESSAGE_HANDLER(WM_ERASEBKGND,OnEraseBkGnd)
_BEGIN_COMMAND_HANDLER()
_COMMAND_HANDLER(IDM_EXIT, OnClose)
_COMMAND_HANDLER(IDM_ABOUT, OnAbout)
_COMMAND_HANDLER(ID_DEBUG_RUN, OnDebugRun)
_COMMAND_HANDLER(ID_DEBUG_TOGGLEBREAKPOINT, OnToggleBreakpoint)
_COMMAND_HANDLER(ID_DEBUG_STEPINTO, OnDebugStepInto)
_COMMAND_HANDLER(ID_DEBUG_STEPOVER, OnDebugStepOver)
_COMMAND_HANDLER(ID_DEBUG_DISABLE, OnDebugDisable)
_COMMAND_HANDLER(ID_FILE_RELOAD, OnFileReload)
_END_COMMAND_HANDLER()
_MESSAGE_HANDLER(WM_NOTIFY,OnNotify)
_END_MSG_MAP()
//
LRESULT OnClose(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT OnCreate(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam);
LRESULT OnSize(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam);
LRESULT OnEraseBkGnd(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam);
LRESULT OnAbout(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam);
LRESULT OnToggleBreakpoint(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam);
LRESULT OnDebugStepInto(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
m_pIScriptSystem->DebugStepInto();
OnClose(hWnd,message,wParam,lParam);
return 1;
};
LRESULT OnDebugStepOver(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
m_pIScriptSystem->DebugStepNext();
OnClose(hWnd,message,wParam,lParam);
return 1;
};
LRESULT OnDebugRun(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
if (m_pIScriptSystem->GetBreakState() == bsStepNext ||
m_pIScriptSystem->GetBreakState() == bsStepInto)
{
// Leave step-by-step debugging
m_pIScriptSystem->DebugContinue();
}
OnClose(hWnd,message,wParam,lParam);
return 1;
};
LRESULT OnDebugDisable(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
// This doesn't completely disable debugging, errors will still cause the debugger to pop up
m_pIScriptSystem->DebugDisable();
m_bDisabled = true;
OnClose(hWnd,message,wParam,lParam);
return 1;
}
LRESULT OnNotify(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
NMHDR *n = (NMHDR *) lParam;
if (n->code == NM_DBLCLK) {
if(n->hwndFrom == m_wFilesTree.m_hWnd)
{
const char *pszFileName = m_wFilesTree.GetCurItemFileName();
LoadFile(pszFileName);
}
if(n->hwndFrom == m_wCallstack.m_hWnd)
{
char temp[512];
int sel=m_wCallstack.GetSelection();
if(sel!=-1)
{
m_wCallstack.GetItemText(sel,1,temp,sizeof(temp));
int linenum=atoi(temp);
if(linenum!=-1){
m_wCallstack.GetItemText(sel,2,temp,sizeof(temp));
LoadFile(temp);
PlaceLineMarker(linenum);
}
}
//jumping in the carrect func
}
}
return 1;
}
LRESULT OnFileReload(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
string strFileName = m_wScriptWindow.GetSourceFile();
if ((* strFileName.begin()) == '@')
strFileName.erase(strFileName.begin());
LoadFile(strFileName.c_str(), true);
return 1;
}
bool Reshape(int w, int h);
HTREEITEM AddVariableToTree(const char *sName, ScriptVarType type, HTREEITEM hParent = NULL);
void DumpTable(HTREEITEM hParent, IScriptObject *pITable, UINT& iRecursionLevel);
void SetScriptSystem(IScriptSystem *pIScriptSystem)
{
m_pIScriptSystem = pIScriptSystem;
m_wScriptWindow.SetScriptSystem(pIScriptSystem);
};
CSourceEdit m_wScriptWindow;
_TinyToolbar m_wToolbar;
_TinyTreeView m_wLocals;
_TinyTreeView m_wWatch;
_TinyListView m_wCallstack;
CFileTree m_wFilesTree;
_TinyWindow m_wndClient;
_TinyStatusBar m_wndStatus;
_TinyCaptionWindow m_wndLocalsCaption;
_TinyCaptionWindow m_wndWatchCaption;
_TinyCaptionWindow m_wndCallstackCaption;
_TinyCaptionWindow m_wndFileViewCaption;
_TinyCaptionWindow m_wndSourceCaption;
_TinySplitter m_wndMainHorzSplitter;
_TinySplitter m_wndWatchSplitter;
_TinySplitter m_wndWatchCallstackSplitter;
_TinySplitter m_wndSrcEditSplitter;
IScriptSystem *m_pIScriptSystem;
ICryPak *m_pIPak;
bool m_bDisabled;
// Used to let the enumeration function access it
IScriptObject *m_pIVariable;
HTREEITEM m_hRoot;
UINT m_iRecursionLevel;
_TinyTreeView *m_pTreeToAdd;
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,80 @@
#include "stdafx.h"
#include "LuaDbgInterface.h"
#include "LUADBG.h"
bool g_bDone = false;
bool InvokeDebugger(CLUADbg *pDebugger, const char *pszSourceFile, int iLine, const char *pszReason)
{
HACCEL hAccelerators = NULL;
MSG msg;
IScriptSystem *pIScriptSystem = NULL;
if (pDebugger == NULL)
return false;
// TODO: Would be better to handle this with a console variable since this
// would give the user a chance to reactivate it. Or maybe using the
// m_bsBreakState of the scripting sytem, but I'm not sure how to add it there
if (pDebugger->IsUserDisabled())
return true;
pIScriptSystem = pDebugger->GetScriptSystem();
// Debugger not inititalized
if (pDebugger == NULL)
return false;
if (!::IsWindow(pDebugger->m_hWnd))
return false;
if ((hAccelerators = LoadAccelerators(_Tiny_GetResourceInstance(), MAKEINTRESOURCE(IDR_LUADGB_ACCEL))) == NULL)
{
// No accelerators
}
// Make sure the debugger is displayed maximized when it was left like that last time
// TODO: Maybe serialize this with the other window settings
if (::IsZoomed(pDebugger->m_hWnd))
::ShowWindow(pDebugger->m_hWnd, SW_MAXIMIZE);
else
::ShowWindow(pDebugger->m_hWnd, SW_NORMAL);
::SetForegroundWindow(pDebugger->m_hWnd);
if (pszSourceFile && pszSourceFile[0] == '@')
{
pDebugger->LoadFile(&pszSourceFile[1]);
iLine = __max(0, iLine);
pDebugger->PlaceLineMarker(iLine);
}
if (pszReason)
pDebugger->SetStatusBarText(pszReason);
pDebugger->GetStackAndLocals();
g_bDone = false;
while (GetMessage(&msg, NULL, 0, 0) && !g_bDone)
{
if (hAccelerators == NULL || TranslateAccelerator(pDebugger->m_hWnd, hAccelerators, &msg) == 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if (!IsWindow(pDebugger->m_hWnd))
DebugBreak();
// Don't hide the window when the debugger will be triggered next frame anyway
if (pIScriptSystem->GetBreakState() != bsStepNext &&
pIScriptSystem->GetBreakState() != bsStepInto)
{
::ShowWindow(pDebugger->m_hWnd, SW_HIDE);
}
DestroyAcceleratorTable(hAccelerators);
return (int) msg.wParam == 0;
return true;
}

View File

@@ -0,0 +1,10 @@
#ifndef __LUA_DBG_INTERFACE_H__
#define __LUA_DBG_INTERFACE_H__
#pragma once
class CLUADbg;
bool InvokeDebugger(CLUADbg *pDebugger, const char *pszSourceFile = NULL, int iLine = 0, const char *pszReason = NULL);
#endif

View File

@@ -0,0 +1,55 @@
#ifndef _TINY_BROWSE_FOLDER_H_
#define _TINY_BROWSE_FOLDER_H_
#pragma once
#ifndef __TINY_MAIN_H__
#error "_TinyBrowseFolder require <_TinyMain.h>"
#endif
#include <Shlobj.h>
#include <windows.h>
// TODO
BOOL _TinyBrowseForFolder(char szPathOut[_MAX_PATH], _TinyWindow *pParent = NULL)
{
BROWSEINFO sInfo;
char szDisplayName[_MAX_PATH];
ITEMIDLIST *pList = NULL;
szPathOut[0] = '\0';
sInfo.hwndOwner = (pParent == NULL) ? NULL : pParent->m_hWnd;
sInfo.pidlRoot = NULL;
sInfo.pszDisplayName = szDisplayName;
sInfo.ulFlags = BIF_RETURNONLYFSDIRS;
sInfo.lpfn = NULL;
sInfo.lParam = 0;
sInfo.iImage = 0;
__try
{
if (FAILED(CoInitialize(NULL)))
__leave;
CoInitialize(NULL);
SHBrowseForFolder(&sInfo);
if ((pList = SHBrowseForFolder(&sInfo)) == NULL)
__leave;
// SHGetPathFromIDList
}
__finally
{
CoUninitialize();
}
return TRUE;
}
// char szTmp[_MAX_PATH];
// extern BOOL g_bTest = _TinyBrowseForFolder(szTmp);
#endif

View File

@@ -0,0 +1,70 @@
#ifndef _TINY_CAPTION_WINDOW_H_
#define _TINY_CAPTION_WINDOW_H_
#pragma once
#include <string>
#include "_TinyWindow.h"
class _TinyCaptionWindow : public _TinyWindow
{
public:
_TinyCaptionWindow() { m_pContent = NULL; };
~_TinyCaptionWindow() { };
BOOL Create(const char *pszTitle, _TinyWindow *pContent, _TinyWindow *pParent)
{
m_strCaption = pszTitle;
if (!_TinyWindow::Create(_T("_default_TinyWindowClass"), pszTitle, WS_VISIBLE | WS_CHILD, 0, NULL, pParent))
return FALSE;
m_pContent = pContent;
m_pContent->MakeChild();
m_pContent->SetParent(this);
NotifyReflection(TRUE);
return TRUE;
};
bool Reshape(int iCX, int iCY)
{
_TinyRect rcClient;
_TinyAssert(m_pContent);
_TinyWindow::Reshape(iCX, iCY);
GetClientRect(&rcClient);
m_pContent->SetWindowPos(0, iTitleBarHeight, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
m_pContent->Reshape(rcClient.right, rcClient.bottom - iTitleBarHeight);
return true;
};
protected:
_TinyWindow *m_pContent;
string m_strCaption;
enum { iTitleBarHeight = 13 };
_BEGIN_MSG_MAP(_TinyCaptionWindow)
_MESSAGE_HANDLER(WM_PAINT, OnPaint)
_END_MSG_MAP()
LRESULT OnPaint(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
_TinyRect rcClient;
PAINTSTRUCT ps;
HDC hDC;
::BeginPaint(m_hWnd, &ps);
hDC = ::GetDC(m_hWnd);
GetClientRect(&rcClient);
rcClient.bottom = iTitleBarHeight;
rcClient.right -= 1;
::FillRect(hDC, &rcClient, GetSysColorBrush(COLOR_ACTIVECAPTION));
::SelectObject(hDC, GetStockObject(ANSI_VAR_FONT));
_TinyVerify(::SetTextColor(hDC, GetSysColor(COLOR_CAPTIONTEXT)) != CLR_INVALID);
::SetBkMode(hDC, TRANSPARENT);
::DrawText(hDC, m_strCaption.c_str(), -1, &rcClient, DT_CENTER | DT_VCENTER);
EndPaint(m_hWnd, &ps);
return 0;
};
};
#endif

View File

@@ -0,0 +1,20 @@
#ifndef _TINYCOOLEDIT_H_
#define _TINYCOOLEDIT_H_
#ifndef _TINY_WINDOW_H_
#error "_TinyCoolEdit require <_TinyWindow.h>"
#endif
class _TinyCoolEdit : public _TinyRichEdit
{
virtual BOOL Create(ULONG nID=0,DWORD dwStyle=WS_VISIBLE,DWORD dwExStyle=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL){
BOOL bRes=_TinyEdit::Create(nID,dwStyle,dwExStyle,pRect,pParentWnd);
if(!bRes)return FALSE;
return TRUE;
}
bool Reshape(int w,int h)
{
}
};
#endif //_TINYCOOLEDIT_H_

View File

@@ -0,0 +1,57 @@
#ifndef __TINY_FILE_ENUM_H__
#define __TINY_FILE_ENUM_H__
#pragma once
#include <io.h>
class _TinyFileEnum {
public:
_TinyFileEnum() { m_hEnumFile = -1L; };
virtual ~_TinyFileEnum() {
if (m_hEnumFile != -1L) {
_findclose(m_hEnumFile);
m_hEnumFile = -1L;
}
};
bool GetNextFile(struct __finddata64_t *pFile) {
if (_findnext64(m_hEnumFile, pFile) == -1L) {
_findclose(m_hEnumFile);
m_hEnumFile = -1L;
return false;
};
return true;
}
bool StartEnumeration(const char *pszEnumPathAndPattern, __finddata64_t *pFile) {
if (m_hEnumFile != -1L) {
_findclose(m_hEnumFile);
m_hEnumFile = -1L;
}
if ((m_hEnumFile = _findfirst64(pszEnumPathAndPattern, pFile)) == -1L) {
_findclose(m_hEnumFile);
m_hEnumFile = -1L;
return false;
}
return true;
}
bool StartEnumeration(char *pszEnumPath, char *pszEnumPattern, __finddata64_t *pFile) {
char szPath[_MAX_PATH];
strcpy(szPath, pszEnumPath);
if (szPath[strlen(szPath)] != '\\' &&
szPath[strlen(szPath)] != '/') {
strcat(szPath, "\\");
}
strcat(szPath, pszEnumPattern);
m_hEnumFile = _findfirst64(szPath, pFile);
return m_hEnumFile != -1;
}
protected:
intptr_t m_hEnumFile;
};
#endif

View File

@@ -0,0 +1,65 @@
#ifndef __TINY_IMAGE_LIST_H__
#define __TINY_IMAGE_LIST_H__
#pragma once
#ifndef __TINY_MAIN_H__
#error "_TinyImageList requires <_TinyMain.h>"
#endif
class _TinyImageList
{
public:
_TinyImageList() { m_hImgLst = NULL; };
~_TinyImageList()
{
if (m_hImgLst)
_TinyVerify(ImageList_Destroy(m_hImgLst));
};
BOOL Create(UINT iFlags = ILC_COLOR, UINT iCX = 16, UINT iCY = 16, UINT iMaxItems = 32)
{
_TinyAssert(m_hImgLst == NULL);
m_hImgLst = ImageList_Create(iCX, iCY, iFlags, 0, iMaxItems);
if (m_hImgLst == NULL)
{
_TINY_CHECK_LAST_ERROR
return FALSE;
}
return TRUE;
};
BOOL CreateFromBitmap(const char *pszBitmap, UINT iCX)
{
_TinyAssert(m_hImgLst == NULL);
m_hImgLst = ImageList_LoadBitmap(_Tiny_GetResourceInstance(), pszBitmap, iCX, 32, 0x00FF00FF);
if (m_hImgLst == NULL)
{
_TINY_CHECK_LAST_ERROR
return FALSE;
}
return TRUE;
};
BOOL AddImage(DWORD dwResource)
{
_TinyAssert(m_hImgLst);
HBITMAP hBmp = LoadBitmap(_Tiny_GetResourceInstance(), MAKEINTRESOURCE(dwResource));
if (hBmp == NULL)
{
_TINY_CHECK_LAST_ERROR
return FALSE;
}
ImageList_Add(m_hImgLst, hBmp, NULL);
_TinyVerify(DeleteObject(hBmp));
};
HIMAGELIST GetHandle() { return m_hImgLst; };
UINT GetImageCount() const { return ImageList_GetImageCount(m_hImgLst); };
protected:
HIMAGELIST m_hImgLst;
};
#endif

View File

@@ -0,0 +1,200 @@
/******************************************************************************************
TINY WINDOWS LIBRARY
copyright by Alberto Demichelis 2001
email: albertodemichelis@hotmail.com
right now this code is not GPL or LGPL in any way
******************************************************************************************/
#ifndef __TINY_MAIN_H__
#define __TINY_MAIN_H__
#pragma once
#include "CryLibrary.h"
#include <commctrl.h>
#pragma comment (lib , "comctl32.lib")
///////////////////////////////////////////////////////////////////////////////////////////
// Common includes
///////////////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <math.h>
///////////////////////////////////////////////////////////////////////////////////////////
// Helper macros
///////////////////////////////////////////////////////////////////////////////////////////
#define _TINY_SIGNED_LOWORD(l) ((int16)((int32)(l) & 0xffff))
#define _TINY_SIGNED_HIWORD(l) ((int16)((int32)(l) >> 16))
#define _T
///////////////////////////////////////////////////////////////////////////////////////////
// Debug functions / macros
///////////////////////////////////////////////////////////////////////////////////////////
#if defined(WIN64) || defined(LINUX64)
#define _TinyVerify(x) { if (!(x)) assert(0); }
#else
#define _TinyVerify(x) { if (!(x)) { DEBUG_BREAK; }; }
#endif
#if defined(_DEBUG) && !defined(WIN64) && !defined(LINUX64)
#define _TinyAssert(x) { if (!(x)) { DEBUG_BREAK; }; }
#else
#define _TinyAssert(x) __noop(x);
#endif
__inline void __cdecl _TinyTrace(const char *sFormat, ...)
{
va_list vl;
static char sTraceString[1024];
va_start(vl, sFormat);
vsprintf(sTraceString, sFormat, vl);
va_end(vl);
strcat(sTraceString, "\n");
::OutputDebugString(sTraceString);
}
#define _TINY_CHECK_LAST_ERROR _TinyCheckLastError(__FILE__, __LINE__);
__inline void _TinyCheckLastError(const char *pszFile, int iLine)
{
if (GetLastError() != ERROR_SUCCESS)
{
// Format an error message
char szMessageBuf[2048];
char szLineFileInfo[_MAX_PATH + 256];
FormatMessage(
FORMAT_MESSAGE_ARGUMENT_ARRAY |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
szMessageBuf,
2048,
NULL
);
sprintf(szLineFileInfo, "Error catched in file %s line %i", pszFile, iLine);
strcat(szMessageBuf, szLineFileInfo);
#ifdef _DEBUG
MessageBox(NULL, szMessageBuf, "Tiny Framework Error", MB_OK | MB_ICONERROR);
#else
_TinyTrace(szMessageBuf);
#endif
// Error processed
SetLastError(ERROR_SUCCESS);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Gobal variables and acessors
///////////////////////////////////////////////////////////////////////////////////////////
#define _TINY_DECLARE_APP() \
LPTSTR g_lpCmdLine; \
HINSTANCE g_hResourceInstance;
extern LPTSTR g_lpCmdLine;
extern HINSTANCE g_hResourceInstance;
inline HINSTANCE _Tiny_GetInstance()
{
return (HINSTANCE) GetModuleHandle(NULL);
}
inline HINSTANCE _Tiny_GetResourceInstance()
{
return g_hResourceInstance;
}
inline LPCTSTR _Tiny_GetCommandLine()
{
return g_lpCmdLine;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Global structures
///////////////////////////////////////////////////////////////////////////////////////////
class _TinyRect: public RECT{
public:
_TinyRect(){
left=0;
right=0;
top=0;
bottom=0;
}
_TinyRect(RECT &rect){
left=rect.left;
right=rect.right;
top=rect.top;
bottom=rect.bottom;
}
_TinyRect(int w,int h){
left=0;
right=w;
top=0;
bottom=h;
}
_TinyRect(int x,int y,int w,int h){
left=x;
right=x+w;
top=y;
bottom=y+h;
}
};
///////////////////////////////////////////////////////////////////////////////////////////
// Main window include
///////////////////////////////////////////////////////////////////////////////////////////
#include "_TinyWindow.h"
///////////////////////////////////////////////////////////////////////////////////////////
// Inititalization
///////////////////////////////////////////////////////////////////////////////////////////
inline BOOL _Tiny_InitApp(HINSTANCE hInstance,HINSTANCE hResourceInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,DWORD nIcon=0)
{
SetLastError(ERROR_SUCCESS);
g_lpCmdLine=lpCmdLine;
g_hResourceInstance=hResourceInstance;
INITCOMMONCONTROLSEX icc;
icc.dwSize=sizeof(INITCOMMONCONTROLSEX);
icc.dwICC=ICC_TREEVIEW_CLASSES |ICC_BAR_CLASSES |ICC_LISTVIEW_CLASSES|ICC_COOL_CLASSES|ICC_WIN95_CLASSES ;
CryLoadLibrary("Riched20.dll");
::InitCommonControlsEx(&icc);
BOOL bRet = __RegisterSmartClass(hInstance,nIcon) ? TRUE : FALSE;
return bRet;
}
/*
if (!TranslateAccelerator(
hwndMain, // handle to receiving window
haccel, // handle to active accelerator table
&msg)) // message data
{
*/
inline int _Tiny_MainLoop(HACCEL hAccelTable = NULL, HWND hAccelTarget = NULL)
{
MSG msg;
//_TinyAssert((hAccelTable == NULL && hAccelTarget == NULL) ||
// (hAccelTable != NULL && hAccelTarget != NULL));
while (GetMessage(&msg, NULL, 0, 0))
{
if (hAccelTable == NULL || TranslateAccelerator(hAccelTarget, hAccelTable, &msg) == 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
#endif

View File

@@ -0,0 +1,73 @@
#ifndef __TINY_REGISTRY_H__
#define __TINY_REGISTRY_H__
#pragma once
class _TinyRegistry {
public:
_TinyRegistry() {};
virtual ~_TinyRegistry() {};
bool WriteNumber(const char *pszKey, const char *pszValueName,
DWORD dwValue, HKEY hRoot = HKEY_CURRENT_USER) {
HKEY hKey = _RegCreateKeyEx(pszKey, hRoot);
if (hKey == NULL)
return false;
if (RegSetValueEx(hKey, pszValueName, 0, REG_DWORD,
(CONST BYTE *) &dwValue, sizeof(DWORD)) != ERROR_SUCCESS) {
RegCloseKey(hKey);
_TINY_CHECK_LAST_ERROR
return false;
}
RegCloseKey(hKey);
return true;
};
bool WriteString(const char *pszKey, const char *pszValueName,
const char *pszString, HKEY hRoot = HKEY_CURRENT_USER) {
HKEY hKey = _RegCreateKeyEx(pszKey, hRoot);
if (hKey == NULL)
return false;
if (RegSetValueEx(hKey, pszValueName, 0, REG_SZ,
(CONST BYTE *) pszString, strlen(pszString) + 1) != ERROR_SUCCESS) {
RegCloseKey(hKey);
_TINY_CHECK_LAST_ERROR
return false;
}
RegCloseKey(hKey);
return true;
};
bool ReadNumber(const char *pszKey, const char *pszValueName, DWORD& dwValOut,
DWORD dwValDefault = 0, HKEY hRoot = HKEY_CURRENT_USER) {
HKEY hKey = _RegCreateKeyEx(pszKey, hRoot);
DWORD dwType, dwSize = sizeof(DWORD);
LONG lRet;
if (hKey == NULL)
return false;
dwValOut = dwValDefault;
lRet = RegQueryValueEx(hKey, pszValueName, NULL, &dwType,
(LPBYTE) &dwValOut, &dwSize);
if (lRet != ERROR_SUCCESS || dwType != REG_DWORD) {
RegCloseKey(hKey);
return false;
}
RegCloseKey(hKey);
return true;
}
protected:
HKEY _RegCreateKeyEx(const char *pszKey, HKEY hRoot = HKEY_CURRENT_USER) {
LONG lRes;
HKEY hKey;
DWORD dwDisp;
lRes = RegCreateKeyEx(hRoot, pszKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, &dwDisp);
if (lRes != ERROR_SUCCESS) {
_TINY_CHECK_LAST_ERROR
return NULL;
}
return hKey;
}
};
#endif

View File

@@ -0,0 +1,219 @@
#ifndef _TINYSPLITTER_H_
#define _TINYSPLITTER_H_
#ifndef _TINY_WINDOW_H_
#error "_TinySplitter require <_TinyWindow.h>"
#endif
#define SPLITTER_WIDTH 3
#define DRAW_RAISED_SPLITTER
class _TinySplitter : public _TinyWindow
{
public:
virtual BOOL Create(_TinyWindow *pParentWnd=NULL, _TinyWindow *pPan0=NULL,_TinyWindow *pPan1=NULL,bool bVertical=false, const RECT* pRect=NULL){
BOOL bRes=_TinyWindow::Create(_T("_default_TinyWindowClass"),_T(""),WS_VISIBLE|WS_CHILD|WS_CLIPCHILDREN,NULL,pRect,pParentWnd);
if(!bRes)return FALSE;
m_bVertical = bVertical;
m_bDragging = false;
SetFirstPan(pPan0);
SetSecondPan(pPan1);
CenterSplitter();
NotifyReflection(TRUE);
return TRUE;
}
void SetFirstPan(_TinyWindow *pWnd)
{
m_pPan0 = pWnd;
if (m_pPan0 != NULL) {
m_pPan0->SetParent(this);
m_pPan0->MakeChild();
m_pPan0->NotifyReflection(TRUE);
}
};
void SetSecondPan(_TinyWindow *pWnd)
{
m_pPan1 = pWnd;
if (m_pPan1) {
m_pPan1->SetParent(this);
m_pPan1->MakeChild();
m_pPan1->NotifyReflection(TRUE);
}
};
bool Reshape(int w,int h)
{
if (m_pPan0 == NULL || m_pPan1 == NULL)
return false;
const int iHlfSplitterWdh = SPLITTER_WIDTH / 2;
SetWindowPos(0, 0, w, h, SWP_NOZORDER | SWP_NOMOVE);
if (m_bVertical) {
int iEndUpper = ReverseYAxis(m_iSplitterPos) - iHlfSplitterWdh;
m_pPan0->Reshape(w, iEndUpper);
m_pPan0->SetWindowPos(0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
m_pPan1->Reshape(w, h - (iEndUpper + iHlfSplitterWdh) - 2);
m_pPan1->SetWindowPos(0, iEndUpper + iHlfSplitterWdh * 2, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
else {
int iEndLeft = m_iSplitterPos - iHlfSplitterWdh;
m_pPan0->Reshape(iEndLeft , h);
m_pPan0->SetWindowPos(0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
m_pPan1->Reshape(w - (iEndLeft + iHlfSplitterWdh) - 2, h);
m_pPan1->SetWindowPos(iEndLeft + iHlfSplitterWdh * 2, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
return true;
}
bool Reshape()
{
_TinyRect rc;
GetClientRect(&rc);
return Reshape(rc.right, rc.bottom);
}
void CenterSplitter() {
if (IsCreated()) {
HWND hWndParent = GetParent(m_hWnd);
if (IsWindow(hWndParent)) {
_TinyRect rc;
::GetClientRect(hWndParent, &rc);
m_iSplitterPos = m_bVertical ? rc.bottom / 2 : rc.right / 2;
}
}
}
UINT GetSplitterPos() const { return m_iSplitterPos; };
void SetSplitterPos(UINT iPos) { m_iSplitterPos = iPos; };
protected:
_BEGIN_MSG_MAP(CSourceEdit)
_MESSAGE_HANDLER(WM_PAINT, OnPaint)
_MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
_MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
_MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
_MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
_END_MSG_MAP()
void ObtainSplitterRect(_TinyRect &rcOut)
{
const int iHlfSplitterWdh = SPLITTER_WIDTH / 2;
GetClientRect(&rcOut);
if (m_bVertical) {
rcOut.top = ReverseYAxis(m_iSplitterPos) - iHlfSplitterWdh - 2;
rcOut.bottom = ReverseYAxis(m_iSplitterPos) + iHlfSplitterWdh + 2;
}
else {
rcOut.left = m_iSplitterPos - iHlfSplitterWdh;
rcOut.right = m_iSplitterPos + iHlfSplitterWdh;
}
}
void EnableMouseTracking()
{
// Enable hover / leave messages
TRACKMOUSEEVENT evt;
evt.cbSize = sizeof(TRACKMOUSEEVENT);
evt.dwFlags = TME_HOVER | TME_LEAVE;
evt.hwndTrack = m_hWnd;
evt.dwHoverTime = 1;
_TrackMouseEvent(&evt);
}
LRESULT OnMouseMove(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
// To receive the leave message
EnableMouseTracking();
HCURSOR hCur = LoadCursor(NULL, m_bVertical ? IDC_SIZENS : IDC_SIZEWE);
_TinyAssert(hCur != NULL);
SetCursor(hCur);
if (m_bDragging) {
int xPos = _TINY_SIGNED_LOWORD(lParam);
int yPos = _TINY_SIGNED_HIWORD(lParam);
m_iSplitterPos = m_bVertical ? ReverseYAxis(yPos) : xPos;
MoveSplitterToValidPos();
Reshape();
}
return 0;
}
LRESULT OnMouseLeave(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
HCURSOR hCur = LoadCursor(NULL, IDC_ARROW);
SetCursor(hCur);
return 0;
}
LRESULT OnLButtonDown(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
m_bDragging = true;
SetCapture();
return 0;
}
LRESULT OnLButtonUp(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
m_bDragging = false;
_TinyVerify(ReleaseCapture());
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
m_iSplitterPos = m_bVertical ? ReverseYAxis(yPos) : xPos;
MoveSplitterToValidPos();
Reshape();
return 0;
}
LRESULT OnPaint(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
_TinyRect rc;
PAINTSTRUCT ps;
HDC hDC;
::BeginPaint(m_hWnd, &ps);
hDC = ::GetDC(m_hWnd);
GetClientRect(&rc);
::FillRect(hDC, &rc, GetSysColorBrush(COLOR_BTNFACE));
ObtainSplitterRect(rc);
#ifdef DRAW_RAISED_SPLITTER
DrawFrameControl(hDC, &rc, DFC_BUTTON, DFCS_BUTTONPUSH);
#else
DrawFrameControl(hDC, &rc, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED);
#endif
EndPaint(m_hWnd,&ps);
return 0;
}
void MoveSplitterToValidPos()
{
return; // TODO
_TinyRect rc;
GetClientRect(&rc);
m_iSplitterPos = __min(__max(m_iSplitterPos, SPLITTER_WIDTH), rc.bottom - SPLITTER_WIDTH);
}
UINT ReverseYAxis(UINT iY) {
_TinyRect rc;
_TinyVerify(GetClientRect(&rc));
return rc.bottom - iY;
}
long m_iSplitterPos;
_TinyWindow *m_pPan0;
_TinyWindow *m_pPan1;
bool m_bVertical;
bool m_bDragging;
};
#endif

View File

@@ -0,0 +1,38 @@
#ifndef __TINY_STATUS_BAR__
#define __TINY_STATUS_BAR__
#pragma once
#ifndef _TINY_WINDOW_H_
#error "_TinyStatusBar requires <_TinyWindow.h>"
#endif
class _TinyStatusBar : public _TinyWindow {
public:
_TinyStatusBar() {};
virtual ~_TinyStatusBar() {};
BOOL Create(ULONG nID=0, const _TinyRect *pRect=NULL, _TinyWindow *pParentWnd = NULL) {
if(!_TinyWindow::Create(STATUSCLASSNAME, _T(""), WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, NULL, pRect, pParentWnd, nID)) {
_TINY_CHECK_LAST_ERROR
return FALSE;
}
if (pParentWnd) {
_TinyRect rc;
GetClientRect(&rc);
Reshape(rc.right - rc.left, rc.bottom - rc.top);
}
return TRUE;
};
void SetPanelText(const char *pszText)
{
SendMessage(SB_SETTEXT, SB_SIMPLEID, (LPARAM) pszText);
};
protected:
};
#endif

View File

@@ -0,0 +1,64 @@
#ifndef _TINYTREELIST_H_
#define _TINYTREELIST_H_
#ifndef _TINY_WINDOW_H_
#error "_TinyTreeList requires <_TinyWindow.h>"
#endif
#define ID_HEADER 1
#define ID_TREE 2
class _TinyTreeList : public _TinyWindow{
protected:
_BEGIN_MSG_MAP(_TinyTreeList)
_MESSAGE_HANDLER(WM_SIZE,OnSize)
_MESSAGE_HANDLER(WM_ERASEBKGND,OnEraseBkGnd)
_END_MSG_MAP()
public:
_TinyTreeList()
{
m_nNumOfColumns=0;
}
BOOL Create(ULONG nID=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL)
{
if(!_TinyWindow::Create(NULL,_T(""),WS_CHILD|WS_VISIBLE,NULL,pRect,pParentWnd,nID))
return FALSE;
m_ttvTreeView.Create(ID_TREE,WS_CHILD|TVS_HASLINES|TVS_HASBUTTONS|WS_VISIBLE,0,pRect,this);
m_thHeader.Create(ID_HEADER,WS_VISIBLE|WS_CHILD | WS_BORDER | HDS_BUTTONS | HDS_HORZ,0,0,this);
if(pParentWnd)
{
_TinyRect rect;
GetClientRect(&rect);
Reshape(rect.right-rect.left,rect.bottom-rect.top);
}
return TRUE;
}
BOOL AddCoulumn(LPSTR sName,int nWidth,BOOL bTree=FALSE)
{
m_thHeader.InsertItem(m_nNumOfColumns,nWidth,sName);
m_nNumOfColumns++;
return TRUE;
}
private:
LRESULT OnSize(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
Reshape(LOWORD(lParam),HIWORD(lParam));
return 0;
}
LRESULT OnEraseBkGnd(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
return 1;
}
void Reshape(int w,int h)
{
m_thHeader.SetWindowPos(0,0,w,20,0);
m_ttvTreeView.SetWindowPos(0,20,w,h-20,0);
}
_TinyTreeView m_ttvTreeView;
_TinyHeader m_thHeader;
int m_nNumOfColumns;
};
#endif

View File

@@ -0,0 +1,772 @@
/******************************************************************************************2
TINY WINDOWS LIBRARY
copyright by Alberto Demichelis 2001
email: albertodemichelis@hotmail.com
right now this code is not GPL or LGPL in any way
******************************************************************************************/
#ifndef _TINY_WINDOW_H_
#define _TINY_WINDOW_H_
#include <Richedit.h>
#ifndef __TINY_MAIN_H__
#error "_TinyWindow require <_TinyMain.h>"
#endif
#include <ISystem.h>
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK _TinyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static BOOL CALLBACK _TinyDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
inline ATOM __RegisterSmartClass(HINSTANCE hInstance,DWORD nIcon)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) _TinyWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(nIcon));
wc.hCursor = 0;
// wc.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
wc.hbrBackground = NULL;
wc.lpszMenuName = 0;
wc.lpszClassName = _T("_default_TinyWindowClass");
return RegisterClass(&wc);
}
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
#define _BEGIN_MSG_MAP(__class) \
virtual LRESULT __Tiny_WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) \
{ int wmId = 0, wmEvent = 0;\
switch(message){
#define _BEGIN_DLG_MSG_MAP(__class) \
virtual LRESULT __Tiny_WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) \
{ int wmId = 0, wmEvent = 0;\
switch(message){
#define _MESSAGE_HANDLER(__message,__handler) \
case __message: \
return __handler(hWnd,message,wParam,lParam); \
break;
#define _BEGIN_COMMAND_HANDLER() \
case WM_COMMAND: \
wmId = LOWORD(wParam); \
wmEvent = HIWORD(wParam); \
switch(wmId){ \
#define _COMMAND_HANDLER(__wmId,__command_handler) \
case __wmId: \
return __command_handler(hWnd,message, wParam, lParam); \
break;
#define _DEFAULT_DLG_COMMAND_HANDLERS() \
case IDOK: \
m_nModalRet=IDOK;\
DestroyWindow(m_hWnd); \
break; \
case IDCANCEL: \
m_nModalRet=IDCANCEL;\
DestroyWindow(m_hWnd); \
break;
#define _BEGIN_CMD_EVENT_FILTER(__wmId) \
case __wmId: \
switch(wmEvent){
#define _EVENT_FILTER(__wmEvent,__command_handler) \
case __wmEvent: \
return __command_handler(hWnd,message, wParam, lParam); \
break;
#define _END_CMD_EVENT_FILTER() \
default: \
break; \
} \
break;
#define _END_COMMAND_HANDLER() \
default: \
return DefWindowProc(hWnd, message, wParam, lParam); \
break; \
} \
break;
#define _END_MSG_MAP() \
default: \
return DefWindowProc(hWnd, message, wParam, lParam); \
break; \
} \
return 0; \
}
#define _END_DLG_MSG_MAP() \
default: \
return FALSE; \
break; \
} \
return 0; \
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class _TinyWindow{
public:
_TinyWindow(){
m_hWnd=NULL;
}
_TinyWindow(HWND hWnd){
m_hWnd=hWnd;
}
virtual ~_TinyWindow(){
Close();
}
virtual void Close(){
if(m_hWnd){
SetWindowLong(m_hWnd,GWLP_USERDATA,NULL);
DestroyWindow(m_hWnd);
m_hWnd=NULL;
}
}
virtual void Quit(){
PostQuitMessage(0);
// g_bDone=true;
//Close();
}
virtual LRESULT __Tiny_WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){return ::DefWindowProc(hWnd,message,wParam,lParam);}
virtual BOOL Create(LPCTSTR lpszClassName,LPCTSTR lpszWindowName,DWORD dwStyle=WS_VISIBLE,DWORD dwExStyle=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL,ULONG_PTR nID=0){
HWND hParent=NULL;
BOOL bSmart=FALSE;
int x=CW_USEDEFAULT,y=CW_USEDEFAULT,width=CW_USEDEFAULT,height=CW_USEDEFAULT;
//class name
if(!lpszClassName){
lpszClassName=_T("_default_TinyWindowClass");
bSmart=TRUE;
}
//parent
if(pParentWnd!=NULL)hParent=pParentWnd->m_hWnd;
//rect
if(pRect){
x=pRect->left;
y=pRect->top;
width=(pRect->right-pRect->left);
height=(pRect->bottom-pRect->top);
}
//create
m_hWnd=::CreateWindowEx(dwExStyle,lpszClassName,
lpszWindowName,
dwStyle,
x,
y,
width,
height,
hParent,
(HMENU)nID,
_Tiny_GetInstance(),
NULL);
if(!m_hWnd)
{
_TINY_CHECK_LAST_ERROR
return FALSE;
}
__Tiny_WindowProc(m_hWnd,WM_CREATE,0,0);
::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR> (this));
return TRUE;
}
virtual BOOL IsCreated() { return IsWindow(m_hWnd); };
virtual MakeChild()
{
_TinyAssert(IsCreated());
DWORD dwStyle = GetWindowLong(m_hWnd, GWL_STYLE);
dwStyle |= WS_CHILD;
SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);
}
virtual bool Reshape(int w, int h)
{
SetWindowPos(0, 0, w, h, SWP_NOZORDER | SWP_NOMOVE);
return true;
}
virtual void CenterOnScreen()
{
_TinyRect rc;
UINT iX = GetSystemMetrics(SM_CXFULLSCREEN);
UINT iY = GetSystemMetrics(SM_CYFULLSCREEN);
GetClientRect(&rc);
SetWindowPos(iX / 2 - rc.right / 2, iY / 2 - rc.bottom / 2, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
public:
HWND m_hWnd;
public:
//wrappers
virtual LRESULT SetTimer(UINT nIDEvent,UINT uElapse){
return (LRESULT)::SetTimer(m_hWnd,nIDEvent,uElapse,NULL);
}
virtual LRESULT KillTimer(UINT nIDEvent){
return (LRESULT)::KillTimer(m_hWnd,nIDEvent);
}
virtual LRESULT ShowWindow(int nCmdShow=SW_SHOW){
return (LRESULT)::ShowWindow(m_hWnd,nCmdShow);
}
virtual LRESULT SendMessage(UINT Msg,WPARAM wParam=0,LPARAM lParam=0){
return (LRESULT)::SendMessage(m_hWnd,Msg,wParam,lParam);
}
virtual LRESULT PostMessage(UINT Msg,WPARAM wParam=0,LPARAM lParam=0){
return (LRESULT)::PostMessage(m_hWnd,Msg,wParam,lParam);
}
virtual LRESULT SetWindowText(LPCTSTR lpString){
return (LRESULT)::SetWindowText(m_hWnd,lpString);
}
virtual LRESULT GetWindowText(LPTSTR lpString,int nMaxCount){
return (LRESULT)::GetWindowText(m_hWnd,lpString,nMaxCount);
}
virtual LRESULT GetClientRect(_TinyRect *pRect){
return (LRESULT)::GetClientRect(m_hWnd,pRect);
}
virtual LRESULT SetWindowPos(int x,int y,int cx,int cy,UINT flags){
return (LRESULT)::SetWindowPos(m_hWnd,0,x,y,cx,cy,flags);
}
virtual LRESULT InvalidateRect(_TinyRect *pRect=NULL,BOOL bErase=FALSE)
{
return ::InvalidateRect(m_hWnd,pRect,bErase);
}
virtual HWND SetParent(_TinyWindow *pParent)
{
if(pParent)
return ::SetParent(m_hWnd,pParent->m_hWnd);
else
return ::SetParent(m_hWnd,NULL);
}
virtual BOOL SetCapture(){
return ::SetCapture(m_hWnd)?TRUE:FALSE;
}
virtual void NotifyReflection(BOOL bEnable){
m_bReflectNotify=bEnable?true:false;
}
virtual BOOL HasNotifyReflection(){
return m_bReflectNotify;
}
private:
BOOL m_bReflectNotify;
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class _TinyDialog : public _TinyWindow{
public:
BOOL Create(LPCTSTR lpTemplate,_TinyWindow *pParent=NULL){
m_nModalRet=0;
HWND hParent=NULL;
if(pParent)hParent=pParent->m_hWnd;
m_hWnd=CreateDialog(_Tiny_GetResourceInstance(),lpTemplate,hParent,(DLGPROC) _TinyDlgProc);
if(!m_hWnd) {
_TINY_CHECK_LAST_ERROR
return FALSE;
}
FakeCreate();
return TRUE;
};
int DoModal(LPCTSTR lpTemplate, _TinyWindow *pParent = NULL)
{
INT_PTR nRet = DialogBoxParam(_Tiny_GetResourceInstance(), lpTemplate, (pParent != NULL) ?
pParent->m_hWnd : NULL, (DLGPROC) _TinyDlgProc, (LPARAM) this);
if (nRet == -1)
{
_TINY_CHECK_LAST_ERROR
return 0;
}
return nRet;
};
/*
int DoModal(){
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return m_nModalRet;
}
*/
protected:
void FakeCreate()
{
// Fake the WM_CREATE message
__Tiny_WindowProc(m_hWnd, WM_CREATE,0,0);
::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
};
public:
int m_nModalRet;
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class _TinyFrameWindow: public _TinyWindow{
public:
_TinyFrameWindow()
{
m_hMenu=NULL;
}
#ifdef WIN_CE
BOOL AddBarMenu(WORD idMenu){
m_hCommandBar = ::CommandBar_Create(_Tiny_GetResourceInstance(), m_hWnd, 1);
::CommandBar_InsertMenubar(m_hCommandBar , _Tiny_GetResourceInstance(), idMenu, 0);
return ::CommandBar_AddAdornments(m_hCommandBar , 0, 0);
}
HWND m_hCommandBar;
#else
bool AddMenu(WORD idMenu)
{
CryError("AddMenu");
m_hMenu=LoadMenu(_Tiny_GetResourceInstance(),MAKEINTRESOURCE(idMenu));
//<<FIXME>>
}
HMENU m_hMenu;
#endif
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class _TinyEdit: public _TinyWindow{
public:
virtual BOOL Create(ULONG nID=0,DWORD dwStyle=WS_VISIBLE,DWORD dwExStyle=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL){
BOOL bRes=_TinyWindow::Create(_T("EDIT"),_T(""),dwStyle,dwExStyle,pRect,pParentWnd,nID);
if(!bRes)return FALSE;
return TRUE;
}
virtual void AppendText(const TCHAR *sText)
{
SendMessage(EM_SETSEL,-1,-1);
SendMessage(EM_REPLACESEL,0,(LPARAM)sText);
SendMessage(EM_SCROLLCARET,0,0);
}
virtual int GetFirstVisibleLine()
{
return SendMessage(EM_GETFIRSTVISIBLELINE,0,0);
}
virtual int GetScrollPos()
{
TEXTMETRIC tm;
POINT pt;
int iSel=GetSel();
int iLine=LineFromChar(iSel);
GetCaretPos(&pt);
GetTextMetrics(&tm);
int cyLine=tm.tmHeight;
// Calculate the first visible line.
// While the vertical coordinate of the caret is greater than
// tmHeight, subtract tmHeight from the vertical coordinate and
// subtract 1 from the line number of the caret.
// The value remaining in the line number variable is the line
// number of the first visible line in the edit control.
int iTopLine=iLine;
while (pt.y > cyLine)
{
pt.y -=cyLine;
iTopLine--;
}
return iTopLine;
}
virtual int LineFromChar(int nSel)
{
return SendMessage(EM_LINEFROMCHAR, nSel, 0L);
}
virtual int GetSel()
{
return SendMessage(EM_GETSEL, NULL, 0L);
}
virtual void GetTextMetrics(TEXTMETRIC *tm)
{
HDC hDC;
HFONT hFont;
hDC=GetDC(m_hWnd);
hFont=(HFONT)SendMessage(WM_GETFONT, 0, 0L);
if (hFont != NULL)
SelectObject(hDC, hFont);
::GetTextMetrics(hDC,(TEXTMETRIC *)tm);
ReleaseDC(m_hWnd, hDC);
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class _TinyRichEdit: public _TinyWindow{
public:
virtual BOOL Create(ULONG nID=0,DWORD dwStyle=WS_VISIBLE,DWORD dwExStyle=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL){
BOOL bRes=_TinyWindow::Create(RICHEDIT_CLASS,_T(""),dwStyle,dwExStyle,pRect,pParentWnd,nID);
int n=::GetLastError();
if(!bRes)return FALSE;
return TRUE;
}
virtual void AppendText(const TCHAR *sText)
{
SendMessage(EM_SETSEL,-1,-1);
SendMessage(EM_REPLACESEL,0,(LPARAM)sText);
SendMessage(EM_SCROLLCARET,0,0);
}
virtual int GetFirstVisibleLine()
{
return SendMessage(EM_GETFIRSTVISIBLELINE,0,0);
}
virtual int GetScrollPos(POINT *pt)
{
return SendMessage(EM_GETSCROLLPOS,0,(LPARAM)pt);
}
virtual void ScrollToLine(UINT iLine)
{
UINT iChar = SendMessage(EM_LINEINDEX, iLine, 0);
UINT iLineLength = SendMessage(EM_LINELENGTH, iChar - 1, 0);
SendMessage(EM_SETSEL, iChar, iChar);
SendMessage(EM_LINESCROLL, 0, -99999);
SendMessage(EM_LINESCROLL, 0, iLine - 5);
}
virtual int LineFromChar(int nSel)
{
return SendMessage(EM_LINEFROMCHAR, nSel, 0L) + 1;
}
virtual int GetSel()
{
DWORD dwStart, dwEnd;
SendMessage(EM_GETSEL, (WPARAM) &dwStart, (LPARAM) &dwEnd);
return dwStart;
}
virtual void GetTextMetrics(TEXTMETRIC *tm)
{
HDC hDC;
HFONT hFont;
hDC=GetDC(m_hWnd);
hFont=(HFONT)SendMessage(WM_GETFONT, 0, 0L);
if (hFont != NULL)
SelectObject(hDC, hFont);
::GetTextMetrics(hDC,(TEXTMETRIC *)tm);
ReleaseDC(m_hWnd, hDC);
}
virtual void SetFont (HFONT hFont)
{
SendMessage(WM_SETFONT, (WPARAM) hFont, (LPARAM) 0);
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class _TinyStatic: public _TinyWindow{
public:
virtual BOOL Create(ULONG nID=0,DWORD dwStyle=WS_VISIBLE,DWORD dwStyleEx=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL){
BOOL bRes=_TinyWindow::Create(_T("STATIC"),_T(""),dwStyle,dwStyleEx,pRect,pParentWnd,nID);
if(!bRes)return FALSE;
return TRUE;
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class _TinyToolbar: public _TinyWindow{
public:
virtual BOOL Create(ULONG nMenuID=0,DWORD dwStyle=WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS,DWORD dwStyleEx=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL)
{
BOOL bRes=_TinyWindow::Create(TOOLBARCLASSNAME,_T(""),dwStyle,dwStyleEx,pRect,pParentWnd,nMenuID);
if(!bRes)
return FALSE;
SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
return TRUE;
}
virtual BOOL AddButtons(DWORD nBitmapID,TBBUTTON *pButtons,DWORD nNumOfButtons)
{
TBADDBITMAP tb;
tb.hInst = _Tiny_GetResourceInstance();
tb.nID = nBitmapID;
DWORD stdidx= SendMessage (TB_ADDBITMAP, nNumOfButtons, (LPARAM)&tb);
for (DWORD index = 0; index < nNumOfButtons; index++)
pButtons[index].iBitmap += stdidx;
SendMessage (TB_ADDBUTTONS, nNumOfButtons, (LPARAM) pButtons);
return TRUE;
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class _TinyListBox: public _TinyWindow{
public:
virtual BOOL Create(ULONG nID=0,DWORD dwStyle=WS_CHILD,DWORD dwStyleEx=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL)
{
BOOL bRes=_TinyWindow::Create(_T("LISTBOX"),_T(""),dwStyle,dwStyleEx,pRect,pParentWnd,nID);
if(!bRes)return FALSE;
return TRUE;
}
virtual int AddString(const TCHAR *sText)
{
return SendMessage(LB_ADDSTRING,0,(LPARAM)sText);
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class _TinyListView: public _TinyWindow{
public:
virtual BOOL Create(ULONG nID=0,DWORD dwStyle=WS_CHILD,DWORD dwStyleEx=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL)
{
BOOL bRes=_TinyWindow::Create(WC_LISTVIEW,_T(""),dwStyle,dwStyleEx,pRect,pParentWnd,nID);
if(!bRes)return FALSE;
return TRUE;
}
virtual void SetViewStyle(DWORD dwView)
{
// Retrieve the current window style.
DWORD dwStyle = GetWindowLong(m_hWnd, GWL_STYLE);
// Only set the window style if the view bits have changed.
if ((dwStyle & LVS_TYPEMASK) != dwView)
SetWindowLong(m_hWnd, GWL_STYLE,
(dwStyle & ~LVS_TYPEMASK) | dwView);
}
virtual int InsertColumn(int nCol,LPCTSTR lpszColumnHeading,int nWidth,int nSubItem=0,int nFormat = LVCFMT_LEFT)
{
LVCOLUMN lvc;
lvc.mask=LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
lvc.cx=nWidth;
lvc.pszText=(LPSTR)lpszColumnHeading;
lvc.iSubItem=nSubItem;
return ListView_InsertColumn(m_hWnd,nCol,&lvc);
}
virtual int InsertItem(int nCol,LPCTSTR pszText,int iSubItem = 0, int nParam=NULL)
{
LVITEM lvi;
lvi.mask=LVIF_PARAM | LVIF_TEXT;
lvi.iItem=nCol;
lvi.iSubItem=iSubItem;
lvi.pszText=(LPTSTR)pszText;
lvi.lParam=(LPARAM) nParam;
return ListView_InsertItem(m_hWnd, &lvi);
}
virtual int SetItemText(int nItem,int nSubItem,LPCTSTR pszText)
{
ListView_SetItemText(m_hWnd,nItem,nSubItem,(LPTSTR)pszText);
return 0;
}
virtual int GetItemText(int iItem,int iSubItem,LPTSTR pszText,int cchTextMax)
{
ListView_GetItemText(m_hWnd,iItem,iSubItem,pszText,cchTextMax);
return 0;
}
virtual int GetSelection()
{
return ListView_GetSelectionMark(m_hWnd); //-1 mean no selection
}
virtual void Clear() { ListView_DeleteAllItems(m_hWnd); };
};
class _TinyHeader: public _TinyWindow
{
public:
virtual BOOL Create(ULONG nID=0,DWORD dwStyle=WS_VISIBLE|WS_CHILD | WS_BORDER | HDS_BUTTONS | HDS_HORZ,DWORD dwStyleEx=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL)
{
BOOL bRes=_TinyWindow::Create(WC_HEADER,_T(""),dwStyle,dwStyleEx,pRect,pParentWnd,nID);
if(!bRes)
return FALSE;
/*if(pParentWnd)
{
_TinyRect rect;
pParentWnd->GetClientRect(&rect);
HDLAYOUT hdl;
WINDOWPOS wp;
hdl.prc = &rect;
hdl.pwpos = &wp;
if (!SendMessage(HDM_LAYOUT, 0, (LPARAM) &hdl))
return FALSE;
SetWindowPos(wp.x, wp.y,wp.cx, wp.cy, wp.flags | SWP_SHOWWINDOW);
}*/
return TRUE;
}
virtual int InsertItem(int iInsertAfter,int nWidth, LPSTR lpsz)
{
HDITEM hdi;
int index;
hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
hdi.pszText = lpsz;
hdi.cxy = nWidth;
hdi.cchTextMax = lstrlen(hdi.pszText);
hdi.fmt = HDF_LEFT | HDF_STRING;
index = SendMessage(HDM_INSERTITEM,
(WPARAM) iInsertAfter, (LPARAM) &hdi);
return index;
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class _TinyTreeView: public _TinyWindow{
public:
virtual BOOL Create(ULONG nID=0,DWORD dwStyle=WS_CHILD|TVS_HASLINES|TVS_HASBUTTONS|WS_VISIBLE,DWORD dwStyleEx=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL)
{
BOOL bRes=_TinyWindow::Create(WC_TREEVIEW,_T(""),dwStyle,dwStyleEx,pRect,pParentWnd,nID);
NotifyReflection(TRUE);
if(!bRes)
return FALSE;
return TRUE;
}
virtual HTREEITEM AddItemToTree(LPTSTR lpszItem,LPARAM ud=NULL,HTREEITEM hParent=NULL, UINT iImage=0)
{
TVITEM tv;
TVINSERTSTRUCT tvins;
static HTREEITEM hPrev = (HTREEITEM) TVI_FIRST;
memset(&tv,0,sizeof(TVITEM));
tv.mask=TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
tv.pszText=lpszItem;
tv.lParam=ud;
tv.iImage = iImage;
tv.iSelectedImage = iImage;
tvins.item = tv;
tvins.hInsertAfter = hPrev;
if(hParent==NULL)
tvins.hParent=TVI_ROOT;
else
tvins.hParent=hParent;
hPrev = (HTREEITEM) SendMessage(TVM_INSERTITEM, 0,
(LPARAM) (LPTVINSERTSTRUCT) &tvins);
TreeView_SortChildren(m_hWnd,hParent,0);
return hPrev;
};
virtual void SetImageList(HIMAGELIST hLst)
{
_TinyAssert(m_hWnd);
TreeView_SetImageList(m_hWnd, hLst, TVSIL_NORMAL);
};
HTREEITEM GetSelectedItem() { return TreeView_GetSelection(m_hWnd); };
LPARAM GetItemUserData(HTREEITEM hItem)
{
TVITEM tvItem;
BOOL bRet;
tvItem.hItem = hItem;
tvItem.mask = TVIF_HANDLE;
bRet = TreeView_GetItem(m_hWnd, &tvItem);
_TinyAssert(bRet);
return tvItem.lParam;
};
void Expand(HTREEITEM hItem)
{
TreeView_Expand(m_hWnd, hItem, TVE_EXPAND);
};
void Clear() { TreeView_DeleteAllItems(m_hWnd); };
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class _TinyScrollBar: public _TinyWindow{
public:
virtual BOOL Create(ULONG nID=0,DWORD dwStyle=WS_VISIBLE,DWORD dwStyleEx=0,const RECT* pRect=NULL,_TinyWindow *pParentWnd=NULL){
BOOL bRes=_TinyWindow::Create(_T("SCROLLBAR"),_T(""),dwStyle,dwStyleEx,pRect,pParentWnd,nID);
int n=GetLastError();
if(SBS_VERT&dwStyle)m_nBar=SB_VERT;
if(SBS_HORZ&dwStyle)m_nBar=SB_HORZ;
if(!bRes)return FALSE;
return TRUE;
}
virtual BOOL SetScrollPos(int nPos,BOOL bRedraw=TRUE){
return ::SetScrollPos(m_hWnd,SB_CTL,nPos,bRedraw);
}
virtual BOOL SetScrollInfo(LPSCROLLINFO lpsi,BOOL bRedraw=TRUE){
return ::SetScrollInfo(m_hWnd,SB_CTL,lpsi,bRedraw);
}
virtual int GetScrollPos(){
SCROLLINFO si;
si.cbSize=sizeof(SCROLLINFO);
si.fMask=SIF_POS;
::GetScrollInfo(m_hWnd,SB_CTL,&si);
return si.nPos;
}
private:
int m_nBar;
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////
static LRESULT CALLBACK _TinyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
_TinyWindow *pWnd;
pWnd=(_TinyWindow *)::GetWindowLongPtr(hWnd,GWLP_USERDATA);
if(pWnd)
{
if(message==WM_NOTIFY && pWnd->HasNotifyReflection())
{
HWND hParentWnd=::GetParent(hWnd);
if(hParentWnd)
{
_TinyWndProc(hParentWnd,WM_NOTIFY,wParam,lParam);
}
}
return pWnd->__Tiny_WindowProc(hWnd,message,wParam,lParam);
}
else
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
static BOOL CALLBACK _TinyDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
_TinyWindow *pWnd = NULL;
if (message == WM_INITDIALOG) {
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) lParam);
pWnd = reinterpret_cast<_TinyWindow *> (lParam);
_TinyAssert(!IsBadReadPtr(pWnd, sizeof(_TinyWindow)));
pWnd->m_hWnd = hWnd;
}
pWnd = (_TinyWindow *) ::GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (pWnd)
return (BOOL) pWnd->__Tiny_WindowProc(hWnd, message, wParam, lParam);
else
return FALSE;
}
#endif //_TINY_WINDOW_H_

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

5
CrySystem/MSSCCPRJ.SCC Normal file
View File

@@ -0,0 +1,5 @@
SCC = This is a source code control file
[CrySystem.vcproj]
SCC_Aux_Path = "P4SCC#perforce:1666##marcoc_code##PC018"
SCC_Project_Name = Perforce Project

View File

@@ -0,0 +1,92 @@
#include "stdafx.h"
#include "MTSafeAllocator.h"
#if defined(LINUX)
#define USE_CRT 1
#else
//#ifdef _DEBUG
//#define USE_CRT 1
//#else
#define USE_CRT 0
//#endif
#endif //LINUX
CMTSafeHeap::CMTSafeHeap(unsigned nInitialSize, unsigned nMaxSize)
{
m_numAllocations = 0;
m_nTotalAllocations = 0;
#if !USE_CRT
m_hHeap = HeapCreate (0, nInitialSize, nMaxSize);
#endif
}
CMTSafeHeap::~CMTSafeHeap()
{
#if !defined(LINUX)
assert (m_numAllocations == 0);
#endif
#if !USE_CRT
assert (HeapValidate(m_hHeap, 0, NULL));
HeapDestroy (m_hHeap);
#endif
}
// consolidates free space inthe heap, uncommits if too much
void CMTSafeHeap::Compact()
{
#if !defined(LINUX)//empty
#if !USE_CRT
HeapCompact(m_hHeap, 0);
#else
_heapmin();
#endif
#endif
}
void* CMTSafeHeap::TryAlloc(size_t nSize, const char* szDbgSource = NULL)
{
#if !USE_CRT
return HeapAlloc (m_hHeap, 0, nSize);
#else
#if !defined(LINUX) && defined(_DEBUG) && defined(_INC_CRTDBG) && defined(WIN32)
return _malloc_dbg (nSize, _NORMAL_BLOCK, szDbgSource, 0);
#else
return ::malloc (nSize);
#endif
#endif
}
void* CMTSafeHeap::Alloc (size_t nSize, const char* szDbgSource = NULL)
{
InterlockedIncrement(&m_numAllocations);
void *pResult = TryAlloc(nSize, szDbgSource);
if (!pResult)
{
Compact();
pResult = TryAlloc(nSize, szDbgSource);
}
if (!pResult)
InterlockedDecrement(&m_numAllocations);
return pResult;
}
void CMTSafeHeap::Free (void*p)
{
if (p)
{
BOOL bFreed;
#if !USE_CRT
bFreed = HeapFree (m_hHeap, 0, p);
#else
#if !defined(LINUX) && defined(_DEBUG) && defined(_INC_CRTDBG) && defined(WIN32)
_free_dbg (p, _NORMAL_BLOCK);
#else
::free (p);
#endif
bFreed = true;
#endif
InterlockedDecrement(&m_numAllocations);
assert (bFreed);
}
}

173
CrySystem/MTSafeAllocator.h Normal file
View File

@@ -0,0 +1,173 @@
#ifndef _CRY_SYSTEM_MT_SAFE_ALLOCATOR_HDR_
#define _CRY_SYSTEM_MT_SAFE_ALLOCATOR_HDR_
#include <stdexcept>
#if defined( LINUX )
# include "WinBase.h"
#endif
class CMTSafeHeap
{
public:
CMTSafeHeap(unsigned nInitialSize, unsigned nMaxSize);
~CMTSafeHeap();
void* Alloc (size_t nSize, const char* szDbgSource);
void Free (void*p);
// the number of allocations this heap holds right now
unsigned NumAllocations()const {return m_numAllocations;}
// the total size of all allocations
size_t GetAllocatedSize()const {return m_nTotalAllocations;}
// consolidates free space inthe heap, uncommits if too much
void Compact();
// zlib-compatible stubs
static void* StaticAlloc (void* pOpaque, unsigned nItems, unsigned nSize)
{
return ((CMTSafeHeap*)pOpaque)->Alloc(nItems * nSize, "zlib-compatible");
}
static void StaticFree (void* pOpaque, void* pAddress)
{
((CMTSafeHeap*)pOpaque)->Free(pAddress);
}
protected:
void* TryAlloc(size_t nSize, const char* szDbgSource);
HANDLE m_hHeap;
LONG m_numAllocations;
size_t m_nTotalAllocations;
};
// this CMTSafeAllocator is MT-safe and is for use in, e.g. Stream Engine
// in multithreaded environment. STL-Compatible
template<class _Ty, class _THeap=CMTSafeHeap>
class CMTSafeAllocator
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef _Ty *pointer;
typedef const _Ty *const_pointer;
typedef _Ty & reference;
typedef const _Ty & const_reference;
typedef _Ty value_type;
template<class _Other>
struct rebind
{ // convert an CMTSafeAllocator<_Ty> to an CMTSafeAllocator <_Other>
typedef CMTSafeAllocator<_Other> other;
};
pointer address(reference _Val) const
{ // return address of mutable _Val
return (&_Val);
}
const_pointer address(const_reference _Val) const
{ // return address of nonmutable _Val
return (&_Val);
}
CMTSafeAllocator(_THeap* pHeap):
m_pHeap(pHeap)
{
}
CMTSafeAllocator(const CMTSafeAllocator<_Ty>&rThat):
m_pHeap(rThat.m_pHeap)
{
}
template<class _Other>
CMTSafeAllocator(const CMTSafeAllocator<_Other, _THeap>&rThat)
{
m_pHeap = rThat.GetHeap();
}
template<class _Other>
CMTSafeAllocator<_Ty>& operator=(const CMTSafeAllocator<_Other>& rThat)
{
m_pHeap = rThat.m_pHeap;
return (*this);
}
pointer allocate (size_type _Count, const void *)
{ // allocate array of _Count elements, ignore hint
return (Allocate(_Count, (pointer)0));
}
pointer allocate(size_type _Count)
{ // allocate array of _Count elements
return Allocate(_Count, (pointer)0);
}
void deallocate(void* _Ptr, size_type)
{ // deallocate object at _Ptr, ignore size
Deallocate(_Ptr);
}
void construct(pointer _Ptr, const _Ty& _Val)
{ // construct object at _Ptr with value _Val
std::_Construct(_Ptr, _Val);
}
void destroy(pointer _Ptr)
{ // destroy object at _Ptr
std::_Destroy(_Ptr);
}
size_t max_size() const
{ // estimate maximum array size
size_t _Count = (size_t)(-1) / sizeof (_Ty);
return (0 < _Count ? _Count : 1);
}
#if defined(WIN64) || defined(LINUX64)
char *_Charalloc(size_type _N)
{
return (char*)(Allocate((difference_type)_N, 0));
}
#endif
public:
_Ty *Allocate(size_t _Count, _Ty *);
void Deallocate(void *);
_THeap* GetHeap()const{return m_pHeap;}
protected:
_THeap* m_pHeap;
};
template<class _Ty, class _THeap>
_Ty *CMTSafeAllocator<_Ty, _THeap>::Allocate(size_t _Count, _Ty *)
{ // allocate storage for _Count elements of type _Ty
_Ty * pMemory = (_Ty *)m_pHeap->Alloc(_Count * sizeof (_Ty), "CMTSafeAllocator<_Ty, _THeap>::Allocate");
//[Timur] std::_Nomemory() is not supported in SGI stlport.
if(!pMemory)
throw std::runtime_error("Not enough memory for CMTSafeAllocator::Allocate()");
return pMemory;
}
template<class _Ty, class _THeap>
void CMTSafeAllocator<_Ty, _THeap>::Deallocate(void *p)
{
m_pHeap->Free (p);
}
template<class _Ty,
class _Other, class _THeap> inline
bool operator==(const CMTSafeAllocator<_Ty, _THeap>&left, const CMTSafeAllocator<_Other, _THeap>&right)
{ // test for allocator equality (always true)
return left.GetHeap() == right.GetHeap();
}
template<class _Ty,
class _Other, class _THeap> inline
bool operator != (const CMTSafeAllocator<_Ty, _THeap>&left, const CMTSafeAllocator<_Other, _THeap>&right)
{ // test for allocator inequality (always false)
return left.GetHeap() != right.GetHeap();
}
#endif

156
CrySystem/Mailer.cpp Normal file
View File

@@ -0,0 +1,156 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2001.
// -------------------------------------------------------------------------
// File name: Mailer.cpp
// Version: v1.00
// Created: 5/12/2001 by Timur.
// Compilers: Visual C++ 6.0
// Description: Send Mail.
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "Mailer.h"
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mapi.h>
#include "mailer.h"
bool CMailer::SendMessage(const char *subject,
const char *messageBody,
const std::vector<const char*> &_recipients,
const std::vector<const char*> &_attachments,
bool bShowDialog)
{
// Preserve directory, (Can be changed if attachment specified)
char dir[MAX_PATH];
GetCurrentDirectory( sizeof(dir),dir );
// Load MAPI dll
HMODULE hMAPILib = LoadLibrary("MAPI32.DLL");
LPMAPISENDMAIL lpfnMAPISendMail = (LPMAPISENDMAIL) GetProcAddress(hMAPILib, "MAPISendMail");
int numRecipients = (int)_recipients.size();
// Handle Attachments
MapiFileDesc* attachments = new MapiFileDesc[_attachments.size()];
int i = 0;
for(unsigned int k=0; k<_attachments.size();k++)
{
FILE *file = fopen(_attachments[k],"r");
if (!file)
continue;
fclose(file);
attachments[i].ulReserved = 0;
attachments[i].flFlags = 0;
attachments[i].nPosition = (ULONG)-1;
attachments[i].lpszPathName = (char*)(const char*)_attachments[k];
attachments[i].lpszFileName = NULL;
attachments[i].lpFileType = NULL;
i++;
}
int numAttachments = i;
// Handle Recipients
MapiRecipDesc* recipients = new MapiRecipDesc[numRecipients];
std::vector<string> addresses;
addresses.resize( numRecipients );
for (i = 0; i < numRecipients; i++)
{
addresses[i] = string("SMTP:") + _recipients[i];
}
for(i=0; i<numRecipients; i++)
{
recipients[i].ulReserved = 0;
recipients[i].ulRecipClass = MAPI_TO;
recipients[i].lpszName = (char*)(const char*)_recipients[i];
recipients[i].lpszAddress = (char*)addresses[i].c_str();
recipients[i].ulEIDSize = 0;
recipients[i].lpEntryID = NULL;
}
/*
// Carbon copy.
recipients[i].ulReserved = 0;
recipients[i].ulRecipClass = MAPI_TO;
recipients[i].lpszName = "Timur Davidenko";
recipients[i].lpszAddress = "timur@crytek.com"
recipients[i].ulEIDSize = 0;
recipients[i].lpEntryID = NULL;
*/
// Create a message. Most members are set to NULL or 0 (the user may set them)
/*
MapiMessage message = {0, // reserved, must be 0
(const char*)_subject, // subject
(const char*)_messageBody, // message body
NULL, // NULL = interpersonal message
NULL, // no date; MAPISendMail ignores it
NULL, // no conversation ID
0L, // no flags, MAPISendMail ignores it
NULL, // no originator, this is ignored too (automatically filled in)
numRecipients, // number of recipients
recipients, // recipients array
numAttachments, // number of attachments
attachments}; // the attachment structure
*/
MapiMessage message;
memset( &message,0,sizeof(message) );
message.lpszSubject = (char*)(const char*)subject;
message.lpszNoteText = (char*)(const char*)messageBody;
message.lpszMessageType = NULL;
message.nRecipCount = numRecipients;
message.lpRecips = recipients;
message.nFileCount = numAttachments;
message.lpFiles = attachments;
//Next, the client calls the MAPISendMail function and stores the return status so it can detect whether the call succeeded. You should use a more sophisticated error reporting mechanism than the C library function printf.
FLAGS flags = bShowDialog ? MAPI_DIALOG : 0;
flags |= MAPI_LOGON_UI;
ULONG err = (*lpfnMAPISendMail) (0L, // use implicit session.
0L, // ulUIParam; 0 is always valid
&message, // the message being sent
flags, // if user allowed to edit the message
0L); // reserved; must be 0
delete [] attachments;
delete [] recipients;
FreeLibrary(hMAPILib); // Free DLL module through handle
// Restore previous directory.
SetCurrentDirectory( dir );
if (err != SUCCESS_SUCCESS )
return false;
return true;
}
#else //WIN32
bool CMailer::SendMessage(const char *subject,
const char *messageBody,
const std::vector<const char*> &_recipients,
const std::vector<const char*> &_attachments,
bool bShowDialog)
{
return true;
}
#endif //WIN32

33
CrySystem/Mailer.h Normal file
View File

@@ -0,0 +1,33 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2001.
// -------------------------------------------------------------------------
// File name: Mailer.h
// Version: v1.00
// Created: 5/12/2001 by Timur.
// Compilers: Visual C++ 6.0
// Description: Send mail.
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#ifndef __Mailer_h__
#define __Mailer_h__
#if _MSC_VER > 1000
#pragma once
#endif
class CMailer
{
public:
static bool SendMessage(const char* _subject, // E-Mail Subject
const char* _messageBody, // Message Text
const std::vector<const char*> &_recipients, // All Recipients' Addresses
const std::vector<const char*> &_attachments, // All File Attachments
bool bShowDialog); // Whether to allow editing by user
};
#endif // __Mailer_h__

14
CrySystem/PakVars.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef _CRY_SYSTEM_PAK_VARS_HDR_
#define _CRY_SYSTEM_PAK_VARS_HDR_
// variables that control behaviour of CryPak/StreamEngine subsystems
struct PakVars
{
int nPriority;
int nReadSlice;
int nLogMissingFiles;
PakVars():nPriority(1),nReadSlice(0), nLogMissingFiles(0){}
};
#endif

116
CrySystem/RandGen.cpp Normal file
View File

@@ -0,0 +1,116 @@
#include "StdAfx.h"
#include "randgen.h"
#define M (397) // a period parameter
#define K (0x9908B0DFU) // a magic constant
#define hiBit(u) ((u) & 0x80000000U) // mask all but highest bit of u
#define loBit(u) ((u) & 0x00000001U) // mask all but lowest bit of u
#define loBits(u) ((u) & 0x7FFFFFFFU) // mask the highest bit of u
#define mixBits(u, v) (hiBit(u)|loBits(v)) // move hi bit of u to hi bit of v
CSysPseudoRandGen::CSysPseudoRandGen()
{
left=-1;
}
CSysPseudoRandGen::~CSysPseudoRandGen()
{
}
void CSysPseudoRandGen::Seed(uint32 seed)
{
//
// We initialize state[0..(N-1)] via the generator
//
// x_new = (69069 * x_old) mod 2^32
//
// from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's
// _The Art of Computer Programming_, Volume 2, 3rd ed.
//
// Notes (SJC): I do not know what the initial state requirements
// of the Mersenne Twister are, but it seems this seeding generator
// could be better. It achieves the maximum period for its modulus
// (2^30) iff x_initial is odd (p. 20-21, Sec. 3.2.1.2, Knuth); if
// x_initial can be even, you have sequences like 0, 0, 0, ...;
// 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...; 2^29, 2^29 + 2^31,
// 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd below.
//
// Even if x_initial is odd, if x_initial is 1 mod 4 then
//
// the lowest bit of x is always 1,
// the next-to-lowest bit of x is always 0,
// the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... ,
// the 3rd-from-lowest bit of x 4-cycles ... 0 1 1 0 0 1 1 0 ... ,
// the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... ,
// ...
//
// and if x_initial is 3 mod 4 then
//
// the lowest bit of x is always 1,
// the next-to-lowest bit of x is always 1,
// the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... ,
// the 3rd-from-lowest bit of x 4-cycles ... 0 0 1 1 0 0 1 1 ... ,
// the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... ,
// ...
//
// The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is
// 16, which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It
// also does well in the dimension 2..5 spectral tests, but it could be
// better in dimension 6 (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth).
//
// Note that the random number user does not see the values generated
// here directly since reloadMT() will always munge them first, so maybe
// none of all of this matters. In fact, the seed values made here could
// even be extra-special desirable if the Mersenne Twister theory says
// so-- that's why the only change I made is to restrict to odd seeds.
//
register uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = state;
register int j;
for(left=0, *s++=x, j=N_RAND_STATE; --j;
*s++ = (x*=69069U) & 0xFFFFFFFFU);
}
uint32 CSysPseudoRandGen::Rand()
{
uint32 y;
if(--left < 0)
return(Reload());
y = *next++;
y ^= (y >> 11);
y ^= (y << 7) & 0x9D2C5680U;
y ^= (y << 15) & 0xEFC60000U;
return(y ^ (y >> 18));
}
float CSysPseudoRandGen::Rand(float fMin, float fMax)
{
static double _1overFFFFFFFF=2.3283064370807973754314699618685e-10;
float fVal=(float)((double)Rand()*_1overFFFFFFFF*(double)(fMax-fMin)+(double)fMin);
return fVal;
}
uint32 CSysPseudoRandGen::Reload()
{
register uint32 *p0=state, *p2=state+2, *pM=state+M, s0, s1;
register int j;
if(left < -1)
Seed(4357U);
left=N_RAND_STATE-1, next=state+1;
for(s0=state[0], s1=state[1], j=N_RAND_STATE-M+1; --j; s0=s1, s1=*p2++)
*p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
for(pM=state, j=M; --j; s0=s1, s1=*p2++)
*p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
s1 ^= (s1 >> 11);
s1 ^= (s1 << 7) & 0x9D2C5680U;
s1 ^= (s1 << 15) & 0xEFC60000U;
return(s1 ^ (s1 >> 18));
}

22
CrySystem/RandGen.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef __RandGen_h__
#define __RandGen_h__
#pragma once
#define N_RAND_STATE (624) // length of state vector
class CSysPseudoRandGen
{
private:
uint32 state[N_RAND_STATE+1]; // state vector + 1 extra to not violate ANSI C
uint32 *next; // next random value is computed from here
int left; // can *next++ this many times before reloading
private:
uint32 Reload();
public:
CSysPseudoRandGen();
virtual ~CSysPseudoRandGen();
void Seed(uint32 seed);
uint32 Rand();
float Rand(float fMin, float fMax);
};
#endif // __RandGen_h__

166
CrySystem/RefReadStream.cpp Normal file
View File

@@ -0,0 +1,166 @@
#include "stdafx.h"
#include "CritSection.h"
#include "RefStreamEngine.h"
#include "RefReadStreamProxy.h"
#include "RefReadStream.h"
// creates a read stream from the file, in the engine,
// with the given default principal client
// the path is always the real path, it shouldn't undergo MOD path adjustments
CRefReadStream::CRefReadStream (const string& strFileName, CRefStreamEngine* pEngine):
m_pEngine (pEngine),
m_bError (false), // no error yet because we didn't try to do anything
m_strFileName (strFileName),
m_nFileSize (0),
m_nSectorSize(0),
m_hFile (INVALID_HANDLE_VALUE),
m_bOverlapped ( false),
m_pZipEntry (NULL)
{
pEngine->Register(this);
}
// activates: opens the file, gets its size. If failed, returns false
bool CRefReadStream::Activate()
{
static CCritSection g_csActivate;
AUTO_LOCK(g_csActivate);
m_bOverlapped = m_pEngine->isOverlappedIoEnabled();
#if !defined(LINUX64)
if (m_pZipEntry == NULL && m_hFile == INVALID_HANDLE_VALUE)
#else
if (m_pZipEntry == 0 && m_hFile == INVALID_HANDLE_VALUE)
#endif
m_hFile = CreateFile (m_strFileName.c_str(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
m_bOverlapped?FILE_FLAG_OVERLAPPED:0,
NULL);
#if !defined(LINUX64)
if (m_pZipEntry == NULL && m_hFile == INVALID_HANDLE_VALUE)
#else
if (m_pZipEntry == 0 && m_hFile == INVALID_HANDLE_VALUE)
#endif
{
// perhaps this is in a zip file
m_pZipEntry = m_pEngine->GetPak()->GetFileData(m_strFileName.c_str());
if (m_pZipEntry)
{
m_nFileSize = m_pZipEntry->GetFileEntry()->desc.lSizeUncompressed;
m_bError = false;
// try to open the actual file if can be done - this is only worthy
// if the data isn't yet in the cache AND the actual file is big enough
// AND it's uncompressed in the zip file
if (!m_pZipEntry->GetData(false)
&& m_pZipEntry->GetFileEntry()->nMethod == ZipFile::METHOD_STORE
//&& m_pZipEntry->GetFileEntry()->nSizeUncompressed > g_nMaxCacheUncompressed
)
{
// try to open the file - this should really be not often the case
const char* szPakFile = m_pZipEntry->GetZip()->GetFilePath();
// even if we can't open it, it doesn't matter: we automatically resort to using the cache
m_hFile = CreateFile (szPakFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
m_bOverlapped?FILE_FLAG_OVERLAPPED:0,
NULL);
}
if (m_hFile == INVALID_HANDLE_VALUE)
m_bOverlapped = false;
return true;
}
else
{
DWORD dwError = GetLastError();
m_bError = true;
m_pEngine->GetPak()->OnMissingFile(m_strFileName.c_str());
return false;
}
}
else
{
if (!m_nFileSize)
{
if (m_pZipEntry)
m_nFileSize = m_pZipEntry->GetFileEntry()->desc.lSizeUncompressed;
else
m_nFileSize = ::GetFileSize (m_hFile, NULL);
if (m_nFileSize == INVALID_FILE_SIZE)
{
m_bError = true;
m_nFileSize = 0;
return false;
}
m_bError = false;
}
return true;
}
}
// the clients are not allowed to destroy this object directly; only via Release()
CRefReadStream::~CRefReadStream()
{
m_pEngine->Unregister(this);
if (m_hFile != INVALID_HANDLE_VALUE)
CloseHandle(m_hFile);
}
// request to abort comes from the proxy. This doesn't means immediate deallocation.
void CRefReadStream::Abort(CRefReadStreamProxy* pProxy)
{
if (m_setProxies.size() == 1)
{
// there's only one proxy that uses this object; so we can safely cancel io
// on this file
CancelIo (m_hFile);
}
}
// Client (through the given Proxy) has requested priority rise
void CRefReadStream::OnRaisePriority (CRefReadStreamProxy* pProxy, unsigned nPriority)
{
if (!pProxy->IsIOExecuted())
m_pEngine->SortIOJobs();
}
#ifndef LINUX
// returns the size of the sector on the disk on which this file resides
unsigned CRefReadStream::GetSectorSize()
{
if (!m_nSectorSize)
m_nSectorSize = m_pEngine->GetSectorSize(m_strFileName.c_str());
return m_nSectorSize;
}
#endif //LINUX
void CRefReadStream::OnIOExecuted(CRefReadStreamProxy* pProxy)
{
m_pEngine->OnIOJobExecuted(pProxy);
}
// dumps all clients (proxies) - each uses the Dump function of the proxy
string CRefReadStream::Dump()
{
string strClients;
for (ProxySet::iterator it = m_setProxies.begin(); it != m_setProxies.end(); ++it)
{
if (!strClients.empty())
strClients += ",";
strClients += (*it)->Dump();
}
return "{"+strClients+"}";
}
// returns the size of allocated memory for this object and all subobjects (Proxies)
size_t CRefReadStream::GetSize()
{
size_t nSize = sizeof(*this);
nSize += m_strFileName.capacity();
for (ProxySet::iterator it = m_setProxies.begin(); it != m_setProxies.end(); ++it)
nSize += sizeof(ProxySet::value_type) + (*it)->GetSize();
return nSize;
}

122
CrySystem/RefReadStream.h Normal file
View File

@@ -0,0 +1,122 @@
#ifndef _REF_READ_STREAM_HDR_
#define _REF_READ_STREAM_HDR_
#include "ZipDir.h"
#include <IStreamEngine.h>
#include "CryPak.h"
class CRefStreamEngine;
class CRefReadStreamProxy;
class CRefReadStream: public _reference_target_t
{
public:
// this is the maximum size in bytes of a file inside zip
// that will be cached even though it's not compressed
enum {g_nMaxCacheUncompressed = 64 * 1024};
// if the file can't be opened, this object permanently returns an error (right after construction)
CRefReadStream (const string& strFileName, CRefStreamEngine* pEngine);
// returns true if the file read was not successful.
virtual bool IsError() {return m_bError;}
// request to abort comes from the proxy. This doesn't means immediate deallocation.
virtual void Abort(CRefReadStreamProxy* pProxy);
// Client (through the given Proxy) has requested priority rise
virtual void OnRaisePriority (CRefReadStreamProxy* pProxy, unsigned nPriority);
// the proxy to this stream appeared, take it into account (increase the ref counter)
void Register (CRefReadStreamProxy* pProxy){this->AddRef();m_setProxies.insert (pProxy);}
// the proxy deallocates, don't take it into account (decrease ref counter)
void Unregister (CRefReadStreamProxy* pProxy) {m_setProxies.erase (pProxy);this->Release();}
// returns the path to the file; this is always the real path, it shouldn't undergo MOD path adjustments
const string& GetFileName() const {return m_strFileName;}
unsigned GetFileSize() const {return m_nFileSize;}
HANDLE GetFile () {return m_hFile;}
void OnIOExecuted(CRefReadStreamProxy* pProxy);
#ifndef LINUX
// returns the size of the sector on the disk on which this file resides
unsigned GetSectorSize();
#endif //LINUX
// activates: opens the file, gets its size. If failed, returns false
bool Activate();
CRefStreamEngine* GetEngine() {return m_pEngine;}
// returns the offset that is to be added to the desired offset in the file handle opened by this stream
// this is an artificial offset that will encounter for the files being in an archive
unsigned GetArchiveOffset()const
{
if (m_pZipEntry)
return m_pZipEntry->GetFileDataOffset();
else
return 0;
}
// this is true when the file was open with FILE_FLAG_OVERLAPPED flag;
// and therefore the operations on the file may and should be overlapped.
// otherwise perhaps some limitation exists and we should only work synchronously.
bool isOverlapped() const {return m_bOverlapped;}
// dumps all clients (proxies) - each uses the Dump function of the proxy
string Dump();
// returns the size of allocated memory for this object and all subobjects (Proxies)
size_t GetSize();
void* GetFileData()
{
if (m_pZipEntry)
return m_pZipEntry->GetData();
else
return NULL;
}
private:
// the clients are not allowed to destroy this object directly; only via Release()
~CRefReadStream();
// parent object
CRefStreamEngine* m_pEngine;
// path of the file. this is always the real path, it shouldn't undergo MOD path adjustments
string m_strFileName;
// the handle to opened file, or invalid handle value if the file couldn't be opened
// if the file can't be opened, this object permanently returns an error (right after construction)
HANDLE m_hFile;
// if this is not NULL, the file actually resides in a virtual file system inside a zip file.
// m_hFile may not or may be NULL. if m_hFile != NULL and this is not null, m_hFile is the handle
// to the actual zip archieve where the file resides
CCachedFileDataPtr m_pZipEntry;
// this is the size of the sector on the disk on which this file resides
unsigned m_nSectorSize;
// the file size, or 0 if the file couldn't be opened
DWORD m_nFileSize;
// the set of proxies
typedef std::set<CRefReadStreamProxy*> ProxySet;
ProxySet m_setProxies;
// error/finished conditions
bool m_bError;
// this flag is meaningful only with valid m_hFile. If it's true, it means the
// file was opened for Overlapped access (it can't be opened so in Win 9x)
bool m_bOverlapped;
};
TYPEDEF_AUTOPTR(CRefReadStream);
typedef std::vector<CRefReadStream_AutoPtr> CRefReadStream_AutoArray;
#endif

View File

@@ -0,0 +1,483 @@
//////////////////////////////////////////////////////////////////////////
// Implementation of CRefReadStreamProxy
// The proxy is the per-client unique object that is acquired by the Streaming
// Engine clients via StartRead() API. Several Proxies can refer to the same
// Stream (file) but perform their operations independently.
#include "stdafx.h"
#include <ISystem.h>
#include <ILog.h>
#include "RefStreamEngine.h"
#include "RefReadStream.h"
#include "RefReadStreamProxy.h"
extern ISystem* g_System;
extern CMTSafeHeap* g_pSmallHeap;
extern CMTSafeHeap* g_pBigHeap;
CRefReadStreamProxy::CRefReadStreamProxy (const char* szSource, CRefReadStream* pStream, IStreamCallback* pCallback, StreamReadParams* pParams):
m_strClient(szSource),
m_pStream (pStream),
m_pCallback(pCallback),
m_bError(false),
m_bFinished (false),
m_bFreeBuffer (false),
m_bPending (false),
m_pBuffer (NULL),
m_numBytesRead (0),
m_numRetries (0)
{
if (pParams)
m_Params = *pParams;
m_pBuffer = m_Params.pBuffer;
#if LOG_IO
g_System->GetILog()->LogToFile ("\006io:CRefReadStreamProxy %p(%s, %p)", this, szSource, pCallback);
#endif
pStream->Register(this);
}
CRefReadStreamProxy::~CRefReadStreamProxy ()
{
if (!m_bFinished && !m_bError)
OnFinishRead(ERROR_UNEXPECTED_DESTRUCTION);
if (m_bFreeBuffer && m_pBuffer)
g_pBigHeap->Free (m_pBuffer);
#if LOG_IO
g_System->GetILog()->LogToFile ("\006io:~CRefReadStreamProxy %p(%s, %p)", this, m_strClient.c_str(), m_pCallback);
#endif
m_pStream->Unregister(this);
}
// returns true if the file read was not successful.
bool CRefReadStreamProxy::IsError()
{
return m_bError;
}
// returns true if the file read was completed (successfully or unsuccessfully)
// check IsError to check if the whole requested file (piece) was read
bool CRefReadStreamProxy::IsFinished()
{
return m_bFinished;
}
// returns the number of bytes read so far (the whole buffer size if IsFinished())
unsigned int CRefReadStreamProxy::GetBytesRead (bool bWait)
{
if (m_bPending)
{
if (m_pStream->isOverlapped())
{
DWORD dwBytesRead;
if (GetOverlappedResult(m_pStream->GetFile(), &m_Overlapped, &dwBytesRead, bWait))
{
m_numBytesRead = m_nPieceOffset + dwBytesRead;
assert (dwBytesRead <= m_nPieceLength);
}
}
}
return m_numBytesRead;
}
// returns the buffer into which the data has been or will be read
// at least GetBytesRead() bytes in this buffer are guaranteed to be already read
const void* CRefReadStreamProxy::GetBuffer ()
{
return m_pBuffer;
}
// tries to stop reading the stream; this is advisory and may have no effect
// but the callback will not be called after this. If you just destructing object,
// dereference this object and it will automatically abort and release all associated resources.
void CRefReadStreamProxy::Abort()
{
// lock this object to avoid preliminary destruction
CRefReadStreamProxy_AutoPtr pLock (this);
if (m_bPending)
{
m_pStream->Abort(this);
// we need to wait to avoid letting the client freeing the buffer before the read is finished
if (!m_bFreeBuffer) // [sergiy] Comment this line (only if) out to let it complete all operations anyway
Wait();
}
else
{
m_pCallback = NULL;
m_bError = true;
m_nIOError = ERROR_USER_ABORT;
}
//assert (m_pCallback == NULL);
// perhaps the callback was already called, or perhaps not. In any case we forget about the callback
m_pCallback = NULL;
}
// tries to raise the priority of the read; this is advisory and may have no effect
void CRefReadStreamProxy::RaisePriority (unsigned nPriority)
{
if (m_Params.nPriority != nPriority)
{
m_Params.nPriority = nPriority;
m_pStream->OnRaisePriority(this, nPriority);
}
}
// unconditionally waits until the callback is called
// i.e. if the stream hasn't yet finish, it's guaranteed that the user-supplied callback
// is called before return from this function (unless no callback was specified)
void CRefReadStreamProxy::Wait()
{
// lock this object to avoid preliminary destruction
CRefReadStreamProxy_AutoPtr pLock (this);
// move it to the top of the corresponding queues
RaisePriority(INT_MAX);
// while the stream reading hasn't finished, OR the callback isn't still called, wait
while ((!m_bFinished && !m_bError) || m_pCallback)
{
m_pStream->GetEngine()->UpdateAndWait(100, IStreamEngine::FLAGS_DISABLE_CALLBACK_TIME_QUOTA);
}
}
// the interface for the actual stream
// returns true if the read has been started and no further attempts to do so are required
// returns false if couldn't start,and retry is required
// nMemQuota is the max number of bytes to allocate from the Engine's "Big Heap" for the piece of file
// that is read. Pass a big value to let it allocate as much as it wants.
bool CRefReadStreamProxy::StartRead (unsigned nMemQuota)
{
if (m_bError || m_bFinished || m_bPending)
{
// Why this assert happened?
//---------------------------
// THe stream read was automatically initiated, while the stream is marked as
// having been read, being read, or failed, i.e. it can't be restarted again.
// This can generally happen when the read has been started, and immediately aborted,
// while being put on hold. When there are enough IO resources to start reading it,
// we detect that it's been already aborted and don't restart it.
// This is the only known reason for that.
assert (m_nIOError == ERROR_USER_ABORT);
return true; // invalid call, no need to retry
}
if (!m_pStream->Activate())
{
OnFinishRead(ERROR_CANT_OPEN_FILE); // can't open file
return true; // no need to retry
}
if (m_pStream->IsError())
{
OnFinishRead(ERROR_REFSTREAM_ERROR); // file is invalid
return true;
}
if (m_Params.nOffset >= m_pStream->GetFileSize())
{
// offset out of range
OnFinishRead(ERROR_OFFSET_OUT_OF_RANGE);
return true;
}
if (m_Params.nSize > m_pStream->GetFileSize())
{
OnFinishRead(ERROR_SIZE_OUT_OF_RANGE);
return true;
}
if (m_Params.nSize == 0)
{
// by default, we read the whole file
m_Params.nSize = m_pStream->GetFileSize() - m_Params.nOffset;
}
else
if (m_Params.nOffset + m_Params.nSize > m_pStream->GetFileSize())
{
// it's impossible to read the specified region of the file
OnFinishRead(ERROR_REGION_OUT_OF_RANGE);
return true;
}
if (!m_pBuffer)
{
if (nMemQuota < m_Params.nSize)
{
// try another time, of fail now if the retries are over
if (++m_numRetries < g_numMaxRetries)
return false;
else
{
OnFinishRead(ERROR_OUT_OF_MEMORY_QUOTA);
return false;
}
}
m_pBuffer = g_pBigHeap->Alloc(m_Params.nSize, "CRefReadStreamProxy::StartRead: m_pBuffer");
if (!m_pBuffer)
{
OnFinishRead(ERROR_OUT_OF_MEMORY);
return true;
}
m_bFreeBuffer = true;
}
HANDLE hFile = m_pStream->GetFile();
m_nPieceOffset = 0; // we're just start reading
// we should load in blocks, if we load overlapped;
// we should load in one continuous read, if we load non-overlapped
unsigned nMaxBlockLength = m_pStream->GetEngine()->GetPak()->GetPakVars()->nReadSlice * 1024;
if (!nMaxBlockLength)
nMaxBlockLength = g_nBlockLength;
m_nPieceLength = m_pStream->isOverlapped() ? min (m_Params.nSize, nMaxBlockLength) : m_Params.nSize;
m_numBytesRead = 0;
// lock the object for the time of read operation
this->AddRef();
if ((m_Params.nFlags & SRP_FLAGS_ASYNC_PROGRESS) && m_pCallback)
m_pCallback->StreamOnProgress(this);
m_bPending = true;
++g_numPendingOperations;
DWORD dwError = CallReadFileEx ();
if (dwError)
{
m_bPending = false;
--g_numPendingOperations;
bool bResult = true; // by default, signal an error
switch (dwError)
{
#if !defined(LINUX)
case ERROR_NOT_ENOUGH_MEMORY:
case ERROR_INVALID_USER_BUFFER:
#endif
case ERROR_NO_SYSTEM_RESOURCES:
if (++m_numRetries < g_numMaxRetries)
bResult = false; // try again
}
// if bResult == false, it means we will want to try again, so we don't finish reading in this case
if (bResult)
OnFinishRead(dwError);
this->Release();
return bResult;
}
else
return true;
}
unsigned CRefReadStreamProxy::g_numPendingOperations = 0;
VOID CALLBACK CRefReadStreamProxy::FileIOCompletionRoutine (
DWORD dwErrorCode, // completion code
DWORD dwNumberOfBytesTransfered, // number of bytes transferred
LPOVERLAPPED lpOverlapped // I/O information buffer
)
{
#if defined(LINUX)
assert(lpOverlapped->pCaller != 0);
CRefReadStreamProxy* pThis = (CRefReadStreamProxy*)lpOverlapped->pCaller;
#else
const LONG_PTR nOOffset = (LONG_PTR)(&((CRefReadStreamProxy*)0)->m_Overlapped);
CRefReadStreamProxy* pThis = (CRefReadStreamProxy*)((LONG_PTR)lpOverlapped - nOOffset);
#endif
// this is only called when the stream is overlapped
assert (pThis->m_pStream->isOverlapped());
pThis->OnIOComplete (dwErrorCode, dwNumberOfBytesTransfered);
}
void CRefReadStreamProxy::OnIOComplete(unsigned nError, unsigned numBytesRead)
{
m_numBytesRead = m_nPieceOffset + numBytesRead;
// if there are more bytes read than was requested (e.g. because of the sector content after the EOF), we trim it.
if (!nError && m_numBytesRead > m_Params.nSize)
m_numBytesRead = m_Params.nSize;
--g_numPendingOperations;
m_bPending = false;
// calculate the next piece offset/length
m_nPieceOffset = m_numBytesRead;
assert (m_Params.nSize>=m_numBytesRead);
unsigned nMaxBlockLength = m_pStream->GetEngine()->GetPak()->GetPakVars()->nReadSlice * 1024;
if (!nMaxBlockLength)
nMaxBlockLength = g_nBlockLength;
m_nPieceLength = min (m_Params.nSize-m_numBytesRead,nMaxBlockLength);
// if there's nothing more to read,
// or there's an error, finish reading
if (nError || !m_nPieceLength)
{
OnFinishRead(nError);
// unlock the object for the time of read operation
this->Release();
}
else
{
// there's no error and there's still a piece to read. Read it further.
// we can't call progress messages from another thread
//if (m_pCallback)
// m_pCallback->StreamOnProgress(this);
m_bPending = true;
DWORD dwError = CallReadFileEx();
if (dwError)
{
m_bPending = false;
OnFinishRead(dwError);
this->Release();
return;
}
else
{
++g_numPendingOperations;
}
}
}
// on the platforms that support overlapped IO, calls ReadFileEx.
// on other platforms merely reads the file, calling OnIOComplete()
DWORD CRefReadStreamProxy::CallReadFileEx ()
{
HANDLE hFile = m_pStream->GetFile();
if (hFile == INVALID_HANDLE_VALUE)
{
// this is a special case, reading from the cache memory directly - we should handle it separately
void* pSource = m_pStream->GetFileData();
if (!pSource)
{
OnIOComplete(ERROR_ZIP_CACHE_FAILURE,0);
return 0;
}
memcpy (((char*)m_pBuffer) + m_nPieceOffset, ((char*)pSource) + m_Params.nOffset + m_nPieceOffset, m_nPieceLength);
OnIOComplete(0, m_nPieceLength);
return 0;
}
if (m_pStream->isOverlapped())
{
memset (&m_Overlapped, 0, sizeof(m_Overlapped));
m_Overlapped.Offset = m_Params.nOffset + m_nPieceOffset + m_pStream->GetArchiveOffset();
#if defined(LINUX)
m_Overlapped.pCaller = (void*)this;//store caller address here
#endif
if (!ReadFileEx (hFile, ((char*)m_pBuffer) + m_nPieceOffset, m_nPieceLength, &m_Overlapped, FileIOCompletionRoutine))
{
DWORD dwError = GetLastError();
if (!dwError)
dwError = ERROR_CANT_START_READING;
return dwError;
}
else
return 0;
}
else
{
// the actual number of bytes read
DWORD dwRead = 0;
unsigned newOffset = m_Params.nOffset + m_nPieceOffset + m_pStream->GetArchiveOffset();
if (SetFilePointer (hFile, newOffset, NULL, FILE_BEGIN) != newOffset)
{
// the positioning error is strange, we should examine it and perhaps retry (in case the file write wasn't finished.)
DWORD dwError = GetLastError();
return dwError;
}
// just read the file
if (!ReadFile (hFile, ((char*)m_pBuffer) + m_nPieceOffset, m_nPieceLength, &dwRead, NULL))
{
// we failed to read; we don't call the callback, but we could as well call OnIOComplete()
// with this error code and return 0 as success flag emulating error during load
DWORD dwError = GetLastError();
//return dwError;
// we call the callback to signal about the error, and return 0 signaling that the operation has completed
OnIOComplete(dwError, dwRead);
return 0;
}
else
{
OnIOComplete (0,dwRead);
return 0;
}
}
}
void CRefReadStreamProxy::OnFinishRead(unsigned nError)
{
// [marco] commented out, according to sergiy this is harmless
//assert (!m_bFinished && !m_bError);
if (!nError)
m_bFinished = true;
else
m_bError = true;
m_nIOError = nError;
m_pStream->OnIOExecuted(this);
}
// this returns true after the main IO job has been executed (either in worker or in main thread)
bool CRefReadStreamProxy::IsIOExecuted()
{
return IsFinished() || IsError();
}
// this gets called upon the IO has been executed to call the callbacks
void CRefReadStreamProxy::FinalizeIO()
{
if (m_pCallback)
{
// be carefull! this object can be deallocated inside the callback!
IStreamCallback* pCallback = m_pCallback;
m_pCallback = NULL; // don't call this callback any more as it may have been deallocated
#if LOG_IO
g_System->GetILog()->LogToFile ("\006io(%s) err %d%s%s%s%s piece(%d:%d) read %d %s userdata %d, pri %d, flags %x, offs %d, size %d", m_strClient.c_str(), m_nIOError,
m_bError?" Error":"", m_bFinished?" Finished":"", m_bFreeBuffer?" FreeBuffer":"", m_bPending?" Pending":"",
m_nPieceOffset, m_nPieceLength,
m_numBytesRead,
m_pStream->GetFileName().c_str(),
m_Params.dwUserData,
m_Params.nPriority,
m_Params.nFlags,
m_Params.nOffset,m_Params.nSize);
#endif
pCallback->StreamOnComplete(this, m_bError?m_nIOError:0);
#if LOG_IO
g_System->GetILog()->LogToFile ("\006io callback %p returned", pCallback);
#endif
}
}
string CRefReadStreamProxy::Dump()
{
char szDump[0x300];
_snprintf (szDump, sizeof(szDump), "%s: callback %p, %s%s%s %d bytes read, offset=%d, size=%d, flags=%x",
m_strClient.c_str(),
m_pCallback,
m_bPending?"PENDING ":"",
m_bFinished?"FINISHED ":"",
m_bError?"ERROR ":"",
m_numBytesRead,
m_Params.nOffset,
m_Params.nSize,
m_Params.nFlags);
return szDump;
}
// returns the size of allocated memory for this object and all subobjects if any
size_t CRefReadStreamProxy::GetSize()
{
size_t nSize = sizeof(*this);
nSize += m_strClient.capacity();
if (m_pBuffer)
nSize += m_Params.nSize;
return nSize;
}

View File

@@ -0,0 +1,132 @@
//////////////////////////////////////////////////////////////////////////
// this is the unique IReadStream* interface implementation,
// that refers to the actual read stream (hence the name proxy)
// The proxy is the per-client unique object that is acquired by the Streaming
// Engine clients via StartRead() API. Several Proxies can refer to the same
// Stream (file) but perform their operations independently.
#ifndef _CRY_SYSTEM_READ_STREAM_PROXY_HDR_
#define _CRY_SYSTEM_READ_STREAM_PROXY_HDR_
#include "IStreamEngine.h"
class CRefReadStreamProxy: public IReadStream
{
public:
// we need a MT-safe reference counting here..
// this class sets the priority order for the proxes
struct Order
{
bool operator ()(const CRefReadStreamProxy* pLeft, const CRefReadStreamProxy* pRight)const
{
return pLeft->GetPriority() > pRight->GetPriority();
}
};
// max number of retries - if the file doesn't start reading after this number of retries, unrecoverable error is returned
enum {g_numMaxRetries = 4};
// this is the length of the block that's read at once.
// big requests are splitted into smaller blocks of this size
enum {g_nBlockLength = 32 * 1024 * 1024}; // 128 k is the max size of the DMA transfer request
CRefReadStreamProxy (const char* szSource, class CRefReadStream* pStream, IStreamCallback* pCallback, StreamReadParams* pParams);
~CRefReadStreamProxy ();
DWORD_PTR GetUserData() {return m_Params.dwUserData;}
// returns true if the file read was not successful.
bool IsError();
// returns true if the file read was completed (successfully or unsuccessfully)
// check IsError to check if the whole requested file (piece) was read
bool IsFinished();
// returns the number of bytes read so far (the whole buffer size if IsFinished())
unsigned int GetBytesRead (bool bWait);
// returns the buffer into which the data has been or will be read
// at least GetBytesRead() bytes in this buffer are guaranteed to be already read
const void* GetBuffer ();
// tries to stop reading the stream; this is advisory and may have no effect
// but the callback will not be called after this. If you just destructing object,
// dereference this object and it will automatically abort and release all associated resources.
void Abort();
// tries to raise the priority of the read; this is advisory and may have no effect
void RaisePriority (unsigned nPriority);
// unconditionally waits until the callback is called
// i.e. if the stream hasn't yet finish, it's guaranteed that the user-supplied callback
// is called before return from this function (unless no callback was specified)
void Wait();
// the interface for the actual stream
// returns true, if the read start finished (with error or success)
// or false if it needs to be restarted again
bool StartRead (unsigned nMemQuota = 0x7FFFFFFF);
// returns the total number of pending read operations
//static unsigned numPendingOperations() {return g_numPendingOperations;}
int GetPriority()const{return m_Params.nPriority;}
// this returns true after the main IO job has been executed (either in worker or in main thread)
bool IsIOExecuted();
// this gets called upon the IO has been executed to call the callbacks
void FinalizeIO();
const StreamReadParams& GetParams() const {return m_Params;}
// finalizes the read operation, forces callback and erases it (so that it doesn't get called twice)
void OnFinishRead(unsigned nError);
string Dump();
// returns the size of allocated memory for this object and all subobjects if any
size_t GetSize();
protected:
// the number of times the StartRead was retried; after too many retries unrecoverable error is returned
unsigned m_numRetries;
static unsigned g_numPendingOperations;
void OnIOComplete(unsigned nError, unsigned numBytesRead);
// on the platforms that support overlapped IO, calls ReadFileEx.
// on other platforms merely reads the file, calling OnIOComplete()
DWORD CallReadFileEx ();
static VOID CALLBACK FileIOCompletionRoutine(
DWORD dwErrorCode, // completion code
DWORD dwNumberOfBytesTransfered, // number of bytes transferred
LPOVERLAPPED lpOverlapped // I/O information buffer
);
// the actual stream
class CRefReadStream* m_pStream;
// the initial data from the user
StreamReadParams m_Params;
// the source for debugging
string m_strClient;
// the callback; may be NULL
IStreamCallback* m_pCallback;
// the actual buffer to read to
void* m_pBuffer;
// the number of bytes read so far
unsigned m_numBytesRead;
// the portion of data (offset, length) currently queued for reading.
// this portion offset is RELATIVELY to the supplied by the client
// offset within the file; so, the offset within the file is m_nPieceOffset + m_Params.nOffset
// This is only used during m_bPending is true
unsigned m_nPieceOffset, m_nPieceLength;
// the structure for asynchronous callback
OVERLAPPED m_Overlapped;
bool m_bError, m_bFinished, m_bFreeBuffer, m_bPending;
unsigned m_nIOError;
};
TYPEDEF_AUTOPTR(CRefReadStreamProxy);
#endif

View File

@@ -0,0 +1,744 @@
#include "stdafx.h"
#include <TArrays.h>
#include <ilog.h>
#include "RefStreamEngine.h"
#include "RefReadStream.h"
#include "RefReadStreamProxy.h"
#ifndef SIZEOF_ARRAY
#define SIZEOF_ARRAY(arr) (sizeof(arr)/sizeof((arr)[0]))
#endif
extern CMTSafeHeap* g_pSmallHeap;
extern CMTSafeHeap* g_pBigHeap;
//////////////////////////////////////////////////////////////////////////
// useWorkerThreads is the number of worker threads to use;
// currently only values 0 and 1 are supported: 0 - overlapped IO in the main thread, and 1 - overlapped IO in the worker thread
// MT: Main thread only
CRefStreamEngine::CRefStreamEngine (CCryPak* pPak, IMiniLog* pLog, unsigned useWorkerThreads, bool bOverlappedIO):
m_pPak(pPak),
m_pLog(pLog),
m_nMaxReadDepth (16),
m_nMaxQueueLength (4*1024),
m_nMaxIOMemPool (128*1024*1024),
#if defined(LINUX)
m_hIOWorker (INVALID_HANDLE_VALUE),//only diff is here, but what can i do?
#else
m_hIOWorker (NULL),
#endif
m_dwWorkerThreadId(0),
m_queIOJobs(ProxyPtrAllocator(g_pSmallHeap)),
m_setIOPending(ProxyPtrPredicate(), ProxyPtrAllocator(g_pSmallHeap)),
m_queIOExecuted(ProxyPtrAllocator(g_pSmallHeap)),
m_bEnableOverlapped (bOverlappedIO),
m_nSuspendCallbackTimeQuota(0)
{
m_dwMainThreadId = GetCurrentThreadId();
CheckOSCaps();
if (!QueryPerformanceFrequency((LARGE_INTEGER*)&m_nPerfFreq))
{
m_nPerfFreq = 0;
m_nSuspendCallbackTimeQuota = 1; // suspend forever
}
//m_nSuspendCallbackTimeQuota = 1; // suspend anyway: we don't support this..
m_nCallbackTimeQuota = 0;
SetCallbackTimeQuota (50000);
m_dwMask=0;
m_hIOJob = CreateEvent (NULL, FALSE, FALSE, NULL);
m_hIOExecuted = CreateEvent (NULL, TRUE, FALSE, NULL);
m_hDummyEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
memset (m_nSectorSizes, 0, sizeof(m_nSectorSizes));
if (useWorkerThreads)
StartWorkerThread();
}
//////////////////////////////////////////////////////////////////////////
// MT: Main thread only
CRefStreamEngine::~CRefStreamEngine()
{
StopWorkerThread();
m_setLockedStreams.clear();
// fail all outstanding requests
// we don't need to lock, since there's already no worker thread at this moment
while (!m_queIOJobs.empty())
{
CRefReadStreamProxy_AutoPtr pJob = m_queIOJobs.front();
m_queIOJobs.pop_front();
pJob->OnFinishRead(ERROR_ABORTED_ON_SHUTDOWN); // aborted
}
// finalize all the jobs that can be finalized
while (!m_queIOExecuted.empty() && FinalizeIOJobs(FLAGS_DISABLE_CALLBACK_TIME_QUOTA) > 0)
continue;
// if we still have some streams, that's because someone didn't release the proxy
if (m_pLog)
for (NameStreamMap::iterator it = m_mapFilesByName.begin(); it != m_mapFilesByName.end(); ++it)
m_pLog->Log("%s: %s", it->first.c_str(), it->second->Dump().c_str());
CloseHandle (m_hIOJob);
CloseHandle (m_hIOExecuted);
CloseHandle (m_hDummyEvent);
}
unsigned CRefStreamEngine::UpdateAndWait (unsigned nMilliseconds, unsigned nFlags)
{
if (IsMainThread())
Update(nFlags);
return Wait (nMilliseconds,nFlags);
}
// returns true if called from the main thread for this engine
bool CRefStreamEngine::IsMainThread()
{
return GetCurrentThreadId() == m_dwMainThreadId;
}
bool CRefStreamEngine::IsWorkerThread()
{
return GetCurrentThreadId() == m_dwWorkerThreadId;
}
//////////////////////////////////////////////////////////////////////////
// Starts asynchronous read from the specified file
// MT: Main thread only
IReadStream_AutoPtr CRefStreamEngine::StartRead (const char* szSource, const char* szFilePathPC, IStreamCallback* pCallback, StreamReadParams* pParams)
{
unsigned nFlags = 0;
if (pParams)
nFlags = pParams->nFlags;
m_pPak->RecordFile( szFilePathPC );
// get rid of some jobs if there are too many in the queue
if (!(nFlags & SRP_QUICK_STARTREAD))
while (numIOJobs(eWaiting) >= m_nMaxQueueLength)
{
m_pLog->LogWarning("StreamEngine: The number of jobs waiting %d >= max queue length %d, waiting to free up the queue", numIOJobs(eWaiting), m_nMaxQueueLength);
UpdateAndWait(20, FLAGS_DISABLE_CALLBACK_TIME_QUOTA);
}
char szFilePathBuf[CCryPak::g_nMaxPath];
const char* szFilePath = m_pPak->AdjustFileName (szFilePathPC, szFilePathBuf, pParams && (pParams->nFlags & SRP_FLAGS_PATH_REAL) ? ICryPak::FLAGS_PATH_REAL: 0);
// first try to find such file; if it's already pending, add a client to it only
CRefReadStream_AutoPtr pStream;
NameStreamMap::iterator it = m_mapFilesByName.find (szFilePath);
if (it == m_mapFilesByName.end())
{
pStream = new CRefReadStream (szFilePath, this);
}
else
pStream = it->second;
// make sure that the permanent streams get locked in memory;
// if it's already locked, insert() won't do anything
if (nFlags & SRP_FLAGS_MAKE_PERMANENT)
m_setLockedStreams.insert (pStream);
else
if (nFlags & SRP_FLAGS_MAKE_TRANSIENT)
m_setLockedStreams.erase (pStream);
// at this moment the stream should self-register in this engine and the stream sets should get initialized
CRefReadStreamProxy_AutoPtr pProxy = new CRefReadStreamProxy(szSource, pStream, pCallback, pParams);
// register the proxy
AddIOJob (pProxy);
if (!(nFlags & SRP_QUICK_STARTREAD))
Update(0);
return (IReadStream*)pProxy;
}
// signals that this proxy needs to be executed (StartRead called)
void CRefStreamEngine::AddIOJob (CRefReadStreamProxy* pJobProxy)
{
if (!m_hIOWorker)
{ // its very simple with single-threaded model: we just put the job to the queue
// for the next update will execute it
m_queIOJobs.push_back(pJobProxy);
SortIOJobs_NoLock();
}
else
// for multi-threaded model, we need to put the job to the queue and signal the worker
// thread about it.
{
// put to the queue
{
AUTO_LOCK (m_csIOJobs);
m_queIOJobs.push_back(pJobProxy);
SortIOJobs_NoLock();
}
SetEvent (m_hIOJob);
}
}
//////////////////////////////////////////////////////////////////////////
// returns the size of the file; returns 0 if there's no such file.
unsigned CRefStreamEngine::GetFileSize (const char* szFilePathPC, unsigned nCryPakFlags)
{
char szFilePathBuf[m_pPak->g_nMaxPath];
const char *szFilePath = m_pPak->AdjustFileName (szFilePathPC, szFilePathBuf, nCryPakFlags);
NameStreamMap::iterator it = m_mapFilesByName.find (szFilePath);
if (it != m_mapFilesByName.end())
{
if (!it->second->GetFileSize())
it->second->Activate();
return it->second->GetFileSize();
}
// we didn't find the file size in the cache - open the file and query the size
#if defined(LINUX)
HANDLE hFile = CreateFile (szFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
#else
HANDLE hFile = CreateFile (szFilePath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
#endif
if (hFile != INVALID_HANDLE_VALUE)
{
unsigned nFileSize = ::GetFileSize(hFile, NULL);
CloseHandle (hFile);
return nFileSize;
}
else
{
CCachedFileDataPtr pFileData = m_pPak->GetFileData(szFilePath);
if (pFileData)
return pFileData->GetFileEntry()->desc.lSizeUncompressed;
else
{
m_pPak->OnMissingFile(szFilePathPC);
return 0;
}
}
}
//////////////////////////////////////////////////////////////////////////
// Gets called regularly, to finalize those proxies whose jobs have
// already been executed (e.g. to call the callbacks)
// - to be called from the main thread only
// - starts new jobs in the single-threaded model
void CRefStreamEngine::Update(unsigned nFlags)
{
unsigned numRemovedJobs = 0;
unsigned numFinalizedJobs = 0;
do {
if (!m_hIOWorker)
{
// If we're in single-threaded mode, update means the whole cycle:
// start the jobs, wait for their IO completion routine and finalize them
numRemovedJobs = StartIOJobs();
// enter alertable state so that the IO completion routines can be called
WaitForSingleObjectEx(m_hDummyEvent, 0, TRUE);
}
// If we're in multi-threaded mode, Update from main thread means
// just finalization of executed in the worker IO jobs.
numFinalizedJobs = FinalizeIOJobs(nFlags);
// Update from worker thread shouldn't be called at all
// We continue updating until all the jobs that are possible to move out
// of the IO Job queue are moved. Even if no jobs were moved, but some were finalized,
// the finalized jobs may have spawned some new jobs, we'll try to start those, too
// but we don't let it go on forever because of the limits
} while(numRemovedJobs | numFinalizedJobs);
}
//////////////////////////////////////////////////////////////////////////
// Only waits at most the specified amount of time for some IO to complete
// - may initiate a new job
// - may be called from any non-worker thread
unsigned CRefStreamEngine::Wait(unsigned nMilliseconds, unsigned nFlags)
{
ResetEvent (m_hIOExecuted);
if (!IsMainThread())
{
// special case - this function is called from non-main thread
// just wait until some io gets executed, if there's anything to wait for
if (numIOJobs(eWaiting)+numIOJobs(ePending) > 0) // no sense to wait here if there are no waiting or pending jobs
WaitForSingleObject(m_hIOExecuted, nMilliseconds);
return 0;
}
AddCallbackTimeQuota (nMilliseconds * 1000);
if (m_hIOWorker)
{
unsigned nFinalized = FinalizeIOJobs(nFlags); // finalize whatever may not have been finalized
if (nFinalized)
return nFinalized; // we don't wait if we finalized something
if (numIOJobs(eWaiting)+numIOJobs(ePending) > 0) // no sense to wait here if there are no waiting or pending jobs
WaitForSingleObject(m_hIOExecuted, nMilliseconds);
}
else
{
// really wait for some IO to complete
if (numIOJobs(ePending) > 0) // no sense to wait here if there are no pending jobs
SleepEx(nMilliseconds, TRUE);
StartIOJobs(); // perhaps there's room for new tasks to be started now
}
return FinalizeIOJobs(nFlags);
}
// adds to the callback time quota in this frame, the specified number of microseconds
void CRefStreamEngine::AddCallbackTimeQuota (int nMicroseconds)
{
m_nCallbackTimeQuota += nMicroseconds * m_nPerfFreq / 1000000;
if (m_nCallbackTimeQuota < 0)
m_nCallbackTimeQuota = 0;
}
void CRefStreamEngine::SetStreamCompressionMask( const DWORD indwMask )
{
m_dwMask=indwMask;
}
void CRefStreamEngine::SetCallbackTimeQuota (int nMicroseconds)
{
// if we have
if (m_nCallbackTimeQuota < 0)
{
m_pLog->LogWarning("\004io: overdraft of callback time quota in the last frame: %I64d mcs", m_nCallbackTimeQuota);
AddCallbackTimeQuota(nMicroseconds);
}
else
m_nCallbackTimeQuota = nMicroseconds * m_nPerfFreq / 1000000;
}
bool CRefStreamEngine::IsCallbackTimeQuota(unsigned nFlags)
{
if (m_nSuspendCallbackTimeQuota == 0
&& !(nFlags&FLAGS_DISABLE_CALLBACK_TIME_QUOTA)
&& m_nCallbackTimeQuota <= 0
)
return false;
return true;
}
// In the Multi-Threaded model (with the IO Worker thread)
// removes the proxies from the IO Queue as needed, and the proxies may call their callbacks
unsigned CRefStreamEngine::FinalizeIOJobs(unsigned nFlags)
{
unsigned numFinalizedJobs = 0;
// we fetch the executed jobs one-by-one, and finalize them
// during finalization, the queue itself may be changed
if (!IsCallbackTimeQuota(nFlags))
return 0;
AUTO_LOCK(m_csIOExecuted);
while (!m_queIOExecuted.empty())
{
CRefReadStreamProxy_AutoPtr pProxy = m_queIOExecuted.front();
m_queIOExecuted.pop_front();
// to avoid locking the whole array during execution of the callbacks:
AUTO_UNLOCK(m_csIOExecuted);
assert(pProxy->IsIOExecuted());
int64 nStartTime, nEndTime;
QueryPerformanceCounter ((LARGE_INTEGER*)&nStartTime);
// TODO: add control over the callback execution time
// this proxy needs to be moved out of the IO queue
pProxy->FinalizeIO ();
++numFinalizedJobs;
QueryPerformanceCounter((LARGE_INTEGER*)&nEndTime);
m_nCallbackTimeQuota -= nEndTime - nStartTime;
if (!IsCallbackTimeQuota(nFlags))
break;
}
return numFinalizedJobs;
}
// this will be the thread that executes everything that can take time
void CRefStreamEngine::IOWorkerThread ()
{
do
{
// we start whatever IO jobs we have in the queue
StartIOJobs();
// we wait for new jobs to arrive or for the IO callbacks to be called
// even if it was a callback, we check for the new jobs: some jobs may have
// been suspended because of performance reasons, until the next callback;
// besides, the callback might have spawned some new jobs.
// the pending->executed move will happen in the callback
WaitForSingleObjectEx(m_hIOJob, INFINITE, TRUE);
}
while (!m_bStopIOWorker);
// wait for pending IO
AUTO_LOCK(m_csIOPending);
for (int nRetries = 0; nRetries < 100 && !m_setIOPending.empty(); ++nRetries)
{
AUTO_UNLOCK(m_csIOPending);
SleepEx(300, TRUE);
}
}
// sort the IO jobs in the IOQueue by priority
void CRefStreamEngine::SortIOJobs()
{
if (m_hIOWorker)
{
AUTO_LOCK(m_csIOJobs);
SortIOJobs_NoLock();
}
else
{
SortIOJobs_NoLock();
}
}
//////////////////////////////////////////////////////////////////////////
// this sorts the IO jobs, without bothering about synchronization
void CRefStreamEngine::SortIOJobs_NoLock()
{
std::sort (m_queIOJobs.begin(), m_queIOJobs.end(), CRefReadStreamProxy::Order());
}
bool CRefStreamEngine::IsSuspended()
{
return false;
}
//////////////////////////////////////////////////////////////////////////
//
unsigned CRefStreamEngine::StartIOJobs()
{
unsigned numMovedJobs = 0;
AUTO_LOCK(m_csIOJobs);
{
AUTO_LOCK(m_csIOPending);
CRefReadStreamProxy* pEndJob = NULL; // the job that will mark the end of loop
// TODO: implement limitation on the number of simultaneous read requests
while(!m_queIOJobs.empty()
&& m_setIOPending.size() < m_nMaxReadDepth
&& !IsSuspended())
{
CRefReadStreamProxy_AutoPtr pProxy = m_queIOJobs.front();
m_queIOJobs.pop_front();
m_setIOPending.insert (pProxy);
// temporary unlock both queue and set and start the reading
bool bReadStarted;
{
AUTO_UNLOCK(m_csIOPending);
{
AUTO_UNLOCK(m_csIOJobs);
// try to start reading
bReadStarted = pProxy->StartRead();
}
}
if (bReadStarted)
{
// in case of no error - this should be in most cases:
// we started the operation successfully
// perhaps now it's even already read and moved from Pending to Executed queue
// in case of unrecoverable error:
// we didn't start reading and can't do so. It's already moved into Executed queue as errorneous
++numMovedJobs;
pEndJob = NULL; // start the whole loop all over again.
}
else
{
// recoverable error - we'll try again next time
m_queIOJobs.push_back(pProxy);
m_setIOPending.erase (pProxy);
if (pEndJob)
{
if (pEndJob == pProxy)
break; // we are looping - we can't start this job for the second time in a row now
}
else
{
pEndJob = pProxy; // mark this job as the end of loop; we'll erase the marker if the job is started
}
}
}
}
return numMovedJobs;
}
void CRefStreamEngine::OnIOJobExecuted (CRefReadStreamProxy* pJobProxy)
{
if (m_hIOWorker && (pJobProxy->GetParams().nFlags & SRP_FLAGS_ASYNC_CALLBACK))
pJobProxy->FinalizeIO();
{
AUTO_LOCK(m_csIOPending);
{
AUTO_LOCK(m_csIOExecuted);
// first add, then erase - to avoid releasing the autopointer
// this is under double-locked CS's to avoid in-between artifacts
m_queIOExecuted.push_back(pJobProxy);
m_setIOPending.erase (pJobProxy);
}
}
SetEvent (m_hIOExecuted);
// perhaps this will free the way for another IO job.
// but we won't call StartIOJobs(), because this same funciton can only be
// called as part of Waiting after which the caller is aware that some jobs may have been executed
}
#ifndef LINUX
// returns the (cached) size of the sector on the volume where the given path points
// MT: MT-Safe + non-blocking, so far as writing to DWORD is atomic operation on the architecture it's executed at.
unsigned CRefStreamEngine::GetSectorSize(const char* szPath)
{
DWORD dwSectorsPerCluster, dwBytesPerSector, dwNumberOfFreeClusters, dwTotalNumberOfClusters;
if (szPath[0] == '\\' && szPath[1] == '\\')
{
// this is a share, try to get the share sector size..
// find the end of the share name \\server\share specification
const char* pEnd = szPath+1; // the pEnd points to \server\share\...
int nSlashes = 0;
while(*pEnd && nSlashes < 2)
{
// the pEnd points to server\share\... the first time the loop is entered
// when it reaches \share\.., nSlashes == 1, and
// when it reaches \..., nSlashes == 2 and pEnd points to the backslash
if (*++pEnd == '\\')
++nSlashes;
}
TElementaryArray<char> pShareName;
pShareName.reinit (pEnd - szPath+1);
memcpy (&pShareName[0], szPath, pEnd - szPath);
pShareName[pEnd - szPath] = '\0';
if (!GetDiskFreeSpace (&pShareName[0], &dwSectorsPerCluster, &dwBytesPerSector, &dwNumberOfFreeClusters, &dwTotalNumberOfClusters))
// set some default for share
dwSectorsPerCluster = 4 * 1024;
return dwSectorsPerCluster;
}
else
if (szPath[0] && szPath[1] == ':')
{
return GetDriveSectorSize(szPath[0]);
}
else
{
// this is relative path
TElementaryArray<char> pDir;
DWORD dwLen = GetCurrentDirectory(0, NULL);
pDir.reinit (dwLen);
if (dwLen != GetCurrentDirectory(dwLen, &pDir[0]))
{
DWORD dwSectorsPerCluster, dwBytesPerSector, dwNumberOfFreeClusters, dwTotalNumberOfClusters;
if (!GetDiskFreeSpace(NULL, &dwSectorsPerCluster, &dwBytesPerSector, &dwNumberOfFreeClusters, &dwTotalNumberOfClusters))
dwSectorsPerCluster = 2 * 1024;
return dwSectorsPerCluster;
}
else
return GetDriveSectorSize(pDir[0]);
}
}
unsigned CRefStreamEngine::GetDriveSectorSize (char cDrive)
{
cDrive = tolower(cDrive);
// this is an absolute path
char szBuf[4] = "X:\\";
szBuf[0] = cDrive;
// determine the pointer to the cached value of the sector size (NULL if there's no such)
unsigned * pCachedSectorSize = NULL;
if (szBuf[0]>='c' && unsigned(szBuf[0] - 'c') < SIZEOF_ARRAY(m_nSectorSizes))
pCachedSectorSize = m_nSectorSizes + szBuf[0]-'c';
// if we have don't have this disk size cache, (or just it wasn't cached yet), calculate and cache it
if (!pCachedSectorSize || *pCachedSectorSize)
{
DWORD dwSectorsPerCluster, dwBytesPerSector, dwNumberOfFreeClusters, dwTotalNumberOfClusters;
if (!GetDiskFreeSpace (szBuf, &dwSectorsPerCluster, &dwBytesPerSector, &dwNumberOfFreeClusters, &dwTotalNumberOfClusters))
// set some default for disk
dwSectorsPerCluster = 2 * 1024;
else
// cache the sector size
*pCachedSectorSize = dwSectorsPerCluster;
}
return *pCachedSectorSize;
}
#endif //LINUX
void CRefStreamEngine::StopWorkerThread()
{
if (m_hIOWorker)
{
m_bStopIOWorker = true;
SetEvent(m_hIOJob);
WaitForSingleObject (m_hIOWorker, INFINITE);
CloseHandle (m_hIOWorker);
m_hIOWorker = NULL;
}
}
void CRefStreamEngine::StartWorkerThread()
{
StopWorkerThread();
m_bStopIOWorker = false;
m_hIOWorker = CreateThread (NULL, 0x8000, IOWorkerThreadProc, this, 0, &m_dwWorkerThreadId);
}
//////////////////////////////////////////////////////////////////////////
// registers a new stream (added to the system: queued)
// MT: Main thread only
void CRefStreamEngine::Register (CRefReadStream* pStream)
{
m_mapFilesByName.insert (NameStreamMap::value_type(pStream->GetFileName(), pStream));
}
//////////////////////////////////////////////////////////////////////////
// unregisters: happens upon release of all resources
// MT: Main thread only
void CRefStreamEngine::Unregister (CRefReadStream* pStream)
{
m_mapFilesByName.erase(pStream->GetFileName());
}
// this function checks for the OS version and disables some capabilities of Streaming Engine when needed
// currently, in Win 9x overlapped IO is disabled
void CRefStreamEngine::CheckOSCaps()
{
#if defined(WIN32)
OSVERSIONINFO os;
os.dwOSVersionInfoSize = sizeof(os);
if (!GetVersionEx(&os))
{
m_bEnableOverlapped = false; // just in case
return;
}
if (os.dwPlatformId != VER_PLATFORM_WIN32_NT)
{
m_pLog->LogWarning("StreamEngine: OS (platform %d) doesn't support streaming, turning overlapped IO off",os.dwPlatformId );
// only NT supports overlapped IO
m_bEnableOverlapped = false;
}
#elif defined(_XBOX) || defined(LINUX)
// in XBox, nothing to disable
#else
#error // if your OS doesn't support it, you should disable Overlapped IO here
m_bEnableOverlapped = false;
#endif
}
unsigned CRefStreamEngine::numIOJobs(IOJobKindEnum nKind)
{
switch (nKind)
{
case eWaiting:
{
AUTO_LOCK(m_csIOJobs);
return (unsigned)m_queIOJobs.size();
}
break;
case ePending:
{
AUTO_LOCK(m_csIOPending);
return (unsigned)m_setIOPending.size();
}
break;
case eExecuted:
{
AUTO_LOCK(m_csIOExecuted);
return (unsigned)m_queIOExecuted.size();
}
break;
}
return 0;
}
//! Puts the memory statistics into the given sizer object
//! According to the specifications in interface ICrySizer
void CRefStreamEngine::GetMemoryStatistics(ICrySizer *pSizer)
{
size_t nSize = sizeof(*this);
for (NameStreamMap::iterator it = m_mapFilesByName.begin(); it != m_mapFilesByName.end(); ++it)
{
nSize += sizeof(NameStreamMap::value_type) + it->first.capacity() + it->second->GetSize();
}
nSize += m_setLockedStreams.size() * sizeof(CRefReadStream_AutoSet::value_type);
// here we calculate the capacities of 3 arrays; we don't want a deadlock so we lock them one by one,
// small discrepancies because something can be moved somewhere don't matter
{
AUTO_LOCK(m_csIOJobs);
nSize += m_queIOJobs.size() * sizeof(CRefReadStreamProxy_AutoDeque_MT::value_type);
}
{
AUTO_LOCK(m_csIOPending);
nSize += m_setIOPending.size() * sizeof(CRefReadStreamProxy_AutoSet_MT::value_type);
}
{
AUTO_LOCK(m_csIOExecuted);
nSize += m_queIOExecuted.size() * sizeof(CRefReadStreamProxy_AutoDeque_MT::value_type);
}
// this is calculated because each queue capacity is taken into account
//nSize += m_SmallHeap.getAllocatedSize();
// this is calculated because each stream Proxy contain pointer to this data
//nSize += m_BigHeap.getAllocatedSize();
pSizer->AddObject(this, nSize);
}
//! Enables or disables callback time quota per frame
void CRefStreamEngine::SuspendCallbackTimeQuota ()
{
if (m_nPerfFreq > 0)
{
++m_nSuspendCallbackTimeQuota;
}
}
void CRefStreamEngine::ResumeCallbackTimeQuota ()
{
if (m_nPerfFreq > 0)
{
--m_nSuspendCallbackTimeQuota;
if (m_nSuspendCallbackTimeQuota == 0 && m_nCallbackTimeQuota < 0)
{
m_pLog->LogWarning("\005io: overdraft of callback time quota after resume: %I64d", m_nCallbackTimeQuota);
m_nCallbackTimeQuota = 0;
}
}
}
DWORD CRefStreamEngine::GetStreamCompressionMask() const
{
return m_dwMask;
}

219
CrySystem/RefStreamEngine.h Normal file
View File

@@ -0,0 +1,219 @@
//////////////////////////////////////////////////////////////////////////
// Reference implementation of streamEngine
#ifndef _CRY_SYSTEM_REFERENCE_STREAM_ENGINE_HDR_
#define _CRY_SYSTEM_REFERENCE_STREAM_ENGINE_HDR_
#include "IMiniLog.h"
#include "IStreamEngine.h"
#include "RefReadStream.h"
#include "RefReadStreamProxy.h"
#include "CritSection.h"
#include "MTSafeAllocator.h"
#include "CryPak.h"
struct ICryPak;
class CRefStreamEngine:public IStreamEngine
{
public:
//! useWorkerThreads is the number of worker threads to use;
//! currently only values 0 and 1 are supported: 0 - overlapped IO in the main thread, and 1 - overlapped IO in the worker thread
CRefStreamEngine(CCryPak* pPak, IMiniLog* pLog, unsigned useWorkerThreads = 1, bool bOverlappedIO = true);
//! destructor
~CRefStreamEngine();
// interface IStreamEngine --------------------------------
virtual DWORD GetStreamCompressionMask() const;
virtual IReadStream_AutoPtr StartRead (const char* szSource, const char* szFile, IStreamCallback* pCallback, StreamReadParams* pParams = NULL);
virtual unsigned GetFileSize (const char* szFile, unsigned nCryPakFlags);
virtual void Update(unsigned nFlags);
virtual unsigned Wait(unsigned nMilliseconds, unsigned nFlags);
virtual void GetMemoryStatistics(ICrySizer *pSizer);
// ------------------------------------------------
//! registers a new stream (added to the system: queued)
void Register (CRefReadStream*);
//! unregisters: happens upon release of all resources
void Unregister (CRefReadStream*);
CCryPak* GetPak() {return m_pPak;}
unsigned UpdateAndWait (unsigned nMilliseconds, unsigned nFlags);
#ifndef LINUX
// returns the (cached) size of the sector on the volume where the given path points
unsigned GetSectorSize(const char* szPath);
unsigned GetDriveSectorSize (char cDrive);
#endif //LINUX
// sort the IO jobs in the IOQueue by priority
void SortIOJobs();
void OnIOJobExecuted (CRefReadStreamProxy* pJobProxy);
bool IsSuspended();
// returns true, if overlapped io with FILE_FLAG_OVERLAPPED and ReadFileEx is enabled
bool isOverlappedIoEnabled() {return m_bEnableOverlapped;}
enum IOJobKindEnum{eWaiting, ePending, eExecuted};
unsigned numIOJobs(IOJobKindEnum nKind);
//!
void SetCallbackTimeQuota(int nMicroseconds);
//!
void SetStreamCompressionMask( const DWORD indwMask );
// returns true if called from the main thread for this engine
bool IsMainThread();
// returns true if called from the worker thread
bool IsWorkerThread();
protected:
// this function checks for the OS version and disables some capabilities of Streaming Engine when needed
// currently, in Win 9x overlapped IO is disabled
void CheckOSCaps();
// this sorts the IO jobs, without bothering about synchronization
void SortIOJobs_NoLock();
// this will be the thread that executes everything that can take time
void IOWorkerThread ();
// the static function used to start the thread
#if defined(LINUX)
static void* WINAPI IOWorkerThreadProc (LPVOID pThis)
{
((CRefStreamEngine*)pThis)->IOWorkerThread();
pthread_exit(NULL);//finish thread
return NULL;
}
#else
static DWORD WINAPI IOWorkerThreadProc (LPVOID pThis)
{
((CRefStreamEngine*)pThis)->IOWorkerThread();
return 0;
}
#endif
void StartWorkerThread();
void StopWorkerThread();
// signals that this proxy needs to be executed (StartRead called)
void AddIOJob (CRefReadStreamProxy* pJobProxy);
// executes StartRead on the proxies that need it, and remove those proxies
// from the IO Queue. As soon as the proxy is removed from the IO Queue, it's on its own
// and should complete the operation itself and unregister upon destruction
// returns the number of jobs moved from the IO Job QUeue
unsigned StartIOJobs();
// In the Multi-Threaded model only (with the IO Worker thread)
// removes the proxies from the IO Queue as needed, and the proxies may call their callbacks
// returns the number of finalized jobs
unsigned FinalizeIOJobs(unsigned nFlags);
// adds to the callback time quota in this frame, the specified number of microseconds
void AddCallbackTimeQuota(int nMicroseconds);
bool IsCallbackTimeQuota(unsigned nFlags);
//! Enables or disables callback time quota per frame
void SuspendCallbackTimeQuota();
void ResumeCallbackTimeQuota();
protected:
DWORD m_dwMask; //!< default: 0, bitmask that affects the stram compression (look into Stream.h)
int64 m_nPerfFreq;
int64 m_nCallbackTimeQuota;
CCryPak* m_pPak;
// the set of file objects (not deleted yet)
typedef std::map<string, CRefReadStream*> NameStreamMap;
NameStreamMap m_mapFilesByName;
typedef std::set<CRefReadStream_AutoPtr> CRefReadStream_AutoSet;
CRefReadStream_AutoSet m_setLockedStreams;
IMiniLog* m_pLog;
// these are the cached sizes of sectors of disks, starting from c
// if the number contained here is 0, it means the sector size wasn't cached
unsigned m_nSectorSizes[8];
// the max number of simultaneous reads
unsigned m_nMaxReadDepth;
// the max length of the IO Job queue: when the max queue length is reached, the next StartRead
// will wait until it's shrinked
unsigned m_nMaxQueueLength;
// the max size of the allocated memory from the big pool
unsigned m_nMaxIOMemPool;
// this is the set of proxies that need to be started (StartRead needs to be called)
// These proxies can be rearranged, added to or removed by the main thread;
// protected by m_csMainWriter
typedef CMTSafeAllocator<CRefReadStreamProxy_AutoPtr> ProxyPtrAllocator;
typedef std::less<CRefReadStreamProxy_AutoPtr> ProxyPtrPredicate;
typedef std::deque<CRefReadStreamProxy_AutoPtr, ProxyPtrAllocator > CRefReadStreamProxy_AutoDeque_MT;
CRefReadStreamProxy_AutoDeque_MT m_queIOJobs;
CCritSection m_csIOJobs;
typedef std::set<CRefReadStreamProxy_AutoPtr, ProxyPtrPredicate, ProxyPtrAllocator> CRefReadStreamProxy_AutoSet_MT;
CRefReadStreamProxy_AutoSet_MT m_setIOPending;
CCritSection m_csIOPending;
// the event used to signal the worker thread that a new job arrived
// the job can be: ask to suspend, ask to read, ask to stop or basically anything that needs attention of the worker thread
EVENT_HANDLE m_hIOJob;//EVENT_HANDLE is a typedef to HANDLE under windows
// signals about arrival of executed jobs. This event is MANUAL-reset
EVENT_HANDLE m_hIOExecuted;//EVENT_HANDLE is a typedef to HANDLE under windows
// the set of proxies awaiting finalization in the main thread
// this is the number of proxes from m_arrSuspendedProxies
// they need attention of the main thread: e.g. they have
// already finished their operations and need to be removed,
// or they need memory allocated from the main thread.
CRefReadStreamProxy_AutoDeque_MT m_queIOExecuted;
CCritSection m_csIOExecuted;
// the handle to the worker thread, or NULL if single-threaded overlapped IO is used
THREAD_HANDLE m_hIOWorker;//THREAD_HANDLE is a typedef to HANDLE under windows
// this event is never signaled
EVENT_HANDLE m_hDummyEvent;//EVENT_HANDLE is a typedef to HANDLE under windows
// this flag is set to stop the worker thread
bool m_bStopIOWorker;
// this flag enables or disables usage of really asynchronous file io (ReadFileEx and FILE_FLAG_OVERLAPPED)
bool m_bEnableOverlapped;
// this flag is set if the callback time quota is enabled
int m_nSuspendCallbackTimeQuota;
// this is the id of the main thread in which this engine operates
DWORD m_dwMainThreadId;
// the id of the worker thread, if any
DWORD m_dwWorkerThreadId;
// This critical section protects the objects that can be written to by the main thread only
// It must be locked for the time of access from non-main thread and for the time of writing from the main thread
// Main thread can have read access to those objects anytime without serialization
//CCritSection m_csMainWriter;
};
#endif

BIN
CrySystem/SSAPI.DLL Normal file

Binary file not shown.

134
CrySystem/ScriptBinding.cpp Normal file
View File

@@ -0,0 +1,134 @@
#include "stdafx.h"
#include "System.h"
#include "ScriptObjectSystem.h"
#include "ScriptObjectParticle.h"
#include "ScriptObjectAnimation.h"
#include "ScriptObjectSound.h"
#include "ScriptObjectMovie.h"
#include "ScriptObjectScript.h"
#include "ScriptObjectEntity.h"
#include "HTTPDownloader.h"
#include <IEntitySystem.h>
struct CScriptBindings
{
CScriptBindings();
~CScriptBindings(){}
bool Init(CSystem *pSystem);
bool ShutDown();
private:
CScriptObjectSystem *m_pScriptObjectSystem;
CScriptObjectParticle *m_pScriptObjectParticle;
CScriptObjectAnimation *m_pScriptObjectAnimation;
CScriptObjectSound *m_pScriptObjectSound;
CScriptObjectMovie *m_pScriptObjectMovie;
CScriptObjectScript *m_pScriptObjectScript;
};
CScriptBindings::CScriptBindings()
{
m_pScriptObjectSystem=NULL;
m_pScriptObjectParticle=NULL;
m_pScriptObjectAnimation=NULL;
m_pScriptObjectSound=NULL;
m_pScriptObjectMovie=NULL;
m_pScriptObjectScript=NULL;
}
bool CScriptBindings::Init(CSystem *pSystem)
{
IScriptSystem *pSS=pSystem->GetIScriptSystem();
//SYSTEM
CScriptObjectSystem::InitializeTemplate(pSS);
m_pScriptObjectSystem=new CScriptObjectSystem;
m_pScriptObjectSystem->Init(pSS,pSystem);
//PARTICLE
CScriptObjectParticle::InitializeTemplate(pSS);
m_pScriptObjectParticle=new CScriptObjectParticle;
m_pScriptObjectParticle->Init(pSS,pSystem);
//ANIMATION
CScriptObjectAnimation::InitializeTemplate(pSS);
m_pScriptObjectAnimation=new CScriptObjectAnimation;
m_pScriptObjectAnimation->Init(pSS,pSystem);
//SOUND
CScriptObjectSound::InitializeTemplate(pSS);
m_pScriptObjectSound=new CScriptObjectSound;
m_pScriptObjectSound->Init(pSS,pSystem);
//MOVIE
CScriptObjectMovie::InitializeTemplate(pSS);
m_pScriptObjectMovie=new CScriptObjectMovie;
m_pScriptObjectMovie->Init(pSS,pSystem);
//SCRIPT
CScriptObjectScript::InitializeTemplate(pSS);
m_pScriptObjectScript=new CScriptObjectScript;
m_pScriptObjectScript->Init(pSS);
//ENTITY
CScriptObjectEntity::InitializeTemplate(pSS);
//DOWNLOAD
#if !defined(LINUX)
CHTTPDownloader::InitializeTemplate(pSS);
#endif
return true;
}
bool CScriptBindings::ShutDown()
{
CScriptObjectSystem::ReleaseTemplate();
SAFE_DELETE(m_pScriptObjectSystem);
CScriptObjectParticle::ReleaseTemplate();
SAFE_DELETE(m_pScriptObjectParticle);
CScriptObjectAnimation::ReleaseTemplate();
SAFE_DELETE(m_pScriptObjectAnimation);
CScriptObjectSound::ReleaseTemplate();
SAFE_DELETE(m_pScriptObjectSound);
CScriptObjectMovie::ReleaseTemplate();
SAFE_DELETE(m_pScriptObjectMovie);
CScriptObjectScript::ReleaseTemplate();
SAFE_DELETE(m_pScriptObjectScript);
CScriptObjectEntity::ReleaseTemplate();
#if !defined(LINUX)
CHTTPDownloader::ReleaseTemplate();
#endif
return true;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
bool CSystem::InitScriptBindings()
{
m_pScriptBindings=new CScriptBindings;
return m_pScriptBindings->Init(this);
}
bool CSystem::ShutDownScriptBindings()
{
if(m_pScriptBindings)
{
bool bres=m_pScriptBindings->ShutDown();
delete m_pScriptBindings;
return bres;
}
return false;
}
void CSystem::CreateEntityScriptBinding(IEntity *ent)
{
CScriptObjectEntity *pSEntity = new CScriptObjectEntity();
pSEntity->Create(m_pScriptSystem, this);
assert(pSEntity->GetScriptObject());
if (ent->GetContainer()){
IScriptObject *pObj=ent->GetContainer()->GetScriptObject();
if(pObj)
pSEntity->SetContainer(pObj);
}
assert(pSEntity->GetScriptObject());
pSEntity->SetEntity(ent);
assert(pSEntity->GetScriptObject());
ent->SetScriptObject(pSEntity->GetScriptObject());
assert(pSEntity->GetScriptObject());
assert(ent->GetScriptObject());
}

View File

@@ -0,0 +1,255 @@
#include "stdafx.h"
#include "ScriptObjectAnimation.h"
#include "CryAnimationScriptCommands.h"
#include <ISystem.h>
#include <I3DEngine.h>
#include <ICryAnimation.h>
#define GET_ANIM_MANAGER(pAnimationManager) ICryCharManager* pAnimationManager = getAnimationManager(); \
if (!pAnimationManager) \
{ \
m_pScriptSystem->RaiseError("System. No Animation System available", pH->GetParamCount()); \
return 0; \
}
#undef REG_FUNC
#define REG_FUNC(_func) CScriptObjectAnimation::RegisterFunction(pSS,#_func,&CScriptObjectAnimation::_func);
_DECLARE_SCRIPTABLEEX(CScriptObjectAnimation)
CScriptObjectAnimation::CScriptObjectAnimation(void)
{
}
CScriptObjectAnimation::~CScriptObjectAnimation(void)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*! Initializes the script-object and makes it available for the scripts.
@param pScriptSystem Pointer to the ScriptSystem-interface
@param pGame Pointer to the Game
@param pSystem Pointer to the System-interface
*/
void CScriptObjectAnimation::Init(IScriptSystem *pScriptSystem, ISystem *pSystem)
{
m_pSystem = pSystem;
m_pScriptSystem = pScriptSystem;
InitGlobal(pScriptSystem,"Animation",this);
}
void CScriptObjectAnimation::InitializeTemplate(IScriptSystem *pSS)
{
_ScriptableEx<CScriptObjectAnimation>::InitializeTemplate(pSS);
REG_FUNC(DumpAnims);
REG_FUNC(DumpModels);
REG_FUNC(TestParticles);
REG_FUNC(StopParticles);
REG_FUNC(TrashAnims);
REG_FUNC(UnloadAnim);
REG_FUNC(ClearDecals);
REG_FUNC(DumpDecals);
REG_FUNC(Start2Anims);
REG_FUNC(DumpStates);
REG_FUNC(ExportModels);
}
ICryCharManager* CScriptObjectAnimation::getAnimationManager()
{
return m_pSystem->GetIAnimationSystem();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*! Dumps memory usage by animations
@param nSort first operand (int) 0: sort by memory size 1: sort by name (not implemented)
@return result of the operation (int)
*/
int CScriptObjectAnimation::DumpAnims(IFunctionHandler *pH)
{
GET_ANIM_MANAGER(pAnimationManager);
switch (pH->GetParamCount())
{
case 0:
{
pAnimationManager->ExecScriptCommand(CASCMD_DUMP_ANIMATIONS);
}
break;
case 1:
{
int nSort;
pH->GetParam(1,nSort);
}
break;
default:
m_pScriptSystem->RaiseError("System.DumpAnims wrong number of arguments (%d)", pH->GetParamCount());
return pH->EndFunctionNull();
}
return pH->EndFunction(0);
}
int CScriptObjectAnimation::TrashAnims(IFunctionHandler *pH)
{
GET_ANIM_MANAGER(pAnimationManager);
switch (pH->GetParamCount())
{
case 0:
{
pAnimationManager->ExecScriptCommand(CASCMD_TRASH_ANIMATIONS);
}
break;
case 1:
{
int numFrames;
if (pH->GetParam(1,numFrames))
pAnimationManager->ExecScriptCommand(CASCMD_TRASH_ANIMATIONS, &numFrames);
else
pAnimationManager->ExecScriptCommand(CASCMD_TRASH_ANIMATIONS);
}
default:
m_pScriptSystem->RaiseError("System.TrashAnims wrong number of arguments (%d)", pH->GetParamCount());
return pH->EndFunctionNull();
}
return pH->EndFunction(0);
}
int CScriptObjectAnimation::ClearDecals(IFunctionHandler* pH)
{
GET_ANIM_MANAGER(pAnimationManager);
switch (pH->GetParamCount())
{
case 0:
pAnimationManager->ExecScriptCommand(CASCMD_CLEAR_DECALS);
break;
default:
m_pScriptSystem->RaiseError("System.ClearDecals wrong number of arguments (%d)", pH->GetParamCount());
return pH->EndFunctionNull();
}
return pH->EndFunction(0);
}
int CScriptObjectAnimation::DumpDecals(IFunctionHandler* pH)
{
GET_ANIM_MANAGER(pAnimationManager);
switch (pH->GetParamCount())
{
case 0:
pAnimationManager->ExecScriptCommand(CASCMD_DUMP_DECALS);
break;
default:
m_pScriptSystem->RaiseError("System.DumpDecals wrong number of arguments (%d)", pH->GetParamCount());
return pH->EndFunctionNull();
}
return pH->EndFunction(0);
}
int CScriptObjectAnimation::Start2Anims(IFunctionHandler* pH)
{
GET_ANIM_MANAGER(pAnimationManager);
switch (pH->GetParamCount())
{
case 5:
{
CASCmdStartAnim sa[2];
CASCmdStartMultiAnims ma;
if (!pH->GetParam (1, sa[0].nLayer)
||!pH->GetParam (2, sa[0].szAnimName)
||!pH->GetParam (3, sa[1].nLayer)
||!pH->GetParam (4, sa[1].szAnimName)
||!pH->GetParam (5, ma.fBlendTime))
m_pScriptSystem->RaiseError("System.UnloadAnim wrong argument type");
ma.numAnims = 2;
ma.pAnims = sa;
pAnimationManager->ExecScriptCommand(CASCMD_START_MANY_ANIMS, &ma);
}
break;
default:
m_pScriptSystem->RaiseError("System.Start2Anims wrong number of arguments (%d), use: Start2Anims(layer,anim,layer,anim,blendin)", pH->GetParamCount());
return pH->EndFunctionNull();
}
return pH->EndFunction(0);
}
int CScriptObjectAnimation::DumpStates(IFunctionHandler* pH)
{
GET_ANIM_MANAGER(pAnimationManager);
switch (pH->GetParamCount())
{
case 0:
pAnimationManager->ExecScriptCommand(CASCMD_DUMP_STATES);
break;
default:
m_pScriptSystem->RaiseError("System.DumpStates wrong number of arguments (%d)", pH->GetParamCount());
return pH->EndFunctionNull();
}
return pH->EndFunction(0);
}
int CScriptObjectAnimation::ExportModels(IFunctionHandler* pH)
{
GET_ANIM_MANAGER(pAnimationManager);
pAnimationManager->ExecScriptCommand(CASCMD_EXPORT_MODELS_ASCII);
return pH->EndFunction(0);
}
int CScriptObjectAnimation::UnloadAnim(IFunctionHandler *pH)
{
GET_ANIM_MANAGER(pAnimationManager);
switch (pH->GetParamCount())
{
case 1:
{
const char* pName;
if (pH->GetParam(1,pName))
pAnimationManager->ExecScriptCommand(CASCMD_UNLOAD_ANIMATION, (void*)pName);
else
{
m_pScriptSystem->RaiseError("System.UnloadAnim wrong argument type (%d) - must be a string", pH->GetParamType(1));
return pH->EndFunctionNull();
}
}
default:
m_pScriptSystem->RaiseError("System.UnloadAnim wrong number of arguments (%d)", pH->GetParamCount());
return pH->EndFunctionNull();
}
return pH->EndFunction(0);
}
int CScriptObjectAnimation::DumpModels(IFunctionHandler *pH)
{
GET_ANIM_MANAGER(pAnimationManager);
pAnimationManager->ExecScriptCommand(CASCMD_DUMP_MODELS);
return pH->EndFunction(0);
}
/*! Starts spawning particles
@param fSpawnRate first operand (float) rate of particle spawn
@return result of the operation (int)
*/
int CScriptObjectAnimation::TestParticles(IFunctionHandler *pH)
{
GET_ANIM_MANAGER(pAnimationManager);
pAnimationManager->ExecScriptCommand (CASCMD_TEST_PARTICLES);
return pH->EndFunction(0);
}
/*! Starts spawning particles
@param fSpawnRate first operand (float) rate of particle spawn
@return result of the operation (int)
*/
int CScriptObjectAnimation::StopParticles(IFunctionHandler *pH)
{
GET_ANIM_MANAGER(pAnimationManager);
pAnimationManager->ExecScriptCommand (CASCMD_STOP_PARTICLES);
return pH->EndFunction(0);
}

View File

@@ -0,0 +1,55 @@
// ScriptObjectAnimation.h: interface for the CScriptObjectAnimation class.
//
//////////////////////////////////////////////////////////////////////
#ifndef __CRY_GAME_SCRIPT_OBJECT_ANIMATION_HDR__
#define __CRY_GAME_SCRIPT_OBJECT_ANIMATION_HDR__
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <IScriptSystem.h>
#include <_ScriptableEx.h>
struct ISystem;
struct ICryCharManager;
/*! This class implements all animation-related (currently only test) script functions.
REMARKS:
After initialization of the script-object it will be globally accessable through scripts using the namespace "Animation".
Example:
Animation:DumpAnims();
IMPLEMENTATIONS NOTES:
These function will never be called from C-Code. They're script-exclusive.
*/
class CScriptObjectAnimation:
public _ScriptableEx<CScriptObjectAnimation>
{
public:
CScriptObjectAnimation(void);
virtual ~CScriptObjectAnimation(void);
void Init(IScriptSystem *pScriptSystem, ISystem *pSystem);
static void InitializeTemplate(IScriptSystem *pSS);
public:
int DumpAnims(IFunctionHandler *pH);
int DumpModels (IFunctionHandler *pH);
int TestParticles (IFunctionHandler *pH);
int StopParticles (IFunctionHandler *pH);
int TrashAnims(IFunctionHandler* pH);
int UnloadAnim(IFunctionHandler* pH);
int ClearDecals(IFunctionHandler* pH);
int DumpDecals(IFunctionHandler* pH);
int Start2Anims(IFunctionHandler* pH);
int DumpStates (IFunctionHandler* pH);
int ExportModels(IFunctionHandler* pH);
ICryCharManager* getAnimationManager();
private:
ISystem *m_pSystem;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,291 @@
// ScriptObjectEntity.h: interface for the CScriptObjectEntity class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_SCRIPTOBJECTENTITY_H__870B7388_021A_46C0_84B4_734EEB08DE7D__INCLUDED_)
#define AFX_SCRIPTOBJECTENTITY_H__870B7388_021A_46C0_84B4_734EEB08DE7D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <IScriptSystem.h>
#include <_ScriptableEx.h>
#define PHYSICPARAM_PARTICLE 0x00000001
#define PHYSICPARAM_VEHICLE 0x00000002
#define PHYSICPARAM_PLAYERDYN 0x00000003
#define PHYSICPARAM_PLAYERDIM 0x00000004
#define PHYSICPARAM_SIMULATION 0x00000005
#define PHYSICPARAM_ARTICULATED 0x00000006
#define PHYSICPARAM_JOINT 0x00000007
#define PHYSICPARAM_ROPE 0x00000008
#define PHYSICPARAM_BUOYANCY 0x00000009
#define PHYSICPARAM_CONSTRAINT 0x0000000A
#define PHYSICPARAM_REMOVE_CONSTRAINT 0x00000B
#define PHYSICPARAM_FLAGS 0x0000000C
#define PHYSICPARAM_WHEEL 0x0000000D
#define PHYSICPARAM_SOFTBODY 0x0000000E
#define PHYSICPARAM_VELOCITY 0x0000000F
#define PHYSICPARAM_PART_FLAGS 0x00000010
#define AIPARAM_SIGHTRANGE 1
#define AIPARAM_ATTACKRANGE 2
#define AIPARAM_ACCURACY 3
#define AIPARAM_AGGRESION 4
#define AIPARAM_GROUPID 5
#define AIPARAM_SOUNDRANGE 6
#define AIPARAM_FOV 7
#define AIPARAM_COMMRANGE 8
#define AIPARAM_FWDSPEED 9
#define AIPARAM_RESPONSIVENESS 10
#define AIPARAM_SPECIES 11
struct IEntity;
struct ISystem;
class CScriptObjectVector;
#include <IPhysics.h>
#define USE_MEMBER_POS
#define ENTITYPROP_CASTSHADOWS 0x00000001
#define ENTITYPROP_DONOTCHECKVIS 0x00000002
enum SOE_MEMBER_LUA_TABLES {
SOE_MEMBER_HELPER_POS,
SOE_MEMBER_BONE_POS,
SOE_MEMBER_BONE_DIR,
SOE_MEMBER_OBJ_VEL,
SOE_MEMBER_LAST
};
/*! In this class are all entity-related script-functions implemented in order tos expose all functionalities provided by an entity.
IMPLEMENTATIONS NOTES:
These function will never be called from C-Code. They're script-exclusive.
*/
class CScriptObjectEntity :
public _ScriptableEx<CScriptObjectEntity>,
public IScriptObjectSink
{
public:
CScriptObjectEntity();
virtual ~CScriptObjectEntity();
bool Create(IScriptSystem *pScriptSystem, ISystem *pSystem);
void SetEntity(IEntity *pEntity);
void SetContainer(IScriptObject *pContainer);
//IScriptObjectSink
void OnRelease()
{
m_pScriptThis->Clear();
m_pScriptThis=NULL;
delete this;
}
static void InitializeTemplate(IScriptSystem *pSS);
static void ReleaseTemplate();
public:
int SelectPipe(IFunctionHandler *pH);
int EnableUpdate(IFunctionHandler *pH);
int SetUpdateIfPotentiallyVisible(IFunctionHandler *pH);
int SetUpdateType(IFunctionHandler *pH);
int SetBBox(IFunctionHandler *pH);
int GetBBox(IFunctionHandler *pH);
int GetLocalBBox(IFunctionHandler *pH);
int SetRadius(IFunctionHandler *pH);
int SetUpdateRadius(IFunctionHandler *pH);
int GetUpdateRadius(IFunctionHandler *pH);
int LoadBreakable(IFunctionHandler *pH);
int BreakEntity(IFunctionHandler *pH);
int TriggerEvent(IFunctionHandler *pH);
int GetHelperPos(IFunctionHandler *pH);
int GetBonePos(IFunctionHandler *pH);
int GetBoneDir(IFunctionHandler *pH);
int GetBoneNameFromTable(IFunctionHandler *pH);
int LoadVehicle(IFunctionHandler *pH);
//int SetDamage(IFunctionHandler *pH);
int CreateParticleEntity(IFunctionHandler *pH);
int GetPos(IFunctionHandler *pH);
int GetCenterOfMassPos(IFunctionHandler *pH);
//int GetWorldPos(IFunctionHandler *pH);
int SetPos(IFunctionHandler *pH);
int SetName(IFunctionHandler *pH);
int GetName(IFunctionHandler *pH);
int SetAIName(IFunctionHandler *pH);
int GetAIName(IFunctionHandler *pH);
int PhysicalizeCharacter(IFunctionHandler *pH);
int LoadObject(IFunctionHandler *pH);
int LoadObjectPiece(IFunctionHandler *pH);
int GetObjectPos(IFunctionHandler *pH);
int SetObjectPos(IFunctionHandler *pH);
int GetObjectAngles(IFunctionHandler *pH);
int SetObjectAngles(IFunctionHandler *pH);
int DrawObject(IFunctionHandler *pH);
int CreateParticlePhys(IFunctionHandler *pH);
int CreateLivingEntity(IFunctionHandler *pH);
int CreateRigidBody(IFunctionHandler *pH);
int CreateArticulatedBody(IFunctionHandler *pH);
int CreateRigidBodyPiece(IFunctionHandler *pH);
int CreateSoftEntity(IFunctionHandler *pH);
int ResetPhysics(IFunctionHandler *pH);
int AwakePhysics(IFunctionHandler *pH);
int AwakeCharacterPhysics(IFunctionHandler *pH);
int CreateStaticEntity(IFunctionHandler *pH);
int SetAngles(IFunctionHandler *pH);
int GetAngles(IFunctionHandler *pH);
//int GetAnglesReal(IFunctionHandler *pH);
int Bind(IFunctionHandler *pH);
int Unbind(IFunctionHandler *pH);
int IsBound(IFunctionHandler *pH);
int NetPresent(IFunctionHandler *pH);
int RenderShadow(IFunctionHandler *pH);
int SetRegisterInSectors(IFunctionHandler *pH);
int SetPhysicParams(IFunctionHandler *pH);
int SetCharacterPhysicParams(IFunctionHandler *pH);
int GetParticleCollisionStatus(IFunctionHandler *pH);
int GetObjectStatus(IFunctionHandler *pH);
int SetObjectStatus(IFunctionHandler *pH);
int GetDirectionVector(IFunctionHandler *pH);
int IsAnimationRunning(IFunctionHandler *pH);
int AddImpulse(IFunctionHandler *pH);
int AddImpulseObj(IFunctionHandler *pH);
int IsPointWithinRadius(IFunctionHandler *pH);
// int RegisterWithAI(IFunctionHandler *pH);
int GetDistanceFromPoint(IFunctionHandler *pH);
int DestroyPhysics(IFunctionHandler *pH);
int EnablePhysics(IFunctionHandler *pH);
int SetSecondShader(IFunctionHandler *pH);
int SetShader(IFunctionHandler *pH);
int GetShader(IFunctionHandler *pH);
int GetCameraPosition(IFunctionHandler *pH);
int SetShaderFloat(IFunctionHandler *pH);
int SetColor(IFunctionHandler *pH);
int SetStatObjScale(IFunctionHandler *pH);
int EnableSave(IFunctionHandler *pH);
int PlaySound(IFunctionHandler *pH);
int KillCharacter(IFunctionHandler *pH);
int DrawCharacter(IFunctionHandler *pH);
int LoadCharacter(IFunctionHandler *pH);
int StartAnimation(IFunctionHandler *pH);
int ResetAnimation(IFunctionHandler *pH);
int SetAnimationEvent(IFunctionHandler *pH);
int SetAnimationKeyEvent(IFunctionHandler *pH);
int DisableAnimationEvent(IFunctionHandler *pH);
int SetAnimationSpeed(IFunctionHandler *pH);
int SetAnimationTime(IFunctionHandler *pH);
int GetAnimationTime(IFunctionHandler *pH);
int GetCurAnimation(IFunctionHandler *pH);
int GetAnimationLength(IFunctionHandler *pH);
int ReleaseLipSync(IFunctionHandler *pH);
int DoRandomExpressions(IFunctionHandler *pH);
int DoExpression(IFunctionHandler *pH);
int SayDialog(IFunctionHandler *pH);
int StopDialog(IFunctionHandler *pH);
int SetTimer(IFunctionHandler *pH);
int KillTimer(IFunctionHandler *pH);
int SetScriptUpdateRate(IFunctionHandler *pH);
// State managment.
int GotoState(IFunctionHandler *pH);
int IsInState(IFunctionHandler *pH);
int GetState(IFunctionHandler *pH);
int RegisterState(IFunctionHandler *pH);
int ApplyForceToEnvironment(IFunctionHandler *pH);
int IsVisible(IFunctionHandler *pH);
//
int GetTouchedSurfaceID(IFunctionHandler *pH);
//
//retrieves point of collision for rigid body
int GetTouchedPoint(IFunctionHandler *pH);
int AttachToBone(IFunctionHandler *pH);
int AttachObjectToBone(IFunctionHandler *pH);
int DetachObjectToBone(IFunctionHandler *pH);
// int TranslatePartIdToDeadBody(IFunctionHandler *pH);
int InitDynamicLight(IFunctionHandler *pH);
int AddDynamicLight(IFunctionHandler *pH);
int AddDynamicLight2(IFunctionHandler *pH);
int RemoveLight(IFunctionHandler *pH);
//
// proseeding humming rockets
int DoHam(IFunctionHandler *pH);
int ResetHam(IFunctionHandler *pH);
int LoadBoat(IFunctionHandler *pH);
// int GetBuildingId(IFunctionHandler *pH);
// int GetSectorId(IFunctionHandler *pH);
int Damage(IFunctionHandler *pH);
// int UpdateInSector(IFunctionHandler *pH);
int GetCameraAngles(IFunctionHandler *pH);
int CreateParticleEmitter(IFunctionHandler *pH);
int CreateParticleEmitterEffect(IFunctionHandler *pH);
int DeleteParticleEmitter(IFunctionHandler *pH);
int GetEntitiesInContact(IFunctionHandler *pH);
int IsAffectedByExplosion(IFunctionHandler *pH);
int SetMaterial(IFunctionHandler *pH);
int GetMaterial(IFunctionHandler *pH);
int TrackColliders(IFunctionHandler *pH);
int CheckCollisions(IFunctionHandler *pH);
int AwakeEnvironment(IFunctionHandler *pH);
int GetViewDistRatio(IFunctionHandler *pH);
int SetViewDistRatio(IFunctionHandler *pH);
int SetViewDistUnlimited(IFunctionHandler *pH);
int SetStateClientside(IFunctionHandler *pH);
private: // -------------------------------------------------------------------------------
int SetEntityPhysicParams(IPhysicalEntity *pe, IFunctionHandler *pH,int iOffs=0, ICryCharInstance *pIChar=0);
int CreateRigidOrArticulatedBody(pe_type type, IFunctionHandler *pH);
void SetMemberVector( SOE_MEMBER_LUA_TABLES member,const Vec3 &vec );
IEntity *m_pEntity;
IEntitySystem *m_pEntitySystem;
ISystem *m_pISystem;
ISoundSystem *m_pSoundSystem;
int m_nCurrSoundId;
#ifdef USE_MEMBER_POS
static IScriptObject *m_pObjectPos;
static IScriptObject *m_pObjectAngles;
static IScriptObject *m_pCameraPosition;
static IScriptObject *m_pGenVector;
#endif
// member script objects (preallocated)
static IScriptObject* m_memberSO[SOE_MEMBER_LAST];
// copy of function from ScriptObjectParticle
bool ReadParticleTable(IScriptObject *pITable, struct ParticleParams &sParamOut);
// pe_params_particle m_RocketParticlePar; // quick fix for hamming rockets
//float m_ControlTime;
//float m_ControlTimeLimit;
//Vec3d m_Control;
// char m_tonno[256];
public:
// Enable/ disable various entity features
int EnableProp(IFunctionHandler * pH);
int InsertSubpipe(IFunctionHandler * pH);
int ChangeAIParameter(IFunctionHandler * pH);
int SetAICustomFloat(IFunctionHandler *pH);
int ActivatePhysics(IFunctionHandler *pH);
int SetHandsIKTarget(IFunctionHandler *pH);
int SetDefaultIdleAnimations(IFunctionHandler *pH);
int GetVelocity(IFunctionHandler *pH);
int ApplyImpulseToEnvironment(IFunctionHandler * pH);
int RemoveDecals(IFunctionHandler * pH);
int SwitchLight(IFunctionHandler * pH);
int ForceCharacterUpdate(IFunctionHandler * pH);
int Hide(IFunctionHandler * pH);
int NoExplosionCollision(IFunctionHandler * pH);
};
#endif // !defined(AFX_SCRIPTOBJECTENTITY_H__870B7388_021A_46C0_84B4_734EEB08DE7D__INCLUDED_)

View File

@@ -0,0 +1,125 @@
#include "stdafx.h"
#include "scriptobjectmovie.h"
#include <ISystem.h>
#include <IMovieSystem.h>
#include <IGame.h>
_DECLARE_SCRIPTABLEEX(CScriptObjectMovie)
//////////////////////////////////////////////////////////////////////////
CScriptObjectMovie::CScriptObjectMovie()
{
}
//////////////////////////////////////////////////////////////////////////
CScriptObjectMovie::~CScriptObjectMovie()
{
}
/*! Initializes the script-object and makes it available for the scripts.
@param pScriptSystem Pointer to the ScriptSystem-interface
@param pGame Pointer to the Game
*/
//////////////////////////////////////////////////////////////////////////
void CScriptObjectMovie::Init(IScriptSystem *pScriptSystem, ISystem *pSystem)
{
m_pSystem=pSystem;
m_pMovieSystem=m_pSystem->GetIMovieSystem();
InitGlobal(pScriptSystem, "Movie", this);
}
//////////////////////////////////////////////////////////////////////////
void CScriptObjectMovie::InitializeTemplate(IScriptSystem *pSS)
{
_ScriptableEx<CScriptObjectMovie>::InitializeTemplate(pSS);
REG_FUNC(CScriptObjectMovie,PlaySequence);
REG_FUNC(CScriptObjectMovie,StopSequence);
REG_FUNC(CScriptObjectMovie,StopAllSequences);
REG_FUNC(CScriptObjectMovie,StopAllCutScenes);
REG_FUNC(CScriptObjectMovie,PauseSequences);
REG_FUNC(CScriptObjectMovie,ResumeSequences);
}
/*! Start a sequence
@param pszName Name of sequence
*/
//////////////////////////////////////////////////////////////////////////
int CScriptObjectMovie::PlaySequence(IFunctionHandler *pH)
{
//CHECK_PARAMETERS(1);
if (pH->GetParamCount()<1)
return pH->EndFunction();
const char *pszName;
pH->GetParam(1, pszName);
IGame *pGame=m_pSystem->GetIGame();
if (!pGame)
{
// can this happen?
return pH->EndFunction();
}
bool bResetFx=true;
if (pH->GetParamCount()==2)
pH->GetParam(2, bResetFx);
m_pSystem->GetIMovieSystem()->PlaySequence(pszName,bResetFx);
return pH->EndFunction();
}
/*! Stop a sequence
@param pszName Name of sequence
*/
//////////////////////////////////////////////////////////////////////////
int CScriptObjectMovie::StopSequence(IFunctionHandler *pH)
{
CHECK_PARAMETERS(1);
const char *pszName;
pH->GetParam(1, pszName);
m_pMovieSystem->StopSequence(pszName);
return pH->EndFunction();
}
//////////////////////////////////////////////////////////////////////////
int CScriptObjectMovie::StopAllSequences(IFunctionHandler *pH)
{
CHECK_PARAMETERS(0);
m_pMovieSystem->StopAllSequences();
return pH->EndFunction();
}
//////////////////////////////////////////////////////////////////////////
int CScriptObjectMovie::StopAllCutScenes(IFunctionHandler *pH)
{
CHECK_PARAMETERS(0);
IGame *pGame=m_pSystem->GetIGame();
if (!pGame)
{
// can this happen?
return pH->EndFunction();
}
//pGame->StopCurrentCutscene();
//m_pMovieSystem->StopAllCutScenes();
m_pSystem->GetIMovieSystem()->StopAllCutScenes();
return pH->EndFunction();
}
int CScriptObjectMovie::PauseSequences(IFunctionHandler *pH)
{
CHECK_PARAMETERS(0);
m_pMovieSystem->Pause();
return pH->EndFunction();
}
int CScriptObjectMovie::ResumeSequences(IFunctionHandler *pH)
{
CHECK_PARAMETERS(0);
m_pMovieSystem->Resume();
return pH->EndFunction();
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include <_ScriptableEx.h>
#include "IScriptSystem.h"
struct IEntity;
class CScriptObjectMovie :
public _ScriptableEx<CScriptObjectMovie>
{
public:
CScriptObjectMovie();
virtual ~CScriptObjectMovie();
static void InitializeTemplate(IScriptSystem *pSS);
void Init(IScriptSystem *pScriptSystem, ISystem *pSystem);
int PlaySequence(IFunctionHandler *pH);
int StopSequence(IFunctionHandler *pH);
int StopAllSequences(IFunctionHandler *pH);
int StopAllCutScenes(IFunctionHandler *pH);
int PauseSequences(IFunctionHandler *pH);
int ResumeSequences(IFunctionHandler *pH);
private:
ISystem *m_pSystem;
IMovieSystem *m_pMovieSystem;
};

View File

@@ -0,0 +1,644 @@
// Scale the direction vsector based on fDirVecScale
// v3SysDir *= fDirVecScale;// ScriptObjectParticle.cpp: implementation of the CScriptObjectParticle class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ScriptObjectParticle.h"
#include "ScriptObjectVector.h"
#include <ISystem.h>
#include <I3DEngine.h>
#include <IEntitySystem.h>
#include <CryParticleSpawnInfo.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
_DECLARE_SCRIPTABLEEX(CScriptObjectParticle)
CScriptObjectParticle::CScriptObjectParticle()
{
}
CScriptObjectParticle::~CScriptObjectParticle()
{
}
void CScriptObjectParticle::Init(IScriptSystem *pScriptSystem, ISystem *pSystem)
{
m_pSystem=pSystem;
m_p3DEngine =m_pSystem->GetI3DEngine();
InitGlobal(pScriptSystem,"Particle",this);
}
void CScriptObjectParticle::InitializeTemplate(IScriptSystem *pSS)
{
_ScriptableEx<CScriptObjectParticle>::InitializeTemplate(pSS);
REG_FUNC(CScriptObjectParticle,CreateParticle);
REG_FUNC(CScriptObjectParticle,CreateParticleLine);
REG_FUNC(CScriptObjectParticle,SpawnEffect);
REG_FUNC(CScriptObjectParticle,CreateDecal);
REG_FUNC(CScriptObjectParticle,Attach);
REG_FUNC(CScriptObjectParticle,Detach);
pSS->SetGlobalValue("CRYPARTICLE_ONE_TIME_SPAWN",CryParticleSpawnInfo::FLAGS_ONE_TIME_SPAWN);
pSS->SetGlobalValue("CRYPARTICLE_RAIN_MODE",CryParticleSpawnInfo::FLAGS_RAIN_MODE);
}
/*!create a particle source
@param v3Pos a table with the x,y,z fileds specifing the origin of the particle source
@param v3SysDir a table with the x,y,z fileds specifing the direction of the particle source(in degrees)
@param pObj a table specifing the particle parameters
particle={
focus
start_color
end_color
speed
rotation
count
size
size_speed
gravity
lifetime
fadeintime
frames
tid
particle_type
tail_length
physics
draw_las
color_based_blending
blend_type
bouncyness
init_angles
dir_vec_scale
stat_obj_entity_id
stat_obj_slot
stat_obj_count
//for child process
ChildProcess={
//all parameters as a normal particle source
}
ChildSpawnPeriod
}
*/
int CScriptObjectParticle::CreateParticle(IFunctionHandler *pH)
{
CHECK_PARAMETERS(3);
_SmartScriptObject pObj(m_pScriptSystem,true);
_SmartScriptObject pChildObj(m_pScriptSystem,true);
CScriptObjectVector oVec(m_pScriptSystem,true);
Vec3 v3Pos,v3SysDir,v3Offset(0,0,0);
static ParticleParams sParam;
if(!pH->GetParam(1,*oVec))
m_pScriptSystem->RaiseError( "<CreateParticles> parameter 1 not specified or nil(pos)" );
v3Pos=oVec.Get();
if(!pH->GetParam(2,*oVec))
m_pScriptSystem->RaiseError( "<CreateParticles> parameter 2 not specified or nil(normal)" );
v3SysDir=oVec.Get();
if(!pH->GetParam(3,*pObj))
m_pScriptSystem->RaiseError( "<CreateParticles> parameter 3 not specified or nil(perticle struct)" );
ReadParticleTable(*pObj, sParam);
sParam.vPosition = v3Pos;
sParam.vDirection = v3SysDir;
pObj->BeginSetGetChain();
if ((sParam).fChildSpawnPeriod && pObj->GetValueChain("ChildProcess", *pChildObj))
{
ParticleParams sChildParams;
ReadParticleTable(*pChildObj, sChildParams);
sParam.pChild = &sChildParams;
if(!pObj->GetValueChain( "ChildSpawnPeriod",sParam.fChildSpawnPeriod ))
sParam.fChildSpawnPeriod=0;
}
else
sParam.pChild = NULL;
//STATIC OBJECT BASED PARTICLES////////////////////////////////////////////////////
sParam.pStatObj = NULL;
INT_PTR nValue=0;
int nCookie=0;
if(pObj->GetUDValueChain("geometry",nValue,nCookie) && (nCookie==USER_DATA_OBJECT))
{
sParam.pStatObj=(IStatObj *)nValue;
}
sParam.vPosition = v3Pos;
m_p3DEngine->SpawnParticles(sParam);
pObj->EndSetGetChain();
return pH->EndFunction();
}
/*!create a decal
@param v3Pos a table with the x,y,z fileds specifing the origin of the particle source
@param v3SysDir a table with the x,y,z fileds specifing the direction of the particle source(in degrees)
@param size the size of the decal
@param tid the texture
@param fAngle rotation in degrees[optional]
*/
int CScriptObjectParticle::CreateDecal(IFunctionHandler *pH)
{
if (pH->GetParamCount() < 5)
{
m_pScriptSystem->RaiseError("CreateDecal: Need at least 5 params");
return pH->EndFunction();;
}
//CHECK_PARAMETERS(5);
CScriptObjectVector oVec(m_pScriptSystem,true);
CryEngineDecalInfo Decal;
int nCookie=0;
USER_DATA nUD=0;
IStatObj *obj=NULL;
pH->GetParam(1,*oVec);
Decal.vPos=oVec.Get();
pH->GetParam(2,*oVec);
Decal.vNormal=oVec.Get();
pH->GetParam(3,Decal.fSize);
pH->GetParam(4,Decal.fLifeTime);
pH->GetParamUDVal(5,Decal.nTid,nCookie);
if(pH->GetParamCount()>=6)
{
if(pH->GetParamUDVal(6,nUD,nCookie))
{
if(nCookie==USER_DATA_OBJECT)
{
obj=(IStatObj *)nUD;
}
}
}
if(pH->GetParamCount()>=7)
{
pH->GetParam(7, Decal.fAngle);
}
if(pH->GetParamCount()>=8)
{
pH->GetParam(8,*oVec);
Decal.vHitDirection = oVec.Get();
}
int ownerID = 0;
if(pH->GetParamCount()>=9)
{
pH->GetParam(9, ownerID);
}
IEntity* owner=m_pSystem->GetIEntitySystem()->GetEntity( ownerID );
if(pH->GetParamCount()>=10)
{
pH->GetParam(10, Decal.nPartID);
}
Decal.pDecalOwner = owner;
Decal.pStatObj = obj;
// get IEntityRender of static object decal owner
if(pH->GetParamCount()>=11)
{
ULONG_PTR ptr = 0;
int nCookie;
if (!pH->GetParamUDVal(11, ptr, nCookie))
ptr = 0;
if (nCookie != USER_DATA_POINTER)
ptr = 0;
Decal.pDecalOwner = (IEntityRender*)ptr;
}
m_p3DEngine->CreateDecal(Decal);
return pH->EndFunction();
}
int CScriptObjectParticle::CreateParticleLine(IFunctionHandler *pH)
{
CHECK_PARAMETERS(4);
_SmartScriptObject pObj(m_pScriptSystem,true);
CScriptObjectVector oVec(m_pScriptSystem,true);
CScriptObjectColor oCol(m_pScriptSystem,true);
Vec3 v3Pos,v3SysDir,v3Offset(0,0,0), vSpaceLoopBoxSize(0,0,0);
float fDensity;
pH->GetParam(1,*oVec);
v3Pos=oVec.Get();
pH->GetParam(2,*oVec);
v3SysDir=oVec.Get();
pH->GetParam(3,*pObj);
pH->GetParam(4,fDensity);
float focus = 0;
Vec3 col;
Vec3 vcol(0,0,0);//dummy
float speed = 0;
int count = 0;
float size = 1;
float size_speed = 0;
float gravity = 0;
float lifetime = 0;
int tid = 0;
int frames = 0;
int color_based_blending = 0;
int iParticleType = 0;
float fTailLength = 0.0f;
int bRealPhys = 0;
if(!pObj->GetValue( "color",*oCol ))
m_pScriptSystem->RaiseError( "<CreateParticles> color field not specified" );
vcol = oCol.Get();
if(!pObj->GetValue( "focus",focus ))
m_pScriptSystem->RaiseError( "<CreateParticles> focus field not specified" );
if(!pObj->GetValue( "speed",speed ))
m_pScriptSystem->RaiseError( "<CreateParticles> speed field not specified" );
if(!pObj->GetValue( "count",count ))
m_pScriptSystem->RaiseError( "<CreateParticles> count field not specified" );
if(!pObj->GetValue( "size" ,size ))
m_pScriptSystem->RaiseError( "<CreateParticles> size field not specified" );
pObj->GetValue( "size_speed",size_speed ) ;
if(!pObj->GetValue( "gravity",gravity ))
m_pScriptSystem->RaiseError( "<CreateParticles> gravity field not specified" );
if(!pObj->GetValue( "lifetime",lifetime )){
//m_pScriptSystem->RaiseError( "<CreateParticles> lifetime field not specified" );
lifetime=0;
}
pObj->GetValue( "frames",frames );
if(!pObj->GetValue( "color_based_blending",color_based_blending ))
m_pScriptSystem->RaiseError( "<CreateParticles> color_based_blending field not specified" );
int nCookie=0;
pObj->GetValue( "tid",tid );
if(!pObj->GetValue( "particle_type", iParticleType ))
iParticleType = PART_FLAG_BILLBOARD;
if(!pObj->GetValue( "tail_length", fTailLength))
fTailLength = 0.0f;
if(!pObj->GetValue( "physics", bRealPhys ))
bRealPhys = 0;
if(pObj->GetValue("offset",*oVec))
v3Offset=oVec.Get();
if(pObj->GetValue("space_box",*oVec))
vSpaceLoopBoxSize=oVec.Get();
float fBouncenes;
if(!pObj->GetValue( "bouncyness", fBouncenes))
fBouncenes = 0.5f;
color_based_blending = (color_based_blending == 3) ? 1 : 0;
col = vcol;
Vec3 currentpos;
v3SysDir-=v3Pos;
float finc = 1.f / (v3SysDir.Length() / fDensity) ;
float t = 0;
while (t<1.0f)
{
currentpos = (v3Pos + t*v3SysDir)+v3Offset;
t+=finc;
ParticleParams Params;
Params.vPosition = currentpos;
Params.vDirection = Vec3(0,0,1);
Params.fFocus = focus;
Params.vColorStart = col;
Params.vColorEnd = col;
Params.fSpeed = speed;
Params.nCount = count;
Params.fSize = size;
Params.fSizeSpeed = size_speed;
Params.vGravity = Vec3 (0,0,-gravity);
Params.fLifeTime = lifetime;
Params.nTexId = tid;
Params.nTexAnimFramesCount = frames;
Params.eBlendType = color_based_blending>0 ? ParticleBlendType_ColorBased : ParticleBlendType_AlphaBased;
Params.nParticleFlags = iParticleType;
Params.bRealPhysics = 0;
Params.pChild = NULL;
Params.fChildSpawnPeriod = 0;
Params.fTailLenght = fTailLength;
Params.bRealPhysics = bRealPhys != 0;
Params.fBouncenes = fBouncenes;
Params.vSpaceLoopBoxSize = vSpaceLoopBoxSize;
m_p3DEngine->SpawnParticles(Params);
}
return pH->EndFunction();
}
bool CScriptObjectParticle::ReadParticleTable(IScriptObject *pITable, ParticleParams &sParamOut)
{
CScriptObjectColor oCol(m_pScriptSystem,true);
Vec3 v3Pos,v3Offset(0,0,0);
CScriptObjectVector oVec(m_pScriptSystem,true);
//default params
float focus = 0;
Vec3 vStartColor(1,1,1);
Vec3 vEndColor(1,1,1);
Vec3 vRotation(0,0,0);
Vec3 vGravity(0,0,0);
float speed = 0;
int count = 1;
float size = 0.05f;
float size_speed = 0;
float gravity = 0;
float lifetime = 0;
float fadeintime = 0;
INT_PTR tid = 0;
int frames = 0;
int draw_last = 0;
int blendType = ParticleBlendType_AlphaBased;
int color_based_blending = 0;
int iParticleType = 0;
float fTailLength = 0.0f;
int bRealPhys = 0;
float fDirVecScale = 1.0f;
int nEntityID=0;
if(!pITable->BeginSetGetChain())
return false;
//FOCUS////////////////////////////////////
if(!pITable->GetValueChain( "focus",focus ))
m_pScriptSystem->RaiseError( "<CreateParticles> focus field not specified" );
//START COLOR////////////////////////////////
if (pITable->GetValueChain( "start_color",oCol ))
vStartColor = oCol.Get();
//END COLOR////////////////////////////////
if (pITable->GetValueChain( "end_color",oCol ))
vEndColor = oCol.Get();
//SPEED////////////////////////////////
if(!pITable->GetValueChain( "speed",speed ))
m_pScriptSystem->RaiseError( "<CreateParticles> speed field not specified" );
//ROTATION////////////////////////////////
if (pITable->GetValueChain( "rotation",oVec ))
vRotation = oVec.Get();
//COUNT////////////////////////////////
if(!pITable->GetValueChain( "count",count ))
m_pScriptSystem->RaiseError( "<CreateParticles> count field not specified" );
//SIZE////////////////////////////////
if(!pITable->GetValueChain( "size" ,size ))
m_pScriptSystem->RaiseError( "<CreateParticles> size field not specified" );
//SIZE SPEED////////////////////////////////
if(!pITable->GetValueChain( "size_speed",size_speed ))
size_speed=0;
//GRAVITY////////////////////////////////
if (pITable->GetValueChain( "gravity",oVec ))
vGravity = oVec.Get();
//LIFETIME////////////////////////////////
if(!pITable->GetValueChain( "lifetime",lifetime ))
m_pScriptSystem->RaiseError( "<CreateParticles> lifetime field not specified" );
//FADEINTIME////////////////////////////////
if(!pITable->GetValueChain( "fadeintime",fadeintime ))
fadeintime=0;//m_pScriptSystem->RaiseError( "<CreateParticles> fadeintime field not specified" );
//FRAMES////////////////////////////////
if(!pITable->GetValueChain( "frames",frames ))
frames=0;
//TID////////////////////////////////
int nCookie=0;
if(!pITable->GetUDValueChain( "tid",tid,nCookie))
tid=0;
//PARTICLE TYPE////////////////////////////////
if(!pITable->GetValueChain( "particle_type", iParticleType ))
iParticleType = PART_FLAG_BILLBOARD;
//TAIL LENGHT////////////////////////////////
if(!pITable->GetValueChain( "tail_length", fTailLength))
fTailLength = 0.0f;
//PHYSICS////////////////////////////////
if(!pITable->GetValueChain( "physics", bRealPhys ))
bRealPhys = 0;
//DRAW LAST////////////////////////////////
if(!pITable->GetValueChain( "draw_last",draw_last ))
draw_last=0;
//COLOR BASED BLENDING (legacy)////////////////////////////////
if (pITable->GetValueChain( "color_based_blending",color_based_blending ))
{
// This for backward compatability.
if (color_based_blending == 3)
blendType = ParticleBlendType_ColorBased;
}
//BLEND TYPE////////////////////////////////
// Read particles blending type.
pITable->GetValueChain( "blend_type",blendType );
//BOUNCENES/////////////////////////////////
float fBouncenes;
if(!pITable->GetValueChain( "bouncyness", fBouncenes))
fBouncenes = 0.5f;
//INIT ANGLE/////////////////////////////////
Vec3 vAngles(0,0,0);
if (pITable->GetValue( "init_angles",oVec ))
vAngles = oVec.Get();
//bounding box size/////////////////////////////////
Vec3 vSpaceLoopBoxSize(0,0,0);
if (pITable->GetValue("space_box",*oVec))
vSpaceLoopBoxSize=oVec.Get();
pITable->GetValueChain( "dir_vec_scale", fDirVecScale );
// turbulence
float fTurbulenceSize=0;
pITable->GetValueChain( "turbulence_size", fTurbulenceSize);
float fTurbulenceSpeed=0;
pITable->GetValueChain( "turbulence_speed", fTurbulenceSpeed);
int nLinearSizeSpeed=0;
pITable->GetValueChain( "bLinearSizeSpeed", nLinearSizeSpeed);
sParamOut.fPosRandomOffset=0;
pITable->GetValueChain( "fPosRandomOffset", sParamOut.fPosRandomOffset);
float fChildSpawnPeriod=0;
pITable->GetValueChain( "ChildSpawnPeriod", fChildSpawnPeriod);
float fAirResistance=0;
pITable->GetValueChain( "AirResistance", fAirResistance);
// after this line GetValueChain will crash
pITable->EndSetGetChain();
//////////////////////////////////////////////////////////////////////////////////////
sParamOut.fFocus = focus;
sParamOut.vColorStart = vStartColor;
sParamOut.vColorEnd = vEndColor;
sParamOut.fSpeed = speed;
sParamOut.fSpeed.variation = 0.25f;
sParamOut.nCount = count;
sParamOut.fSize = size;
sParamOut.fSizeSpeed = size_speed;
sParamOut.vGravity = vGravity;
sParamOut.fLifeTime = lifetime;
sParamOut.fFadeInTime = fadeintime;
sParamOut.nTexId = tid;
sParamOut.nTexAnimFramesCount = frames;
sParamOut.eBlendType = (ParticleBlendType)blendType;
sParamOut.nParticleFlags = iParticleType;
if(nLinearSizeSpeed)
sParamOut.nParticleFlags |= PART_FLAG_SIZE_LINEAR;
sParamOut.bRealPhysics = bRealPhys != 0;
sParamOut.pChild = NULL;
sParamOut.fChildSpawnPeriod = fChildSpawnPeriod;
sParamOut.fTailLenght = fTailLength;
sParamOut.nDrawLast = !draw_last;
sParamOut.vRotation = vRotation;
sParamOut.fBouncenes = fBouncenes;
sParamOut.vInitAngles = vAngles;
// Scale the direction vsector based on fDirVecScale
sParamOut.vDirection *= fDirVecScale;
sParamOut.fTurbulenceSize=fTurbulenceSize;
sParamOut.fTurbulenceSpeed=fTurbulenceSpeed;
sParamOut.vSpaceLoopBoxSize = vSpaceLoopBoxSize;
sParamOut.fAirResistance = fAirResistance;
return true;
}
int CScriptObjectParticle::Attach(IFunctionHandler * pH)
{
_SmartScriptObject pObj(m_pScriptSystem,true);
_SmartScriptObject pChildObj(m_pScriptSystem,true);
CScriptObjectVector oVec(m_pScriptSystem,true);
Vec3 v3Pos,v3SysDir,v3Offset(0,0,0);
int nID,nFlags=0;
float fSpawnRate = 0;
const char *szBoneName;
ParticleParams sParam;
CryParticleSpawnInfo cpsi;
if(!pH->GetParam(1,nID))
m_pScriptSystem->RaiseError( "<Particle::Attach> parameter 1 not specified or nil (entity id to attach to)" );
if(!pH->GetParam(2,*pObj))
m_pScriptSystem->RaiseError( "<Particle::Attach> parameter 2 not specified or nil(particle stuct)" );
if(!pH->GetParam(3,fSpawnRate))
m_pScriptSystem->RaiseError( "<Particle::Attach> spawn rate not specified" );
IEntity *pEntity = m_pSystem->GetIEntitySystem()->GetEntity(nID);
if (!pEntity)
{
m_pScriptSystem->RaiseError( "<Particle::Attach> specified entity ID does not exist)" );
return pH->EndFunctionNull();
}
cpsi.fSpawnRate = fSpawnRate;
ICryCharInstance *pInstance = pEntity->GetCharInterface()->GetCharacter(0);
if (pH->GetParam(4,szBoneName))
{
if (pInstance)
{
cpsi.nBone = pInstance->GetModel()->GetBoneByName(szBoneName);
}
cpsi.nFlags |= CryParticleSpawnInfo::FLAGS_SPAWN_FROM_BONE;
if(pH->GetParam(5,*oVec))
cpsi.vBonePos = oVec.Get();
else
cpsi.vBonePos.Set(0,0,0);
if (pH->GetParam(6,nFlags))
cpsi.nFlags = nFlags;
}
ReadParticleTable(*pObj, sParam);
/*sParam.vPosition = v3Pos;
sParam.vDirection = v3SysDir;
*/
/* pObj->BeginSetGetChain();
if ((sParam).fChildSpawnPeriod && pObj->GetValueChain("ChildProcess", *pChildObj))
{
ParticleParams sChildParams;
ReadParticleTable(*pChildObj, sChildParams);
sParam.pChild = &sChildParams;
if(!pObj->GetValueChain( "ChildSpawnPeriod",sParam.fChildSpawnPeriod ))
sParam.fChildSpawnPeriod=0;
}
else
sParam.pChild = NULL;
*/
return pH->EndFunction(pInstance->AddParticleEmitter(sParam,cpsi));
}
int CScriptObjectParticle::Detach(IFunctionHandler * pH)
{
CHECK_PARAMETERS(2);
int nID,nHandle;
pH->GetParam(1,nID);
pH->GetParam(2,nHandle);
IEntity *pEntity = m_pSystem->GetIEntitySystem()->GetEntity(nID);
if (!pEntity)
{
m_pScriptSystem->RaiseError( "<Particle::Detach> specified entity ID does not exist)" );
return pH->EndFunction();
}
ICryCharInstance *pInstance = pEntity->GetCharInterface()->GetCharacter(0);
pInstance->RemoveParticleEmitter(nHandle);
return pH->EndFunction();
}
//////////////////////////////////////////////////////////////////////////
int CScriptObjectParticle::SpawnEffect(IFunctionHandler *pH)
{
CScriptObjectVector oVec(m_pScriptSystem,true);
Vec3 pos,dir;
const char *sEffectName = 0;
float fScale = 1.0f;
if(!pH->GetParam(1,*oVec))
m_pScriptSystem->RaiseError( "<SpawnEffect> parameter 1 not specified or nil(pos)" );
pos = oVec.Get();
if(!pH->GetParam(2,*oVec))
m_pScriptSystem->RaiseError( "<SpawnEffect> parameter 2 not specified or nil(normal)" );
dir = oVec.Get();
if(!pH->GetParam(3,sEffectName))
m_pScriptSystem->RaiseError( "<SpawnEffect> parameter 3 not specified or nil(Effect Name)" );
// Optional argument for scale.
// pH->GetParam(4,fScale);
if(pH->GetParamCount()>3)
pH->GetParam(4,fScale);
if (sEffectName)
{
IParticleEffect *pEffect = m_p3DEngine->FindParticleEffect( sEffectName );
if (pEffect)
pEffect->Spawn( pos,dir,fScale );
}
return pH->EndFunction();
}

View File

@@ -0,0 +1,53 @@
// ScriptObjectParticle.h: interface for the CScriptObjectParticle class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_SCRIPTOBJECTPARTICLE_H__893DBB83_74EB_421D_A995_066F02F85156__INCLUDED_)
#define AFX_SCRIPTOBJECTPARTICLE_H__893DBB83_74EB_421D_A995_066F02F85156__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <IScriptSystem.h>
#include <_ScriptableEx.h>
struct ISystem;
struct I3DEngine;
struct ParticleParams;
/*! This class implements script-functions for particles and decals.
REMARKS:
After initialization of the script-object it will be globally accessable through scripts using the namespace "Particle".
Example:
Particle.CreateDecal(pos, normal, scale, lifetime, decal.texture, decal.object, rotation);
IMPLEMENTATIONS NOTES:
These function will never be called from C-Code. They're script-exclusive.
*/
class CScriptObjectParticle :
public _ScriptableEx<CScriptObjectParticle>
{
public:
static void InitializeTemplate(IScriptSystem *pSS);
int CreateParticleLine(IFunctionHandler *pH);
CScriptObjectParticle();
virtual ~CScriptObjectParticle();
void Init(IScriptSystem *pScriptSystem, ISystem *pSystem);
int CreateParticle(IFunctionHandler *pH); //vector vector obj(return void)
int CreateDecal(IFunctionHandler *pH); //Vector,Vector,float,float,int(return void)
int SpawnEffect(IFunctionHandler *pH); //pos,dir,sEffectName (return void)
bool ReadParticleTable(IScriptObject *pITable, ParticleParams &sParamOut);
private:
ISystem *m_pSystem;
I3DEngine *m_p3DEngine;
public:
int Attach(IFunctionHandler * pH);
int Detach(IFunctionHandler * pH);
};
#endif // !defined(AFX_SCRIPTOBJECTPARTICLE_H__893DBB83_74EB_421D_A995_066F02F85156__INCLUDED_)

View File

@@ -0,0 +1,376 @@
// ScriptObjectScript.cpp: implementation of the CScriptObjectScript class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ScriptObjectScript.h"
#include <ILog.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
_DECLARE_SCRIPTABLEEX(CScriptObjectScript)
CScriptObjectScript::CScriptObjectScript()
{
}
CScriptObjectScript::~CScriptObjectScript()
{
}
void CScriptObjectScript::Init(IScriptSystem *pScriptSystem)
{
InitGlobal(pScriptSystem,"Script",this);
}
void CScriptObjectScript::Debug_Full_recursive( IScriptObject *pCurrent, string &sPath, std::set<const void *> &setVisited )
{
assert(pCurrent);
pCurrent->BeginIteration();
while(pCurrent->MoveNext())
{
char *szKeyName;
if(!pCurrent->GetCurrentKey(szKeyName))
szKeyName="NO";
ScriptVarType type=pCurrent->GetCurrentType();
if(type==svtObject) // svtNull,svtFunction,svtString,svtNumber,svtUserData,svtObject
{
const void *pVis;
pCurrent->GetCurrentPtr(pVis);
GetISystem()->GetILog()->Log(" table '%s/%s'",sPath.c_str(),szKeyName);
if(setVisited.count(pVis)!=0)
{
GetISystem()->GetILog()->Log(" .. already processed ..");
continue;
}
setVisited.insert(pVis);
{
IScriptObject *pNewObject = m_pScriptSystem->CreateEmptyObject();
pCurrent->GetCurrent(pNewObject);
#if defined(LINUX)
string s = sPath+string("/")+szKeyName;
Debug_Full_recursive(pNewObject,s,setVisited);
#else
Debug_Full_recursive(pNewObject,sPath+string("/")+szKeyName,setVisited);
#endif
pNewObject->Release();
}
}
else if(type==svtFunction) // svtNull,svtFunction,svtString,svtNumber,svtUserData,svtObject
{
unsigned int *pCode=0;
int iSize=0;
if(pCurrent->GetCurrentFuncData(pCode,iSize))
{
// lua function
if(pCode)
GetISystem()->GetILog()->Log(" lua function '%s' size=%d",szKeyName,(DWORD)iSize);
else
GetISystem()->GetILog()->Log(" cpp function '%s'",szKeyName);
}
}
else // svtNull,svtFunction,svtString,svtNumber,svtUserData,svtObject
{
GetISystem()->GetILog()->Log(" data '%s'",szKeyName);
}
}
pCurrent->EndIteration();
}
DWORD CScriptObjectScript::Debug_Buckets_recursive( IScriptObject *pCurrent, string &sPath, std::set<const void *> &setVisited,
const DWORD dwMinBucket )
{
assert(pCurrent);
DWORD dwTableElementCount=0;
pCurrent->BeginIteration();
while(pCurrent->MoveNext())
{
char *szKeyName;
dwTableElementCount++;
if(!pCurrent->GetCurrentKey(szKeyName))
szKeyName="NO";
ScriptVarType type=pCurrent->GetCurrentType();
if(type==svtObject) // svtNull,svtFunction,svtString,svtNumber,svtUserData,svtObject
{
const void *pVis;
pCurrent->GetCurrentPtr(pVis);
if(setVisited.count(pVis)!=0)
continue;
setVisited.insert(pVis);
{
IScriptObject *pNewObject = m_pScriptSystem->CreateEmptyObject();
pCurrent->GetCurrent(pNewObject);
#if defined(LINUX)
string s = sPath+string("/")+szKeyName;
DWORD dwSubTableCount = Debug_Buckets_recursive(pNewObject,s,setVisited,dwMinBucket);
#else
DWORD dwSubTableCount = Debug_Buckets_recursive(pNewObject,sPath+string("/")+szKeyName,setVisited,dwMinBucket);
#endif
pNewObject->Release();
if(dwSubTableCount>=dwMinBucket)
{
GetISystem()->GetILog()->Log(" %8d '%s/%s'\n",dwSubTableCount,sPath.c_str(),szKeyName);
}
else dwTableElementCount+=dwSubTableCount;
}
}
/* else if(type==svtFunction) // svtNull,svtFunction,svtString,svtNumber,svtUserData,svtObject
{
unsigned int *pCode=0;
int iSize=0;
if(pCurrent->GetCurrentFuncData(pCode,iSize))
if(pCode)
{
// lua function
char str[256];
sprintf(str,"%s lua '%s' size=%d\n",sPath.c_str(),szKeyName,(DWORD)iSize);
OutputDebugString(str);
}
}
*/
}
pCurrent->EndIteration();
return dwTableElementCount;
}
void CScriptObjectScript::Debug_Elements( IScriptObject *pCurrent, string &sPath, std::set<const void *> &setVisited )
{
assert(pCurrent);
pCurrent->BeginIteration();
while(pCurrent->MoveNext())
{
char *szKeyName;
if(!pCurrent->GetCurrentKey(szKeyName))
szKeyName="NO";
ScriptVarType type=pCurrent->GetCurrentType();
if(type==svtObject) // svtNull,svtFunction,svtString,svtNumber,svtUserData,svtObject
{
const void *pVis;
pCurrent->GetCurrentPtr(pVis);
if(setVisited.count(pVis)!=0)
continue;
setVisited.insert(pVis);
{
IScriptObject *pNewObject = m_pScriptSystem->CreateEmptyObject();
pCurrent->GetCurrent(pNewObject);
#if defined(LINUX)
string s = sPath+string("/")+szKeyName;
DWORD dwSubTableCount = Debug_Buckets_recursive(pNewObject,s,setVisited,0xffffffff);
#else
DWORD dwSubTableCount = Debug_Buckets_recursive(pNewObject,sPath+string("/")+szKeyName,setVisited,0xffffffff);
#endif
pNewObject->Release();
GetISystem()->GetILog()->Log(" %8d '%s' '%s'\n",dwSubTableCount,sPath.c_str(),szKeyName);
}
}
}
pCurrent->EndIteration();
}
int CScriptObjectScript::Debug(IFunctionHandler *pH)
{
/* deactivate because it can be used to hack
CHECK_PARAMETERS(0);
IScriptObject *pGlobals=m_pScriptSystem->GetGlobalObject();
{
std::set<const void *> setVisited;
GetISystem()->GetILog()->Log("CScriptObjectScript::Debug globals recursive minbuckets");
DWORD dwCount=Debug_Buckets_recursive(pGlobals,string(""),setVisited,50);
GetISystem()->GetILog()->Log(" %8d '' ''\n",dwCount);
}
{
std::set<const void *> setVisited;
GetISystem()->GetILog()->Log("CScriptObjectScript::Debug globals");
Debug_Elements(pGlobals,string(""),setVisited);
}
pGlobals->Release();
*/
return pH->EndFunction();
}
int CScriptObjectScript::DebugFull(IFunctionHandler *pH)
{
/* deactivate because it can be used to hack
CHECK_PARAMETERS(0);
IScriptObject *pGlobals=m_pScriptSystem->GetGlobalObject();
{
std::set<const void *> setVisited;
GetISystem()->GetILog()->Log("CScriptObjectScript::Debug full");
Debug_Full_recursive(pGlobals,string(""),setVisited);
}
pGlobals->Release();
*/
return pH->EndFunction();
}
void CScriptObjectScript::InitializeTemplate(IScriptSystem *pSS)
{
_ScriptableEx<CScriptObjectScript>::InitializeTemplate(pSS);
REG_FUNC(CScriptObjectScript,ReloadScripts);
REG_FUNC(CScriptObjectScript,ReloadScript);
REG_FUNC(CScriptObjectScript,LoadScript);
REG_FUNC(CScriptObjectScript,UnloadScript);
REG_FUNC(CScriptObjectScript,DumpLoadedScripts);
REG_FUNC(CScriptObjectScript,Debug);
REG_FUNC(CScriptObjectScript,DebugFull);
}
/*!reload all previosly loaded scripts
*/
int CScriptObjectScript::ReloadScripts(IFunctionHandler *pH)
{
CHECK_PARAMETERS(0);
m_pScriptSystem->ReloadScripts();
return pH->EndFunction();
}
/*!reload a specified script. If the script wasn't loaded at least once before the function will fail
@param sFileName path of the script that has to be reloaded
*/
int CScriptObjectScript::ReloadScript(IFunctionHandler *pH)
{
CHECK_PARAMETERS(1);
const char *sFileName;
pH->GetParam(1,sFileName);
if(!sFileName)
return pH->EndFunction(); // ReloadScript filename is nil
m_pScriptSystem->ExecuteFile(sFileName,true,true);
//m_pScriptSystem->ReloadScript(sFileName);
return pH->EndFunction();
}
/*!load a specified script
@param sFileName path of the script that has to be loaded
*/
int CScriptObjectScript::LoadScript(IFunctionHandler *pH)
{
bool bReload = false;
bool bRaiseError = true;
if (pH->GetParamCount() >= 3)
{
pH->GetParam(3, bRaiseError);
}
if (pH->GetParamCount() >= 2)
{
if (pH->GetParamType(2) == svtNumber)
{
int iReload;
if (pH->GetParam(2, iReload))
{
bReload = (iReload != 0);
}
}
}
const char *sScriptFile;
pH->GetParam(1,sScriptFile);
if (m_pScriptSystem->ExecuteFile(sScriptFile, bRaiseError, bReload))
return pH->EndFunction(1);
else
return pH->EndFunctionNull();
}
/*!unload script from the "loaded scripts map" so if this script is loaded again
the Script system will reloadit. this function doesn't
involve the LUA VM so the resources allocated by the script will not be released
unloading the script
@param sFileName path of the script that has to be loaded
*/
int CScriptObjectScript::UnloadScript(IFunctionHandler *pH)
{
CHECK_PARAMETERS(1);
const char *sScriptFile;
pH->GetParam(1,sScriptFile);
m_pScriptSystem->UnloadScript(sScriptFile);
return pH->EndFunction();
}
/*!Dump all loaded scripts path calling IScriptSystemSink::OnLoadedScriptDump
@see IScriptSystemSink
*/
int CScriptObjectScript::DumpLoadedScripts(IFunctionHandler *pH)
{
m_pScriptSystem->DumpLoadedScripts();
return pH->EndFunction();
}

View File

@@ -0,0 +1,57 @@
// ScriptObjectScript.h: interface for the CScriptObjectScript class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_SCRIPTOBJECTSCRIPT_H__2432459C_19FC_4AC4_8EAA_D73967BC4B37__INCLUDED_)
#define AFX_SCRIPTOBJECTSCRIPT_H__2432459C_19FC_4AC4_8EAA_D73967BC4B37__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <IScriptSystem.h>
#include <_ScriptableEx.h>
#include <set> // STL set<>
/*! This class implements script-functions for exposing the scripting system functionalities
REMARKS:
After initialization of the script-object it will be globally accessable through scripts using the namespace "Script".
Example:
Script.LoadScript("scripts/common.lua")
IMPLEMENTATIONS NOTES:
These function will never be called from C-Code. They're script-exclusive.
*/
class CScriptObjectScript :
public _ScriptableEx<CScriptObjectScript>
{
public:
CScriptObjectScript();
virtual ~CScriptObjectScript();
void Init(IScriptSystem *pScriptSystem);
int LoadScript(IFunctionHandler *pH);
int ReloadScripts(IFunctionHandler *pH);
int ReloadScript(IFunctionHandler *pH);
int UnloadScript(IFunctionHandler *pH);
int DumpLoadedScripts(IFunctionHandler *pH);
int Debug(IFunctionHandler *pH);
int DebugFull(IFunctionHandler *pH);
static void InitializeTemplate(IScriptSystem *pSS);
private: // -------------------------------------------------------------------------
//! recursive
//! /return amount of table elements (recursive)
DWORD Debug_Buckets_recursive( IScriptObject *pCurrent, string &sPath, std::set<const void *> &setVisited, const DWORD dwMinBucket );
//! not recursive
void Debug_Elements( IScriptObject *pCurrent, string &sPath, std::set<const void *> &setVisited );
//! recursive
void Debug_Full_recursive( IScriptObject *pCurrent, string &sPath, std::set<const void *> &setVisited );
};
#endif // !defined(AFX_SCRIPTOBJECTSCRIPT_H__2432459C_19FC_4AC4_8EAA_D73967BC4B37__INCLUDED_)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
// ScriptObjectSound.h: interface for the CScriptObjectSound class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_SCRIPTOBJECTSOUND_H__A6B9BF56_1C4A_495C_A1B7_F0A052F6C05D__INCLUDED_)
#define AFX_SCRIPTOBJECTSOUND_H__A6B9BF56_1C4A_495C_A1B7_F0A052F6C05D__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <IScriptSystem.h>
#include <_ScriptableEx.h>
struct IMusicSystem;
struct ISoundSystem;
/*! In this class are all sound-related script-functions implemented.
IMPLEMENTATIONS NOTES:
These function will never be called from C-Code. They're script-exclusive.
*/
class CScriptObjectSound :
public _ScriptableEx<CScriptObjectSound>
{
public:
//! constructor
CScriptObjectSound();
//! destructor
virtual ~CScriptObjectSound();
//!
void Init(IScriptSystem *pScriptSystem, ISystem *pSystem);
static void InitializeTemplate(IScriptSystem *pSS);
int IsPlaying(IFunctionHandler *pH); //int (return int)
int LoadSound(IFunctionHandler *pH); //char * (return int)
int Load3DSound(IFunctionHandler *pH); //char * (return int)
int LoadStreamSound(IFunctionHandler *pH); //char * (return int)
int PlaySound(IFunctionHandler *pH); //int (return void)
int SetSoundVolume(IFunctionHandler *pH); //int int (return void)
int SetSoundLoop(IFunctionHandler *pH); //int int (return void)
int SetSoundFrequency(IFunctionHandler *pH); //int int (return void)
int SetSoundPitching(IFunctionHandler *pH); //int float (return void)
int StopSound(IFunctionHandler *pH); // int (return void)
int SetSoundPosition(IFunctionHandler *pH); //int vector(return void)
int SetSoundSpeed(IFunctionHandler *pH); //int vector(return void)
int GetListener(IFunctionHandler *pH); // Not implemented yet
int SetMinMaxDistance(IFunctionHandler *pH); // int float float float (return void)
int SetLoopPoints(IFunctionHandler *pH); // int int int (return void)
int AddSoundFlags(IFunctionHandler *pH); // int int (return void)
int SetMasterVolumeScale(IFunctionHandler *pH); // int int (return void)
int AddToScaleGroup(IFunctionHandler *pH); // int int (return void)
int RemoveFromScaleGroup(IFunctionHandler *pH); // int int (return void)
int SetGroupScale(IFunctionHandler *pH); // int int (return bool)
int SetSoundProperties(IFunctionHandler *pH); // int int (return void)
int SetEaxEnvironment(IFunctionHandler *pH); // int (return void)
int FXEnable(IFunctionHandler *pH); // pSound, int nEffectNumber (return void)
int SetFXSetParamEQ(IFunctionHandler *pH); // pSound, float fCenter,float fBandwidth,float fGain (return void)
int SetDirectionalAttenuation(IFunctionHandler *pH);
int GetDirectionalAttenuationMaxScale(IFunctionHandler *pH);
int LoadMusic(IFunctionHandler *pH); // string (return bool)
int UnloadMusic(IFunctionHandler *pH);
int SetMusicTheme(IFunctionHandler *pH);
int ResetMusicThemeOverride(IFunctionHandler *pH);
int SetMusicMood(IFunctionHandler *pH);
int SetDefaultMusicMood(IFunctionHandler *pH);
int GetMusicThemes(IFunctionHandler *pH);
int GetMusicMoods(IFunctionHandler *pH);
int AddMusicMoodEvent(IFunctionHandler *pH);
int IsInMusicTheme(IFunctionHandler *pH);
int IsInMusicMood(IFunctionHandler *pH);
int GetMusicStatus(IFunctionHandler *pH);
int SetSoundRatio(IFunctionHandler *pH);
int PlaySoundFadeUnderwater(IFunctionHandler *pH);
int GetSoundLength(IFunctionHandler * pH);
private: // -------------------------------------------------------
ISystem * m_pSystem; //!<
ISoundSystem * m_pSoundSystem; //!< might be 0 (e.g. dedicated server or Init() wasn't successful)
IMusicSystem * m_pMusicSystem; //!< might be 0 (e.g. dedicated server or Init() wasn't successful)
};
#endif // !defined(AFX_SCRIPTOBJECTSOUND_H__A6B9BF56_1C4A_495C_A1B7_F0A052F6C05D__INCLUDED_)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,188 @@
// ScriptObjectSystem.h: interface for the CScriptObjectSystem class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_SCRIPTOBJECTSYSTEM_H__AE30A606_B76F_45EA_8187_B97044772DD0__INCLUDED_)
#define AFX_SCRIPTOBJECTSYSTEM_H__AE30A606_B76F_45EA_8187_B97044772DD0__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <IScriptSystem.h>
#include <_ScriptableEx.h>
struct ISystem;
struct ILog;
struct ISoundSystem;
struct IRenderer;
struct IConsole;
struct IInput;
struct ITimer;
struct IEntitySystem;
struct I3DEngine;
class IPhysicalWorld;
/*! This class implements script-functions for exposing the System functionalities
REMARKS:
this object doesn't have a global mapping(is not present as global variable into the script state)
IMPLEMENTATIONS NOTES:
These function will never be called from C-Code. They're script-exclusive.
*/
class CScriptObjectSystem :
public _ScriptableEx<CScriptObjectSystem>
{
public:
CScriptObjectSystem();
virtual ~CScriptObjectSystem();
void Init(IScriptSystem *pScriptSystem,ISystem *pSystem);
public:
int CreateDownload(IFunctionHandler *pH);
int LoadFont(IFunctionHandler *pH); //string (return void)
int ExecuteCommand(IFunctionHandler *pH); //string (return void)
int LogToConsole(IFunctionHandler *pH); //string (return void)
int ClearConsole(IFunctionHandler *pH); // void (return void)
int GetConsoleKeyName(IFunctionHandler *pH); // void (return string)
int Log(IFunctionHandler *pH); // void (string))
int LogAlways(IFunctionHandler *pH); // void (string))
int Warning(IFunctionHandler *pH); //string (return void)
int Error(IFunctionHandler *pH); //string (return void)
int GetCurrTime(IFunctionHandler *pH); //void (return float)
int GetCurrAsyncTime(IFunctionHandler *pH); //void (return float)
int GetFrameTime(IFunctionHandler *pH); //void (return float)
int GetLocalOSTime(IFunctionHandler *pH); //void (return float)
int ShowConsole(IFunctionHandler *pH); //int (return void)
// int PostMessage(IFunctionHandler *pH); //string (return void)
int GetEntity(IFunctionHandler *pH); //int (return obj)
int GetEntities(IFunctionHandler *pH); //int (return obj[])
int GetEntitiesInRadius(IFunctionHandler *pH); // table of entities
int GetTeamMembers(IFunctionHandler *pH); // table of entities
int GetEntityByName(IFunctionHandler *pH); //char * (return obj)
int LoadAnimatedTexture(IFunctionHandler *pH); //char *,int (return int)
int LoadTexture(IFunctionHandler *pH); //char *, int (return int)
int LoadObject(IFunctionHandler *pH);
int DrawSprite(IFunctionHandler *pH); //char * vector int(return int)
int DrawLabelImage(IFunctionHandler *pH); //Vec3d,float,int (return void)
int DeformTerrain(IFunctionHandler *pH);//Vector,float,int(return void)
int ScreenToTexture(IFunctionHandler *pH); //void(return void)
int LoadImage(IFunctionHandler *pH); //const char* (return int)
int FreeImage(IFunctionHandler *pH); //int (return int)
int DrawTriStrip(IFunctionHandler *pH);
int DrawLine(IFunctionHandler *pH);
int Draw2DLine(IFunctionHandler *pH);
int DrawImage(IFunctionHandler *pH); //int,int,int,int,int,int (return void)
int DrawImageColor(IFunctionHandler *pH); //int,int,int,int,int,int,float,float,float,float (return void)
int DrawImageColorCoords(IFunctionHandler *pH); //int,int,int,int,int,int,float,float,float,float, float, float, float, float (return void)
int DrawImageCoords(IFunctionHandler *pH); //int,int,int,int,int,int,float,float,float,float, float, float, float, float (return void)
int SetWorldColorRatio(IFunctionHandler *pH); //float
int SetGammaDelta(IFunctionHandler *pH); //float
int DrawRectShader(IFunctionHandler *pH); //const char*,int,int,int,int
int SetScreenShader(IFunctionHandler *pH);//const char*
// tiago: added
int SetScreenFx(IFunctionHandler *pH);//const char*, int
int SetScreenFxParamInt(IFunctionHandler *pH);//const char*, const char*, int
int SetScreenFxParamFloat(IFunctionHandler *pH);//const char*, const char*, float
int GetScreenFx(IFunctionHandler *pH);//const char*
int GetScreenFxParamInt(IFunctionHandler *pH);//const char*, const char*
int GetScreenFxParamFloat(IFunctionHandler *pH);//const char*, const char*
int SetScissor(IFunctionHandler *pH);//int, int, int, int
// CW: added for script based system analysis
int GetCPUQuality( IFunctionHandler *pH );
int GetGPUQuality( IFunctionHandler *pH );
int GetSystemMem( IFunctionHandler *pH );
int GetVideoMem( IFunctionHandler *pH );
int IsPS20Supported( IFunctionHandler *pH );
int IsHDRSupported( IFunctionHandler *pH );
int RemoveEntity(IFunctionHandler *pH); //int (return void)
int SpawnEntity(IFunctionHandler *pH); //int (return int)
int ActivateLight(IFunctionHandler *pH); //name, activate
// int ActivateMainLight(IFunctionHandler *pH); //pos, activate
int SetSkyBox(IFunctionHandler *pH); //szShaderName, fBlendTime, bUseWorldBrAndColor
int SetWaterVolumeOffset(IFunctionHandler *pH); //szShaderName, fBlendTime, bUseWorldBrAndColor
int MeasureTime(IFunctionHandler *pH);
int IsValidMapPos(IFunctionHandler *pH);
int EnableMainView(IFunctionHandler *pH);
int EnableOceanRendering(IFunctionHandler *pH); // int
int ScanDirectory(IFunctionHandler *pH);
int DebugStats(IFunctionHandler *pH);
int ViewDistanceSet(IFunctionHandler *pH);
int ViewDistanceGet(IFunctionHandler *pH);
int SetFogEnd(IFunctionHandler *pH);
int SetFogStart(IFunctionHandler *pH);
int SetFogColor(IFunctionHandler *pH);
int GetFogEnd(IFunctionHandler *pH);
int GetFogStart(IFunctionHandler *pH);
int GetFogColor(IFunctionHandler *pH);
int GetWorldColor(IFunctionHandler *pH);
int SetWorldColor(IFunctionHandler *pH);
int GetOutdoorAmbientColor(IFunctionHandler *pH);
int SetOutdoorAmbientColor(IFunctionHandler *pH);
int SetBFCount(IFunctionHandler *pH);
int GetBFCount(IFunctionHandler *pH);
int SetGrasshopperCount(IFunctionHandler *pH);
int GetGrasshopperCount(IFunctionHandler *pH);
int SetGrasshopperCGF(IFunctionHandler *pH);
int GetTerrainElevation(IFunctionHandler *pH);
int SetSkyFade(IFunctionHandler *pH);
// int SetIndoorColor(IFunctionHandler *pH);
int ActivatePortal(IFunctionHandler *pH);
int DumpMMStats(IFunctionHandler *pH);
int EnumAAFormats(IFunctionHandler *pH);
int EnumDisplayFormats(IFunctionHandler *pH);
int IsPointIndoors(IFunctionHandler *pH);
int SetConsoleImage(IFunctionHandler *pH);
int ProjectToScreen(IFunctionHandler *pH);
int EnableHeatVision(IFunctionHandler *pH);
int ShowDebugger(IFunctionHandler *pH);
int FrameProfiler(IFunctionHandler *pH);
int DumpMemStats (IFunctionHandler *pH);
int DumpWinHeaps (IFunctionHandler *pH);
int Break(IFunctionHandler *pH);
int DumpCommandsVars(IFunctionHandler *pH);
int GetViewCameraPos(IFunctionHandler *pH);
int RayWorldIntersection(IFunctionHandler *pH);
int RayTraceCheck(IFunctionHandler *pH);
int BrowseURL(IFunctionHandler *pH);
int IsDevModeEnable(IFunctionHandler* pH);
int SaveConfiguration(IFunctionHandler *pH);
int SetSystemShaderRenderFlags(IFunctionHandler *pH);
static void InitializeTemplate(IScriptSystem *pSS);
static void ReleaseTemplate();
private:
ISystem * m_pSystem;
ILog * m_pLog;
ISoundSystem * m_pSoundSytem;
IRenderer * m_pRenderer;
IConsole * m_pConsole;
ITimer * m_pTimer;
IEntitySystem * m_pEntitySystem;
I3DEngine * m_p3DEngine;
IPhysicalWorld * m_pPhysicalWorld;
ICVar *e_deformable_terrain; //!< the Cvar is created in cry3dengine, this is just a pointer
//log a tring to console and/or to disk with support for different languages
void LogString(IFunctionHandler *pH,bool bToConsoleOnly);
//Vlad is too lazy to add this to 3DEngine - so I have to put it here. It should
//not be here, but I have to put it somewhere.....
float m_SkyFadeStart; // when fogEnd less - start to fade sky to fog
float m_SkyFadeEnd; // when fogEnd less - no sky, just fog
static IScriptObject *m_pScriptTimeTable;
public:
int ApplyForceToEnvironment(IFunctionHandler * pH);
//int IndoorSoundAllowed(IFunctionHandler * pH);
//int ApplyStormToEnvironment(IFunctionHandler * pH);
};
#endif // !defined(AFX_SCRIPTOBJECTSYSTEM_H__AE30A606_B76F_45EA_8187_B97044772DD0__INCLUDED_)

336
CrySystem/ScriptSink.cpp Normal file
View File

@@ -0,0 +1,336 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: scriptsink.cpp
// Version: v1.00
// Created: 30/9/2002 by Timur.
// Compilers: Visual Studio.NET
// Description:
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "ScriptSink.h"
#include "System.h"
#include <IRenderer.h>
#include <I3DEngine.h>
#include <ISound.h>
#include <ILog.h>
#include <IConsole.h>
#include <ITimer.h>
#include <IGame.h>
#include <IAISystem.h> // AISystem
#include "XConsole.h"
//////////////////////////////////////////////////////////////////////////
CScriptSink::CScriptSink( CSystem *pSystem,CXConsole *pConsole)
{
assert( pSystem );
m_pSystem = pSystem;
m_pConsole = pConsole;
m_lastGCTime = 0;
m_fGCFreq = 10;
}
//////////////////////////////////////////////////////////////////////////
void CScriptSink::Init()
{
IScriptSystem *pScriptSystem = m_pSystem->GetIScriptSystem();
if (pScriptSystem)
{
// Set global time variable into the script.
pScriptSystem->SetGlobalValue( "_time", 0 );
pScriptSystem->SetGlobalValue( "_frametime",0 );
pScriptSystem->SetGlobalValue( "_aitick",0 );
m_nLastGCCount=pScriptSystem->GetCGCount();
}
else
m_nLastGCCount=0;
}
//////////////////////////////////////////////////////////////////////////
void CScriptSink::OnLoadSource(const char *sSourceName,unsigned char *sSource,long nSourceSize)
{
}
//////////////////////////////////////////////////////////////////////
void CScriptSink::OnScriptError(const char *sSourceFile,const char *sFuncName,int nLineNum,const char *sErrorDesc)
{
string sTemp;
int n=0;
if(nLineNum!=-1) // line no info?
{
m_pSystem->Warning( VALIDATOR_MODULE_SCRIPTSYSTEM,VALIDATOR_ERROR,VALIDATOR_FLAG_SCRIPT,sSourceFile,
"$3#SCRIPT ERROR File: %s, Line [%03d], Function: %s,\n%s",sSourceFile,nLineNum,sFuncName,sErrorDesc );
}
else
{
m_pSystem->Warning( VALIDATOR_MODULE_SCRIPTSYSTEM,VALIDATOR_ERROR,VALIDATOR_FLAG_SCRIPT,sSourceFile,
"$3#SCRIPT ERROR File: %s, Function: %s,\n%s",sSourceFile,sFuncName,sErrorDesc );
}
m_pSystem->GetILog()->Log("\001$6#Function %s ",sFuncName);
while(sErrorDesc[n]!=0)
{
if(sErrorDesc[n]=='\n')
{
m_pSystem->GetILog()->Log("\001$6# %s",sTemp.c_str());
sTemp="";
while(sErrorDesc[n]=='\n')n++;
}else{
sTemp+=sErrorDesc[n];
n++;
}
}
if(!sTemp.empty())
m_pSystem->GetILog()->LogError("\001$6# %s ",sTemp.c_str());
if (m_pSystem->GetLuaDebugger())
{
if (sSourceFile != NULL &&
_stricmp(sSourceFile, "__script_buffer__") != 0 &&
_stricmp(sSourceFile, "=C") != 0 &&
_stricmp(sSourceFile, "undefined") != 0 &&
nLineNum!=-1 &&
sSourceFile[0] != '\0')
{
// char szMessage[2048];
// sprintf(szMessage, "Lua runtime error found in '%s' line %03d function '%s' - open debugger ?",
// sSourceFile, nLineNum, sFuncName);
// if (MessageBox(NULL, szMessage, "Lua Runtime Error", MB_YESNO | MB_ICONERROR) == IDYES)
m_pSystem->ShowDebugger(sSourceFile, nLineNum, sErrorDesc);
}
}
}
void CScriptSink::OnLoadedScriptDump(const char *sScriptPath)
{
m_pSystem->GetILog()->Log(sScriptPath);
}
//////////////////////////////////////////////////////////////////////
bool CScriptSink::CanSetGlobal(const char *sVarName)
{
if (!m_pConsole)
{
m_pSystem->GetILog()->LogWarning("\001Attempt to change variable %s denied: no console system found", sVarName);
return false; // we can't change globals unless we have console
}
IGame*pGame = m_pSystem->GetIGame();
if (!pGame)
return true; // we may change whatever we want until we're not in the game
ICVar* pVar = m_pConsole->GetCVar(sVarName);
if (!pVar)
{
m_pSystem->GetILog()->Log("\001Attempt to change variable %s denied: no such variable found", sVarName);
return false; // we aren't allowed to change global that doesn't exist
}
int nFlags = pVar->GetFlags();
if((nFlags & VF_REQUIRE_NET_SYNC) && !pGame->GetModuleState(EGameServer) && pGame->GetModuleState(EGameClient))
{
m_pSystem->GetILog()->Log("\001Attempt to change variable %s on client denied:", sVarName);
m_pSystem->GetILog()->Log("\001The variable is Server-synchronized and the game is not server.");
return false;
}
if ((nFlags & VF_CHEAT) && (!m_pSystem->IsDevMode()))
{
// No Cheat Log. m_pSystem->GetILog()->Log("\001Variable %s is cheat protected.", sVarName);
return false;
}
if (nFlags & VF_READONLY)
{
m_pSystem->GetILog()->Log("\001Variable %s is read only.", sVarName);
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////
void CScriptSink::OnSetGlobal(const char *sVarName)
{
if (m_pConsole)
m_pConsole->RefreshVariable(sVarName);
}
//////////////////////////////////////////////////////////////////////
void CScriptSink::OnCollectUserData(INT_PTR nValue,int nCookie)
{
//m_Log.Log("OnCollectUserData %d", nValue);
switch(nCookie)
{
case USER_DATA_SOUND:
{
ISound *m_pISound;
m_pISound=(ISound *)nValue;
//m_pSystem->GetILog()->Log("collecting %s",m_pISound->GetName());
//::OutputDebugString(m_pISound->GetName());
//::OutputDebugString(" OnCollect USER_DATA_SOUND\n");
if(m_pISound)
m_pISound->Release();
}
break;
case USER_DATA_TEXTURE:
{
//::OutputDebugString("OnCollect USER_DATA_TEXTURE\n");
INT_PTR nTid=nValue;
IRenderer *pRenderer = m_pSystem->GetIRenderer();
if (pRenderer)
pRenderer->RemoveTexture(nTid);
}
break;
case USER_DATA_OBJECT:
{
//::OutputDebugString("OnCollect USER_DATA_OBJECT\n");
I3DEngine *p3DEngine = m_pSystem->GetI3DEngine();
IStatObj *pObj=(IStatObj *)nValue;
// if you have crash here - pObj is invalid pointer
// ( maybe attempt to use IStatObj pointer after I3DEngine::ClearRenderResources() )
// char chTest = pObj->GetFileName()[0];
if (p3DEngine)
p3DEngine->ReleaseObject(pObj);
}
break;
case USER_DATA_LIGHT:
{
//::OutputDebugString("OnCollect USER_DATA_LIGHT\n");
INT_PTR nLightId=nValue;
I3DEngine *p3DEngine = m_pSystem->GetI3DEngine();
if (p3DEngine)
p3DEngine->DeleteStaticLightSource(nLightId);
}
break;
default:
{
//m_Log.Log("OnCollectUserData WARINING unknown user data type %d [cookie=%d]", nValue,nCookie);
//if(m_pSystem->m_pGame)
// m_pSystem->m_pGame->OnCollectUserData(nValue,nCookie);
}
}
}
/////////////////////////////////////////////////////////////
//LUA DEBUGGER
/////////////////////////////////////////////////////////////
class ___Temp : public IScriptObjectDumpSink
{
void OnElementFound(int nIdx,ScriptVarType type){}
void OnElementFound(const char *sName,ScriptVarType type)
{
switch(type)
{
case svtNull:
//GetILog()->LogToConsole("<<NULL>> %s",sName);
break;
case svtString:
//GetILog()->LogToConsole("<<STRING>> %s",sName);
break;
case svtNumber:
//GetILog()->LogToConsole("<<NUMBER>> %s",sName);
break;
case svtFunction:
//GetILog()->LogToConsole("<<FUNCTION>> %s",sName);
break;
case svtObject:
//GetILog()->LogToConsole("<<OBJECT>> %s",sName);
break;
case svtUserData:
//GetILog()->LogToConsole("<<USERDATA>> %s",sName);
break;
}
}
};
//////////////////////////////////////////////////////////////////////////
void CScriptSink::OnExecuteLine(ScriptDebugInfo &sdiDebugInfo)
{
/*
___Temp temp;
IScriptObject *pLocals = m_pSystem->GetIScriptSystem()->GetLocalVariables();
m_pSystem->GetILog()->LogToConsole("START DUMP");
pLocals->Dump(&temp);
pLocals->Release();
*/
if (m_pSystem->GetLuaDebugger())
{
m_pSystem->ShowDebugger(sdiDebugInfo.sSourceName,
sdiDebugInfo.nCurrentLine, "Breakpoint Hit");
}
}
//////////////////////////////////////////////////////////////////////////
void CScriptSink::Update( bool bNoLuaGC )
{
ITimer *pTimer=m_pSystem->GetITimer();
float currTime=pTimer->GetCurrTime();
float frameTime=pTimer->GetFrameTime();
IScriptSystem *pScriptSystem = m_pSystem->GetIScriptSystem();
// Set global time variable into the script.
pScriptSystem->SetGlobalValue( "_time", currTime );
pScriptSystem->SetGlobalValue( "_frametime",frameTime );
{
int aiTicks = 0;
IAISystem *pAISystem=m_pSystem->GetAISystem();
if(pAISystem)
aiTicks = pAISystem->GetAITickCount();
pScriptSystem->SetGlobalValue( "_aitick",aiTicks );
}
// garbage-collect script-variables
pTimer->MeasureTime("PreLuaGC");
//TRACE("GC DELTA %d",m_pScriptSystem->GetCGCount()-nStartGC);
//int nStartGC = pScriptSystem->GetCGCount();
bool bKickIn=false; // Invoke Gargabe Collector
if(currTime-m_lastGCTime>m_fGCFreq) // g_GC_Frequence->GetIVal())
bKickIn=true;
int nGCCount=pScriptSystem->GetCGCount();
if(nGCCount-m_nLastGCCount>2000 && !bNoLuaGC) //
bKickIn=true;
if(bKickIn)
{
FRAME_PROFILER( "Lua GC",m_pSystem,PROFILE_SCRIPT );
//float fTimeBefore=pTimer->GetAsyncCurTime()*1000;
pScriptSystem->ForceGarbageCollection();
m_nLastGCCount=pScriptSystem->GetCGCount();
m_lastGCTime = currTime;
//float fTimeAfter=pTimer->GetAsyncCurTime()*1000;
//CryLog("--[after coll]GC DELTA %d ",pScriptSystem->GetCGCount()-nGCCount);
//TRACE("--[after coll]GC DELTA %d [time =%f]",m_pScriptSystem->GetCGCount()-nStartGC,fTimeAfter-fTimeBefore);
}
pTimer->MeasureTime("LuaGC");
}

66
CrySystem/ScriptSink.h Normal file
View File

@@ -0,0 +1,66 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: scriptsink.h
// Version: v1.00
// Created: 30/9/2002 by Timur.
// Compilers: Visual Studio.NET
// Description:
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#ifndef __scriptsink_h__
#define __scriptsink_h__
#if _MSC_VER > 1000
#pragma once
#endif
#include <IScriptSystem.h>
class CSystem;
class CXConsole;
/** Implements callback of script system.
*/
class CScriptSink :
public IScriptSystemSink,
public IScriptDebugSink
{
public:
CScriptSink( CSystem *pSystem,CXConsole *pConsole );
void Init();
//! Called every frame to handle ScriptSystem needs..
void Update( bool bNoLuaGC=false );
void OnLoadSource(const char *sSourceName,unsigned char *sSource,long nSourceSize);
void OnExecuteLine(ScriptDebugInfo &sdiDebugInfo);
///////////////////////////////////////////////////////////////////////////
//! @name IScriptSytemSink implementation
//@{
void OnScriptError(const char *sSourceFile,const char *sFuncName,int nLineNum,const char *sErrorDesc);
void OnSetGlobal(const char *sVarName);
bool CanSetGlobal(const char* sVarName);
void OnLoadedScriptDump(const char *sScriptPath);
void OnCollectUserData(INT_PTR nValue,int nCookie);
//@}
//! \param freq time in seconds
void SetGCFreq( const float fFreq ) { m_fGCFreq = fFreq; };
private: // ----------------------------------------------------------------
float m_fGCFreq; //!< relative time in seconds
float m_lastGCTime; //!< absolute time in seconds
int m_nLastGCCount; //!<
//there's no need to use interface inside the same module
CSystem * m_pSystem; //!<
CXConsole * m_pConsole; //!<
};
#endif // __scriptsink_h__

View File

@@ -0,0 +1,109 @@
#include "StdAfx.h"
#include "SourceSafeHelper.h"
#if defined(WIN32) && !defined(WIN64) // windows specific implementation
#include <objbase.h>
#include <comdef.h>
#include "TCHAR.h" // _T()
#import "SSAPI.DLL" no_namespace
#pragma comment (lib, "ole32.lib")
#endif // WIN32
//
bool _GetSSFileInfo( const char *inszSourceSafePath, const char *inszSSProject, const char *inszDirProject, const char *inszFileName,
char *outszName, char *outszComment, char *outszDate, const unsigned int innBufferSize )
{
assert(innBufferSize>0);
// to make sure the result is empty if this function failes
outszName[0]=0;outszComment[0]=0;outszDate[0]=0;
#if !(defined(WIN32) && !defined(WIN64)) // non windows specific implementation
return false; // this plattform is not supporting SourceSafeInfo
#endif // WIN32
#if defined(WIN32) && !defined(WIN64) // windows specific implementation
char sSSFilePath[_MAX_PATH]; // max SS path size (_MAX_PATH might be not right here)
sprintf(sSSFilePath,"%s/%s",inszSSProject,inszFileName);
// if path is absolute, remove leading part
if(_strnicmp(inszDirProject,inszFileName,strlen(inszDirProject))==0)
{
char cSeperator=inszFileName[strlen(inszDirProject)];
if(cSeperator=='/' || cSeperator=='\\')
sprintf(sSSFilePath,"%s/%s",inszSSProject,&inszFileName[strlen(inszDirProject)+1]);
}
// replace '\' by '/'
{
char *p=sSSFilePath;
while(*p)
{
if(*p=='\\') *p='/';
p++;
}
}
try
{
IVSSDatabasePtr pDatabase;
IVSSItemPtr pIRootItem;
pDatabase.CreateInstance(_T("SourceSafe"));
pDatabase->Open(inszSourceSafePath, _T(""), _T("")); // open ( sourcesafe, username, password )
pIRootItem = pDatabase->GetVSSItem(sSSFilePath, VARIANT_FALSE); // specify file
IVSSVersionsPtr pVersions=pIRootItem->GetVersions(0);
IEnumVARIANTPtr pEnum=pVersions->_NewEnum();
_variant_t var;
pEnum->Next(1,&var,NULL);
IVSSVersionPtr pVer=var;
_bstr_t name=pVer->GetUsername();
_bstr_t comment=pVer->GetComment();
DATE date=pVer->GetDate();
BSTR wdatestring;
_bstr_t t;
// this may cause a problem:
// LOCALE_SYSTEM_DEFAULT or LOCALE_USER_DEFAULT is used (output varies from windows settings)
VarBstrFromDate(date,0,VAR_FOURDIGITYEARS|VAR_CALENDAR_GREGORIAN|VAR_DATEVALUEONLY,&wdatestring);
t.Attach(wdatestring);
char datestring[256];
strcpy(datestring,(TCHAR *)t);
//if(WideCharToMultiByte(CP_ACP,WC_NO_BEST_FIT_CHARS,(LPCWSTR)wdatestring,-1,datestring,256,NULL,NULL)==0)
//return false;
if(strncpy(outszName,(TCHAR *)name,innBufferSize)==0)return false;
if(strncpy(outszComment,(TCHAR *)comment,innBufferSize)==0)return false;
if(strncpy(outszDate,(TCHAR *)datestring,innBufferSize)==0)return false;
//::SysFreeString(wdatestring);
}
catch(_com_error &e)
{
// error handling (return false
_bstr_t error=e.Description();
return false;
}
#endif // WIN32
return true;
}

View File

@@ -0,0 +1,28 @@
#pragma once
// platform: windows ascii/unicode (is compiled to nil on other plattforms)
//
// * make sure ::CoInitialize(NULL); is called before this class is used and ( don't forget ::CoUninitialize(); )
// * SourceSafe has to be installed
// * This is written as gloabal function to make it easy to include in MFC and non MFC projects
//
// written by AlbertoD, MartinM
//
// dependencies: none
//! get info about the last SourceSafe action for a specifed file
//! relative path form inszFileName is extracted, combined with inszSSProject to geth the SS path
//! (e.g. "$/AssMan/AssManShellExt/AssManMenu.cpp")
//! SS connection is opened and closed in this call
//! \param inszSourceSafePath e.g. "\\\\server1\\vss\\srcsafe.ini"
//! \param inszSSProject inszSSProject!=0, e.g. "$/AssMan"
//! \param inszDirProject inszDirProject!=0, e.g. "c:\\mastercd\\AssMan"
//! \param inszFileName inszFileName!=0, e.g. "c:\\mastercd\\AssMan\\AssManShellExt\\AssManMenu.cpp"
//! \param outszName outszName!=0, [0..indwBufferSize-1]
//! \param outszComment outszComment!=0, [0..indwBufferSize-1]
//! \param outszDate outszDate!=0, [0..indwBufferSize-1]
//! \param indwBufferSize >0
//! \return true=success, false otherwise (output parameters are set to empty strings)
bool _GetSSFileInfo( const char *inszSourceSafePath, const char *inszSSProject, const char *inszDirProject, const char *inszFileName,
char *outszName, char *outszComment, char *outszDate, const unsigned int innBufferSize );

17
CrySystem/StdAfx.cpp Normal file
View File

@@ -0,0 +1,17 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: stdafx.cpp
// Version: v1.00
// Created: 30/9/2002 by Timur.
// Compilers: Visual Studio.NET
// Description: Precompiled Header Generator.
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include <CrtDebugStats.h>

126
CrySystem/StdAfx.h Normal file
View File

@@ -0,0 +1,126 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: stdafx.h
// Version: v1.00
// Created: 30/9/2002 by Timur.
// Compilers: Visual Studio.NET
// Description: Precompiled Header.
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#ifndef __stdafx_h__
#define __stdafx_h__
#if _MSC_VER > 1000
#pragma once
#endif
//////////////////////////////////////////////////////////////////////////
// THIS MUST BE AT THE VERY BEGINING OF STDAFX.H FILE.
// Disable STL threading support, (makes STL faster)
//////////////////////////////////////////////////////////////////////////
#define _NOTHREADS
#define _STLP_NO_THREADS
//////////////////////////////////////////////////////////////////////////
#include <platform.h>
//////////////////////////////////////////////////////////////////////////
// CRT
//////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <memory.h>
#if !defined(LINUX)
#include <assert.h>
#endif
#include <malloc.h>
#include <stdlib.h>
#include <fcntl.h>
#if defined( LINUX )
# include <sys/io.h>
#else
# include <io.h>
#endif
/////////////////////////////////////////////////////////////////////////////
// STL //////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
#include <vector>
#include <list>
#include <map>
#ifdef WIN64
#define hash_map map
#else
#if defined(LINUX)
#include <ext/hash_map>
#else
#include <hash_map>
#endif
#endif
#include <set>
#include <stack>
#include <string>
#include <deque>
#include <algorithm>
#ifdef WIN64
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#if !defined(min) && !defined(LINUX)
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#else
using std::min;
using std::max;
#endif
#include "platform.h"
// If not XBOX/GameCube/...
#ifdef WIN32
//#include <process.h>
#endif
/////////////////////////////////////////////////////////////////////////////
// CRY Stuff ////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//#define USE_NEWPOOL
//#include <CryMemoryManager.h>
#include "Cry_Math.h"
#include <smartptr.h>
#include <Cry_Camera.h>
#include <Range.h>
#include <TString.h>
#include <CrySizer.h>
/////////////////////////////////////////////////////////////////////////////
//forward declarations for common Interfaces.
/////////////////////////////////////////////////////////////////////////////
struct ITexPic;
struct IRenderer;
struct ISystem;
struct IScriptSystem;
struct ITimer;
struct IFFont;
struct IInput;
struct IKeyboard;
struct ICVar;
struct IConsole;
struct IGame;
struct IEntitySystem;
struct IProcess;
struct ICryPak;
struct ICryFont;
struct I3DEngine;
struct IMovieSystem;
struct ISoundSystem;
class IPhysicalWorld;
#endif // __stdafx_h__

View File

@@ -0,0 +1,4 @@
#include "stdafx.h"
#include "MTSafeAllocator.h"
#include <IStreamEngine.h>
#include "StreamEngine.h"

11
CrySystem/StreamEngine.h Normal file
View File

@@ -0,0 +1,11 @@
//////////////////////////////////////////////////////////////////////////
// Declaration of CStreamEngine: implementation of IStreamEngine interface
//
#ifndef _CRY_SYSTEM_STREAM_ENGINE_HDR_
#define _CRY_SYSTEM_STREAM_ENGINE_HDR_
#include "RefStreamEngine.h"
// This is reference implementation
typedef CRefStreamEngine CStreamEngine;
#endif

1273
CrySystem/System.cpp Normal file

File diff suppressed because it is too large Load Diff

545
CrySystem/System.h Normal file
View File

@@ -0,0 +1,545 @@
//////////////////////////////////////////////////////////////////////
//
// Crytek CryENGINE Source code
//
// File: System.h
//
// History:
// -Jan 31,2001:Originally Created by Marco Corbetta
// -: modified by all
//
//////////////////////////////////////////////////////////////////////
#ifndef SYSTEM_H
#define SYSTEM_H
#if _MSC_VER > 1000
# pragma once
#endif
#include <ISystem.h>
#include <ISound.h>
#include <IRenderer.h>
#include <IPhysics.h>
#include "Timer.h"
#include <CryVersion.h>
#include "FrameProfileSystem.h"
#include "StreamEngine.h"
#include "MTSafeAllocator.h"
#include "CPUDetect.h"
#include "PakVars.h"
#include "DownloadManager.h"
#if defined(LINUX)
#include "CryLibrary.h"
#endif
#ifdef WIN32
#include <Tlhelp32.h>
#endif
#ifdef WIN32
typedef HMODULE WIN_HMODULE;
#else
typedef void* WIN_HMODULE;
#endif
//forward declarations
class CScriptSink;
class CLUADbg;
struct IMusicSystem;
struct SDefaultValidator;
struct IDataProbe;
#define PHSYICS_OBJECT_ENTITY 0
typedef void (__cdecl *VTuneFunction)(void);
extern VTuneFunction VTResume;
extern VTuneFunction VTPause;
/*
===========================================
The System interface Class
===========================================
*/
class CXConsole;
//////////////////////////////////////////////////////////////////////
//! ISystem implementation
class CSystem :
public ISystem
{
public:
CSystem();
~CSystem();
bool IsDedicated(){return m_bDedicatedServer;}
///////////////////////////////////////////////////////////////////////////
//! @name ISystem implementation
//@{
virtual bool Init( const SSystemInitParams &params );
virtual void Release();
// Release all resources.
void ShutDown(bool bRelaunch);
virtual bool CreateGame( const SGameInitParams &params );
virtual bool Update( int updateFlags=0, int nPauseMode=0);
virtual void UpdateScriptSink();
//! Begin rendering frame.
void RenderBegin();
//! Render subsystems.
void Render();
//! End rendering frame and swap back buffer.
void RenderEnd();
//! Update screen during loading.
void UpdateLoadingScreen();
//! Renders the statistics; this is called from RenderEnd, but if the
//! Host application (Editor) doesn't employ the Render cycle in ISystem,
//! it may call this method to render the essencial statistics
void RenderStatistics ();
//! dumps the memory usage statistics to the log
void DumpMemoryUsageStatistics();
void Relaunch( bool bRelaunch );
bool IsRelaunch() const { return m_bRelaunch; };
void Quit();
bool IsQuitting();
void SetAffinity();
const char *GetUserName();
IGame *GetIGame(){ return m_pGame; }
INetwork *GetINetwork(){ return m_pNetwork; }
IRenderer *GetIRenderer(){ return CSystem::m_pRenderer; }
IInput *GetIInput(){ return m_pIInput; }
ITimer *GetITimer(){ return &m_Time; }
ICryPak *GetIPak(){ return m_pIPak; }
IConsole *GetIConsole();
IScriptSystem *GetIScriptSystem(){ return m_pScriptSystem; }
I3DEngine *GetI3DEngine(){ return m_pI3DEngine; }
ICryCharManager *GetIAnimationSystem() {return m_pICryCharManager;}
ISoundSystem *GetISoundSystem(){ return m_pISound; }
IMusicSystem *GetIMusicSystem(){ return m_pIMusic; }
IPhysicalWorld *GetIPhysicalWorld(){ return m_pIPhysicalWorld;}
IMovieSystem *GetIMovieSystem() { return m_pIMovieSystem; };
IAISystem *GetAISystem(){ return m_pAISystem;}
IMemoryManager *GetIMemoryManager(){ return m_pMemoryManager;}
IEntitySystem *GetIEntitySystem(){ return m_pEntitySystem;}
ICryFont *GetICryFont(){ return m_pICryFont; }
ILog *GetILog(){ return m_pLog; }
IStreamEngine *GetStreamEngine() {return m_pStreamEngine;}
CLUADbg *GetLuaDebugger() { return m_pLuaDebugger; }
IValidator *GetIValidator() { return m_pValidator; };
IFrameProfileSystem* GetIProfileSystem() { return &m_FrameProfileSystem; }
const char *GetGameMOD() { if (m_szGameMOD[0]) return (m_szGameMOD);return (NULL); }
XDOM::IXMLDOMDocument *CreateXMLDocument();
//////////////////////////////////////////////////////////////////////////
virtual XmlNodeRef CreateXmlNode( const char *sNodeName="" );
virtual XmlNodeRef LoadXmlFile( const char *sFilename );
virtual XmlNodeRef LoadXmlFromString( const char *sXmlString );
//////////////////////////////////////////////////////////////////////////
void SetViewCamera(class CCamera &Camera){ m_ViewCamera = Camera; }
CCamera& GetViewCamera() { return m_ViewCamera; }
virtual int GetCPUFlags()
{
int Flags = 0;
if (!m_pCpu)
return Flags;
if (m_pCpu->hasMMX())
Flags |= CPUF_MMX;
if (m_pCpu->hasSSE())
Flags |= CPUF_SSE;
if (m_pCpu->hasSSE2())
Flags |= CPUF_SSE;
if (m_pCpu->has3DNow())
Flags |= CPUF_3DNOW;
return Flags;
}
virtual double GetSecondsPerCycle()
{
if (!m_pCpu)
return 0;
else
return m_pCpu->m_Cpu[0].m_SecondsPerCycle;
}
void CreateEntityScriptBinding(IEntity *pEntity);
void IgnoreUpdates( bool bIgnore ) { m_bIgnoreUpdates = bIgnore; };
void SetGCFrequency( const float fRate );
void SetIProcess(IProcess *process);
IProcess* GetIProcess(){ return m_pProcess; }
bool IsTestMode() const { return m_bTestMode; }
//@}
IRenderer *CreateRenderer(bool fullscreen, void* hinst, void* hWndAttach = 0);
virtual void Error( const char *format,... );
// Validator Warning.
void Warning( EValidatorModule module,EValidatorSeverity severity,int flags,const char *file,const char *format,... );
bool CheckLogVerbosity( int verbosity );
virtual void DebugStats(bool checkpoint, bool leaks);
void DumpWinHeaps();
// this enumeration describes the purpose for which the statistics is gathered.
// if it's gathered to be dumped, then some different rules may be applied
enum MemStatsPurposeEnum {nMSP_ForDisplay, nMSP_ForDump};
void GetExeSizes (ICrySizer* pSizer, MemStatsPurposeEnum nPurpose = nMSP_ForDisplay);
// tries to log the call stack . for DEBUG purposes only
void LogCallStack();
struct DumpHeap32Stats
{
DumpHeap32Stats():dwFree(0),dwMoveable(0),dwFixed(0),dwUnknown(0)
{}
void operator += (const DumpHeap32Stats& right)
{
dwFree += right.dwFree;
dwMoveable += right.dwMoveable;
dwFixed += right.dwFixed;
dwUnknown += right.dwUnknown;
}
DWORD dwFree;
DWORD dwMoveable;
DWORD dwFixed;
DWORD dwUnknown;
};
#if defined(_XBOX) || defined(LINUX)
//ASH: HEAPLIST32 doesn't exist on xbox.
//void DumpHeap32 (const HEAPLIST32& hl, DumpHeap32Stats& stats);
#else // _XBOX
void DumpHeap32 (const HEAPLIST32& hl, DumpHeap32Stats& stats);
#endif // _XBOX
virtual int DumpMMStats(bool log);
//! Return pointer to user defined callback.
ISystemUserCallback* GetUserCallback() const { return m_pUserCallback; };
//! refreshes the m_pMemStats if necessary; creates it if it's not created
void TickMemStats(MemStatsPurposeEnum nPurpose = nMSP_ForDisplay);
void SaveConfiguration();
ESystemConfigSpec GetConfigSpec();
private:
//! @name Initialization routines
//@{
bool InitNetwork();
bool InitInput(WIN_HINSTANCE hinst,WIN_HWND hwnd);
bool InitConsole();
bool InitRenderer(WIN_HINSTANCE hinst,WIN_HWND hwnd,const char *szCmdLine);
bool InitSound(WIN_HWND hwnd);
bool InitPhysics();
bool InitFont();
bool InitFlash();
bool InitAISystem();
bool InitScriptSystem();
bool InitFileSystem();
bool InitStreamEngine();
bool Init3DEngine();
bool InitAnimationSystem();
bool InitMovieSystem();
bool InitEntitySystem(WIN_HINSTANCE hInstance, WIN_HWND hWnd);
bool InitScriptBindings();
bool OpenRenderLibrary(int type);
#if !defined(LINUX)
int AutoDetectRenderer(char *Vendor, char *Device);
#endif
bool OpenRenderLibrary(const char *t_rend);
bool CloseRenderLibrary();
bool ShutDownScriptBindings();
//@}
void Strange();
bool ParseSystemConfig(string &sFileName);
//////////////////////////////////////////////////////////////////////////
// Helper functions.
//////////////////////////////////////////////////////////////////////////
void CreateRendererVars();
void CreateSystemVars();
void RenderStats();
void RenderMemStats();
// collects the whole memory statistics into the given sizer object
void CollectMemStats (class CrySizerImpl* pSizer, MemStatsPurposeEnum nPurpose = nMSP_ForDisplay);
WIN_HMODULE LoadDLL( const char *dllName, bool bQuitIfNotFound=true);
#if defined(LINUX)
void FreeLib(HMODULE hLibModule);
#else
void FreeLib(IN OUT HMODULE hLibModule);
#endif
void QueryVersionInfo();
void LogVersion();
void SetDevMode( bool bEnable );
void InitScriptDebugger();
public:
// interface ISystem -------------------------------------------
virtual void ShowDebugger(const char *pszSourceFile, int iLine, const char *pszReason);
virtual bool GetSSFileInfo( const char *inszFileName, char *outszInfo, const DWORD indwBufferSize );
virtual IDataProbe* GetIDataProbe() { return m_pDataProbe; };
virtual void SetForceNonDevMode( const bool bValue );
virtual bool GetForceNonDevMode() const;
virtual bool WasInDevMode() const { return m_bWasInDevMode; };
virtual bool IsDevMode() const { return m_bInDevMode && !GetForceNonDevMode(); }
// -------------------------------------------------------------
//! attaches the given variable to the given container;
//! recreates the variable if necessary
ICVar* attachVariable (const char* szVarName, int* pContainer, const char *szComment,int dwFlags=0 );
private: // ------------------------------------------------------
CTimer m_Time; //!<
CCamera m_ViewCamera; //!<
CXConsole * m_pConsole; //!<
bool m_bQuit; //!< if is true the system is quitting
bool m_bRelaunch; //!< relaunching the app or not (true beforerelaunch)
bool m_bRelaunched; //!< Application was started with the -RELAUNCH option (true after relaunch)
bool m_bTestMode; //!< If running in testing mode.
bool m_bEditor; //!< If running in Editor.
bool m_bDedicatedServer; //!< If running as Dedicated server.
bool m_bIgnoreUpdates; //!< When set to true will ignore Update and Render calls,
IValidator * m_pValidator; //!< Pointer to validator interface.
bool m_bForceNonDevMode; //!< true when running on a cheat protected server or a client that is connected to it (not used in singlplayer)
bool m_bWasInDevMode; //!< Set to true if was in dev mode.
bool m_bInDevMode; //!< Set to true if was in dev mode.
SDefaultValidator * m_pDefaultValidator; //!<
int m_nStrangeRatio; //!<
//! Input system
//! @see CRenderer
IRenderer *m_pRenderer;
//! CPU features
CCpuFeatures *m_pCpu;
//! DLLs handles.
struct SDllHandles
{
WIN_HMODULE hRenderer;
WIN_HMODULE hInput;
WIN_HMODULE hFlash;
WIN_HMODULE hSound;
WIN_HMODULE hEntitySystem;
WIN_HMODULE hNetwork;
WIN_HMODULE hAI;
WIN_HMODULE hMovie;
WIN_HMODULE hPhysics;
WIN_HMODULE hFont;
WIN_HMODULE hScript;
WIN_HMODULE h3DEngine;
WIN_HMODULE hAnimation;
WIN_HMODULE hIndoor;
WIN_HMODULE hGame;
};
SDllHandles m_dll;
//! Input system
//! @see CInput
IInput *m_pIInput;
//! Log interface.
ILog* m_pLog;
//! THe streaming engine
CStreamEngine* m_pStreamEngine;
//! current active process
IProcess *m_pProcess;
IMemoryManager *m_pMemoryManager;
//! Pack file system.
CCryPak* m_pIPak;
//! Flash Module
//IFlash *m_pFlashManager;
//! Sound System
//! @see CSoundSystem
ISoundSystem* m_pISound;
//! Music System
//! @see CMusicSystem
IMusicSystem* m_pIMusic;
//! Entity System
//! @see CEntitySystem
IEntitySystem * m_pEntitySystem;
//! Network Module
//! @see CNetwork
INetwork *m_pNetwork;
//! AI System
//! @see CAISystem
IAISystem *m_pAISystem;
//! Physics System
IPhysicalWorld* m_pIPhysicalWorld;
//! Movie System.
IMovieSystem* m_pIMovieSystem;
//! Font System
//! @see CCryFont
ICryFont* m_pICryFont;
//! Script System
//! @see CScriptSystem
IScriptSystem *m_pScriptSystem;
//[Timur] CREATEDOMDOCUMENT_FNCPTR m_CreateDOMDocument;
//! 3D Engine
//! @see C3DEngine
I3DEngine *m_pI3DEngine;
ICryCharManager* m_pICryCharManager;
//! The default font
IFFont* m_pIFont;
//! game path folder
char m_szGameMOD[MAX_PATH];
//! to hold the values stored in system.cfg
//! because editor uses it's own values,
//! and then saves them to file, overwriting the user's resolution.
int m_iHeight;
int m_iWidth;
int m_iColorBits;
// System console variables.
//////////////////////////////////////////////////////////////////////////
ICVar *m_cvAIUpdate;
ICVar *m_rWidth;
ICVar *m_rHeight;
ICVar *m_rColorBits;
ICVar *m_rDepthBits;
ICVar *m_rStencilBits;
ICVar *m_rFullscreen;
ICVar *m_rDriver;
ICVar *m_rDisplayInfo;
ICVar *m_sysNoUpdate;
ICVar *i_direct_input;
ICVar *sys_script_debugger;
ICVar *m_cvEntitySuppressionLevel;
ICVar *m_pCVarQuit;
ICVar *m_cvMemStats;
ICVar *m_cvMemStatsThreshold;
ICVar *m_cvMemStatsMaxDepth;
ICVar *m_sysWarnings; //!< might be 0, "sys_warnings" - Treat warning as errors.
ICVar *m_cvSSInfo; //!< might be 0, "sys_SSInfo" 0/1 - get file sourcesafe info
ICVar *m_sys_profile;
ICVar *m_sys_profile_graph;
ICVar *m_sys_profile_graphScale;
ICVar *m_sys_profile_pagefaultsgraph;
ICVar *m_sys_profile_filter;
ICVar *m_sys_profile_network;
ICVar *m_sys_profile_peak;
ICVar *m_sys_profile_memory;
ICVar *m_sys_spec;
ICVar *m_sys_skiponlowspec;
ICVar *m_sys_firstlaunch;
ICVar *m_sys_StreamCallbackTimeBudget;
ICVar *m_sys_StreamCompressionMask; //!< bitmask, lossy compression, useful for network comunication, should be 0 for load/save
string m_sSavedRDriver; //!< to restore the driver when quitting the dedicated server
ICVar* m_cvPakPriority;
ICVar* m_cvPakReadSlice;
ICVar* m_cvPakLogMissingFiles;
// the contents of the pak priority file
PakVars m_PakVar;
//////////////////////////////////////////////////////////////////////////
CScriptSink *m_pScriptSink;
//! User define callback for system events.
ISystemUserCallback *m_pUserCallback;
WIN_HWND m_hWnd;
WIN_HINSTANCE m_hInst;
// this is the memory statistics that is retained in memory between frames
// in which it's not gathered
class CrySizerStats* m_pMemStats;
class CrySizerImpl* m_pSizer;
struct CScriptBindings* m_pScriptBindings;
CFrameProfileSystem m_FrameProfileSystem;
int m_profile_old;
//int m_nCurrentLogVerbosity;
SFileVersion m_fileVersion;
SFileVersion m_productVersion;
IDataProbe *m_pDataProbe;
public:
//! Pointer to Game Interface,
IGame *m_pGame;
//! Pointer to the download manager
CDownloadManager *m_pDownloadManager;
CLUADbg *m_pLuaDebugger;
#ifdef USE_FRAME_PROFILER
void SetFrameProfiler(bool on, bool display, char *prefix) { m_FrameProfileSystem.SetProfiling(on, display, prefix, this); };
void StartProfilerSection( CFrameProfilerSection *pProfileSection );
void EndProfilerSection( CFrameProfilerSection *pProfileSection );
#else
void SetFrameProfiler(bool on, bool display, char *prefix) {};
void StartProfilerSection( CFrameProfilerSection *pProfileSection ) {};
void EndProfilerSection( CFrameProfilerSection *pProfileSection ) {};
#endif
//////////////////////////////////////////////////////////////////////////
// VTune.
virtual void VTuneResume();
virtual void VTunePause();
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// File version.
//////////////////////////////////////////////////////////////////////////
virtual const SFileVersion& GetFileVersion();
virtual const SFileVersion& GetProductVersion();
bool WriteCompressedFile(char *filename, void *data, unsigned int bitlen);
unsigned int ReadCompressedFile(char *filename, void *data, unsigned int maxbitlen);
unsigned int GetCompressedFileSize(char *filename);
void InitVTuneProfiler();
void OpenBasicPaks();
void OpenLanguagePak( const char *sLanguage );
void Deltree(const char *szFolder, bool bRecurse);
void LoadConfiguration(const string &sFilename);
protected: // -------------------------------------------------------------
// this heap is used for small allocations - the queues
CMTSafeHeap m_SmallHeap;
// this heap is used for big allocations - the chunks to be loaded
CMTSafeHeap m_BigHeap;
friend struct SDefaultValidator;
};
#endif // SYSTEM_H

223
CrySystem/SystemCFG.cpp Normal file
View File

@@ -0,0 +1,223 @@
//////////////////////////////////////////////////////////////////////
//
// Crytek CryENGINE Source code
//
// File: SystemCFG.cpp
// Description: handles system cfg
//
// History:
// -Jan 21,2004: created
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "System.h"
#include <time.h>
#include "XConsole.h"
#include <IGame.h>
#include <IScriptSystem.h>
#include "SystemCfg.h"
#if defined(LINUX)
#include "ILog.h"
#endif
//////////////////////////////////////////////////////////////////////////
const SFileVersion& CSystem::GetFileVersion()
{
return m_fileVersion;
}
//////////////////////////////////////////////////////////////////////////
const SFileVersion& CSystem::GetProductVersion()
{
return m_productVersion;
}
//////////////////////////////////////////////////////////////////////////
void CSystem::QueryVersionInfo()
{
#if defined(LINUX)
//do we need some other values here?
m_fileVersion.v[0] = VERSION_INFO;
m_fileVersion.v[1] = 1;
m_fileVersion.v[2] = 1;
m_fileVersion.v[3] = 1;
m_productVersion.v[0] = VERSION_INFO;
m_productVersion.v[1] = 1;
m_productVersion.v[2] = 1;
m_productVersion.v[3] = 1;
#else
char moduleName[_MAX_PATH];
DWORD dwHandle;
UINT len;
char ver[1024*8];
// GetModuleFileName( NULL, moduleName, _MAX_PATH );//retrieves the PATH for the current module
strcpy(moduleName,"CrySystem.dll"); // we want to version from the system dll (FarCry.exe we cannot change because of CopyProtection)
int verSize = GetFileVersionInfoSize( moduleName,&dwHandle );
if (verSize > 0)
{
GetFileVersionInfo( moduleName,dwHandle,1024*8,ver );
VS_FIXEDFILEINFO *vinfo;
VerQueryValue( ver,"\\",(void**)&vinfo,&len );
m_fileVersion.v[0] = vinfo->dwFileVersionLS & 0xFFFF;
m_fileVersion.v[1] = vinfo->dwFileVersionLS >> 16;
m_fileVersion.v[2] = vinfo->dwFileVersionMS & 0xFFFF;
m_fileVersion.v[3] = vinfo->dwFileVersionMS >> 16;
m_productVersion.v[0] = vinfo->dwProductVersionLS & 0xFFFF;
m_productVersion.v[1] = vinfo->dwProductVersionLS >> 16;
m_productVersion.v[2] = vinfo->dwProductVersionMS & 0xFFFF;
m_productVersion.v[3] = vinfo->dwProductVersionMS >> 16;
}
#endif
}
//////////////////////////////////////////////////////////////////////////
void CSystem::LogVersion()
{
//! Get time.
time_t ltime;
time( &ltime );
tm *today = localtime( &ltime );
char s[1024];
//! Use strftime to build a customized time string.
//strftime( timebuf,128,"Logged at %A, %B %d,%Y\n\n", today );
strftime( s,128,"Log Started at %#c", today );
CryLogAlways( s );
CryLogAlways( "FileVersion: %d.%d.%d.%d",m_fileVersion.v[3],m_fileVersion.v[2],m_fileVersion.v[1],m_fileVersion.v[0] );
CryLogAlways( "ProductVersion: %d.%d.%d.%d",m_productVersion.v[3],m_productVersion.v[2],m_productVersion.v[1],m_productVersion.v[0] );
CryLogAlways( "" );
}
//////////////////////////////////////////////////////////////////////////
void CSystem::SaveConfiguration()
{
// save config before we quit
if (!m_pGame)
return;
string sSave=m_rDriver->GetString();
if(m_sSavedRDriver!="")
m_rDriver->Set(m_sSavedRDriver.c_str());
// get player's profile
ICVar *pProfile=m_pConsole->GetCVar("g_playerprofile");
if (pProfile)
{
const char *sProfileName=pProfile->GetString();
m_pGame->SaveConfiguration( "system.cfg","game.cfg",sProfileName);
}
// always save the current profile in the root, otherwise, nexttime, the game will have the default one
// wich is annoying
m_pGame->SaveConfiguration( "system.cfg","game.cfg",NULL);
m_rDriver->Set(sSave.c_str());
}
//////////////////////////////////////////////////////////////////////////
ESystemConfigSpec CSystem::GetConfigSpec()
{
if (m_sys_spec)
return (ESystemConfigSpec)m_sys_spec->GetIVal();
return CONFIG_VERYHIGH_SPEC; // highest spec.
}
//////////////////////////////////////////////////////////////////////////
// system cfg
//////////////////////////////////////////////////////////////////////////
CSystemConfiguration::CSystemConfiguration(const string& strSysConfigFilePath,CSystem *pSystem)
: m_strSysConfigFilePath( strSysConfigFilePath )
//, m_colCCVars()
{
m_pSystem=pSystem;
ParseSystemConfig();
}
//////////////////////////////////////////////////////////////////////////
CSystemConfiguration::~CSystemConfiguration()
{
}
//////////////////////////////////////////////////////////////////////////
void CSystemConfiguration::ParseSystemConfig()
{
//m_pScriptSystem->ExecuteFile(sFilename.c_str(),false);
FILE *pFile=fxopen(m_strSysConfigFilePath.c_str(), "rb");
if (!pFile)
return;
char szLine[512];
char szBuffer[512];
while (fgets(szLine,512,pFile))
{
string strLine(szLine);
// skip comments
if (0<strLine.find( "--" ))
{
// extract key
string::size_type posEq( strLine.find( "=", 0 ) );
if (string::npos!=posEq)
{
#if defined(LINUX)
string s( strLine, 0, posEq );
string strKey( RemoveWhiteSpaces(s) );
#else
string strKey( RemoveWhiteSpaces( string( strLine, 0, posEq ) ) );
#endif
if (!strKey.empty())
{
// extract value
string::size_type posValueStart( strLine.find( "\"", posEq + 1 ) + 1 );
string::size_type posValueEnd( strLine.find( "\"", posValueStart ) );
if( string::npos != posValueStart && string::npos != posValueEnd )
{
string strValue( strLine, posValueStart, posValueEnd - posValueStart );
ICVar *pCvar=m_pSystem->GetIConsole()->GetCVar(strKey.c_str(),false); // false=not case sensitive (slow but more convenient)
if (pCvar)
{
m_pSystem->GetILog()->Log("Setting %s to %s",strKey.c_str(),strValue.c_str());
pCvar->Set(strValue.c_str());
}
else
{
if (strstr(strKey.c_str(),"#") || strstr(strValue.c_str(),"#"))
{
m_pSystem->GetILog()->Log("Invalid buffer (%s,%s)",strKey.c_str(),strValue.c_str());
}
else
{
m_pSystem->GetILog()->Log("Lua cvar: (%s,%s)",strKey.c_str(),strValue.c_str());
sprintf(szBuffer,"%s = \"%s\"",strKey.c_str(),strValue.c_str());
m_pSystem->GetIScriptSystem()->ExecuteBuffer(szBuffer,strlen(szBuffer));
}
}
}
}
}
} //--
} // while fgets
fclose(pFile);
}
//////////////////////////////////////////////////////////////////////////
void CSystem::LoadConfiguration(const string &sFilename)
{
if (!sFilename.empty())
{
//m_pScriptSystem->ExecuteFile(sFilename.c_str(),false);
m_pLog->Log("Loading system configuration");
CSystemConfiguration tempConfig(sFilename,this);
}
}

45
CrySystem/SystemCFG.h Normal file
View File

@@ -0,0 +1,45 @@
//////////////////////////////////////////////////////////////////////
//
// Crytek CryENGINE Source code (c) 2002-2004
//
// File: SystemCfg.h
//
// History:
// -Jan 22,2004:Created
//
//////////////////////////////////////////////////////////////////////
#pragma once
#include <math.h>
#include <string>
#include <map>
typedef string SysConfigKey;
typedef string SysConfigValue;
//////////////////////////////////////////////////////////////////////////
class CSystemConfiguration
{
public:
CSystemConfiguration( const string& strSysConfigFilePath,CSystem *pSystem);
~CSystemConfiguration();
string RemoveWhiteSpaces( string& s )
{
string s1;
for (int i = 0; i < (int)(s.size()); i++)
if (s[i] != ' ') s1.push_back(s[i]);
s = s1;
return s;
//return( string( s.begin(), std::remove( s.begin(), s.end(), ' ' ) ) );
}
private:
void ParseSystemConfig();
CSystem *m_pSystem;
string m_strSysConfigFilePath;
};

1525
CrySystem/SystemInit.cpp Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More