LINUX.ORG.RU
решено ФорумGames

Исследование CryEngine 2 SDK 1.4.0

 длинная простыня


0

1

как известно, именно на этом движке работает 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 найдено не было.

★★★★

Можно было просто написать: ребята, я предчувствую игры (вендокапец). Ничего бы не изменилось, а текста было бы гораздо меньше. Хотя нет, мой вариант более информативный.

anonymous
()
Ответ на: комментарий от xtraeft

так в том и дело что пока тока фороникс принёс.

я читал только отрывок из какогото интервью про варфэйс где на вопрос по мотивам материалов с фороникс был ответ что варфэйс для линукса не не планируется. там вопрос поддержки линукса краенджином был не опровергнут и не подтверждён самым искусным образом.

Thero ★★★★★
()
Ответ на: комментарий от winddos

Спасибо.

однако они зачем-то собирают D3D рендер для Linux...

	 ifeq ($(ARCH_OS),Linux)
	  PROJECTS_Renderer := CryRenderNULL XRenderD3D10

pashazz ★★★★
() автор топика
Ответ на: комментарий от pashazz

Более того, он там когда то был.
Файловая структура движка не поменялась с первой версии.

winddos ★★★
()
Ответ на: комментарий от pashazz

Заглушка.
Можешь в хидерах посмотреть соседство DEDICATED и LINUX.

winddos ★★★
()

На правах вопроса

#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 _CPU_X86 && !defined(LINUX)
  if (OptFlags & CPUF_SSE)
    multMatrixf_Transp2_SSE(pOut, pM1, pM2);

// Inline assembly syntax for use with Visual C++
//много-много асма

  if (OptFlags & CPUF_SSE)
    multMatrixf_Transp2_SSE(pOut, pM1, pM2);
  else
#endif

и в чем прикол выполнения

if (OptFlags & CPUF_SSE)
    multMatrixf_Transp2_SSE(pOut, pM1, pM2);
и до вставки ассемблерной, и после

Chubakur ★★
()
Ответ на: комментарий от xtraeft

Ну если желание с чем то разобраться не поощрять, то из кого тогда будут рости злые хацкеры и специалисты по портированию игр на линупсы?:)

winddos ★★★
()
Ответ на: комментарий от Chubakur

я просто 2 куска кода рядом поставил из разных мест

pashazz ★★★★
() автор топика
Ответ на: комментарий от xtraeft

Я и не заявлял, что я в этом компетентен.

pashazz ★★★★
() автор топика
Ответ на: комментарий от xtraeft

через месяц-два этот сайт мне тоже надоест, и я куда-нибудь свалю, не бойся.

dmfd
()
Ответ на: комментарий от winddos

Была демо-версия под Линукс? Не слышал о таком.

OpenGL у них в SS3 давно есть, они его почти сразу прикрутили. Но в том же Wine он работает с переменным успехом, так что в этом случае, наличие OpenGL-рендера ни о чем не говорит.

tekk ★★★★★
()
Ответ на: комментарий от tekk

Ошибся я, просто когда то попадалась на глаза Serious Sam Beta 3 for Linux.
А это была бетка первой игры вообще :)

winddos ★★★
()
Ответ на: комментарий от anonymous

продавать не негде, а некому.

Мама денег не дает?

devl547 ★★★★★
()
Ответ на: комментарий от Behem0th

Смотри нисемоноготари

Ну эту фансервисную поделку. Только в bakemonogatari живёт упоротый импрессионистский дух Shaft'а.

dmfd
()
Ответ на: комментарий от Behem0th

Хоть бы тогда опять тех же веществ приняли. А то ведь стиль скопирован (и ничего нового не привнесено), а выглядит всё как подделка, название прямо в точку.

А ранобец - совсем не указ. Вот в Suzumia Haruhi no * он вообще просто эталон графомании и унылости, по литературной ценности равносилен школьному сочинению, но аниме отличное.

dmfd
()
Ответ на: комментарий от dmfd

Упоротость в nisemonogatari не сильно меньше чем в bakemonogatari. Но фансервисов больше раз в 100, это факт.

И это, по теме. Не читал код, все таки время не подходящее для работы мозгом, но вангую серверную часть онли под линуксы. Я угадал, да?

no-steam ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.