3 Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
22 #include "b3Defines.h"
23 #include "Bullet3Serialize/Bullet2FileLoader/b3Serializer.h"
24 #include "Bullet3Common/b3AlignedAllocator.h"
25 #include "Bullet3Common/b3MinMax.h"
27 #define B3_SIZEOFBLENDERHEADER 12
28 #define MAX_ARRAY_LENGTH 512
29 using namespace bParse;
30 #define MAX_STRLEN 1024
32 const char *getCleanName(const char *memName, char *buffer)
34 int slen = strlen(memName);
35 assert(slen < MAX_STRLEN);
36 slen = b3Min(slen, MAX_STRLEN);
37 for (int i = 0; i < slen; i++)
39 if (memName[i] == ']' || memName[i] == '[')
45 buffer[i] = memName[i];
52 // ----------------------------------------------------- //
53 bFile::bFile(const char *filename, const char headerString[7])
63 for (int i = 0; i < 7; i++)
65 m_headerString[i] = headerString[i];
68 FILE *fp = fopen(filename, "rb");
71 fseek(fp, 0L, SEEK_END);
73 fseek(fp, 0L, SEEK_SET);
75 mFileBuffer = (char *)malloc(mFileLen + 1);
77 bytesRead = fread(mFileBuffer, mFileLen, 1, fp);
86 // ----------------------------------------------------- //
87 bFile::bFile(char *memoryBuffer, int len, const char headerString[7])
97 for (int i = 0; i < 7; i++)
99 m_headerString[i] = headerString[i];
101 mFileBuffer = memoryBuffer;
107 // ----------------------------------------------------- //
110 if (mOwnsBuffer && mFileBuffer)
120 // ----------------------------------------------------- //
121 void bFile::parseHeader()
123 if (!mFileLen || !mFileBuffer)
126 char *blenderBuf = mFileBuffer;
127 char header[B3_SIZEOFBLENDERHEADER + 1];
128 memcpy(header, blenderBuf, B3_SIZEOFBLENDERHEADER);
129 header[B3_SIZEOFBLENDERHEADER] = '\0';
131 if (strncmp(header, m_headerString, 6) != 0)
133 memcpy(header, m_headerString, B3_SIZEOFBLENDERHEADER);
137 if (header[6] == 'd')
139 mFlags |= FD_DOUBLE_PRECISION;
142 char *ver = header + 9;
143 mVersion = atoi(ver);
146 //printf("Warning, %d not fully tested : <= 242\n", mVersion);
149 int littleEndian = 1;
150 littleEndian = ((char *)&littleEndian)[0];
153 if (header[7] == '-')
155 mFlags |= FD_FILE_64;
157 mFlags |= FD_BITS_VARIES;
160 mFlags |= FD_BITS_VARIES;
163 if (header[8] == 'V')
165 if (littleEndian == 1)
166 mFlags |= FD_ENDIAN_SWAP;
168 else if (littleEndian == 0)
169 mFlags |= FD_ENDIAN_SWAP;
174 // ----------------------------------------------------- //
177 return (mFlags & FD_OK) != 0;
180 // ----------------------------------------------------- //
181 void bFile::parseInternal(int verboseMode, char *memDna, int memDnaLength)
183 if ((mFlags & FD_OK) == 0)
186 char *blenderData = mFileBuffer;
190 char *tempBuffer = blenderData;
191 for (int i = 0; i < mFileLen; i++)
193 // looking for the data's starting position
194 // and the start of SDNA decls
196 if (!mDataStart && strncmp(tempBuffer, "REND", 4) == 0)
199 if (strncmp(tempBuffer, "DNA1", 4) == 0)
201 // read the DNA1 block and extract SDNA
202 if (getNextBlock(&dna, tempBuffer, mFlags) > 0)
204 if (strncmp((tempBuffer + ChunkUtils::getOffset(mFlags)), "SDNANAME", 8) == 0)
205 dna.oldPtr = (tempBuffer + ChunkUtils::getOffset(mFlags));
212 // Some Bullet files are missing the DNA1 block
213 // In Blender it's DNA1 + ChunkUtils::getOffset() + SDNA + NAME
214 // In Bullet tests its SDNA + NAME
215 else if (strncmp(tempBuffer, "SDNANAME", 8) == 0)
217 dna.oldPtr = blenderData + i;
218 dna.len = mFileLen - i;
220 // Also no REND block, so exit now.
221 if (mVersion == 276) break;
224 if (mDataStart && dna.oldPtr) break;
227 if (!dna.oldPtr || !dna.len)
229 //printf("Failed to find DNA1+SDNA pair\n");
234 mFileDNA = new bDNA();
236 ///mFileDNA->init will convert part of DNA file endianness to current CPU endianness if necessary
237 mFileDNA->init((char *)dna.oldPtr, dna.len, (mFlags & FD_ENDIAN_SWAP) != 0);
242 for (i = 0; i < mFileDNA->getNumNames(); i++)
244 if (strcmp(mFileDNA->getName(i), "int") == 0)
246 mFlags |= FD_BROKEN_DNA;
249 if ((mFlags & FD_BROKEN_DNA) != 0)
251 //printf("warning: fixing some broken DNA version\n");
255 if (verboseMode & FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS)
256 mFileDNA->dumpTypeDefinitions();
258 mMemoryDNA = new bDNA();
259 int littleEndian = 1;
260 littleEndian = ((char *)&littleEndian)[0];
262 mMemoryDNA->init(memDna, memDnaLength, littleEndian == 0);
264 ///@todo we need a better version check, add version/sub version info from FileGlobal into memory DNA/header files
265 if (mMemoryDNA->getNumNames() != mFileDNA->getNumNames())
267 mFlags |= FD_VERSION_VARIES;
268 //printf ("Warning, file DNA is different than built in, performance is reduced. Best to re-export file with a matching version/platform");
271 // as long as it kept up to date it will be ok!!
272 if (mMemoryDNA->lessThan(mFileDNA))
274 //printf ("Warning, file DNA is newer than built in.");
277 mFileDNA->initCmpFlags(mMemoryDNA);
281 resolvePointers(verboseMode);
286 // ----------------------------------------------------- //
287 void bFile::swap(char *head, bChunkInd &dataChunk, bool ignoreEndianFlag)
290 short *strc = mFileDNA->getStruct(dataChunk.dna_nr);
292 const char s[] = "SoftBodyMaterialData";
294 if (strncmp((char *)&dataChunk.code, "ARAY", 4) == 0)
296 short *oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
297 char *oldType = mFileDNA->getType(oldStruct[0]);
298 if (strncmp(oldType, s, szs) == 0)
304 int len = mFileDNA->getLength(strc[0]);
306 for (int i = 0; i < dataChunk.nr; i++)
308 swapStruct(dataChunk.dna_nr, data, ignoreEndianFlag);
313 void bFile::swapLen(char *dataPtr)
315 const bool VOID_IS_8 = ((sizeof(void *) == 8));
318 if (mFlags & FD_BITS_VARIES)
320 bChunkPtr4 *c = (bChunkPtr4 *)dataPtr;
321 if ((c->code & 0xFFFF) == 0)
323 B3_SWITCH_INT(c->len);
324 B3_SWITCH_INT(c->dna_nr);
325 B3_SWITCH_INT(c->nr);
329 bChunkPtr8 *c = (bChunkPtr8 *)dataPtr;
330 if ((c->code & 0xFFFF) == 0)
332 B3_SWITCH_INT(c->len);
333 B3_SWITCH_INT(c->dna_nr);
334 B3_SWITCH_INT(c->nr);
339 if (mFlags & FD_BITS_VARIES)
341 bChunkPtr8 *c = (bChunkPtr8 *)dataPtr;
342 if ((c->code & 0xFFFF) == 0)
344 B3_SWITCH_INT(c->len);
345 B3_SWITCH_INT(c->dna_nr);
346 B3_SWITCH_INT(c->nr);
350 bChunkPtr4 *c = (bChunkPtr4 *)dataPtr;
351 if ((c->code & 0xFFFF) == 0)
353 B3_SWITCH_INT(c->len);
355 B3_SWITCH_INT(c->dna_nr);
356 B3_SWITCH_INT(c->nr);
361 void bFile::swapDNA(char *ptr)
363 bool swap = ((mFlags & FD_ENDIAN_SWAP) != 0);
365 char *data = &ptr[20];
366 // void bDNA::init(char *data, int len, bool swap)
372 intPtr = (int *)data;
375 SDNA (4 bytes) (magic number)
377 <nr> (4 bytes) amount of names (int)
382 if (strncmp(data, "SDNA", 4) == 0)
391 dataLen = ChunkUtils::swapInt(*intPtr);
395 *intPtr = ChunkUtils::swapInt(*intPtr);
400 for (i = 0; i < dataLen; i++)
406 cp = b3AlignPointer(cp, 4);
410 <nr> amount of types (int)
416 assert(strncmp(cp, "TYPE", 4) == 0);
420 dataLen = ChunkUtils::swapInt(*intPtr);
424 *intPtr = ChunkUtils::swapInt(*intPtr);
429 for (i = 0; i < dataLen; i++)
435 cp = b3AlignPointer(cp, 4);
439 <len> (short) the lengths of types
445 assert(strncmp(cp, "TLEN", 4) == 0);
448 shtPtr = (short *)intPtr;
449 for (i = 0; i < dataLen; i++, shtPtr++)
452 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
460 <nr> amount of structs (int)
469 intPtr = (int *)shtPtr;
471 assert(strncmp(cp, "STRC", 4) == 0);
475 dataLen = ChunkUtils::swapInt(*intPtr);
479 *intPtr = ChunkUtils::swapInt(*intPtr);
483 shtPtr = (short *)intPtr;
484 for (i = 0; i < dataLen; i++)
490 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
491 shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
495 for (int a = 0; a < len; a++, shtPtr += 2)
497 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
498 shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
502 // shtPtr+= (2*shtPtr[1])+2;
506 void bFile::writeFile(const char *fileName)
508 FILE *f = fopen(fileName, "wb");
509 fwrite(mFileBuffer, 1, mFileLen, f);
513 void bFile::preSwap()
515 //const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
517 //byte 8 determines the endianness of the file, little (v) versus big (V)
518 int littleEndian = 1;
519 littleEndian = ((char *)&littleEndian)[0];
521 if (mFileBuffer[8] == 'V')
523 mFileBuffer[8] = 'v';
527 mFileBuffer[8] = 'V';
532 char *dataPtr = mFileBuffer + mDataStart;
536 bool ignoreEndianFlag = true;
538 //we always want to swap here
540 int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
541 //dataPtr += ChunkUtils::getOffset(mFlags);
542 char *dataPtrHead = 0;
547 if (dataChunk.code == B3_SDNA || dataChunk.code == B3_DNA1 || dataChunk.code == B3_TYPE || dataChunk.code == B3_TLEN || dataChunk.code == B3_STRC)
554 //if (dataChunk.code == DNA1) break;
555 dataPtrHead = dataPtr + ChunkUtils::getOffset(mFlags);
558 if (dataChunk.dna_nr >= 0)
560 swap(dataPtrHead, dataChunk, ignoreEndianFlag);
564 //printf("unknown chunk\n");
571 seek = getNextBlock(&dataChunk, dataPtr, mFlags);
576 if (mFlags & FD_ENDIAN_SWAP)
578 mFlags &= ~FD_ENDIAN_SWAP;
582 mFlags |= FD_ENDIAN_SWAP;
586 // ----------------------------------------------------- //
587 char *bFile::readStruct(char *head, bChunkInd &dataChunk)
589 bool ignoreEndianFlag = false;
591 if (mFlags & FD_ENDIAN_SWAP)
592 swap(head, dataChunk, ignoreEndianFlag);
594 if (!mFileDNA->flagEqual(dataChunk.dna_nr))
596 // Ouch! need to rebuild the struct
597 short *oldStruct, *curStruct;
598 char *oldType, *newType;
599 int oldLen, curLen, reverseOld;
601 oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
602 oldType = mFileDNA->getType(oldStruct[0]);
604 oldLen = mFileDNA->getLength(oldStruct[0]);
606 if ((mFlags & FD_BROKEN_DNA) != 0)
608 if ((strcmp(oldType, "b3QuantizedBvhNodeData") == 0) && oldLen == 20)
612 if ((strcmp(oldType, "b3ShortIntIndexData") == 0))
615 char *dataAlloc = new char[(dataChunk.nr * allocLen) + 1];
616 memset(dataAlloc, 0, (dataChunk.nr * allocLen) + 1);
617 short *dest = (short *)dataAlloc;
618 const short *src = (short *)head;
619 for (int i = 0; i < dataChunk.nr; i++)
622 if (mFlags & FD_ENDIAN_SWAP)
624 B3_SWITCH_SHORT(dest[i]);
627 addDataBlock(dataAlloc);
632 ///don't try to convert Link block data, just memcpy it. Other data can be converted.
633 if (strcmp("Link", oldType) != 0)
635 reverseOld = mMemoryDNA->getReverseType(oldType);
637 if ((reverseOld != -1))
639 // make sure it's here
640 //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
643 curStruct = mMemoryDNA->getStruct(reverseOld);
644 newType = mMemoryDNA->getType(curStruct[0]);
645 curLen = mMemoryDNA->getLength(curStruct[0]);
647 // make sure it's the same
648 assert((strcmp(oldType, newType) == 0) && "internal error, struct mismatch!");
650 // numBlocks * length
652 int allocLen = (curLen);
653 char *dataAlloc = new char[(dataChunk.nr * allocLen) + 1];
654 memset(dataAlloc, 0, (dataChunk.nr * allocLen));
657 addDataBlock(dataAlloc);
659 char *cur = dataAlloc;
661 for (int block = 0; block < dataChunk.nr; block++)
663 bool fixupPointers = true;
664 parseStruct(cur, old, dataChunk.dna_nr, reverseOld, fixupPointers);
665 mLibPointers.insert(old, (bStructHandle *)cur);
675 //printf("Link found\n");
680 //#define DEBUG_EQUAL_STRUCTS
681 #ifdef DEBUG_EQUAL_STRUCTS
684 oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
685 oldType = mFileDNA->getType(oldStruct[0]);
686 printf("%s equal structure, just memcpy\n", oldType);
690 char *dataAlloc = new char[(dataChunk.len) + 1];
691 memset(dataAlloc, 0, dataChunk.len + 1);
694 addDataBlock(dataAlloc);
696 memcpy(dataAlloc, head, dataChunk.len);
700 // ----------------------------------------------------- //
701 void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers)
703 if (old_dna == -1) return;
704 if (new_dna == -1) return;
706 //disable this, because we need to fixup pointers/ListBase
707 if (0) //mFileDNA->flagEqual(old_dna))
709 short *strc = mFileDNA->getStruct(old_dna);
710 int len = mFileDNA->getLength(strc[0]);
712 memcpy(strcPtr, dtPtr, len);
716 // Ok, now build the struct
717 char *memType, *memName, *cpc, *cpo;
718 short *fileStruct, *filePtrOld, *memoryStruct, *firstStruct;
719 int elementLength, size, revType, old_nr, new_nr, fpLen;
720 short firstStructType;
722 // File to memory lookup
723 memoryStruct = mMemoryDNA->getStruct(new_dna);
724 fileStruct = mFileDNA->getStruct(old_dna);
725 firstStruct = fileStruct;
727 filePtrOld = fileStruct;
728 firstStructType = mMemoryDNA->getStruct(0)[0];
730 // Get number of elements
731 elementLength = memoryStruct[1];
736 for (int ele = 0; ele < elementLength; ele++, memoryStruct += 2)
738 memType = mMemoryDNA->getType(memoryStruct[0]);
739 memName = mMemoryDNA->getName(memoryStruct[1]);
741 size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]);
742 revType = mMemoryDNA->getReverseType(memoryStruct[0]);
744 if (revType != -1 && memoryStruct[0] >= firstStructType && memName[0] != '*')
746 cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld);
749 int arrayLen = mFileDNA->getArraySizeNew(filePtrOld[1]);
750 old_nr = mFileDNA->getReverseType(memType);
752 fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]);
755 parseStruct(cpc, cpo, old_nr, new_nr, fixupPointers);
762 for (int i = 0; i < arrayLen; i++)
764 parseStruct(tmpCpc, tmpCpo, old_nr, new_nr, fixupPointers);
765 tmpCpc += size / arrayLen;
766 tmpCpo += fpLen / arrayLen;
777 getMatchingFileDNA(fileStruct, memName, memType, cpc, dtPtr, fixupPointers);
783 // ----------------------------------------------------- //
784 static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData)
786 #define b3GetEle(value, current, type, cast, size, ptr) \
787 if (strcmp(current, type) == 0) \
789 value = (*(cast *)ptr); \
793 #define b3SetEle(value, current, type, cast, size, ptr) \
794 if (strcmp(current, type) == 0) \
796 (*(cast *)ptr) = (cast)value; \
801 for (int i = 0; i < arrayLen; i++)
803 b3GetEle(value, old, "char", char, sizeof(char), oldPtr);
804 b3SetEle(value, cur, "char", char, sizeof(char), curData);
805 b3GetEle(value, old, "short", short, sizeof(short), oldPtr);
806 b3SetEle(value, cur, "short", short, sizeof(short), curData);
807 b3GetEle(value, old, "ushort", unsigned short, sizeof(unsigned short), oldPtr);
808 b3SetEle(value, cur, "ushort", unsigned short, sizeof(unsigned short), curData);
809 b3GetEle(value, old, "int", int, sizeof(int), oldPtr);
810 b3SetEle(value, cur, "int", int, sizeof(int), curData);
811 b3GetEle(value, old, "long", int, sizeof(int), oldPtr);
812 b3SetEle(value, cur, "long", int, sizeof(int), curData);
813 b3GetEle(value, old, "float", float, sizeof(float), oldPtr);
814 b3SetEle(value, cur, "float", float, sizeof(float), curData);
815 b3GetEle(value, old, "double", double, sizeof(double), oldPtr);
816 b3SetEle(value, cur, "double", double, sizeof(double), curData);
820 // ----------------------------------------------------- //
821 void bFile::swapData(char *data, short type, int arraySize, bool ignoreEndianFlag)
823 if (ignoreEndianFlag || (mFlags & FD_ENDIAN_SWAP))
825 if (type == 2 || type == 3)
827 short *sp = (short *)data;
828 for (int i = 0; i < arraySize; i++)
830 sp[0] = ChunkUtils::swapShort(sp[0]);
834 if (type > 3 && type < 8)
838 for (int i = 0; i < arraySize; i++)
852 void bFile::safeSwapPtr(char *dst, const char *src)
857 int ptrFile = mFileDNA->getPointerSize();
858 int ptrMem = mMemoryDNA->getPointerSize();
860 if (ptrFile == ptrMem)
862 memcpy(dst, src, ptrMem);
864 else if (ptrMem == 4 && ptrFile == 8)
866 b3PointerUid *oldPtr = (b3PointerUid *)src;
867 b3PointerUid *newPtr = (b3PointerUid *)dst;
869 if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
871 //Bullet stores the 32bit unique ID in both upper and lower part of 64bit pointers
872 //so it can be used to distinguish between .blend and .bullet
873 newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
877 //deal with pointers the Blender .blend style way, see
878 //readfile.c in the Blender source tree
879 b3Long64 longValue = *((b3Long64 *)src);
880 //endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros
881 if (mFlags & FD_ENDIAN_SWAP)
882 B3_SWITCH_LONGINT(longValue);
883 *((int *)dst) = (int)(longValue >> 3);
886 else if (ptrMem == 8 && ptrFile == 4)
888 b3PointerUid *oldPtr = (b3PointerUid *)src;
889 b3PointerUid *newPtr = (b3PointerUid *)dst;
890 if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
892 newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
893 newPtr->m_uniqueIds[1] = 0;
897 *((b3Long64 *)dst) = *((int *)src);
902 printf("%d %d\n", ptrFile, ptrMem);
903 assert(0 && "Invalid pointer len");
907 // ----------------------------------------------------- //
908 void bFile::getMatchingFileDNA(short *dna_addr, const char *lookupName, const char *lookupType, char *strcData, char *data, bool fixupPointers)
910 // find the matching memory dna data
911 // to the file being loaded. Fill the
912 // memory with the file data...
914 int len = dna_addr[1];
917 for (int i = 0; i < len; i++, dna_addr += 2)
919 const char *type = mFileDNA->getType(dna_addr[0]);
920 const char *name = mFileDNA->getName(dna_addr[1]);
922 int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]);
924 if ((mFlags & FD_BROKEN_DNA) != 0)
926 if ((strcmp(type, "short") == 0) && (strcmp(name, "int") == 0))
932 if (strcmp(lookupName, name) == 0)
934 //int arrayLenold = mFileDNA->getArraySize((char*)name.c_str());
935 int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]);
936 //assert(arrayLenold == arrayLen);
941 int ptrFile = mFileDNA->getPointerSize();
942 int ptrMem = mMemoryDNA->getPointerSize();
943 safeSwapPtr(strcData, data);
949 //void **sarray = (void**)strcData;
950 //void **darray = (void**)data;
953 cpc = (char *)strcData;
956 for (int a = 0; a < arrayLen; a++)
958 safeSwapPtr(cpc, cpo);
959 m_pointerFixupArray.push_back(cpc);
967 m_pointerPtrFixupArray.push_back(strcData);
969 m_pointerFixupArray.push_back(strcData);
974 // printf("skipped %s %s : %x\n",type.c_str(),name.c_str(),strcData);
978 else if (strcmp(type, lookupType) == 0)
979 memcpy(strcData, data, eleLen);
981 getElement(arrayLen, lookupType, type, data, strcData);
990 // ----------------------------------------------------- //
991 char *bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos)
993 short *old = firstStruct; //mFileDNA->getStruct(old_nr);
994 int elementLength = old[1];
997 for (int i = 0; i < elementLength; i++, old += 2)
999 char *type = mFileDNA->getType(old[0]);
1000 char *name = mFileDNA->getName(old[1]);
1001 int len = mFileDNA->getElementSize(old[0], old[1]);
1003 if (strcmp(lookupName, name) == 0)
1005 if (strcmp(type, lookupType) == 0)
1018 // ----------------------------------------------------- //
1019 void bFile::swapStruct(int dna_nr, char *data, bool ignoreEndianFlag)
1021 if (dna_nr == -1) return;
1023 short *strc = mFileDNA->getStruct(dna_nr);
1024 //short *firstStrc = strc;
1026 int elementLen = strc[1];
1029 short first = mFileDNA->getStruct(0)[0];
1032 for (int i = 0; i < elementLen; i++, strc += 2)
1034 char *type = mFileDNA->getType(strc[0]);
1035 char *name = mFileDNA->getName(strc[1]);
1037 int size = mFileDNA->getElementSize(strc[0], strc[1]);
1038 if (strc[0] >= first && name[0] != '*')
1040 int old_nr = mFileDNA->getReverseType(type);
1041 int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
1044 swapStruct(old_nr, buf, ignoreEndianFlag);
1049 for (int i = 0; i < arrayLen; i++)
1051 swapStruct(old_nr, tmpBuf, ignoreEndianFlag);
1052 tmpBuf += size / arrayLen;
1058 //int arrayLenOld = mFileDNA->getArraySize(name);
1059 int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
1060 //assert(arrayLenOld == arrayLen);
1061 swapData(buf, strc[0], arrayLen, ignoreEndianFlag);
1067 void bFile::resolvePointersMismatch()
1069 // printf("resolvePointersStructMismatch\n");
1073 for (i = 0; i < m_pointerFixupArray.size(); i++)
1075 char *cur = m_pointerFixupArray.at(i);
1076 void **ptrptr = (void **)cur;
1077 void *ptr = *ptrptr;
1078 ptr = findLibPointer(ptr);
1081 //printf("Fixup pointer!\n");
1086 // printf("pointer not found: %x\n",cur);
1090 for (i = 0; i < m_pointerPtrFixupArray.size(); i++)
1092 char *cur = m_pointerPtrFixupArray.at(i);
1093 void **ptrptr = (void **)cur;
1095 bChunkInd *block = m_chunkPtrPtrMap.find(*ptrptr);
1098 int ptrMem = mMemoryDNA->getPointerSize();
1099 int ptrFile = mFileDNA->getPointerSize();
1101 int blockLen = block->len / ptrFile;
1103 void *onptr = findLibPointer(*ptrptr);
1106 char *newPtr = new char[blockLen * ptrMem];
1107 addDataBlock(newPtr);
1108 memset(newPtr, 0, blockLen * ptrMem);
1110 void **onarray = (void **)onptr;
1111 char *oldPtr = (char *)onarray;
1114 while (blockLen-- > 0)
1116 b3PointerUid dp = {{0}};
1117 safeSwapPtr((char *)dp.m_uniqueIds, oldPtr);
1119 void **tptr = (void **)(newPtr + p * ptrMem);
1120 *tptr = findLibPointer(dp.m_ptr);
1132 ///this loop only works fine if the Blender DNA structure of the file matches the headerfiles
1133 void bFile::resolvePointersChunk(const bChunkInd &dataChunk, int verboseMode)
1135 bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1137 short int *oldStruct = fileDna->getStruct(dataChunk.dna_nr);
1138 short oldLen = fileDna->getLength(oldStruct[0]);
1139 //char* structType = fileDna->getType(oldStruct[0]);
1141 char *cur = (char *)findLibPointer(dataChunk.oldPtr);
1142 for (int block = 0; block < dataChunk.nr; block++)
1144 resolvePointersStructRecursive(cur, dataChunk.dna_nr, verboseMode, 1);
1149 int bFile::resolvePointersStructRecursive(char *strcPtr, int dna_nr, int verboseMode, int recursion)
1151 bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1155 short firstStructType = fileDna->getStruct(0)[0];
1157 char *elemPtr = strcPtr;
1159 short int *oldStruct = fileDna->getStruct(dna_nr);
1161 int elementLength = oldStruct[1];
1166 for (int ele = 0; ele < elementLength; ele++, oldStruct += 2)
1168 memType = fileDna->getType(oldStruct[0]);
1169 memName = fileDna->getName(oldStruct[1]);
1171 int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
1172 if (memName[0] == '*')
1176 void **array = (void **)elemPtr;
1177 for (int a = 0; a < arrayLen; a++)
1179 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1181 for (int i = 0; i < recursion; i++)
1186 printf("<%s type=\"pointer\"> ", &memName[1]);
1187 printf("%p ", array[a]);
1188 printf("</%s>\n", &memName[1]);
1191 array[a] = findLibPointer(array[a]);
1196 void **ptrptr = (void **)elemPtr;
1197 void *ptr = *ptrptr;
1198 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1200 for (int i = 0; i < recursion; i++)
1204 printf("<%s type=\"pointer\"> ", &memName[1]);
1206 printf("</%s>\n", &memName[1]);
1208 ptr = findLibPointer(ptr);
1212 // printf("Fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
1214 if (memName[1] == '*' && ptrptr && *ptrptr)
1216 // This will only work if the given **array is continuous
1217 void **array = (void **)*(ptrptr);
1218 void *np = array[0];
1222 np = findLibPointer(array[n]);
1223 if (np) array[n] = np;
1230 // printf("Cannot fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
1236 int revType = fileDna->getReverseType(oldStruct[0]);
1237 if (oldStruct[0] >= firstStructType) //revType != -1 &&
1239 char cleanName[MAX_STRLEN];
1240 getCleanName(memName, cleanName);
1242 int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
1245 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1247 for (int i = 0; i < recursion; i++)
1254 printf("<%s type=\"%s\" count=%d>\n", cleanName, memType, arrayLen);
1258 printf("<%s type=\"%s\">\n", cleanName, memType);
1262 for (int i = 0; i < arrayLen; i++)
1264 byteOffset += resolvePointersStructRecursive(elemPtr + byteOffset, revType, verboseMode, recursion + 1);
1266 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1268 for (int i = 0; i < recursion; i++)
1272 printf("</%s>\n", cleanName);
1277 //export a simple type
1278 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1280 if (arrayLen > MAX_ARRAY_LENGTH)
1282 printf("too long\n");
1286 //printf("%s %s\n",memType,memName);
1288 bool isIntegerType = (strcmp(memType, "char") == 0) || (strcmp(memType, "int") == 0) || (strcmp(memType, "short") == 0);
1292 const char *newtype = "int";
1293 int dbarray[MAX_ARRAY_LENGTH];
1295 char *tmp = elemPtr;
1296 dbPtr = &dbarray[0];
1299 char cleanName[MAX_STRLEN];
1300 getCleanName(memName, cleanName);
1303 getElement(arrayLen, newtype, memType, tmp, (char *)dbPtr);
1304 for (i = 0; i < recursion; i++)
1307 printf("<%s type=\"%s\">", cleanName, memType);
1309 printf("<%s type=\"%s\" count=%d>", cleanName, memType, arrayLen);
1310 for (i = 0; i < arrayLen; i++)
1311 printf(" %d ", dbPtr[i]);
1312 printf("</%s>\n", cleanName);
1317 const char *newtype = "double";
1318 double dbarray[MAX_ARRAY_LENGTH];
1320 char *tmp = elemPtr;
1321 dbPtr = &dbarray[0];
1325 getElement(arrayLen, newtype, memType, tmp, (char *)dbPtr);
1326 for (i = 0; i < recursion; i++)
1328 char cleanName[MAX_STRLEN];
1329 getCleanName(memName, cleanName);
1333 printf("<%s type=\"%s\">", memName, memType);
1337 printf("<%s type=\"%s\" count=%d>", cleanName, memType, arrayLen);
1339 for (i = 0; i < arrayLen; i++)
1340 printf(" %f ", dbPtr[i]);
1341 printf("</%s>\n", cleanName);
1349 int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]);
1357 ///Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory structures
1358 void bFile::resolvePointers(int verboseMode)
1360 bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1362 //char *dataPtr = mFileBuffer+mDataStart;
1364 if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES))
1366 resolvePointersMismatch();
1370 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1372 printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
1373 int numitems = m_chunks.size();
1374 printf("<bullet_physics version=%d itemcount = %d>\n", b3GetVersion(), numitems);
1376 for (int i = 0; i < m_chunks.size(); i++)
1378 const bChunkInd &dataChunk = m_chunks.at(i);
1380 if (!mFileDNA || fileDna->flagEqual(dataChunk.dna_nr))
1383 short int *oldStruct = fileDna->getStruct(dataChunk.dna_nr);
1384 char *oldType = fileDna->getType(oldStruct[0]);
1386 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1387 printf(" <%s pointer=%p>\n", oldType, dataChunk.oldPtr);
1389 resolvePointersChunk(dataChunk, verboseMode);
1391 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1392 printf(" </%s>\n", oldType);
1396 //printf("skipping mStruct\n");
1399 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1401 printf("</bullet_physics>\n");
1406 // ----------------------------------------------------- //
1407 void *bFile::findLibPointer(void *ptr)
1409 bStructHandle **ptrptr = getLibPointers().find(ptr);
1415 void bFile::updateOldPointers()
1419 for (i = 0; i < m_chunks.size(); i++)
1421 bChunkInd &dataChunk = m_chunks[i];
1422 dataChunk.oldPtr = findLibPointer(dataChunk.oldPtr);
1425 void bFile::dumpChunks(bParse::bDNA *dna)
1429 for (i = 0; i < m_chunks.size(); i++)
1431 bChunkInd &dataChunk = m_chunks[i];
1432 char *codeptr = (char *)&dataChunk.code;
1433 char codestr[5] = {codeptr[0], codeptr[1], codeptr[2], codeptr[3], 0};
1435 short *newStruct = dna->getStruct(dataChunk.dna_nr);
1436 char *typeName = dna->getType(newStruct[0]);
1437 printf("%3d: %s ", i, typeName);
1439 printf("code=%s ", codestr);
1441 printf("ptr=%p ", dataChunk.oldPtr);
1442 printf("len=%d ", dataChunk.len);
1443 printf("nr=%d ", dataChunk.nr);
1444 if (dataChunk.nr != 1)
1455 ifd.just_print_it = 1;
1456 for (i=0; i<bf->m_blocks.size(); ++i)
1458 BlendBlock* bb = bf->m_blocks[i];
1459 printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]", bb->tag, bb,bf->types[bb->type_index].name,bb->m_array_entries_.size());
1460 block_ID_finder(bb, bf, &ifd);
1466 void bFile::writeChunks(FILE *fp, bool fixupPointers)
1468 bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1470 for (int i = 0; i < m_chunks.size(); i++)
1472 bChunkInd &dataChunk = m_chunks.at(i);
1474 // Ouch! need to rebuild the struct
1475 short *oldStruct, *curStruct;
1476 char *oldType, *newType;
1477 int oldLen, curLen, reverseOld;
1479 oldStruct = fileDna->getStruct(dataChunk.dna_nr);
1480 oldType = fileDna->getType(oldStruct[0]);
1481 oldLen = fileDna->getLength(oldStruct[0]);
1482 ///don't try to convert Link block data, just memcpy it. Other data can be converted.
1483 reverseOld = mMemoryDNA->getReverseType(oldType);
1485 if ((reverseOld != -1))
1487 // make sure it's here
1488 //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
1490 curStruct = mMemoryDNA->getStruct(reverseOld);
1491 newType = mMemoryDNA->getType(curStruct[0]);
1492 // make sure it's the same
1493 assert((strcmp(oldType, newType) == 0) && "internal error, struct mismatch!");
1495 curLen = mMemoryDNA->getLength(curStruct[0]);
1496 dataChunk.dna_nr = reverseOld;
1497 if (strcmp("Link", oldType) != 0)
1499 dataChunk.len = curLen * dataChunk.nr;
1503 // printf("keep length of link = %d\n",dataChunk.len);
1506 //write the structure header
1507 fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
1509 short int *curStruct1;
1510 curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr);
1511 assert(curStruct1 == curStruct);
1513 char *cur = fixupPointers ? (char *)findLibPointer(dataChunk.oldPtr) : (char *)dataChunk.oldPtr;
1515 //write the actual contents of the structure(s)
1516 fwrite(cur, dataChunk.len, 1, fp);
1520 printf("serious error, struct mismatch: don't write\n");
1525 // ----------------------------------------------------- //
1526 int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
1529 bool varies = false;
1531 if (flags & FD_ENDIAN_SWAP)
1533 if (flags & FD_BITS_VARIES)
1541 memcpy(&head, dataPtr, sizeof(bChunkPtr4));
1545 chunk.code = head.code;
1546 chunk.len = head.len;
1547 chunk.m_uniqueInts[0] = head.m_uniqueInt;
1548 chunk.m_uniqueInts[1] = 0;
1549 chunk.dna_nr = head.dna_nr;
1554 if ((chunk.code & 0xFFFF) == 0)
1557 B3_SWITCH_INT(chunk.len);
1558 B3_SWITCH_INT(chunk.dna_nr);
1559 B3_SWITCH_INT(chunk.nr);
1562 memcpy(dataChunk, &chunk, sizeof(bChunkInd));
1567 memcpy(&c, dataPtr, sizeof(bChunkPtr8));
1571 if ((c.code & 0xFFFF) == 0)
1574 B3_SWITCH_INT(c.len);
1575 B3_SWITCH_INT(c.dna_nr);
1576 B3_SWITCH_INT(c.nr);
1579 memcpy(dataChunk, &c, sizeof(bChunkInd));
1587 memcpy(&head, dataPtr, sizeof(bChunkPtr8));
1590 chunk.code = head.code;
1591 chunk.len = head.len;
1593 if (head.m_uniqueInts[0] == head.m_uniqueInts[1])
1595 chunk.m_uniqueInt = head.m_uniqueInts[0];
1599 b3Long64 oldPtr = 0;
1600 memcpy(&oldPtr, &head.m_uniqueInts[0], 8);
1602 B3_SWITCH_LONGINT(oldPtr);
1603 chunk.m_uniqueInt = (int)(oldPtr >> 3);
1606 chunk.dna_nr = head.dna_nr;
1611 if ((chunk.code & 0xFFFF) == 0)
1614 B3_SWITCH_INT(chunk.len);
1615 B3_SWITCH_INT(chunk.dna_nr);
1616 B3_SWITCH_INT(chunk.nr);
1619 memcpy(dataChunk, &chunk, sizeof(bChunkInd));
1624 memcpy(&c, dataPtr, sizeof(bChunkPtr4));
1628 if ((c.code & 0xFFFF) == 0)
1631 B3_SWITCH_INT(c.len);
1632 B3_SWITCH_INT(c.dna_nr);
1633 B3_SWITCH_INT(c.nr);
1635 memcpy(dataChunk, &c, sizeof(bChunkInd));
1639 if (dataChunk->len < 0)
1643 print ("----------");
1644 print (dataChunk->code);
1645 print (dataChunk->len);
1646 print (dataChunk->old);
1647 print (dataChunk->dna_nr);
1648 print (dataChunk->nr);
1650 return (dataChunk->len + ChunkUtils::getOffset(flags));