void* F_CALLBACK VisionFM_Realloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) { #ifndef _VISION_XENON if (ptr) { unsigned int iOldSize = g_FmodAllocations[ptr]; g_FmodAllocations.RemoveKey(ptr); void* pNewPtr = vMemAlloc(size); g_FmodAllocations.SetAt(pNewPtr, size); memcpy(pNewPtr, ptr, iOldSize < size ? iOldSize : size); vMemFree(ptr); return pNewPtr; } else { void* ptr = vMemAlloc(size); g_FmodAllocations.SetAt(ptr, size); return vMemAlloc(size); } #else return VFmodXenonRealloc(ptr, size, (type & FMOD_MEMORY_XBOX360_PHYSICAL)!=0); #endif }
void VRTLSupport_cl::SetText(const wchar_t *pText) { VASSERT(pText!=NULL); //clear text vars for multiple SetText calls if(m_ppTextLines!=NULL) { for(int i=0;i<m_iTextLines;i++) { V_SAFE_FREE(m_ppTextLines[i]); } } V_SAFE_FREE(m_ppTextLines); //create a tokenizer in order to separate the text lines VArrayHelper_cl<wchar_t> tokenizer(pText, L"\n"); //create line pointers m_iTextLines = tokenizer.CalcNumberOfTokens(); m_ppTextLines = (char **)vMemAlloc(m_iTextLines * sizeof(char *)); int iLineIndex=0; int iWLen, iSize; while( tokenizer.HasNextToken() ) { //get the current text line const wchar_t *pCurrentLine = tokenizer.NextToken(); //length of the current line int iLength = VArrayHelper_cl<wchar_t>::Length(pCurrentLine); //allocate the target buffer (original length + terminator) wchar_t *pReversed = (wchar_t *) vMemAlloc(sizeof(wchar_t)*(iLength+1)); //pre-terminate buffer pReversed[iLength] = 0; //transform LTR to RTL for(int i=0;i<iLength;i++) { pReversed[iLength-i-1] = pCurrentLine[i]; } // Convert to UTF8 and assign the reversed line iWLen = (int)wcslen(pReversed); iSize = VString::ConvertWCharToUTF8String(pReversed, iWLen, NULL, 0); m_ppTextLines[iLineIndex] = new char[iSize+1]; VString::ConvertWCharToUTF8String(pReversed, iWLen, m_ppTextLines[iLineIndex], iSize); m_ppTextLines[iLineIndex][iSize] = '\0'; V_SAFE_DELETE(pReversed); iLineIndex++; } }
// -------------------------------------------------------------------------- // // Fmod memory callbacks // -------------------------------------------------------------------------- // void* F_CALLBACK VisionFM_Alloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) { #ifndef _VISION_XENON void* ptr = vMemAlloc(size); g_FmodAllocations.SetAt(ptr, size); return ptr; #else return VFmodXenonAlloc(size, (type & FMOD_MEMORY_XBOX360_PHYSICAL)!=0); #endif }
/// \brief /// Creates a NULL-terminated copy of the specified buffer with the predefined length. static ELEM_TYPE * Copy(const ELEM_TYPE * pBuffer, int length) { VASSERT(pBuffer); //create an empty buffer ELEM_TYPE *pCopy = (ELEM_TYPE *) vMemAlloc(sizeof(ELEM_TYPE)*(length+1)); //copy and terminate memcpy((void *)pCopy, (void*) pBuffer, sizeof(ELEM_TYPE)*length); pCopy[length] = NULL; return pCopy; }
inline wchar_t* vwStrDup(const wchar_t* the_string) { if (the_string) { wchar_t* szTempBuffer = (wchar_t*)vMemAlloc((wcslen(the_string)+1)*sizeof(wchar_t)); VASSERT(szTempBuffer); #pragma warning(push) #pragma warning(disable:4996) return (wcscpy(szTempBuffer, the_string)); #pragma warning(pop) } return (NULL); }
inline char* vStrDup(const char* the_string) { if (the_string) { char* szTempBuffer = (char*)vMemAlloc(strlen(the_string)+1); VASSERT(szTempBuffer); #pragma warning(push) #pragma warning(disable:4996) return (strcpy(szTempBuffer, the_string)); #pragma warning(pop) } return (NULL); }
void VArabicSupport_cl::SetText(const wchar_t *pArabicText, bool isContextualArabic, bool duplicateSpacesDuringConversion) { VASSERT(pArabicText!=NULL); //clear text vars for multiple SetText calls if(m_ppTextLines!=NULL) { for(int i=0;i<m_iTextLines;i++) { V_SAFE_FREE(m_ppTextLines[i]); } } V_SAFE_FREE(m_ppTextLines); //create a tokenizer in order to separate the text lines VArrayHelper_cl<wchar_t> tokenizer(pArabicText, L"\n"); //create line pointers m_iTextLines = tokenizer.CalcNumberOfTokens(); m_ppTextLines = (char **)vMemAlloc(m_iTextLines * sizeof(char *)); int iWLen, iSize; int iLineIndex=0; while( tokenizer.HasNextToken() ) { wchar_t *pConverted = NULL; if(isContextualArabic) { //duplicate line pConverted = VArrayHelper_cl<wchar_t>::Copy(tokenizer.NextToken()); } else { //convert to contextual pConverted = UniformToContextualLine(m_pFont, tokenizer.NextToken(), duplicateSpacesDuringConversion); } // Convert to UTF8 and assign the reversed line iWLen = (int)wcslen(pConverted); iSize = VString::ConvertWCharToUTF8String(pConverted, iWLen, NULL, 0); m_ppTextLines[iLineIndex] = new char[iSize+1]; VString::ConvertWCharToUTF8String(pConverted, iWLen, m_ppTextLines[iLineIndex], iSize); m_ppTextLines[iLineIndex][iSize] = '\0'; V_SAFE_DELETE(pConverted); iLineIndex++; } }
inline void CloneData(VTerrainLockObject &target) { target.Init(m_iPos[0],m_iPos[1],m_iSize[0],m_iSize[1],0); if (!IsValid()) return; target.m_iStride = m_iStride; target.m_iComponentSize = m_iComponentSize; target.m_bOwnsData = true; int iByteCount = m_iStride*m_iSize[1]*m_iComponentSize; target.m_pData = vMemAlloc(iByteCount); memcpy(target.m_pData,m_pData,iByteCount); // copy additional properties (important since resource infos might be stored) target.m_pTerrain = m_pTerrain; memcpy(target.m_iSectorRect,m_iSectorRect,sizeof(m_iSectorRect)); memcpy(target.m_iReserved,m_iReserved,sizeof(m_iReserved)); memcpy(target.m_pReserved,m_pReserved,sizeof(m_pReserved)); }
wchar_t* VArabicSupport_cl::UniformToContextualLine(VisFont_cl * pArabicFont, const wchar_t * pUniformArabic, bool duplicateSpaces) { if(pUniformArabic==NULL) return NULL; //length of the current line int iLength = VArrayHelper_cl<wchar_t>::Length(pUniformArabic); //count spaces int iNumSpaces = 0; if(duplicateSpaces) { for(int i=0;i<iLength;i++) { if(pUniformArabic[i]==L' ') iNumSpaces++; } } //allocate the target buffer (original length + number of duplicates space + terminator) wchar_t *pContextualArabic = (wchar_t *) vMemAlloc(sizeof(wchar_t)*(iLength+iNumSpaces+1)); //pre-terminate buffer pContextualArabic[iLength+iNumSpaces] = 0; wchar_t wcCurLetter = pUniformArabic[0]; //start with the first letter wchar_t wcPrevLetter = 0; //init wcPrevLetter, because the assignment is done at the end of the for loop //is the current (first) letter an Arabic letter? bool bCurIsArabic = isUniformArabic(pUniformArabic[0]); bool bPrevIsArabic = false; //at the beginning the previous letter is never Arabic bool bNextIsArabic; //calculated inside the loop //transform and terminate the target buffer for(int i=0;i<iLength;i++) { //start at the right side with the first character at index 0 (because Arabic is RTL) wcCurLetter = pUniformArabic[i]; bNextIsArabic = i<(iLength-1) ? isUniformArabic(pUniformArabic[i+1]) : false; if(bCurIsArabic) { //first uniform letter is 'alif madda: 0x0622 (maps to contextual representation 0xFE81) int iIndex = wcCurLetter-0x0622; //number of iterations wchar_t wcContextual = 0xFE81; //contextual representation of 'alif madda //calculate contextual representation of current uniform representation //(count up transformation steps) for(int j=0;j<iIndex;j++) { if(s_pArabicLetterMap[j]==0) wcContextual +=2; else if(s_pArabicLetterMap[j]==1) wcContextual +=4; //else skip (-1) } //now adjust character according to the in-word position wchar_t wcCandidate = wcContextual; //we experiment with a candidate character since it's not sure that the candidate exists! //end character if( bPrevIsArabic && isInnerLetter(wcPrevLetter) && (!bNextIsArabic || isEndLetter(wcCurLetter)) ) { wcCandidate+=1; //start character } else if( bNextIsArabic && (!bPrevIsArabic || isEndLetter(wcPrevLetter)) ) { if(s_pArabicLetterMap[iIndex]!=0) wcCandidate+=2; //inner character } else if( i>0 && bPrevIsArabic && bNextIsArabic && isInnerLetter(wcPrevLetter) && isInnerLetter(wcCurLetter) ) { if(s_pArabicLetterMap[iIndex]!=0) wcCandidate+=3; } //else isolated (default) //candidate check (do we have this character in the font..?) VRectanglef requiredSpace = GetCharacterDimension(wcCandidate, pArabicFont); if(requiredSpace.GetSizeX()<=0) { wcCandidate = wcContextual; //restore from backup (because the character is missing) //just in case: fall-back to non-contextual VRectanglef requiredSpace = GetCharacterDimension(wcCandidate, pArabicFont); if(requiredSpace.GetSizeX()<=0) wcCandidate = wcCurLetter; } #ifdef HK_DEBUG_SLOW requiredSpace = GetCharacterDimension(wcCandidate, pArabicFont); VASSERT_MSG(requiredSpace.GetSizeX()>0, "Your text contains a character which is not present in your font!") #endif //candidate approved: pContextualArabic[iLength+iNumSpaces-i-1] = wcCandidate; } else { //invert directional symbols switch(wcCurLetter) { case L'(': wcCurLetter = L')'; break; case L')': wcCurLetter = L'('; break; case L'<': wcCurLetter = L'>'; break; case L'>': wcCurLetter = L'<'; break; case L'{': wcCurLetter = L'}'; break; case L'}': wcCurLetter = L'{'; break; case L'[': wcCurLetter = L']'; break; case L']': wcCurLetter = L'['; break; case L'/': wcCurLetter = L'\\'; break; case L'\\': wcCurLetter = L'/'; break; case L' ': if(duplicateSpaces) { pContextualArabic[iLength+iNumSpaces-i-1] = L' '; iNumSpaces--; } break; default: break; } pContextualArabic[iLength+iNumSpaces-i-1] = wcCurLetter; } //prepare for next loop iteration wcPrevLetter = wcCurLetter; bPrevIsArabic = bCurIsArabic; bCurIsArabic = bNextIsArabic; } return pContextualArabic; }
void VFmodManager::InitFmodSystem() { // Give the application a chance to modify the m_config. VFmodConfigCallbackData config(&OnBeforeInitializeFmod, m_config); OnBeforeInitializeFmod.TriggerCallbacks(&config); // Set debug output level. Has only effect when using Fmod logging libs, otherwise will return FMOD_ERR_UNSUPPORTED. #ifdef HK_DEBUG_SLOW FMOD_WARNINGCHECK(FMOD::Debug_SetLevel(m_config.iDebugLevel)); #endif // initialize memory { FMOD_RESULT result = FMOD_OK; if (!m_config.bUseMemoryPool) result = FMOD::Memory_Initialize(NULL, 0, VisionFM_Alloc, VisionFM_Realloc, VisionFM_Free, 0); else { #ifndef _VISION_XENON pMemoryPool = vMemAlloc(m_config.iMemoryPoolSize); #else pMemoryPool = VFmodXenonAlloc(m_config.iMemoryPoolSize, true); #endif VASSERT(pMemoryPool != NULL); result = FMOD::Memory_Initialize(pMemoryPool,m_config.iMemoryPoolSize, NULL, NULL, NULL); } // In case the old Sound Plugin and the new Fmod Plugin are both loaded inside vForge (required for converting scenes), // it can happen that the Fmod system is already initialized by the old Sound Plugin. Then Memory_Initialize() will be // called after Fmod system is already initialized, which is illegal. Therefore inside vForge failing to call Memory_Initialize() // in such a case is not treated as fatal error. Fmod will simply not use Vision De-/ Allocators or a preallocated memory block, // instead it will use it own de-/ allocators. This should be fine in case of converting scenes. Otherwise it should be anyway // avoided to load both plugins simultaneously. if (!Vision::Editor.IsInEditor()) FMOD_ERRORCHECK(result); else { if(result == FMOD_ERR_INITIALIZED) Vision::Error.Warning("Failed to initialize Fmod memory system, this is most probably because the old Sound Plugin is loaded, too. This should only be done for converting scenes."); else FMOD_ERRORCHECK(result); } } FMOD_ERRORCHECK(FMOD::EventSystem_Create(&m_pEventSystem)); #ifdef VFMOD_SUPPORTS_NETWORK if (m_config.bUseNetworkSystem) { #ifdef _VISION_PS3 bool bNetworkInitialized = VInitializeNetworkPS3(); VASSERT(bNetworkInitialized == true); #endif FMOD_ERRORCHECK(FMOD::NetEventSystem_Init(m_pEventSystem)); } #endif FMOD_ERRORCHECK(m_pEventSystem->getSystemObject(&m_pSystem)); unsigned int iVersion = 0; FMOD_ERRORCHECK(m_pEventSystem->getVersion(&iVersion)); VASSERT(iVersion >= FMOD_VERSION) FMOD_ERRORCHECK(m_pSystem->setSoftwareFormat(m_config.iSampleRate, m_config.iFormat, 0,m_config.iMaxInputChannels, m_config.iResampleMethod)); // install file manager callbacks FMOD_ERRORCHECK(m_pSystem->setFileSystem(VisionFM_Open, VisionFM_Close, VisionFM_Read, VisionFM_Seek, NULL, NULL, 4096)); #ifdef _VISION_ANDROID // Increase DSP buffer size on Android { unsigned int iBlocksize = 0; int iNumblocks = 0; m_pSystem->getDSPBufferSize(&iBlocksize, &iNumblocks); m_pSystem->setDSPBufferSize(iBlocksize*2, iNumblocks); #ifdef HK_DEBUG_SLOW int iBufferSize = iNumblocks*iBlocksize; Vision::Error.Warning("Fmod DSP buffer size increased from %i to %i, in order to get correct sound output", iBufferSize, iBufferSize*2); #endif } #endif #ifndef _VISION_PS3 FMOD_RESULT result = m_pEventSystem->init(m_config.iMaxChannels, FMOD_INIT_NORMAL, NULL, FMOD_EVENT_INIT_NORMAL); FMOD_WARNINGCHECK(result); #else VSpursHandler *spursHandler = Vision::GetSpursHandler(); VASSERT(spursHandler != NULL); CellSpurs *spurs = spursHandler->GetSpurs(); FMOD_PS3_EXTRADRIVERDATA extradriverdata; memset(&extradriverdata, 0, sizeof(FMOD_PS3_EXTRADRIVERDATA)); extradriverdata.spurs = spurs; /* Using SPURS */ extradriverdata.spu_thread_priority = 16; /* Default, THIS WILL BE IGNORED */ FMOD_RESULT result = m_pEventSystem->init(m_config.iMaxChannels, FMOD_INIT_NORMAL, (void *)&extradriverdata, FMOD_EVENT_INIT_NORMAL); FMOD_WARNINGCHECK(result); #endif // In case of missing sound card, we need to deinitialize the Fmod Event System. // However it is still ensured, that the application can be run, by preventing calls to native Fmod functions. if(result != FMOD_OK) { DeInitFmodSystem(); Vision::Error.Warning("The application will run without sound output!"); return; } FMOD_ERRORCHECK(m_pSystem->set3DSettings(1.0, m_config.fFmodToVisionScale, 1.0f)); // get the master channel group where all sound instances go to initially FMOD_ERRORCHECK(m_pSystem->getMasterChannelGroup(&m_pMasterGroup)); VASSERT(m_pMasterGroup!=NULL); // create a special channel group for background music FMOD_ERRORCHECK(m_pSystem->createChannelGroup("music", &m_pMusicGroup)); VASSERT(m_pMusicGroup!=NULL); IVisCallbackDataObject_cl data(&OnAfterInitializeFmod); OnAfterInitializeFmod.TriggerCallbacks(&data); }
void VFmodManager::InitFmodSystem() { // Give the application a chance to modify the m_config. VFmodConfigCallbackData config(&OnBeforeInitializeFmod, m_config); OnBeforeInitializeFmod.TriggerCallbacks(&config); // Set debug output level. Has only effect when using Fmod logging libs, otherwise will return FMOD_ERR_UNSUPPORTED. #ifdef HK_DEBUG_SLOW FMOD_WARNINGCHECK(FMOD::Debug_SetLevel(m_config.iDebugLevel)); #endif // initialize memory { FMOD_RESULT result = FMOD_OK; if (!m_config.bUseMemoryPool) result = FMOD::Memory_Initialize(NULL, 0, VisionFM_Alloc, VisionFM_Realloc, VisionFM_Free, 0); else { #ifndef _VISION_XENON pMemoryPool = vMemAlloc(m_config.iMemoryPoolSize); #else pMemoryPool = VFmodXenonAlloc(m_config.iMemoryPoolSize, true); #endif VASSERT(pMemoryPool != NULL); result = FMOD::Memory_Initialize(pMemoryPool,m_config.iMemoryPoolSize, NULL, NULL, NULL); } // In case the old Sound Plugin and the new Fmod Plugin are both loaded inside vForge (required for converting scenes), // it can happen that the Fmod system is already initialized by the old Sound Plugin. Then Memory_Initialize() will be // called after Fmod system is already initialized, which is illegal. Therefore inside vForge failing to call Memory_Initialize() // in such a case is not treated as fatal error. Fmod will simply not use Vision De-/ Allocators or a preallocated memory block, // instead it will use it own de-/ allocators. This should be fine in case of converting scenes. Otherwise it should be anyway // avoided to load both plugins simultaneously. if (!Vision::Editor.IsInEditor()) FMOD_ERRORCHECK(result); else { if(result == FMOD_ERR_INITIALIZED) hkvLog::Warning("Failed to initialize Fmod memory system, this is most probably because the old Sound Plugin is loaded, too. This should only be done for converting scenes."); else FMOD_ERRORCHECK(result); } } FMOD_ERRORCHECK(FMOD::EventSystem_Create(&m_pEventSystem)); #ifdef VFMOD_SUPPORTS_NETWORK if (m_config.bUseNetworkSystem) { #ifdef _VISION_PS3 bool bNetworkInitialized = VInitializeNetworkPS3(); VASSERT(bNetworkInitialized == true); #endif FMOD_ERRORCHECK(FMOD::NetEventSystem_Init(m_pEventSystem)); } #endif FMOD_ERRORCHECK(m_pEventSystem->getSystemObject(&m_pSystem)); unsigned int iVersion = 0; FMOD_ERRORCHECK(m_pEventSystem->getVersion(&iVersion)); VASSERT(iVersion >= FMOD_VERSION) FMOD_ERRORCHECK(m_pSystem->setSoftwareFormat(m_config.iSampleRate, m_config.iFormat, 0,m_config.iMaxInputChannels, m_config.iResampleMethod)); // install file manager callbacks FMOD_ERRORCHECK(m_pSystem->setFileSystem(VisionFM_Open, VisionFM_Close, VisionFM_Read, VisionFM_Seek, NULL, NULL, 4096)); //listen to system events (eg. new device - headphones) FMOD_ERRORCHECK(m_pSystem->setCallback(VisionFM_System)); #ifdef _VISION_ANDROID // Increase DSP buffer size on Android { unsigned int iBlocksize = 0; int iNumblocks = 0; m_pSystem->getDSPBufferSize(&iBlocksize, &iNumblocks); m_pSystem->setDSPBufferSize(iBlocksize*2, iNumblocks); #ifdef HK_DEBUG_SLOW int iBufferSize = iNumblocks*iBlocksize; hkvLog::Warning("Fmod DSP buffer size increased from %i to %i, in order to get correct sound output", iBufferSize, iBufferSize*2); #endif } #endif VFmodSoundInit_e initResult = InitDevice(); switch(initResult) { case VFMODSOUNDINIT_NO_HARDWARE: hkvLog::Warning("No sound card present!"); break; case VFMODSOUNDINIT_NO_SPEAKERS: hkvLog::Warning("No speakers or headphones connected."); break; default: //case VSOUNDINIT_OK: hkvLog::Info("Sound successfully initialized."); break; } }