MFString MFString::SubStr(int offset, int count) const { if(!pData) return *this; // limit within the strings range int maxChars = (int)pData->bytes - offset; if(count < 0 || count > maxChars) count = maxChars; // bail if we don't need to do anything if(count == (int)pData->bytes) return *this; // allocate a new string MFString t; t.Reserve(count + 1); t.pData->bytes = count; // copy sub string MFString_CopyN(t.pData->pMemory, pData->pMemory + offset, count); t.pData->pMemory[count] = 0; return t; }
void ParseID3(MFAudioStream *pStream, MFID3 *pID3, int dataSize) { unsigned char *pData = pID3->pID3Data; while(pData - pID3->pID3Data <= dataSize) { if(pID3->major == 2) { // for the moment, to be safe... // MFDebug_Assert(false, "Make this work!!"); return; //int size = (int)pData[5] | ((int)pData[4] << 7) | ((int)pData[3] << 14); //pData += 6 + size; } if(pID3->major > 2) { ID3Chunk *pChunkHeader = (ID3Chunk*)pData; int size = GetSynchSafeInt(pData + 4); if(*pData == 'T') { //uint8 encoding = pData[10]; const char *pString = (const char*)pData + 11; switch(pChunkHeader->id) { case MFMAKEFOURCC('T', 'I', 'T', '2'): MFString_CopyN(pStream->streamInfo.songName, pString, MFMin(size-1, (int)sizeof(pStream->streamInfo.songName)-1)); break; case MFMAKEFOURCC('T', 'A', 'L', 'B'): MFString_CopyN(pStream->streamInfo.albumName, pString, MFMin(size-1, (int)sizeof(pStream->streamInfo.albumName)-1)); break; case MFMAKEFOURCC('T', 'P', 'E', '1'): case MFMAKEFOURCC('T', 'P', 'E', '2'): MFString_CopyN(pStream->streamInfo.artistName, pString, MFMin(size-1, (int)sizeof(pStream->streamInfo.artistName)-1)); break; case MFMAKEFOURCC('T', 'C', 'O', 'N'): MFString_CopyN(pStream->streamInfo.genre, pString, MFMin(size-1, (int)sizeof(pStream->streamInfo.genre)-1)); break; } } pData += 10 + size; } } }
MFString& MFString::Replace(int offset, int range, MFString string) { if(!pData) { pData = string.pData; if(pData) ++pData->refCount; return *this; } // limit within the strings range offset = MFMin(offset, (int)pData->bytes); int maxChars = (int)pData->bytes - offset; if(range > maxChars) range = maxChars; // bail if we don't need to do anything int strLen = string.NumBytes(); if(range == 0 && strLen == 0) return *this; int reposition = strLen - range; int newSize = (int)pData->bytes + reposition; // reserve memory for the new string Reserve(newSize); // move tail into place if(reposition) { int tailOffset = offset + range; char *pSrc = pData->pMemory + tailOffset; char *pDest = pSrc + reposition; if(pDest < pSrc) { while(*pSrc) *pDest++ = *pSrc++; *pDest = 0; } else { int len = (int)pData->bytes - tailOffset; while(len >= 0) { pDest[len] = pSrc[len]; --len; } } } // insert string if(strLen) MFString_CopyN(pData->pMemory + offset, string.pData->pMemory, strLen); pData->bytes = newSize; return *this; }
MF_API MFTexture* MFTexture_CreateRenderTarget(const char *pName, int width, int height, MFTextureFormat targetFormat) { MFTexture *pTexture = MFTexture_FindTexture(pName); if(!pTexture) { pTexture = &gTextureBank.Create(pName); if(targetFormat & TexFmt_SelectNicest) { targetFormat = TexFmt_A8R8G8B8; } pTexture->pTemplateData = (MFTextureTemplateData*)MFHeap_AllocAndZero(sizeof(MFTextureTemplateData) + sizeof(MFTextureSurfaceLevel)); pTexture->pTemplateData->pSurfaces = (MFTextureSurfaceLevel*)&pTexture->pTemplateData[1]; pTexture->pTemplateData->magicNumber = MFMAKEFOURCC('F','T','E','X'); pTexture->pTemplateData->imageFormat = targetFormat; pTexture->pTemplateData->mipLevels = 1; pTexture->pTemplateData->flags = TEX_RenderTarget; pTexture->pTemplateData->pSurfaces->width = width; pTexture->pTemplateData->pSurfaces->height = height; pTexture->pTemplateData->pSurfaces->bitsPerPixel = MFTexture_GetBitsPerPixel(pTexture->pTemplateData->imageFormat); pTexture->pTemplateData->pSurfaces->xBlocks = width; pTexture->pTemplateData->pSurfaces->yBlocks = height; pTexture->pTemplateData->pSurfaces->bitsPerBlock = pTexture->pTemplateData->pSurfaces->bitsPerPixel; pTexture->pTemplateData->pSurfaces->pImageData = NULL; pTexture->pTemplateData->pSurfaces->bufferLength = 0; pTexture->pTemplateData->pSurfaces->pPaletteEntries = NULL; pTexture->pTemplateData->pSurfaces->paletteBufferLength = 0; pTexture->refCount = 1; MFString_CopyN(pTexture->name, pName, sizeof(pTexture->name) - 1); pTexture->name[sizeof(pTexture->name) - 1] = 0; D3DFORMAT platformFormat = (D3DFORMAT)MFTexture_GetPlatformFormatID(targetFormat, MFDD_D3D9); HRESULT hr = pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, platformFormat, D3DPOOL_DEFAULT, (IDirect3DTexture9**)&pTexture->pInternalData, NULL); if(hr != D3D_OK) { MFHeap_Free(pTexture->pTemplateData); gTextureBank.DestroyItem(*pTexture); pTexture = NULL; } } else { pTexture->refCount++; } return pTexture; }
MF_API const char * MFStrN(const char *pSource, size_t n) { char *pBuffer = &gStringBuffer[gStringOffset]; MFString_CopyN(pBuffer, pSource, (int)n); pBuffer[n] = 0; gStringOffset += (uint32)n+1; if(gStringOffset >= sizeof(gStringBuffer) - 1024) gStringOffset = 0; return pBuffer; }
MFString::MFString(const char *pString, size_t maxChars) { if(!pString) { pData = NULL; } else { pData = MFStringData_Alloc(); pData->bytes = MFString_LengthN(pString, (int)maxChars); pData->pMemory = (char*)stringHeap.Alloc(pData->bytes + 1, &pData->allocated); MFString_CopyN(pData->pMemory, pString, (int)pData->bytes); pData->pMemory[pData->bytes] = 0; } }
void MFSound_InitModulePlatformSpecific(int *pSoundDataSize, int *pVoiceDataSize) { MFCALLSTACK; gDevices.Init(sizeof(AudioDevice), 8, 8); ALCint minor, major; alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &major); alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &minor); gAPIVersion = major*100 + minor; bool bCanEnumerate, bHasCapture; if(gAPIVersion >= 101) { bCanEnumerate = true; bHasCapture = true; } else { bCanEnumerate = alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") == AL_TRUE; bHasCapture = alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE") == AL_TRUE; } if(bCanEnumerate) { const char *pDevices = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); const char *pDefault = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); while(pDevices && *pDevices) { bool bIsDefault = !MFString_Compare(pDevices, pDefault); MFDebug_Log(2, MFStr("OpenAL: found output device '%s'%s", pDevices, bIsDefault ? " (default)" : "")); MFDevice *pDevice = MFDevice_AllocDevice(MFDT_AudioRender, &DestroyDevice); pDevice->pInternal = gDevices.AllocAndZero(); pDevice->state = MFDevState_Ready; AudioDevice &device = *(AudioDevice*)pDevice->pInternal; MFString_CopyN(pDevice->strings[MFDS_ID], pDevices, sizeof(pDevice->strings[MFDS_ID])-1); pDevice->strings[MFDS_ID][sizeof(pDevice->strings[MFDS_ID])-1] = 0; device.pDevice = NULL; if(bIsDefault) MFDevice_SetDefaultDevice(MFDT_AudioRender, MFDDT_All, pDevice); pDevices += MFString_Length(pDevices) + 1; } if(!MFDevice_GetDefaultDevice(MFDT_AudioRender, MFDDT_Default)) { MFDebug_Warn(2, "OpenAL: No default output device?"); // HACK: set it to the first one... MFDevice *pDevice = MFDevice_GetDeviceByIndex(MFDT_AudioRender, 0); MFDevice_SetDefaultDevice(MFDT_AudioRender, MFDDT_All, pDevice); } if(bHasCapture) { pDevices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); pDefault = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); while(pDevices && *pDevices) { bool bIsDefault = !MFString_Compare(pDevices, pDefault); MFDebug_Log(2, MFStr("OpenAL: found capture device '%s'%s", pDevices, bIsDefault ? " (default)" : "")); MFDevice *pDevice = MFDevice_AllocDevice(MFDT_AudioCapture, &DestroyDevice); pDevice->pInternal = gDevices.AllocAndZero(); pDevice->state = MFDevState_Ready; AudioDevice &device = *(AudioDevice*)pDevice->pInternal; MFString_CopyN(pDevice->strings[MFDS_ID], pDevices, sizeof(pDevice->strings[MFDS_ID])-1); pDevice->strings[MFDS_ID][sizeof(pDevice->strings[MFDS_ID])-1] = 0; device.pDevice = NULL; if(bIsDefault) MFDevice_SetDefaultDevice(MFDT_AudioCapture, MFDDT_All, pDevice); pDevices += MFString_Length(pDevices) + 1; } if(!MFDevice_GetDefaultDevice(MFDT_AudioCapture, MFDDT_Default)) MFDebug_Warn(2, "OpenAL: No default capture device?"); } } // create a context Context *pContext = CreateContext(MFDevice_GetDefaultDevice(MFDT_AudioRender, MFDDT_Default)); MakeCurrent(pContext); // we need to return the size of the internal structures so the platform independant // code can make the correct allocations.. *pSoundDataSize = sizeof(MFSoundDataInternal); *pVoiceDataSize = sizeof(MFVoiceDataInternal); }
void CreateVorbisStream(MFAudioStream *pStream, const char *pFilename) { MFCALLSTACK; MFVorbisStream *pVS = (MFVorbisStream*)MFHeap_Alloc(sizeof(MFVorbisStream)); pStream->pStreamData = pVS; // open vorbis file MFFile* hFile = MFFileSystem_Open(pFilename); if(!hFile) return; // attempt to cache the vorbis stream MFOpenDataCachedFile cachedOpen; cachedOpen.cbSize = sizeof(MFOpenDataCachedFile); cachedOpen.openFlags = MFOF_Read | MFOF_Binary | MFOF_Cached_CleanupBaseFile; cachedOpen.maxCacheSize = 256*1024; // 256k cache for vorbis stream should be heaps!! cachedOpen.pBaseFile = hFile; MFFile *pCachedFile = MFFile_Open(MFFileSystem_GetInternalFileSystemHandle(MFFSH_CachedFileSystem), &cachedOpen); if(pCachedFile) hFile = pCachedFile; // setup vorbis read callbacks ov_callbacks callbacks; callbacks.read_func = MFFile_StdRead; callbacks.seek_func = MFSound_VorbisSeek; callbacks.close_func = MFFile_StdClose; callbacks.tell_func = MFFile_StdTell; // open vorbis file if(ov_test_callbacks(hFile, &pVS->vorbisFile, NULL, 0, callbacks)) { MFDebug_Assert(false, "Not a vorbis file."); MFHeap_Free(pVS); return; } ov_test_open(&pVS->vorbisFile); // get vorbis file info pVS->pInfo = ov_info(&pVS->vorbisFile, -1); #if defined(VORBIS_TREMOR) // pStream->trackLength = (float)ov_pcm_total(&pVS->vorbisFile, -1) / (float)pVS->pInfo->rate; pStream->trackLength = 1000.0f; #else pStream->trackLength = (float)ov_time_total(&pVS->vorbisFile, -1); #endif // fill out the stream info pStream->streamInfo.sampleRate = pVS->pInfo->rate; pStream->streamInfo.channels = pVS->pInfo->channels; pStream->streamInfo.bitsPerSample = 16; pStream->streamInfo.bufferLength = pVS->pInfo->rate; // read the vorbis comment data pVS->pComment = ov_comment(&pVS->vorbisFile, -1); if(pVS->pComment) { const char *pTitle = vorbis_comment_query(pVS->pComment, "TITLE", 0); const char *pArtist = vorbis_comment_query(pVS->pComment, "ALBUM", 0); const char *pAlbum = vorbis_comment_query(pVS->pComment, "ARTIST", 0); const char *pGenre = vorbis_comment_query(pVS->pComment, "GENRE", 0); if(pTitle) MFString_CopyN(pStream->streamInfo.songName, pTitle, sizeof(pStream->streamInfo.songName)-1); if(pArtist) MFString_CopyN(pStream->streamInfo.artistName, pArtist, sizeof(pStream->streamInfo.artistName)-1); if(pAlbum) MFString_CopyN(pStream->streamInfo.albumName, pAlbum, sizeof(pStream->streamInfo.albumName)-1); if(pGenre) MFString_CopyN(pStream->streamInfo.genre, pGenre, sizeof(pStream->streamInfo.genre)-1); } }
int* ParseMaterialList(const char *pText, F3DSubObject &sub, int numFaces) { int *pMatFaces = NULL; const char *pMatList = FindSectionInScope(pText, "MeshMaterialList"); if(pMatList) { SkipToken(pMatList, "MeshMaterialList"); SkipToken(pMatList, "{"); int numMats = GetInt(pMatList, &pMatList); MFDebug_Assert(numMats < 16, "Exceeded maximum 16 materials per subobject..."); int numMatFaces = GetInt(pMatList, &pMatList); MFDebug_Assert(numMatFaces == numFaces, "Number of material faces does not match number of mesh faces"); pMatFaces = (int*)MFHeap_Alloc(sizeof(int)*numMatFaces); GetIntArray(pMatList, pMatFaces, numMatFaces, &pMatList); // process materials... const char *pToken = GetNextToken(pMatList, &pMatList); // MFDebug_Assert(!MFString_Compare(pToken, ";"), "Value is not terminated with a semicolon.\n"); if(!MFString_Compare(pToken, ";")) pToken = GetNextToken(pMatList, &pMatList); while(MFString_Compare(pToken, "}")) { if(!MFString_Compare(pToken, "Material")) { const char *pMatName = GetNextToken(pMatList, &pToken); if(MFString_Compare(pMatName, "{")) pMatList = pToken; else pMatName = "Unknown Material"; int matID = pModel->GetMaterialChunk()->GetMaterialIndexByName(pMatName); F3DMaterialSubobject &matSub = sub.matSubobjects.push(); if(matID != -1) { matSub.materialIndex = matID; SkipSection(pMatList); } else { matSub.materialIndex = pModel->GetMaterialChunk()->materials.size(); F3DMaterial &mat = pModel->GetMaterialChunk()->materials.push(); MFString_CopyN(mat.name, pMatName, 64); SkipToken(pMatList, "{"); mat.diffuse.x = GetFloat(pMatList, &pMatList); mat.diffuse.y = GetFloat(pMatList, &pMatList); mat.diffuse.z = GetFloat(pMatList, &pMatList); mat.diffuse.w = GetFloat(pMatList, &pMatList); SkipToken(pMatList, ";"); mat.specularLevel = GetFloat(pMatList, &pMatList); mat.specular.x = GetFloat(pMatList, &pMatList); mat.specular.y = GetFloat(pMatList, &pMatList); mat.specular.z = GetFloat(pMatList, &pMatList); mat.diffuse.w = 0.0f; SkipToken(pMatList, ";"); mat.emissive.x = GetFloat(pMatList, &pMatList); mat.emissive.y = GetFloat(pMatList, &pMatList); mat.emissive.z = GetFloat(pMatList, &pMatList); mat.emissive.w = 0.0f; SkipToken(pMatList, ";"); // any textures... pToken = GetNextToken(pMatList, &pMatList); while(MFString_Compare(pToken, "}")) { if(!MFString_Compare(pToken, "TextureFilename")) { SkipToken(pMatList, "{"); MFString_Copy(mat.maps[0], GetString(pMatList, &pMatList)); SkipToken(pMatList, "}"); } else { MFDebug_Warn(4, MFStr("Unknown token '%s'\n", pToken)); } pToken = GetNextToken(pMatList, &pMatList); } } } else if(!MFString_Compare(pToken, "{")) { // read material name const char *pMatName = GetNextToken(pMatList, &pMatList); int matID = pModel->GetMaterialChunk()->GetMaterialIndexByName(pMatName); F3DMaterialSubobject &matSub = sub.matSubobjects.push(); if(matID != -1) { matSub.materialIndex = matID; } else { matSub.materialIndex = pModel->GetMaterialChunk()->materials.size(); F3DMaterial &mat = pModel->GetMaterialChunk()->materials.push(); MFString_CopyN(mat.name, pMatName, 64); } pToken = GetNextToken(pMatList, &pMatList); MFDebug_Assert(!MFString_Compare(pToken, "}"), "Scope not closed.\n"); } else { MFDebug_Warn(4, MFStr("Unknown token '%s'\n", pToken)); } pToken = GetNextToken(pMatList, &pMatList); } } return pMatFaces; }