как известно, именно на этом движке работает Crysis 2.
В толксах был когда-то топик о слухах о том, что cryengine3 есть под Linux.
Я скачал свежий CryEngine3 SDK версии 1.4.
Итак, что же я увидел:
Во-первых в директории Code/CryEngine/CryCommon есть 4 интересных файла:
LinuxSpecific.h
Linux32Specific.h
Linux64Specific.h
Linux_Win32Wrapper.h (объемный)
Но и это еще не все. Код буквально испещрен упоминаниями Linux:
CryPool/CryPool.h
#if defined(LINUX) || defined(PS3)
#define CPA_ALLOC memalign
#define CPA_FREE free
#else
#define CPA_ALLOC _aligned_malloc
#define CPA_FREE _aligned_free
#endif
BitFlidding.h
#if defined(LINUX)
#define countLeadingZeros32(x) __builtin_clz(x)
CryMath.h
#ifdef LINUX
#include <values.h>
#endif
CryVector2.h
#if defined(LINUX64)
typedef Vec2_tpl<int> vector2l;
#else
typedef Vec2_tpl<long> vector2l;
#endif
CryXOptimise.h
#if defined(LINUX64)
#define PrefetchLine(ptr, off) cryPrefetchT0SSE((void*)((UINT_PTR)ptr + off))
#define ResetLine128(ptr, off) (void)(0)
#else
#define PrefetchLine(ptr, off) cryPrefetchT0SSE((void*)((unsigned int)ptr + off))
#define ResetLine128(ptr, off) (void)(0)
#endif
#if defined _CPU_X86 && !defined(LINUX)
if (OptFlags & CPUF_SSE)
multMatrixf_Transp2_SSE(pOut, pM1, pM2);
else
#endif
#if defined _CPU_X86 && !defined(LINUX)
// Inline assembly syntax for use with Visual C++
//много-много асма
#endif
#if defined _CPU_X86 && !defined(LINUX)
if (OptFlags & CPUF_SSE)
multMatrixf_Transp2_SSE(pOut, pM1, pM2);
else
#endif
#if defined(LINUX64)
#define PrefetchLine(ptr, off) cryPrefetchT0SSE((void*)((UINT_PTR)ptr + off))
#define ResetLine128(ptr, off) (void)(0)
#else
#define PrefetchLine(ptr, off) cryPrefetchT0SSE((void*)((unsigned int)ptr + off))
#define ResetLine128(ptr, off) (void)(0)
#endif
и дальше в этом же файле дофига асма и дефайнов LINUX
CryArray.h
#if !defined(LINUX)
template<> struct IntTraits<unsigned long>
{
typedef long TSigned;
};
#endif
CryFixedString.h
#if defined(PS3) || defined(LINUX)
_Self& operator=( const CryStringT<T> &str );
#endif
#if defined(LINUX)
template<size_t AnySize>
_Self& operator=(const CryStackStringT<T, AnySize> &str)
{
_Assign( str.c_str(),str.size() ) ;
return *this;
}
#endif
#if defined(PS3) || defined(LINUX)
_Self& operator+=( const CryStringT<T> &str );
#endif
#if defined(PS3) || defined(LINUX)
template <class T, size_t S>
inline CryStackStringT<T,S>::CryStackStringT( const CryStringT<T> &str )
{
_Initialize();
size_t nLength = str.size();
if (nLength > 0)
{
_AllocData(nLength);
CharTraits<T>::_copy( m_str,str.c_str(),nLength );
CRY_STRING_DEBUG(m_str)
}
}
#endif
#if defined(PS3) || defined(LINUX)
template <class T, size_t S>
inline CryStackStringT<T,S>& CryStackStringT<T,S>::operator=( const CryStringT<T> &str )
{
_Assign( str.c_str(),str.size() ) ;
return *this;
}
template <class T, size_t S>
inline CryStackStringT<T,S>& CryStackStringT<T,S>::operator+=( const CryStringT<T> &str )
{
_ConcatenateInPlace( str.c_str(),str.size() );
return *this;
}
#endif
#if defined(LINUX)
template<size_t AnySize>
_Self& operator=(const CryStackStringT<T, AnySize> &str)
{
_Assign( str.c_str(),str.size() ) ;
return *this;
}
#endif
#if defined(PS3) || defined(LINUX)
CryStackStringT( const CryStringT<T> &str );
#endif
CryHalf.inl
# if defined(WIN32) || defined(WIN64) || defined(LINUX)
__forceinline CryHalf CryConvertFloatToHalf(const float Value)
{
#ifdef LINUX
asm volatile("" ::: "memory");
#endif
CryLibrary.h ВНИМАНИЕ
#elif (defined(LINUX) && !defined(_LIB))
#include <dlfcn.h>
#include <stdlib.h>
#include "platform.h"
// for compatibility with code written for windows
#define CrySharedLibraySupported true
#define CrySharedLibrayExtension ".so"
#define CryGetProcAddress(libHandle, procName) ::dlsym(libHandle, procName)
#define CryFreeLibrary(libHandle) ::dlclose(libHandle)
#define HMODULE void*
static const char* gEnvName("MODULE_PATH");
static const char* GetModulePath()
{
return getenv(gEnvName);
}
static void SetModulePath(const char* pModulePath)
{
setenv(gEnvName, pModulePath?pModulePath:"",true);
}
static HMODULE CryLoadLibrary(const char* libName, const bool cAppend = true, const bool cLoadLazy = false)
{
//[K01]: linux version
char path[_MAX_PATH];
sprintf(path, "%s/%s", GetModulePath(), libName);
return ::dlopen(path, RTLD_LAZY);
}
CryMemoryAllocator.h
#ifdef LINUX64
#include <sys/mman.h>
#endif
#elif defined(LINUX64)
enum {_ALIGNMENT = 16, _ALIGN_SHIFT = 4, __MAX_BYTES = 512, NFREELISTS=32, ADDRESSSPACE = 2 * 1024 * 1024, ADDRESS_SHIFT = 40};
#else
enum {_ALIGNMENT = 8, _ALIGN_SHIFT = 3, __MAX_BYTES = 512, NFREELISTS = 64, ADDRESSSPACE = 2 * 1024 * 1024, ADDRESS_SHIFT = 20};
#endif
// Allocators!
enum EAllocFreeType
{
eCryDefaultMalloc,
eCryMallocCryFreeCRTCleanup,
eCryLinuxMalloc
};
#ifdef LINUX64
template <>
struct Node_Allocator<eCryLinuxMalloc>
{
struct _MemHead
{
void* ptr;
size_t size;
};
inline void * pool_alloc(size_t size)
{
char *p = (char*)mmap(NULL, size + sizeof(_MemHead), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_32BIT | MAP_ANONYMOUS, -1, 0);
_MemHead* pH = (_MemHead*)p;
pH->ptr = p;
pH->size = size;
p += sizeof(_MemHead);
return p;
};
inline void * cleanup_alloc(size_t size)
{
char* p = (char*)mmap(NULL, size + sizeof(_MemHead), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_32BIT | MAP_ANONYMOUS, -1, 0);
_MemHead* pH = (_MemHead*)p;
pH->ptr = p;
pH->size = size;
p += sizeof(_MemHead);
return p;
};
inline size_t pool_free(void * ptr)
{
_MemHead* pH = (_MemHead*)((char*)ptr - sizeof(_MemHead));
size_t n = pH->size;
munmap(pH->ptr, pH->size + sizeof(_MemHead));
return n;
};
inline void cleanup_free(void * ptr)
{
_MemHead* pH = (_MemHead*)((char*)ptr - sizeof(_MemHead));
munmap(pH->ptr, pH->size + sizeof(_MemHead));
};
inline size_t getSize(void * ptr)
{
_MemHead* pH = (_MemHead*)((char*)ptr - sizeof(_MemHead));
return pH->size;
}
};
#endif // LINUX64
//#ifdef LINUX
//#define USE_WRITELOCKS
//#endif
CryMemoryManager.h
#if defined(PS3) || defined(LINUX)
#include <new>
#if defined(_DEBUG) && !defined(PS3) && !defined(LINUX)
#include <crtdbg.h>
#endif //_DEBUG
CryMemoryManager_impl.h
#ifdef LINUX
for(iter=0,hMod=::dlopen(NULL, RTLD_LAZY); hMod; iter++)
#else //LINUX
for(iter=0,hMod=GetModuleHandle(0); hMod; iter++)
#endif //LINUX
#ifdef LINUX
hMod = CryLoadLibrary("CrySystem.so");
#else //LINUX
hMod = CryLoadLibrary("CrySystem.dll");
#endif //LINUX
#ifdef WIN32
MessageBox(NULL, "Could not access CrySystem.dll (check working directory)", "Memory Manager", MB_OK);
#else
if (!hMod)
OutputDebugString("Could not access CrySystem.dll (check working directory)");
else
OutputDebugString("Could not get Memory Functions in CrySystem.dll");
#endif
CrySizer.h
#ifdef LINUX
#include <tr1/unordered_map>
#else
#include <unordered_map>
#endif
CryThread.h
#if defined(LINUX)
#include <CryThread_pthreads.h>
#elif defined(WIN32) || defined(WIN64)
#include <CryThread_windows.h>
CryThread_pthreads.h:
#ifndef _CryThread_pthreads_h_
#define _CryThread_pthreads_h_ 1
#include <ISystem.h>
#include <ILog.h>
#ifndef __SPU__
# include <sys/types.h>
# include <sys/time.h>
# include <pthread.h>
# include <semaphore.h>
# include <sched.h>
#endif
CryThreadImpl.h
// Include architecture specific code.
#if defined(LINUX)
#include <CryThreadImpl_pthreads.h>
#elif defined(WIN32) || defined(WIN64)
#include <CryThreadImpl_windows.h>
CryTypeInfo.h
#if defined(PS3) || defined(LINUX)
#undef CVTDIGITHEX
#undef CVTDIGITDEC
#define CVTDIGITHEX(VALUE, P, STRING) \
{ \
if (VALUE) \
{ \
unsigned int _digit = (VALUE % 16); \
_digit += (_digit > 10) ? 'a' - 10 : '0'; \
*P++ = (char)_digit; \
} \
else \
{ \
*P = 0; \
return STRING; \
} \
VALUE /= 16; \
}
#define CVTDIGITDEC(VALUE, P, STRING) \
{ \
if (VALUE) \
*P++ = '0' + (char)(VALUE % 10); \
else \
{ \
*P = 0; \
return STRING; \
} \
VALUE /= 10; \
}
#undef CVTDIGITDEC
#undef CVTDIGITHEX
#endif // PS3 || LINUX
#ifndef LINUX64
TYPE_INFO_INT(long)
TYPE_INFO_INT(unsigned long)
#endif
#ifndef LINUX64
// long
string ToString(long const& val)
{
char buffer[64];
ltoa(val, buffer, 10);
return buffer;
}
// ulong
string ToString(unsigned long const& val)
{
char buffer[64];
ultoa(val, buffer, 10);
return buffer;
}
#endif
#ifndef LINUX64
bool FromString(long& val, const char* s) { return ClampedIntFromString(val, s); }
bool FromString(unsigned long& val, const char* s) { return ClampedIntFromString(val, s); }
#endif
// CRAIG: just a temp workaround to try and get things working
#ifndef LINUX
pSizer->AddString(*(string*)data);
#endif
}
Endian.h
#if defined(WIN64) || defined(LINUX64)
template<class T>
ILINE void SwapEndian(T* t, unsigned int nCount, bool bSwapEndian = eLittleEndian)
{
if (bSwapEndian)
SwapEndianBase(t, nCount);
}
#endif
IAgent.h, IAIGroup.h, IAIRecoder.h
#ifdef LINUX
# include "platform.h"
#endif
ICryPak.h
#if defined(LINUX)
char adjustedName[MAX_PATH];
GetFilenameNoCase(file, adjustedName, bWriteAccess);
int accessFlag = R_OK;
if (bWriteAccess)
accessFlag |= W_OK;
// check if file exists
int err = access(adjustedName, F_OK);
if (err != 0)
{
// file not exists, so fail in case of not bWriteAccess
// in case of bWriteAccess check parent directory permission
if (!bWriteAccess)
return 0;
char parentDir[MAX_PATH];
strcpy_s(parentDir, adjustedName);
char* p = strrchr(parentDir, '/');
if (0 != p)
{
*p = 0;
}
else
{
parentDir[0] = '.';
parentDir[1] = 0;
}
err = access(parentDir, accessFlag);
}
else
{
// file exists so check permission on it
err = access(adjustedName, accessFlag);
}
if (0 == err)
return fopen(adjustedName, mode);
else
return 0;
#else
// This is on windows or xbox.
//опущено
#endif //LINUX
IJobManager.h
#if defined(WIN64) || defined(LINUX64)
volatile int64 exchangeValue;
#else
volatile long exchangeValue;
#endif
//sizes for accessing the SQueueNodeSPU array
#if defined(WIN64) || defined(LINUX64)
static const unsigned int scSizeOfSJobQueueEntry = 256; //sizeof SInfoBlock (extra coded because shift)
static const unsigned int scSizeOfSJobQueueEntryShift = 8; //SInfoBlock in shifts
#else
static const unsigned int scSizeOfSJobQueueEntry = 128; //sizeof SInfoBlock (extra coded because shift)
static const unsigned int scSizeOfSJobQueueEntryShift = 7; //SInfoBlock in shifts
#endif
#if defined(WIN64) || defined(LINUX64)
pDst[4] = cpSrc[4];
pDst[5] = cpSrc[5];
pDst[6] = cpSrc[6];
pDst[7] = cpSrc[7];
#endif
#if defined(WIN64) || defined(LINUX64)
if((SPU_DRIVER_INT_PTR)cNextPtr >= (SPU_DRIVER_INT_PTR)m_RingBufferEnd) cNextPtr = (SPU_DRIVER_INT_PTR)m_RingBufferStart;
return (void*)cNextPtr;
#else
const unsigned int cNextPtrMask = (unsigned int)(((int)(cNextPtr - m_RingBufferEnd)) >> 31);
return (void*)(cNextPtr & cNextPtrMask | m_RingBufferStart & ~cNextPtrMask);
#endif
#if defined(WIN64) || defined(LINUX64)// for 64 bit, we need to atomicly swap 128 bit
int64 compareValue[2] = { *alias_cast<int64*>(&curQueueRunningState),(int64)nPushPtr};
#if defined(WIN64)
_InterlockedCompareExchange128((volatile int64*)this, (int64)markedPushPtr, *alias_cast<int64*>(&curQueueRunningState), compareValue);
#else //LINUX64
CryInterlockedCompareExchange128((volatile int64*)this, (int64)markedPushPtr, *alias_cast<int64*>(&curQueueRunningState), compareValue);
#endif
IShader.h
#if defined(LINUX) || defined(PS3)
#include <platform.h>
#endif
#if !defined(PS3) && !defined(LINUX)
ENUM_INFO_BEGIN(ETEX_Format)
ENUM_ELEM_INFO(, eTF_Unknown)
ENUM_ELEM_INFO(, eTF_R8G8B8)
ENUM_ELEM_INFO(, eTF_A8R8G8B8)
ENUM_ELEM_INFO(, eTF_X8R8G8B8)
ENUM_ELEM_INFO(, eTF_A8)
ENUM_ELEM_INFO(, eTF_A8L8)
ENUM_ELEM_INFO(, eTF_L8)
ENUM_ELEM_INFO(, eTF_A4R4G4B4)
ENUM_ELEM_INFO(, eTF_R5G6B5)
ENUM_ELEM_INFO(, eTF_R5G5B5)
ENUM_ELEM_INFO(, eTF_V8U8)
ENUM_ELEM_INFO(, eTF_CxV8U8)
ENUM_ELEM_INFO(, eTF_X8L8V8U8)
ENUM_ELEM_INFO(, eTF_L8V8U8)
ENUM_ELEM_INFO(, eTF_L6V5U5)
ENUM_ELEM_INFO(, eTF_V16U16)
ENUM_ELEM_INFO(, eTF_A16B16G16R16)
ENUM_ELEM_INFO(, eTF_A16B16G16R16F)
ENUM_ELEM_INFO(, eTF_A32B32G32R32F)
ENUM_ELEM_INFO(, eTF_G16R16F)
ENUM_ELEM_INFO(, eTF_R16F)
ENUM_ELEM_INFO(, eTF_R32F)
ENUM_ELEM_INFO(, eTF_DXT1)
ENUM_ELEM_INFO(, eTF_DXT3)
ENUM_ELEM_INFO(, eTF_DXT5)
ENUM_ELEM_INFO(, eTF_3DC)
ENUM_ELEM_INFO(, eTF_G16R16)
ENUM_ELEM_INFO(, eTF_NULL)
ENUM_ELEM_INFO(, eTF_DF16)
ENUM_ELEM_INFO(, eTF_DF24)
ENUM_ELEM_INFO(, eTF_D16)
ENUM_ELEM_INFO(, eTF_D24S8)
ENUM_ELEM_INFO(, eTF_D32F)
ENUM_ELEM_INFO(, eTF_DEPTH16)
ENUM_ELEM_INFO(, eTF_DEPTH24)
ENUM_ELEM_INFO(, eTF_A2R10G10B10)
ENUM_INFO_END(ETEX_Format)
#endif
ISystem.h
#if defined(LINUX)
void (*pCheckFunc)(void*); // Authentication function (must be set).
#else
void *pCheckFunc; // Authentication function (must be set).
#endif
IValidator.h
#if defined(WIN32) || defined(WIN64) || defined(LINUX)
# define MAX_WARNING_LENGTH 4096
#else
# define MAX_WARNING_LENGTH 512
// reduce max warning length for consoles (e.g. to prevent overflows on PS3 where thread stack are rather small)
#endif
IXml.h
#ifndef LINUX64
void setAttr( const char* key,unsigned long value ) { setAttr( key,(unsigned int)value ); };
void setAttr( const char* key,long value ) { setAttr( key,(int)value ); };
#endif
#ifndef LINUX64
bool getAttr( const char *key,long &value ) const { int v; if (getAttr(key,v)) { value = v; return true; } else return false; }
bool getAttr( const char *key,unsigned long &value ) const { unsigned int v; if (getAttr(key,v)) { value = v; return true; } else return false; }
#endif
MultiThread.h
#if defined(LINUX64)
unsigned char CryInterlockedCompareExchange128( int64 volatile *dst, int64 exchangehigh, int64 exchangelow, int64* comperand );
#endif
physinterface.h
#if defined(LINUX)
//#include "Stream.h"
//#include "validator.h"
#endif
platform.h
#if defined(LINUX)
#define _FILE_OFFSET_BITS 64 // define large file support > 2GB
#endif
// Compile with unit testing enabled
#if !defined(PS3) && !defined(_XBOX_VER) && !defined(LINUX)
#define CRY_UNIT_TESTING
#endif
ProjectDefines.h
#if defined(LINUX)
# define EXCLUDE_SCALEFORM_SDK
# define EXCLUDE_CRI_SDK
ScriptHelpers.h
// [K01]: disabled int version since it is overloaded with float and isn't compiled
// under GCC for enum types
#ifndef LINUX
void RegisterGlobal( const char *sName,int nValue )
{
m_pSS->SetGlobalValue(sName,nValue);
}
#endif
smartptr.h
#if defined(LINUX64)
_smart_ptr(typeof(__null)) : p(NULL) {}
#endif
StlUtils.h
#if (_MSC_VER >= 1400) && !defined(_STLP_BEGIN_NAMESPACE) // Visual Studio 2005 without STLPort
#include <hash_map>
#undef std__hash_map
#define std__hash_map stdext::hash_map
#elif defined(LINUX) && !defined(USING_STLPORT)
#include "platform.h"
#include <ext/hash_map>
#define std__hash_map __gnu_cxx::hash_map
#else
#include <hash_map>
#endif
StringUtils.h
#if defined(LINUX)
#include <ctype.h>
#endif
WinBase.cpp
///////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: WinBase.cpp
// Version: v1.00
// Created: 10/3/2004 by Michael Glueck
// Compilers: GCC
// Description: Linux port support for Win32API calls
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
полностью: http://paste.kde.org/518084
SharedParams/SharedParamsManager.h
#ifdef LINUX
#include <tr1/unordered_map>
#else
#include <unordered_map>
#endif
Вывод: порт CryEngine3 для Linux существует, и, я думаю, CryTek может выпустить Crysis 2 для Linux когда выйдет Steam. Логично, что они не сделали этого раньше, ибо продавать негде.
P.S. Никаких упоминаний Darwin и/или MacOSX найдено не было.