123
This commit is contained in:
82
CrySystem/ApplicationHelper.cpp
Normal file
82
CrySystem/ApplicationHelper.cpp
Normal 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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
CrySystem/ApplicationHelper.h
Normal file
50
CrySystem/ApplicationHelper.h
Normal 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
1077
CrySystem/CPUDetect.cpp
Normal file
File diff suppressed because it is too large
Load Diff
163
CrySystem/CPUDetect.h
Normal file
163
CrySystem/CPUDetect.h
Normal 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
|
||||
97
CrySystem/CompressedFile.cpp
Normal file
97
CrySystem/CompressedFile.cpp
Normal 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
89
CrySystem/CritSection.h
Normal 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
|
||||
498
CrySystem/CryMemoryManager.cpp
Normal file
498
CrySystem/CryMemoryManager.cpp
Normal 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
1867
CrySystem/CryPak.cpp
Normal file
File diff suppressed because it is too large
Load Diff
626
CrySystem/CryPak.h
Normal file
626
CrySystem/CryPak.h
Normal 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
169
CrySystem/CrySizerImpl.cpp
Normal 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
144
CrySystem/CrySizerImpl.h
Normal 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
363
CrySystem/CrySizerStats.cpp
Normal 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
183
CrySystem/CrySizerStats.h
Normal 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
BIN
CrySystem/CrySystem.aps
Normal file
Binary file not shown.
267
CrySystem/CrySystem.rc
Normal file
267
CrySystem/CrySystem.rc
Normal 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
1587
CrySystem/CrySystem.vcproj
Normal file
File diff suppressed because it is too large
Load Diff
10
CrySystem/CrySystem.vcproj.vspscc
Normal file
10
CrySystem/CrySystem.vcproj.vspscc
Normal 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"
|
||||
}
|
||||
604
CrySystem/CrySystem_XBox.vcproj
Normal file
604
CrySystem/CrySystem_XBox.vcproj
Normal 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=""$/Game01/CrySystem", 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>
|
||||
10
CrySystem/CrySystem_XBox.vcproj.vspscc
Normal file
10
CrySystem/CrySystem_XBox.vcproj.vspscc
Normal 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
14
CrySystem/CryWaterMark.h
Normal 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
871
CrySystem/DataProbe.cpp
Normal 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
91
CrySystem/DataProbe.h
Normal 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__
|
||||
|
||||
768
CrySystem/DebugCallStack.cpp
Normal file
768
CrySystem/DebugCallStack.cpp
Normal 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( <ime );
|
||||
tm *today = localtime( <ime );
|
||||
|
||||
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
|
||||
93
CrySystem/DebugCallStack.h
Normal file
93
CrySystem/DebugCallStack.h
Normal 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
85
CrySystem/DllMain.cpp
Normal 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;
|
||||
}
|
||||
};
|
||||
94
CrySystem/DownloadManager.cpp
Normal file
94
CrySystem/DownloadManager.cpp
Normal 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
|
||||
27
CrySystem/DownloadManager.h
Normal file
27
CrySystem/DownloadManager.h
Normal 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
187
CrySystem/DxDiag.h
Normal 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_ */
|
||||
|
||||
|
||||
1118
CrySystem/FrameProfileRender.cpp
Normal file
1118
CrySystem/FrameProfileRender.cpp
Normal file
File diff suppressed because it is too large
Load Diff
896
CrySystem/FrameProfileSystem.cpp
Normal file
896
CrySystem/FrameProfileSystem.cpp
Normal 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
|
||||
331
CrySystem/FrameProfileSystem.h
Normal file
331
CrySystem/FrameProfileSystem.h
Normal 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__
|
||||
353
CrySystem/HTTPDownloader.cpp
Normal file
353
CrySystem/HTTPDownloader.cpp
Normal 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
|
||||
83
CrySystem/HTTPDownloader.h
Normal file
83
CrySystem/HTTPDownloader.h
Normal 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
678
CrySystem/Log.cpp
Normal 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( <ime );
|
||||
struct tm *today = localtime( <ime );
|
||||
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
89
CrySystem/Log.h
Normal 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
|
||||
28
CrySystem/LuaDebugger/AboutWnd.h
Normal file
28
CrySystem/LuaDebugger/AboutWnd.h
Normal 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
|
||||
2
CrySystem/LuaDebugger/FileTree.cpp
Normal file
2
CrySystem/LuaDebugger/FileTree.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "stdafx.h"
|
||||
#include "FileTree.h"
|
||||
85
CrySystem/LuaDebugger/FileTree.h
Normal file
85
CrySystem/LuaDebugger/FileTree.h
Normal 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
|
||||
761
CrySystem/LuaDebugger/LUADBG.cpp
Normal file
761
CrySystem/LuaDebugger/LUADBG.cpp
Normal 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);
|
||||
}
|
||||
418
CrySystem/LuaDebugger/LUADBG.h
Normal file
418
CrySystem/LuaDebugger/LUADBG.h
Normal 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;
|
||||
|
||||
};
|
||||
BIN
CrySystem/LuaDebugger/LUADBG.ico
Normal file
BIN
CrySystem/LuaDebugger/LUADBG.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
80
CrySystem/LuaDebugger/LuaDbgInterface.cpp
Normal file
80
CrySystem/LuaDebugger/LuaDbgInterface.cpp
Normal 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;
|
||||
}
|
||||
10
CrySystem/LuaDebugger/LuaDbgInterface.h
Normal file
10
CrySystem/LuaDebugger/LuaDbgInterface.h
Normal 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
|
||||
55
CrySystem/LuaDebugger/_TinyBrowseFolder.h
Normal file
55
CrySystem/LuaDebugger/_TinyBrowseFolder.h
Normal 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
|
||||
70
CrySystem/LuaDebugger/_TinyCaptionWindow.h
Normal file
70
CrySystem/LuaDebugger/_TinyCaptionWindow.h
Normal 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
|
||||
20
CrySystem/LuaDebugger/_TinyCoolEdit.h
Normal file
20
CrySystem/LuaDebugger/_TinyCoolEdit.h
Normal 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_
|
||||
57
CrySystem/LuaDebugger/_TinyFileEnum.h
Normal file
57
CrySystem/LuaDebugger/_TinyFileEnum.h
Normal 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
|
||||
65
CrySystem/LuaDebugger/_TinyImageList.h
Normal file
65
CrySystem/LuaDebugger/_TinyImageList.h
Normal 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
|
||||
200
CrySystem/LuaDebugger/_TinyMain.h
Normal file
200
CrySystem/LuaDebugger/_TinyMain.h
Normal 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
|
||||
73
CrySystem/LuaDebugger/_TinyRegistry.h
Normal file
73
CrySystem/LuaDebugger/_TinyRegistry.h
Normal 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
|
||||
219
CrySystem/LuaDebugger/_TinySplitter.h
Normal file
219
CrySystem/LuaDebugger/_TinySplitter.h
Normal 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
|
||||
38
CrySystem/LuaDebugger/_TinyStatusBar.h
Normal file
38
CrySystem/LuaDebugger/_TinyStatusBar.h
Normal 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
|
||||
64
CrySystem/LuaDebugger/_TinyTreeList.h
Normal file
64
CrySystem/LuaDebugger/_TinyTreeList.h
Normal 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
|
||||
772
CrySystem/LuaDebugger/_TinyWindow.h
Normal file
772
CrySystem/LuaDebugger/_TinyWindow.h
Normal 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 = ▭
|
||||
hdl.pwpos = ℘
|
||||
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_
|
||||
BIN
CrySystem/LuaDebugger/res/TreeView.bmp
Normal file
BIN
CrySystem/LuaDebugger/res/TreeView.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
CrySystem/LuaDebugger/res/toolbar1.bmp
Normal file
BIN
CrySystem/LuaDebugger/res/toolbar1.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
CrySystem/LuaDebugger/small.ico
Normal file
BIN
CrySystem/LuaDebugger/small.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
5
CrySystem/MSSCCPRJ.SCC
Normal file
5
CrySystem/MSSCCPRJ.SCC
Normal 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
|
||||
92
CrySystem/MTSafeAllocator.cpp
Normal file
92
CrySystem/MTSafeAllocator.cpp
Normal 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
173
CrySystem/MTSafeAllocator.h
Normal 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
156
CrySystem/Mailer.cpp
Normal 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
33
CrySystem/Mailer.h
Normal 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
14
CrySystem/PakVars.h
Normal 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
116
CrySystem/RandGen.cpp
Normal 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
22
CrySystem/RandGen.h
Normal 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
166
CrySystem/RefReadStream.cpp
Normal 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
122
CrySystem/RefReadStream.h
Normal 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
|
||||
483
CrySystem/RefReadStreamProxy.cpp
Normal file
483
CrySystem/RefReadStreamProxy.cpp
Normal 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;
|
||||
}
|
||||
132
CrySystem/RefReadStreamProxy.h
Normal file
132
CrySystem/RefReadStreamProxy.h
Normal 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
|
||||
744
CrySystem/RefStreamEngine.cpp
Normal file
744
CrySystem/RefStreamEngine.cpp
Normal 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
219
CrySystem/RefStreamEngine.h
Normal 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
BIN
CrySystem/SSAPI.DLL
Normal file
Binary file not shown.
134
CrySystem/ScriptBinding.cpp
Normal file
134
CrySystem/ScriptBinding.cpp
Normal 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());
|
||||
}
|
||||
255
CrySystem/ScriptObjectAnimation.cpp
Normal file
255
CrySystem/ScriptObjectAnimation.cpp
Normal 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);
|
||||
}
|
||||
|
||||
55
CrySystem/ScriptObjectAnimation.h
Normal file
55
CrySystem/ScriptObjectAnimation.h
Normal 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
|
||||
5199
CrySystem/ScriptObjectEntity.cpp
Normal file
5199
CrySystem/ScriptObjectEntity.cpp
Normal file
File diff suppressed because it is too large
Load Diff
291
CrySystem/ScriptObjectEntity.h
Normal file
291
CrySystem/ScriptObjectEntity.h
Normal 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_)
|
||||
|
||||
125
CrySystem/ScriptObjectMovie.cpp
Normal file
125
CrySystem/ScriptObjectMovie.cpp
Normal 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();
|
||||
}
|
||||
22
CrySystem/ScriptObjectMovie.h
Normal file
22
CrySystem/ScriptObjectMovie.h
Normal 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;
|
||||
};
|
||||
644
CrySystem/ScriptObjectParticle.cpp
Normal file
644
CrySystem/ScriptObjectParticle.cpp
Normal 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();
|
||||
}
|
||||
53
CrySystem/ScriptObjectParticle.h
Normal file
53
CrySystem/ScriptObjectParticle.h
Normal 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_)
|
||||
376
CrySystem/ScriptObjectScript.cpp
Normal file
376
CrySystem/ScriptObjectScript.cpp
Normal 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();
|
||||
}
|
||||
57
CrySystem/ScriptObjectScript.h
Normal file
57
CrySystem/ScriptObjectScript.h
Normal 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_)
|
||||
1290
CrySystem/ScriptObjectSound.cpp
Normal file
1290
CrySystem/ScriptObjectSound.cpp
Normal file
File diff suppressed because it is too large
Load Diff
84
CrySystem/ScriptObjectSound.h
Normal file
84
CrySystem/ScriptObjectSound.h
Normal 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_)
|
||||
3039
CrySystem/ScriptObjectSystem.cpp
Normal file
3039
CrySystem/ScriptObjectSystem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
188
CrySystem/ScriptObjectSystem.h
Normal file
188
CrySystem/ScriptObjectSystem.h
Normal 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
336
CrySystem/ScriptSink.cpp
Normal 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
66
CrySystem/ScriptSink.h
Normal 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__
|
||||
109
CrySystem/SourceSafeHelper.cpp
Normal file
109
CrySystem/SourceSafeHelper.cpp
Normal 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;
|
||||
}
|
||||
|
||||
28
CrySystem/SourceSafeHelper.h
Normal file
28
CrySystem/SourceSafeHelper.h
Normal 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
17
CrySystem/StdAfx.cpp
Normal 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
126
CrySystem/StdAfx.h
Normal 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__
|
||||
4
CrySystem/StreamEngine.cpp
Normal file
4
CrySystem/StreamEngine.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "stdafx.h"
|
||||
#include "MTSafeAllocator.h"
|
||||
#include <IStreamEngine.h>
|
||||
#include "StreamEngine.h"
|
||||
11
CrySystem/StreamEngine.h
Normal file
11
CrySystem/StreamEngine.h
Normal 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
1273
CrySystem/System.cpp
Normal file
File diff suppressed because it is too large
Load Diff
545
CrySystem/System.h
Normal file
545
CrySystem/System.h
Normal 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 ¶ms );
|
||||
virtual void Release();
|
||||
// Release all resources.
|
||||
void ShutDown(bool bRelaunch);
|
||||
|
||||
virtual bool CreateGame( const SGameInitParams ¶ms );
|
||||
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
223
CrySystem/SystemCFG.cpp
Normal 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( <ime );
|
||||
tm *today = localtime( <ime );
|
||||
|
||||
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
45
CrySystem/SystemCFG.h
Normal 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
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
Reference in New Issue
Block a user