uint8 CBMPFormat::detectBMPVersion(void) { CDataReader *pDataReader = CDataReader::getInstance(); uint8 uiBMPVersion = 0; pDataReader->setPeek(true); string strHeader = pDataReader->readString(2); if (strHeader.c_str()[0] == '\0' && strHeader.c_str()[1] == '\0') { // BMP version 1.x uiBMPVersion = 1; } else if (strHeader.c_str()[0] == 'B' && strHeader.c_str()[1] == 'M') { // BMP version 2.x, 3.x or 4.x pDataReader->setSeek(12); switch (pDataReader->readUint32()) { case 12: // BMP version 2.x uiBMPVersion = 2; break; case 40: // BMP version 3.x uiBMPVersion = 3; break; case 108: // BMP version 4.x uiBMPVersion = 4; } } pDataReader->setPeek(false); pDataReader->setSeek(0); return uiBMPVersion; }
uint32 CCOLEntry::calculateShadowMeshVertexCount(void) { CDataReader *pDataReader = CDataReader::getInstance(); eCOLVersion eCOLVersionValue = getCOLVersion() == nullptr ? COL_UNKNOWN : getCOLVersion()->getVersionId(); //CDebugger::log("getHeaderStartOffset(): " + CStringUtility::toString(getHeaderStartOffset())); //CDebugger::log("getShadowMeshFacesOffset(): " + CStringUtility::toString(getShadowMeshFacesOffset())); //CDebugger::log("getShadowMeshFaceCount(): " + CStringUtility::toString(getShadowMeshFaceCount())); //CDebugger::log("getCOLVersion(): " + CStringUtility::toString(getCOLVersion())); pDataReader->setSeek(getHeaderStartOffset() + 4 + getShadowMeshFacesOffset()); string strShadowMeshFacesData = pDataReader->readString(getShadowMeshFaceCount() * (eCOLVersionValue == 1 ? 16 : 8)); // 12 or 6 = sizeof(TVertex) //CDebugger::log("part 2 -- strShadowMeshFacesData.length(): " + CStringUtility::toString(strShadowMeshFacesData.length())); uint32 uiSeek = 0; uint32 uiHighestVertexIndex = 0; if (getShadowMeshFaceCount() == 0) { return 0; } if (eCOLVersionValue == COL_1) { // COL 1 for (uint32 i = 0, j = getShadowMeshFaceCount(); i < j; i++) { for (uint8 i2 = 0; i2 < 3; i2++) { uint32 uiVertexIndex = CStringUtility::unpackUint32(strShadowMeshFacesData.substr(uiSeek, 4), false); if (uiVertexIndex > uiHighestVertexIndex) { uiHighestVertexIndex = uiVertexIndex; } uiSeek += 4; // 4 is sizeof(uint32) } uiSeek += 4; // 4 is sizeof(TSurface) } } else { // COL 2, 3 & 4 for (uint32 i = 0, j = getShadowMeshFaceCount(); i < j; i++) { for (uint8 i2 = 0; i2 < 3; i2++) { uint32 uiVertexIndex = CStringUtility::unpackUint16(strShadowMeshFacesData.substr(uiSeek, 2), false); if (uiVertexIndex > uiHighestVertexIndex) { uiHighestVertexIndex = uiVertexIndex; } uiSeek += 2; // 2 is sizeof(uint16) } uiSeek += 2; // 1 byte for material, 1 byte for light } } return uiHighestVertexIndex + 1; }
eDATPathFormat CDATPathFormat::detectPathsFormat(void) { CDataReader *pDataReader = CDataReader::getInstance(); eDATPathFormat eDATPathFormatValue; uint32 uiPreviousSeek = pDataReader->getSeek(); pDataReader->setPeek(true); if (CStringUtility::unpackUint32(pDataReader->readString(4), false) == 0xFFFFFFFF && pDataReader->readString(4) == "FM92") { eDATPathFormatValue = DAT_PATH_FASTMAN92; } else { eDATPathFormatValue = DAT_PATH_DEFAULT; } pDataReader->setSeek(uiPreviousSeek); pDataReader->setPeek(false); return eDATPathFormatValue; }
void CCOLEntry::unserialize(void) { CDataReader *pDataReader = CDataReader::getInstance(); uint32 uiHeaderStartPosition = pDataReader->getSeek(); setHeaderStartOffset(uiHeaderStartPosition); // COL 1 2 3 & 4 header setCOLVersion(CCOLManager::getCOLVersionFromFourCC(pDataReader->readString(4))); if (getCOLVersion() == nullptr) { throw EXCEPTION_UNKNOWN_FORMAT; } uint32 uiEntrySize = pDataReader->readUint32(); // entry size from after this value setModelName(CStringUtility::rtrimFromLeft(pDataReader->readString(22))); setModelId(pDataReader->readUint16()); parseBoundingObjects(); eCOLVersion eCOLVersionValue = getCOLVersion() == nullptr ? COL_UNKNOWN : getCOLVersion()->getVersionId(); if (eCOLVersionValue == COL_1) { // COL 1 header & body // read collision sphere count setCollisionSphereCount(pDataReader->readUint32()); // read collision spheres array setCollisionSpheresOffset(pDataReader->getSeek()); parseCollisionSpheres(); // read unknown1 count setUnknown1(pDataReader->readUint32()); // number of unknown data (0) // read collision box count setCollisionBoxCount(pDataReader->readUint32()); // read collision boxes array setCollisionBoxesOffset(pDataReader->getSeek()); parseCollisionBoxes(); // read collision mesh vertex count setCollisionMeshVertexCount(pDataReader->readUint32()); // read collision mesh vertices array setCollisionMeshVerticesOffset(pDataReader->getSeek()); parseCollisionMeshVertices(); // read collision mesh face count setCollisionMeshFaceCount(pDataReader->readUint32()); // read collision mesh faces array setCollisionMeshFacesOffset(pDataReader->getSeek()); parseCollisionMeshFaces(); } else { // COL 2 3 & 4 header setCollisionSphereCount(pDataReader->readUint16()); setCollisionBoxCount(pDataReader->readUint16()); setCollisionMeshFaceCount(pDataReader->readUint16()); setCollisionConeCount(pDataReader->readUint8()); uint8 ucPadding1 = pDataReader->readUint8(); // 1 byte padding setFlags(pDataReader->readUint32()); setCollisionSpheresOffset(pDataReader->readUint32()); setCollisionBoxesOffset(pDataReader->readUint32()); setCollisionConesOffset(pDataReader->readUint32()); setCollisionMeshVerticesOffset(pDataReader->readUint32()); setCollisionMeshFacesOffset(pDataReader->readUint32()); setTrianglePlanesOffset(pDataReader->readUint32()); if ((getFlags() & 8) != 0) { // entry does have face groups uint32 uiCurrentSeek = pDataReader->getSeek(); // read face group count uint32 uiFaceGroupCountSeek = (getHeaderStartOffset() + 4 + getCollisionMeshFacesOffset()) - 4; pDataReader->setSeek(uiFaceGroupCountSeek); setCollisionMeshFaceGroupCount(pDataReader->readUint32()); // read face groups offset setCollisionMeshFaceGroupsOffset((getCollisionMeshFacesOffset() - 4) - (28 * getCollisionMeshFaceGroupCount())); // 28 = sizeof(TFaceGroup) // restore parser seek position pDataReader->setSeek(uiCurrentSeek); } else { // entry does not have face groups setCollisionMeshFaceGroupCount(0); setCollisionMeshFaceGroupsOffset(0); } if (eCOLVersionValue == COL_3 || eCOLVersionValue == COL_4) { // COL 3 & 4 header setShadowMeshFaceCount(pDataReader->readUint32()); setShadowMeshVerticesOffset(pDataReader->readUint32()); setShadowMeshFacesOffset(pDataReader->readUint32()); if (eCOLVersionValue == COL_4) { // COL 4 header setUnknown1(pDataReader->readUint32()); } } // calculate vertex counts // COL 2 3 & 4 uint32 uiCollisionMeshVertexCount = calculateCollisionMeshVertexCount(); setCollisionMeshVertexCount(uiCollisionMeshVertexCount); if (eCOLVersionValue == COL_3 || eCOLVersionValue == COL_4) { // COL 3 & 4 uint32 uiShadowMeshVertexCount = calculateShadowMeshVertexCount(); setShadowMeshVertexCount(uiShadowMeshVertexCount); } // COL 2 3 & 4 body pDataReader->setSeek(getHeaderStartOffset() + 4 + getCollisionSpheresOffset()); parseCollisionSpheres(); pDataReader->setSeek(getHeaderStartOffset() + 4 + getCollisionBoxesOffset()); parseCollisionBoxes(); pDataReader->setSeek(getHeaderStartOffset() + 4 + getCollisionMeshVerticesOffset()); parseCollisionMeshVertices(); pDataReader->setSeek(getHeaderStartOffset() + 4 + getCollisionMeshFaceGroupsOffset()); parseCollisionMeshFaceGroups(); pDataReader->setSeek(getHeaderStartOffset() + 4 + getCollisionMeshFacesOffset()); parseCollisionMeshFaces(); if (eCOLVersionValue == COL_3 || eCOLVersionValue == COL_4) { // COL 3 & 4 body pDataReader->setSeek(getHeaderStartOffset() + 4 + getShadowMeshVerticesOffset()); parseShadowMeshVertices(); pDataReader->setSeek(getHeaderStartOffset() + 4 + getShadowMeshFacesOffset()); parseShadowMeshFaces(); } } if (!pDataReader->canSeekTo(getHeaderStartOffset() + uiEntrySize + 8)) { // EOF return; } pDataReader->setSeek(getHeaderStartOffset() + uiEntrySize + 8); }