char* GetString(char *pFilePtr, char **ppString) { char *pEnd; pFilePtr = MFSkipWhite(pFilePtr); if(*pFilePtr != '\"') { MFDebug_Warn(3, "Error: GetString() expected a string."); *ppString = (char*)""; return pFilePtr; } pFilePtr++; pEnd = pFilePtr; while(*pEnd != '\"' && *pEnd != 0 && !MFIsNewline(*pEnd)) pEnd++; if(*pEnd != '\"') { MFDebug_Warn(3, "Error: GetString() encountered an unterminated String."); *ppString = (char*)""; return pFilePtr; } *ppString = (char*)MFStrN(pFilePtr, (int)(pEnd - pFilePtr)); pFilePtr = pEnd + 1; return pFilePtr; }
MF_API int MFFileSystem_MountFujiPath(const char *pMountpoint, const char *pFujiPath, int priority, uint32 flags) { const char *pColon = MFString_Chr(pFujiPath, ':'); if(!pColon) return -1; // not a fuji path. needs a volume name! MFMount *pMount = MFFileSystem_FindVolume(MFStrN(pFujiPath, pColon-pFujiPath)); if(!pMount) return -2; // volume not mounted // get the path // ++pColon; // const char *pNewPath = MFStr("%s%s", pColon, MFString_EndsWith(pColon, "/") ? "" : "/"); MFMount *pNew = (MFMount*)MFHeap_Alloc(sizeof(MFMount) + MFString_Length(pMountpoint) + 1); MFCopyMemory(pNew, pMount, sizeof(MFMount)); pNew->volumeInfo.pVolumeName = (const char*)&pNew[1]; MFString_Copy((char*)pNew->volumeInfo.pVolumeName, pMountpoint); pNew->volumeInfo.priority = priority; pNew->volumeInfo.flags = (pNew->volumeInfo.flags & ~MFMF_DontCacheTOC) | flags; return MFFileSystem_AddVolume(pNew); }
char* GetFloat(char *pFilePtr, float *pFloat) { char *pEnd, *pToken; bool negative = false; int dotFound = 1; pFilePtr = MFSkipWhite(pFilePtr); if(*pFilePtr == '-') { negative = true; pFilePtr++; } pEnd = pFilePtr; while(MFIsNumeric(*pEnd) || (*pEnd == '.' && dotFound--)) pEnd++; pToken = (char*)MFStrN(pFilePtr, (int)(pEnd-pFilePtr)); if(*pEnd == 'f') pEnd++; if(!MFIsWhite(*pEnd) && !MFIsNewline(*pEnd) && *pEnd != 0) { MFDebug_Warn(3, "Error: GetFloat() found non numeric character."); *pFloat = 0.0f; return pFilePtr; } pFilePtr = pEnd; *pFloat = (float)atof(pToken); if(negative) *pFloat = -*pFloat; return pFilePtr; }
char* GetInt(char *pFilePtr, int *pInt) { char *pEnd, *pToken; bool negative = false; pFilePtr = MFSkipWhite(pFilePtr); if(*pFilePtr == '-') { negative = true; pFilePtr++; } pEnd = pFilePtr; while(MFIsNumeric(*pEnd)) pEnd++; if(!MFIsWhite(*pEnd) && !MFIsNewline(*pEnd) && *pEnd != 0) { MFDebug_Warn(3, "Error: GetInt() found non numeric character."); *pInt = 0; return pFilePtr; } pToken = (char*)MFStrN(pFilePtr, (int)(pEnd - pFilePtr)); pFilePtr = pEnd; *pInt = atoi(pToken); if(negative) *pInt = -*pInt; return pFilePtr; }
const char* GetMaterialName(const char *pSkin, const char *pSubobjectName) { if(pSkin) { char *pTok = MFString_Chr(pSkin, ','); while(pTok) { char *pT = pTok-1; for(; pT > pSkin && pT[-1] != '\n'; --pT) { } // get subobject name char *pTokTemp = pTok - (uintp)pT; const char *pSubName = MFStrN(pT, (int&)pTokTemp); ++pTok; if(!MFString_CaseCmp(pSubName, pSubobjectName)) { for(pT = pTok; *pT != 0 && *pT != '\r' && *pT != '\n'; ++pT) { } // get texture name pTokTemp = pT - (uintp)pTok; char *pMaterialName = (char*)MFStrN(pTok, (int&)pTokTemp); for(pT = pMaterialName+MFString_Length(pMaterialName); pT > pMaterialName && pT[-1] != '/' && pT[-1] != '\\' && pT[-1] != '\n' && pT[-1] != '\r'; --pT) { } pT[MFString_Length(pT) - 4] = 0; return pT; } pTok = MFString_Chr(pTok, ','); } } return NULL; }
// open a file from the mounted filesystem stack MF_API MFFile* MFFileSystem_Open(const char *pFilename, uint32 openFlags) { MFDebug_Log(5, MFStr("Call: MFFileSystem_Open(\"%s\", 0x%x)", pFilename, openFlags)); GET_MODULE_DATA(MFFileSystemState); MFMount *pMount = pModuleData->pMountList; const char *pMountpoint = NULL; // search for a mountpoint size_t len = MFString_Length(pFilename); for(size_t a=0; a<len; a++) { if(pFilename[a] == ':') { pMountpoint = MFStrN(pFilename, a); pFilename += a+1; break; } if(pFilename[a] == '.') { // if we have found a dot, this cant be a mountpoint // (mountpoints may only be alphanumeric) break; } } // search for file through the mount list... while(pMount) { int onlyexclusive = pMount->volumeInfo.flags & MFMF_OnlyAllowExclusiveAccess; if((!pMountpoint && !onlyexclusive) || (pMountpoint && !MFString_CaseCmp(pMountpoint, pMount->volumeInfo.pVolumeName))) { // open the file from a mount MFFile *hFile = pModuleData->ppFileSystemList[pMount->volumeInfo.fileSystem]->callbacks.FSOpen(pMount, pFilename, openFlags); if(hFile) return hFile; } pMount = pMount->pNext; } if(!(openFlags & MFOF_TryOpen)) MFDebug_Warn(4, MFStr("MFFile_Open(\"%s\", 0x%x) - Failed to open file", pFilename, openFlags)); return NULL; }
const char *GetRestOfLine(const char *&pString) { while(MFIsWhite(*pString)) ++pString; const char *pEnd = pString; while(*pEnd && !MFIsNewline(*pEnd)) ++pEnd; const char *pRestOfLine = MFStrN(pString, (int)((uintp)pEnd - (uintp)pString)); pString = pEnd; return pRestOfLine; }
const char *GetNextIndex(const char *&pString) { if(*pString == '/') ++pString; const char *pEnd = pString; while(*pEnd && *pEnd != '/') ++pEnd; const char *pToken = MFStrN(pString, (int)((uintp)pEnd-(uintp)pString)); pString = pEnd; return pToken; }
const char *GetNextToken(const char *&pString) { while(MFIsWhite(*pString) || MFIsNewline(*pString)) ++pString; const char *pEnd = pString; while(*pEnd && !MFIsWhite(*pEnd) && !MFIsNewline(*pEnd)) ++pEnd; const char *pToken = MFStrN(pString, (int)((uintp)pEnd-(uintp)pString)); pString = pEnd; return pToken; }
char *ProcessBlock(char *pFilePtr, const char *pBlockName, char* (*BlockFunc)(char*, char*)) { char *pEnd; char *pToken; int braceCount = 0; bool inQuote = false; pFilePtr = MFSkipWhite(pFilePtr); if(*pFilePtr != '{') { MFDebug_Warn(3, MFStr("Error: Expected %s Block.", pBlockName)); return pFilePtr; } pFilePtr++; while(*pFilePtr != 0) { while(!(*pFilePtr == '*' && !braceCount && !inQuote) && *pFilePtr != 0) { if(*pFilePtr == '\"') inQuote = !inQuote; if(!inQuote) { if(*pFilePtr == '{') braceCount++; if(*pFilePtr == '}') braceCount--; } pFilePtr++; if(braceCount < 0) return pFilePtr; } pEnd = pFilePtr; while(!MFIsWhite(*pEnd) && *pEnd != 0) pEnd++; pToken = (char*)MFStrN(pFilePtr, (int)(pEnd - pFilePtr)); pFilePtr = pEnd; pFilePtr = BlockFunc(pFilePtr, pToken); } return pFilePtr; }
MFTOCEntry *MFFileSystem_GetTocEntry(const char *pFilename, MFTOCEntry *pEntry, int numEntries) { MFCALLSTACK; const char *pSearchString = pFilename; size_t nameLen = MFString_Length(pFilename); bool isDirectory = false; for(size_t a=0; a<nameLen; a++) { if(pFilename[a] == '/') { isDirectory = true; pSearchString = MFStrN(pFilename, a); pFilename += a+1; break; } } for(int a=0; a<numEntries; a++) { if(!MFString_CaseCmp(pSearchString, pEntry[a].pName)) { if(isDirectory) { if(pEntry[a].info.attributes & MFFA_Directory) { return MFFileSystem_GetTocEntry(pFilename, pEntry[a].pChildren, pEntry[a].numChildren); } } else { if(!(pEntry[a].info.attributes & MFFA_Directory)) { return &pEntry[a]; } } } } return NULL; }
void ParseMD3File(char *pBuffer, uint32 bufferSize, const char *pFilename, const char *pSkin) { int a,b; F3DMeshChunk *pMC = pModel->GetMeshChunk(); F3DSkeletonChunk *pSC = pModel->GetSkeletonChunk(); MD3Header *pHeader = (MD3Header*)pBuffer; // DBGASSERT(pHeader->ident == (('3'<<24) | ('P'<<16) | ('D'<<8) | 'I'), "Invalid MD3 header."); // DBGASSERT(pHeader->version == 15, "Invalid MD3 version."); // DBGASSERT(pHeader->offsetEnd == bufferSize, "Incorrect MD3 Size."); (char*&)pHeader->pTags += (uintp)pBuffer; (char*&)pHeader->pSurfaces += (uintp)pBuffer; // read materials if(pSkin) { char *pT, *pTok = MFString_Chr(pSkin, ','); while(pTok) { ++pTok; for(pT = pTok; *pT != 0 && *pT != '\r' && *pT != '\n'; ++pT) { } // get texture name char *pTT = pT - (uintp)pTok; char *pMaterialName = (char*)MFStrN(pTok, (int&)pTT); for(pT = pMaterialName+MFString_Length(pMaterialName); pT > pMaterialName && pT[-1] != '/' && pT[-1] != '\\' && pT[-1] != '\n' && pT[-1] != '\r'; --pT) { } pT[MFString_Length(pT) - 4] = 0; if(*pT && pModel->GetMaterialChunk()->GetMaterialIndexByName(pT) == -1) { F3DMaterial &mat = pModel->GetMaterialChunk()->materials.push(); mat.name = pT; mat.maps[0] = pT; } pTok = MFString_Chr(pTok, ','); } } // process bones for(a=0; a<pHeader->numTags; a++) { F3DBone &bone = pSC->bones.push(); bone.name = pHeader->pTags[a].tagName; bone.worldMatrix.SetXAxis3(MakeVector(pHeader->pTags[a].rotationMatrix[0][0], pHeader->pTags[a].rotationMatrix[0][1], pHeader->pTags[a].rotationMatrix[0][2])); bone.worldMatrix.SetYAxis3(MakeVector(pHeader->pTags[a].rotationMatrix[1][0], pHeader->pTags[a].rotationMatrix[1][1], pHeader->pTags[a].rotationMatrix[1][2])); bone.worldMatrix.SetZAxis3(MakeVector(pHeader->pTags[a].rotationMatrix[2][0], pHeader->pTags[a].rotationMatrix[2][1], pHeader->pTags[a].rotationMatrix[2][2])); bone.worldMatrix.SetTrans3(MakeVector(pHeader->pTags[a].origin[0], pHeader->pTags[a].origin[1], pHeader->pTags[a].origin[2])); } // process mesh for(a=0; a<pHeader->numSurfaces; a++) { // DBGASSERT(pHeader->pSurfaces->identity == (('3'<<24) | ('P'<<16) | ('D'<<8) | 'I'), "Invalid MD3 surface header."); (char*&)pHeader->pSurfaces->pTextureCoords += (uintp)pHeader->pSurfaces; (char*&)pHeader->pSurfaces->pTriangles += (uintp)pHeader->pSurfaces; (char*&)pHeader->pSurfaces->pVertices += (uintp)pHeader->pSurfaces; F3DSubObject &sub = pMC->subObjects.push(); F3DMaterialSubobject &matSub = sub.matSubobjects[0]; // read subobject name sub.name = pHeader->pSurfaces->surfaceName; // find material info matSub.materialIndex = pModel->GetMaterialChunk()->GetMaterialIndexByName(GetMaterialName(pSkin, sub.name.CStr())); // create one colour (white) sub.colours.resize(1); sub.colours[0] = MFVector::one; // read vertex data sub.uvs.resize(pHeader->pSurfaces->numVertices); sub.positions.resize(pHeader->pSurfaces->numVertices); sub.normals.resize(pHeader->pSurfaces->numVertices); for(b=0; b<pHeader->pSurfaces->numVertices; b++) { sub.uvs[b] = MakeVector(pHeader->pSurfaces->pTextureCoords[b].u, pHeader->pSurfaces->pTextureCoords[b].v); sub.normals[b] = MD3DecodeNormal(pHeader->pSurfaces->pVertices[b].encodedNormal); sub.positions[b] = MakeVector(pHeader->pSurfaces->pVertices[b].x, pHeader->pSurfaces->pVertices[b].y, pHeader->pSurfaces->pVertices[b].z); // scale vertex appropriately.. // sub.positions[b].Mul3(sub.positions[b], 1.0f/6400.0f); sub.positions[b].Mul3(sub.positions[b], 1.0f/64.0f); matSub.vertices[b].colour = 0; matSub.vertices[b].normal = b; matSub.vertices[b].uv[0] = b; matSub.vertices[b].position = b; } // read triangles matSub.triangles.resize(pHeader->pSurfaces->numTriangles); for(b=0; b<pHeader->pSurfaces->numTriangles; b++) { matSub.triangles[b].v[0] = pHeader->pSurfaces->pTriangles[b].indices[0]; matSub.triangles[b].v[1] = pHeader->pSurfaces->pTriangles[b].indices[2]; matSub.triangles[b].v[2] = pHeader->pSurfaces->pTriangles[b].indices[1]; } // skip to next surface (char*&)pHeader->pSurfaces += pHeader->pSurfaces->surfaceSize; } }
MF_API MFFind* MFFileSystem_FindFirst(const char *pSearchPattern, MFFindData *pFindData) { GET_MODULE_DATA(MFFileSystemState); const char *pMountpoint = NULL; MFFind *pFind = NULL; // search for a mountpoint const char *pColon = MFString_Chr(pSearchPattern, ':'); if(pColon) { pMountpoint = MFStrN(pSearchPattern, pColon - pSearchPattern); pSearchPattern = pColon + 1; } MFDebug_Assert(pMountpoint, "A volume name must be specified in the search pattern."); // find the volume MFMount *pMount = MFFileSystem_FindVolume(pMountpoint); if(!pMount) { MFDebug_Warn(2, MFStr("MFFileSystem_FindFirst: Volume '%s' in not mounted.", pMountpoint)); return NULL; } // search for file through the mount list... if(!(pMount->volumeInfo.flags & MFMF_DontCacheTOC)) { if(pMount->numFiles) { pFind = pModuleData->gFinds.Create(); pFind->pMount = pMount; MFString_Copy(pFind->searchPattern, pSearchPattern); size_t file = 0; for(; file < pFind->pMount->numFiles; ++file) { if(MFString_PatternMatch(pSearchPattern, pMount->pEntries[file].pName)) break; } if(file == pFind->pMount->numFiles) { pModuleData->gFinds.Destroy(pFind); pFind = NULL; } else { pFind->pFilesystemData = (void*)file; MFString_Copy(pFindData->pFilename, pMount->pEntries[file].pName); MFString_Copy(pFindData->pSystemPath, (char*)pMount->pEntries[file].pFilesysData); pFindData->info = pMount->pEntries[file].info; } } } else { pFind = pModuleData->gFinds.Create(); pFind->pMount = pMount; pFind->pFilesystemData = NULL; MFString_Copy(pFind->searchPattern, pSearchPattern); if(!pModuleData->ppFileSystemList[pMount->volumeInfo.fileSystem]->callbacks.FindFirst(pFind, pSearchPattern, pFindData)) { pModuleData->gFinds.Destroy(pFind); pFind = NULL; } } return pFind; }
void MFInputLinux_InitGamepad(int fd, LinuxGamepad *pGamepad) { #if !defined(__CYGWIN__) MFCALLSTACK; pGamepad->joyFD = fd; // get the pad details ioctl(fd, JSIOCGNAME(80), pGamepad->identifier); ioctl(fd, JSIOCGAXES, &pGamepad->numAxiis); ioctl(fd, JSIOCGBUTTONS, &pGamepad->numButtons); MFGamepadInfo *pGI = pGamepadMappingRegistry; // we need to find a better way to get the VID/PID from the gamepad... if(!MFString_CompareN(pGamepad->identifier, "HID", 3)) { // the device was unnamed, but it is a HID device, so we'll try and match the VID/PID char *pBase = pGamepad->identifier + 3, *pEnd; // get the VID string while(*pBase && !MFIsHex(*pBase)) ++pBase; pEnd = pBase + 1; while(MFIsHex(*pEnd)) ++pEnd; uint32 vid = MFHexToInt(MFStrN(pBase, pEnd - pBase)); // get the PID string pBase = pEnd; while(*pBase && !MFIsHex(*pBase)) ++pBase; pEnd = pBase + 1; while(MFIsHex(*pEnd)) ++pEnd; uint32 pid = MFHexToInt(MFStrN(pBase, pEnd - pBase)); // find a matching descriptor for(; pGI; pGI = pGI->pNext) { if(pGI->vendorID == vid && pGI->productID == pid) break; } } else { // the device is named, so we'll compare the name against our list and hope its the same as windows.. // since we dont have the VID/PID though, we cant verify its not a device with an aliased name. pGI = pGI->pNext; // skip the first one for(; pGI; pGI = pGI->pNext) { // since linux appends the manufacturer name, we'll just check for a match on the end of the string int len1 = MFString_Length(pGamepad->identifier); int len2 = MFString_Length(pGI->pIdentifier); if(!MFString_Compare(pGamepad->identifier + (len1 - len2), pGI->pIdentifier)) break; } } if(!pGI) { // use default descriptor pGamepad->pGamepadInfo = pGamepadMappingRegistry; MFDebug_Warn(1, MFStr("Found an unknown gamepad '%s', using default mappings.", pGamepad->identifier)); // offer to send email detailing controller info.. // MessageBox(NULL, "An unknown gamepad has been detected.\r\nWe strive to support every gamepad natively, please report your gamepad to Manu at [email protected].\r\nI will contact you and request a few details about the gamepad so it can be added to the registry for the next release.", "Unknown gamepad detected...", MB_OK); } else { // use applicable descriptor pGamepad->pGamepadInfo = pGI; MFDebug_Log(2, MFStr("Found gamepad: %s '%s'.", pGI->pName, pGI->pIdentifier)); } /* // fix up the linux mapping table const int *pButtonMap = pGamepad->pGamepadInfo->pButtonMap; int numAxiis = 0; for(int a=0; a<60; a++) { for(int b=0; b<GamepadType_Max; ++b) { if((pButtonMap[b] & AID_Analog) && MFGETAXIS(pButtonMap[b]) == a) { pGamepad->axisMap[a] = numAxiis; printf("%d = %d\n", a, numAxiis); ++numAxiis; } } } */ #endif }
void ParseASEFile(char *pFilePtr, F3DFile *_pModel) { pModel = _pModel; char *pEnd; char *pToken; int braceCount = 0; bool inQuote = false; while(*pFilePtr != 0) { while(!(*pFilePtr == '*' && !braceCount && !inQuote) && *pFilePtr != 0) { if(*pFilePtr == '\"') inQuote = !inQuote; if(!inQuote) { if(*pFilePtr == '{') braceCount++; if(*pFilePtr == '}') braceCount--; } pFilePtr++; } pEnd = pFilePtr; while(!MFIsWhite(*pEnd) && *pEnd != 0) pEnd++; pToken = (char*)MFStrN(pFilePtr, (int)(pEnd - pFilePtr)); pFilePtr = pEnd; if(!MFString_CaseCmp(pToken, "*3DSMAX_ASCIIEXPORT")) { int version = 0; pFilePtr = GetInt(pFilePtr, &version); MFDebug_Log(4, MFStr("Recognised .ASE file version: %d\n", version)); } else if(!MFString_CaseCmp(pToken, "*COMMENT")) { char *pComment; pFilePtr = GetString(pFilePtr, &pComment); MFDebug_Log(4, MFStr("Comment: %s", pComment)); } else if(!MFString_CaseCmp(pToken, "*SCENE")) { pFilePtr = ProcessBlock(pFilePtr, "*SCENE", ReadSceneChunk); } else if(!MFString_CaseCmp(pToken, "*MATERIAL_LIST")) { pFilePtr = ProcessBlock(pFilePtr, "*MATERIAL_LIST", ReadMaterialChunk); } else if(!MFString_CaseCmp(pToken, "*GEOMOBJECT")) { pFilePtr = ProcessBlock(pFilePtr, "*GEOMOBJECT", ReadGeomChunk); } else { MFDebug_Warn(3, MFStr("Unknown token: %s", pToken)); } } }