MF_API MFRenderer* MFRenderer_Create(MFRenderLayerDescription *pLayers, int numLayers, MFStateBlock *pGlobal, MFStateBlock *pOverride) { int debugLayer = numLayers; #if !defined(MF_RETAIL) // add a layer for the system/debug stuff numLayers += 1; #endif MFRenderer *pRenderer = (MFRenderer*)MFHeap_AllocAndZero(sizeof(MFRenderer) + sizeof(MFRenderLayer)*numLayers); pRenderer->pLayers = (MFRenderLayer*)&pRenderer[1]; pRenderer->numLayers = numLayers; pRenderer->pGlobal = pGlobal; pRenderer->pOverride = pOverride; MFRenderTarget *pRT = MFRenderer_GetDeviceRenderTarget(); for(int a=0; a<numLayers; ++a) { pRenderer->pLayers[a].pName = a < debugLayer ? pLayers[a].pName : "Debug"; pRenderer->pLayers[a].pRenderTarget = pRT; MFResource_AddRef(pRT); } #if !defined(MF_RETAIL) MFRenderLayer_SetLayerSortMode(&pRenderer->pLayers[debugLayer], MFRL_SM_None); #endif return pRenderer; }
MF_API MFMaterial* MFMaterial_Create(const char *pName) { MFCALLSTACK; MFMaterial *pMat = MFMaterial_Find(pName); if(!pMat) { pMat = (MFMaterial*)MFHeap_AllocAndZero(sizeof(MFMaterial) + MFString_Length(pName) + 1); pName = MFString_Copy((char*)&pMat[1], pName); MFResource_AddResource(pMat, MFRT_Material, MFUtil_HashString(pName) ^ 0x0a7e01a1, pName); // TODO: how to determine size? pMat->pMaterialState = MFStateBlock_Create(256); pMat->bStateDirty = true; MaterialDefinition *pDef = pDefinitionRegistry; while(pDef) { MFIniLine *pLine = pDef->pIni->GetFirstLine()->FindEntry("section",pName); if (pLine) { MaterialInternal_InitialiseFromDefinition(pDef->pIni, pMat, pName); break; } pDef = pDef->pNextDefinition; } if(!pDef) { // assign material type pMat->pType = MaterialInternal_GetMaterialType("Standard"); pMat->pInstanceData = MFHeap_AllocAndZero(pMat->pType->instanceDataSize); pMat->pType->materialCallbacks.pCreateInstance(pMat); // set diffuse map parameter MFMaterial_SetParameterS(pMat, MFMatStandard_Texture, MFMatStandard_Tex_DifuseMap, pName); } } return pMat; }
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 MFWindow *MFWindow_BindExisting(void *pWindowHandle) { MFWindow_PC *pWindow = (MFWindow_PC*)MFHeap_AllocAndZero(sizeof(MFWindow_PC)); pWindow->hWnd = (HWND)pWindowHandle; MFDebug_Assert(false, "TODO!"); // TODO: fill out params from window data... // pWindow->params.x = SetWindowLongPtr(pWindow->hWnd, GWLP_USERDATA, (LONG_PTR)pWindow); return pWindow; }
MF_API MFWindow *MFWindow_Create(MFWindowParams *pParams) { MFWindow_PC *pWindow = (MFWindow_PC*)MFHeap_AllocAndZero(sizeof(MFWindow_PC)); pWindow->params = *pParams; // create window RECT rect; rect.left = 0; rect.right = (long)pParams->width; rect.top = 0; rect.bottom = (long)pParams->height; DWORD dwStyle = WS_POPUP; DWORD dwExStyle = WS_EX_APPWINDOW; if(!pParams->bFullscreen) { if(pParams->flags & MFWF_WindowFrame) { dwExStyle |= WS_EX_WINDOWEDGE; dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; if(pParams->flags & MFWF_CanResize) dwStyle |= WS_THICKFRAME; } if(pParams->flags & MFWF_AlwaysOnTop) dwExStyle |= WS_EX_TOPMOST; AdjustWindowRectEx(&rect, dwStyle, FALSE, dwExStyle); rect.right += -rect.left + (long)pParams->x; rect.left = (long)pParams->x; rect.bottom += -rect.top + (long)pParams->y; rect.top = (long)pParams->y; } pWindow->hWnd = CreateWindowEx(dwExStyle, "FujiWin", gDefaults.display.pWindowTitle, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, NULL, NULL, hInstance, NULL); if(!pWindow->hWnd) { MessageBox(NULL,"Failed To Create Window.","Error!",MB_OK|MB_ICONERROR); MFHeap_Free(pWindow); return NULL; } SetWindowLongPtr(pWindow->hWnd, GWLP_USERDATA, (LONG_PTR)pWindow); ShowWindow(pWindow->hWnd, SW_SHOW); SetForegroundWindow(pWindow->hWnd); SetFocus(pWindow->hWnd); return pWindow; }
MF_API MFIndexBuffer *MFVertex_CreateIndexBuffer(int numIndices, uint16 *pIndexBufferMemory, const char *pName) { int nameLen = pName ? MFString_Length(pName) + 1 : 0; MFIndexBuffer *pIB = (MFIndexBuffer*)MFHeap_AllocAndZero(sizeof(MFIndexBuffer) + nameLen); if(pName) pName = MFString_Copy((char*)&pIB[1], pName); pIB->numIndices = numIndices; if(!MFVertex_CreateIndexBufferPlatformSpecific(pIB, pIndexBufferMemory)) { MFHeap_Free(pIB); return NULL; } MFResource_AddResource(pIB, MFRT_IndexBuffer, (uint32)(MFUtil_HashPointer(pIB) & 0xFFFFFFFF), pName); return pIB; }
// mount a filesystem MF_API int MFFileSystem_Mount(MFFileSystemHandle fileSystem, MFMountData *pMountData) { GET_MODULE_DATA(MFFileSystemState); MFMount *pMount; pMount = (MFMount*)MFHeap_AllocAndZero(sizeof(MFMount) + MFString_Length(pMountData->pMountpoint) + 1); pMount->volumeInfo.flags = pMountData->flags; pMount->volumeInfo.fileSystem = fileSystem; pMount->volumeInfo.priority = pMountData->priority; pMount->volumeInfo.pVolumeName = (const char*)&pMount[1]; MFString_Copy((char*)&pMount[1], pMountData->pMountpoint); // call the mount callback int result = pModuleData->ppFileSystemList[fileSystem]->callbacks.FSMount(pMount, pMountData); if(result < 0) { MFHeap_Free(pMount); return -1; } return MFFileSystem_AddVolume(pMount); }
void MaterialInternal_InitialiseFromDefinition(MFIni *pDefIni, MFMaterial *pMat, const char *pDefinition) { MFCALLSTACK; MFIniLine *pLine = pDefIni->GetFirstLine()->FindEntry("section", pDefinition); if(pLine) { pLine = pLine->Sub(); if(pLine && pLine->IsString(0, "type")) { pMat->pType = MaterialInternal_GetMaterialType(pLine->GetString(1)); if(!pMat->pType) pMat->pType = MaterialInternal_GetMaterialType("Standard"); pLine = pLine->Next(); } else { pMat->pType = MaterialInternal_GetMaterialType("Standard"); } pMat->pInstanceData = MFHeap_AllocAndZero(pMat->pType->instanceDataSize); if(pMat->pType->materialCallbacks.pCreateInstance) pMat->pType->materialCallbacks.pCreateInstance(pMat); while(pLine) { if(pLine->IsString(0,"type")) { MFDebug_Warn(2, MFStr("'type' MUST be the first parameter in a material definition... Ignored, Using type '%s'.", pMat->pType->pTypeName)); } else if(pLine->IsString(0,"alias")) { MFDebug_Warn(2, "'alias' MUST be the first parameter in a material definition... Ignored."); MFDebug_Assert(false, "Fix Me!!!"); // const char *pAlias = pLine->GetString(1); // MaterialInternal_InitialiseFromDefinition(pDefIni, pMat, pAlias); } else { const char *pParam = pLine->GetString(0); const MFMaterialParameterInfo *pInfo = MFMaterial_GetParameterInfoFromName(pMat, pParam); int lineArg = 1; int param = pInfo->parameterIndex; int argIndex = 0; switch(pInfo->argIndex.type) { case MFParamType_Int: argIndex = pLine->GetInt(lineArg++); break; case MFParamType_Enum: argIndex = pLine->GetEnum(lineArg++, pInfo->argIndex.pEnumKeys); break; default: argIndex = pInfo->argIndex.defaultValue; break; } switch(pInfo->argIndexHigh.type) { case MFParamType_Int: argIndex |= pLine->GetInt(lineArg++) << 16; break; case MFParamType_Enum: argIndex |= pLine->GetEnum(lineArg++, pInfo->argIndexHigh.pEnumKeys) << 16; break; default: argIndex |= pInfo->argIndexHigh.defaultValue << 16; break; } if(pInfo->numValues == 1) { switch(pInfo->pValues[0].type) { case MFParamType_Constant: { MFMaterial_SetParameterI(pMat, param, argIndex, pInfo->pValues[0].defaultValue); break; } case MFParamType_String: { const char *pString = pLine->GetString(lineArg); MFMaterial_SetParameterS(pMat, param, argIndex, pString); break; } case MFParamType_Float: { float value = pLine->GetFloat(lineArg); MFMaterial_SetParameterF(pMat, param, argIndex, value); break; } case MFParamType_Int: { int value = pLine->GetStringCount() > lineArg ? pLine->GetInt(lineArg) : pInfo->pValues[0].defaultValue; MFMaterial_SetParameterI(pMat, param, argIndex, value); break; } case MFParamType_Enum: { int value; if(pLine->GetStringCount() > lineArg) value = pLine->GetEnum(lineArg, pInfo->pValues[0].pEnumKeys); else value = pInfo->pValues[0].defaultValue; MFMaterial_SetParameterI(pMat, param, argIndex, value); break; } case MFParamType_Bool: { bool value = pLine->GetStringCount() > lineArg ? pLine->GetBool(lineArg) : !!pInfo->pValues[0].defaultValue; MFMaterial_SetParameterI(pMat, param, argIndex, value ? 1 : 0); break; } case MFParamType_Colour: { MFVector vector = pLine->GetColour(lineArg); MFMaterial_SetParameterV(pMat, param, argIndex, vector); break; } case MFParamType_Vector3: { MFVector vector = pLine->GetVector3(lineArg); MFMaterial_SetParameterV(pMat, param, argIndex, vector); break; } case MFParamType_Vector4: { MFVector vector = pLine->GetVector4(lineArg); MFMaterial_SetParameterV(pMat, param, argIndex, vector); break; } case MFParamType_Matrix: { MFDebug_Assert(false, "Cant read a matrix from an ini file... yet..."); break; } default: MFDebug_Assert(false, "Unknown parameter type.."); } } else if(pInfo->numValues > 1) { // produce a struct representing the args MFALIGN_BEGIN(16) char argBuffer[256] MFALIGN_END(16); int offset = 0; for(int a=0; a<pInfo->numValues; a++) { switch(pInfo->pValues[a].type) { case MFParamType_Constant: { offset = MFALIGN(offset, sizeof(int)); (int&)argBuffer[offset] = pInfo->pValues[a].defaultValue; offset += sizeof(int); break; } case MFParamType_String: { offset = MFALIGN(offset, sizeof(const char *)); (const char *&)argBuffer[offset] = pLine->GetString(lineArg++); offset += sizeof(const char *); break; } case MFParamType_Float: { offset = MFALIGN(offset, sizeof(float)); (float&)argBuffer[offset] = pLine->GetFloat(lineArg++); offset += sizeof(float); break; } case MFParamType_Int: { offset = MFALIGN(offset, sizeof(int)); (int&)argBuffer[offset] = pLine->GetInt(lineArg++); offset += sizeof(int); break; } case MFParamType_Enum: { offset = MFALIGN(offset, sizeof(int)); (int&)argBuffer[offset] = pLine->GetEnum(lineArg++, pInfo->pValues[a].pEnumKeys); offset += sizeof(int); break; } case MFParamType_Bool: { offset = MFALIGN(offset, sizeof(bool)); (bool&)argBuffer[offset] = pLine->GetBool(lineArg++); offset += sizeof(bool); break; } case MFParamType_Colour: case MFParamType_Vector3: case MFParamType_Vector4: case MFParamType_Matrix: { MFDebug_Assert(false, "Cant read type into structure... yet..."); break; } default: MFDebug_Assert(false, "Unknown parameter type.."); } } MFMaterial_SetParameter(pMat, param, argIndex, (uintp)argBuffer); } } pLine = pLine->Next(); } }
MF_API MFVertexDeclaration *MFVertex_CreateVertexDeclaration(const MFVertexElement *pElementArray, int elementCount) { // assign the auto format components before calculating the hash MFVertexElement elements[16]; MFCopyMemory(elements, pElementArray, sizeof(MFVertexElement)*elementCount); for(int e=0; e<elementCount; ++e) { if(pElementArray[e].format == MFVDF_Auto) elements[e].format = MFVertex_ChoooseVertexDataTypePlatformSpecific(pElementArray[e].type, pElementArray[e].componentCount); } uint32 hash = MFUtil_HashBuffer(elements, sizeof(MFVertexElement)*elementCount); MFVertexDeclaration *pDecl = (MFVertexDeclaration*)MFResource_Find(hash); if(!pDecl) { pDecl = (MFVertexDeclaration*)MFHeap_AllocAndZero(sizeof(MFVertexDeclaration) + (sizeof(MFVertexElement) + sizeof(MFVertexElementData))*elementCount); pDecl->numElements = elementCount; pDecl->pElements = (MFVertexElement*)&pDecl[1]; pDecl->pElementData = (MFVertexElementData*)&pDecl->pElements[elementCount]; MFCopyMemory(pDecl->pElements, elements, sizeof(MFVertexElement)*elementCount); int streamOffsets[16]; MFZeroMemory(streamOffsets, sizeof(streamOffsets)); // set the element data and calculate the strides for(int e=0; e<elementCount; ++e) { pDecl->pElementData[e].offset = streamOffsets[elements[e].stream]; pDecl->pElementData[e].stride = 0; streamOffsets[elements[e].stream] += gVertexDataStride[elements[e].format]; pDecl->streamsUsed |= MFBIT(elements[e].stream); } // set the strides for each component for(int e=0; e<elementCount; ++e) pDecl->pElementData[e].stride = streamOffsets[elements[e].stream]; if(!MFVertex_CreateVertexDeclarationPlatformSpecific(pDecl)) { MFHeap_Free(pDecl); return NULL; } MFResource_AddResource(pDecl, MFRT_VertexDecl, hash); if(pDecl->streamsUsed != 1) { // create the stream declarations... MFVertexElement streamElements[64]; for(int s=0; s<16; ++s) { if(!(pDecl->streamsUsed & (1 << s))) continue; int numStreamElements = 0; for(int e=0; e<elementCount; ++e) { if(elements[e].stream == s) { streamElements[numStreamElements] = elements[e]; streamElements[numStreamElements].stream = 0; ++numStreamElements; } } if(numStreamElements) pDecl->pStreamDecl[s] = MFVertex_CreateVertexDeclaration(streamElements, numStreamElements); } } } return pDecl; }
void MFMidi_InitModulePlatformSpecific() { UINT numInputDevices = midiInGetNumDevs(); for (UINT i = 0; i < numInputDevices; ++i) { MIDIINCAPS caps; MMRESULT r = midiInGetDevCaps(i, &caps, sizeof(caps)); if (r != MMSYSERR_NOERROR) { wchar_t errorBuffer[256]; midiOutGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to query midi input device: %s", MFString_WCharAsUTF8(errorBuffer))); continue; } MFDevice *pDevice = MFDevice_AllocDevice(MFDT_MidiInput, &DestroyInputDevice); pDevice->pInternal = MFHeap_AllocAndZero(sizeof(MFMidiPC_MidiInputDevice)); pDevice->state = MFDevState_Available; MFMidiPC_MidiOutputDevice *pDev = (MFMidiPC_MidiOutputDevice*)pDevice->pInternal; pDev->mid = caps.wMid; pDev->pid = caps.wPid; MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_ID], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_DeviceName], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_Description], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_InterfaceName], caps.szPname); // MFDS_Manufacturer MFDebug_Log(0, MFStr("Found midi input device: %s (%04X:%04X) - state: %d", pDevice->strings[MFDS_ID], caps.wMid, caps.wPid, pDevice->state)); } UINT numOutputDevices = midiOutGetNumDevs(); for (UINT i = 0; i < numOutputDevices; ++i) { MIDIOUTCAPS caps; MMRESULT r = midiOutGetDevCaps(i, &caps, sizeof(caps)); if (r != MMSYSERR_NOERROR) { wchar_t errorBuffer[256]; midiOutGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to query midi output device: %s", MFString_WCharAsUTF8(errorBuffer))); continue; } MFDevice *pDevice = MFDevice_AllocDevice(MFDT_MidiOutput, &DestroyOutputDevice); pDevice->pInternal = MFHeap_AllocAndZero(sizeof(MFMidiPC_MidiOutputDevice)); pDevice->state = MFDevState_Available; MFMidiPC_MidiOutputDevice *pDev = (MFMidiPC_MidiOutputDevice*)pDevice->pInternal; pDev->mid = caps.wMid; pDev->pid = caps.wPid; MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_ID], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_DeviceName], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_Description], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_InterfaceName], caps.szPname); // MFDS_Manufacturer MFDebug_Log(0, MFStr("Found midi output device: %s (%04X:%04X) - state: %d", pDevice->strings[MFDS_ID], caps.wMid, caps.wPid, pDevice->state)); } }
void CreateWAVStream(MFAudioStream *pStream, const char *pFilename) { MFCALLSTACK; // open wav 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 wav stream should be heaps!! cachedOpen.pBaseFile = hFile; MFFile *pCachedFile = MFFile_Open(MFFileSystem_GetInternalFileSystemHandle(MFFSH_CachedFileSystem), &cachedOpen); if(pCachedFile) hFile = pCachedFile; RIFFHeader header; MFFile_Read(hFile, &header, sizeof(header)); if(header.RIFF != MFMAKEFOURCC('R', 'I', 'F', 'F') || header.WAVE != MFMAKEFOURCC('W', 'A', 'V', 'E')) return; // not a .wav file... // if everything's good, and it appears to be a valid wav file MFWAVStream *pWS = (MFWAVStream*)MFHeap_AllocAndZero(sizeof(MFWAVStream)); pStream->pStreamData = pWS; pWS->pStream = hFile; size_t read; size_t fptr = sizeof(header); do { MFFile_Seek(hFile, fptr, MFSeek_Begin); WAVChunk dataChunk; MFZeroMemory(&dataChunk, sizeof(dataChunk)); read = MFFile_Read(hFile, &dataChunk, sizeof(dataChunk)); fptr += sizeof(dataChunk) + dataChunk.size; if(dataChunk.id == MFMAKEFOURCC('f', 'm', 't', ' ')) { read = MFFile_Read(hFile, &pWS->format, dataChunk.size); if(pWS->format.cbSize) read = (size_t)MFFile_Seek(hFile, pWS->format.cbSize, MFSeek_Current); } else if(dataChunk.id == MFMAKEFOURCC('d', 'a', 't', 'a')) { pWS->dataOffset = (size_t)MFFile_Tell(hFile); pWS->dataSize = dataChunk.size; } } while(read); // return to the start of the audio data MFFile_Seek(pWS->pStream, (int)pWS->dataOffset, MFSeek_Begin); // calculate the track length pWS->sampleSize = (pWS->format.nChannels * pWS->format.wBitsPerSample) >> 3; pStream->trackLength = (float)(pWS->dataSize / pWS->sampleSize) / (float)pWS->format.nSamplesPerSec; // fill out the stream info pStream->streamInfo.sampleRate = pWS->format.nSamplesPerSec; pStream->streamInfo.channels = pWS->format.nChannels; pStream->streamInfo.bitsPerSample = pWS->format.wBitsPerSample; pStream->streamInfo.bufferLength = pWS->format.nSamplesPerSec; }