Bullet Collision Detection & Physics Library: bFile.cpp Source File

Bullet Collision Detection & Physics Library

bFile.cpp
Go to the documentation of this file.
1 /*
2 bParse
3 Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
4
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:
10
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.
14 */
15 #include "bFile.h"
16 #include "bCommon.h"
17 #include "bChunk.h"
18 #include "bDNA.h"
19 #include <math.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include "bDefines.h"
23 #include "LinearMath/btSerializer.h"
24 #include "LinearMath/btAlignedAllocator.h"
25 #include "LinearMath/btMinMax.h"
26
27 #define SIZEOFBLENDERHEADER 12
28 #define MAX_ARRAY_LENGTH 512
29 using namespace bParse;
30 #define MAX_STRLEN 1024
31
32 const char* getCleanName(const char* memName, char* buffer)
33 {
34 int slen = strlen(memName);
35 assert(slen<MAX_STRLEN);
36 slen=btMin(slen,MAX_STRLEN);
37 for (int i=0;i<slen;i++)
38 {
39 if (memName[i]==']'||memName[i]=='[')
40 {
41 buffer[i] = 0;//'_';
42 } else
43 {
44 buffer[i] = memName[i];
45 }
46 }
47 buffer[slen]=0;
48 return buffer;
49 }
50
51
52 int numallocs = 0;
53
54 // ----------------------------------------------------- //
55 bFile::bFile(const char *filename, const char headerString[7])
56 : mOwnsBuffer(true),
57 mFileBuffer(0),
58 mFileLen(0),
59 mVersion(0),
60 mDataStart(0),
61 mFileDNA(0),
62 mMemoryDNA(0),
63 mFlags(FD_INVALID)
64 {
65 for (int i=0;i<7;i++)
66 {
67 m_headerString[i] = headerString[i];
68 }
69
70 FILE *fp = fopen(filename, "rb");
71 if (fp)
72 {
73 fseek(fp, 0L, SEEK_END);
74 mFileLen = ftell(fp);
75 fseek(fp, 0L, SEEK_SET);
76
77 mFileBuffer = (char*)malloc(mFileLen+1);
78 size_t bytesRead;
79 bytesRead = fread(mFileBuffer, mFileLen, 1, fp);
80
81 fclose(fp);
82
83 //
84 parseHeader();
85
86 }
87 }
88
89 // ----------------------------------------------------- //
90 bFile::bFile( char *memoryBuffer, int len, const char headerString[7])
91 : mOwnsBuffer(false),
92 mFileBuffer(0),
93 mFileLen(0),
94 mVersion(0),
95 mDataStart(0),
96 mFileDNA(0),
97 mMemoryDNA(0),
98 mFlags(FD_INVALID)
99 {
100 for (int i=0;i<7;i++)
101 {
102 m_headerString[i] = headerString[i];
103 }
104 mFileBuffer = memoryBuffer;
105 mFileLen = len;
106
107 parseHeader();
108
109 }
110
111
112 // ----------------------------------------------------- //
113 bFile::~bFile()
114 {
115 if (mOwnsBuffer && mFileBuffer)
116 {
117 free(mFileBuffer);
118 mFileBuffer = 0;
119 }
120
121
122 delete mMemoryDNA;
123 delete mFileDNA;
124 }
125
126
127
128
129
130 // ----------------------------------------------------- //
131 void bFile::parseHeader()
132 {
133 if (!mFileLen || !mFileBuffer)
134 return;
135
136 char *blenderBuf = mFileBuffer;
137 char header[SIZEOFBLENDERHEADER+1] ;
138 memcpy(header, blenderBuf, SIZEOFBLENDERHEADER);
139 header[SIZEOFBLENDERHEADER]='\0';
140
141 if (strncmp(header, m_headerString, 6)!=0)
142 {
143 memcpy(header, m_headerString, SIZEOFBLENDERHEADER);
144 return;
145 }
146
147 if (header[6] == 'd')
148 {
149 mFlags |= FD_DOUBLE_PRECISION;
150 }
151
152 char *ver = header+9;
153 mVersion = atoi(ver);
154 if (mVersion <= 241)
155 {
156 //printf("Warning, %d not fully tested : <= 242\n", mVersion);
157 }
158
159 int littleEndian= 1;
160 littleEndian= ((char*)&littleEndian)[0];
161
162 // swap ptr sizes...
163 if (header[7]=='-')
164 {
165 mFlags |= FD_FILE_64;
166 if (!VOID_IS_8)
167 mFlags |= FD_BITS_VARIES;
168 }
169 else if (VOID_IS_8) mFlags |= FD_BITS_VARIES;
170
171 // swap endian...
172 if (header[8]=='V')
173 {
174 if (littleEndian ==1)
175 mFlags |= FD_ENDIAN_SWAP;
176 }
177 else
178 if (littleEndian==0)
179 mFlags |= FD_ENDIAN_SWAP;
180
181
182 mFlags |= FD_OK;
183 }
184
185 // ----------------------------------------------------- //
186 bool bFile::ok()
187 {
188 return (mFlags &FD_OK)!=0;
189 }
190
191 void bFile::setFileDNA(int verboseMode, char* dnaBuffer, int dnaLen)
192 {
193 mFileDNA = new bDNA();
194
196 mFileDNA->init((char*)dnaBuffer, dnaLen, (mFlags & FD_ENDIAN_SWAP)!=0);
197
198 if (verboseMode & FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS)
199 mFileDNA->dumpTypeDefinitions();
200 }
201
202 // ----------------------------------------------------- //
203 void bFile::parseInternal(int verboseMode, char* memDna,int memDnaLength)
204 {
205 if ( (mFlags &FD_OK) ==0)
206 return;
207
208 if (mFlags & FD_FILEDNA_IS_MEMDNA)
209 {
210 setFileDNA(verboseMode,memDna,memDnaLength);
211 }
212
213 if (mFileDNA==0)
214 {
215 char *blenderData = mFileBuffer;
216 bChunkInd dna;
217 dna.oldPtr = 0;
218
219 char *tempBuffer = blenderData;
220 for (int i=0; i<mFileLen; i++)
221 {
222 // looking for the data's starting position
223 // and the start of SDNA decls
224
225 if (!mDataStart && strncmp(tempBuffer, "REND", 4)==0)
226 mDataStart = i;
227
228 if (strncmp(tempBuffer, "DNA1", 4)==0)
229 {
230 // read the DNA1 block and extract SDNA
231 if (getNextBlock(&dna, tempBuffer, mFlags) > 0)
232 {
233 if (strncmp((tempBuffer + ChunkUtils::getOffset(mFlags)), "SDNANAME", 8) ==0)
234 dna.oldPtr = (tempBuffer + ChunkUtils::getOffset(mFlags));
235 else dna.oldPtr = 0;
236 }
237 else dna.oldPtr = 0;
238 }
239 // Some Bullet files are missing the DNA1 block
240 // In Blender it's DNA1 + ChunkUtils::getOffset() + SDNA + NAME
241 // In Bullet tests its SDNA + NAME
242 else if (strncmp(tempBuffer, "SDNANAME", 8) ==0)
243 {
244 dna.oldPtr = blenderData + i;
245 dna.len = mFileLen-i;
246
247 // Also no REND block, so exit now.
248 if (mVersion==276) break;
249 }
250
251 if (mDataStart && dna.oldPtr) break;
252 tempBuffer++;
253 }
254 if (!dna.oldPtr || !dna.len)
255 {
256 //printf("Failed to find DNA1+SDNA pair\n");
257 mFlags &= ~FD_OK;
258 return;
259 }
260
261
262 mFileDNA = new bDNA();
263
264
266 mFileDNA->init((char*)dna.oldPtr, dna.len, (mFlags & FD_ENDIAN_SWAP)!=0);
267
268
269 if (mVersion==276)
270 {
271 int i;
272 for (i=0;i<mFileDNA->getNumNames();i++)
273 {
274 if (strcmp(mFileDNA->getName(i),"int")==0)
275 {
276 mFlags |= FD_BROKEN_DNA;
277 }
278 }
279 if ((mFlags&FD_BROKEN_DNA)!=0)
280 {
281 //printf("warning: fixing some broken DNA version\n");
282 }
283 }
284
285
286
287 if (verboseMode & FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS)
288 mFileDNA->dumpTypeDefinitions();
289 }
290 mMemoryDNA = new bDNA();
291 int littleEndian= 1;
292 littleEndian= ((char*)&littleEndian)[0];
293
294 mMemoryDNA->init(memDna,memDnaLength,littleEndian==0);
295
296
297
298
300 if (mMemoryDNA->getNumNames() != mFileDNA->getNumNames())
301 {
302 mFlags |= FD_VERSION_VARIES;
303 //printf ("Warning, file DNA is different than built in, performance is reduced. Best to re-export file with a matching version/platform");
304 }
305
306 // as long as it kept up to date it will be ok!!
307 if (mMemoryDNA->lessThan(mFileDNA))
308 {
309 //printf ("Warning, file DNA is newer than built in.");
310 }
311
312
313 mFileDNA->initCmpFlags(mMemoryDNA);
314
315 parseData();
316
317 resolvePointers(verboseMode);
318
319 updateOldPointers();
320
321
322 }
323
324
325
326 // ----------------------------------------------------- //
327 void bFile::swap(char *head, bChunkInd& dataChunk, bool ignoreEndianFlag)
328 {
329 char *data = head;
330 short *strc = mFileDNA->getStruct(dataChunk.dna_nr);
331
332
333
334 const char s[] = "SoftBodyMaterialData";
335 int szs = sizeof(s);
336 if (strncmp((char*)&dataChunk.code,"ARAY",4)==0)
337 {
338 short *oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
339 char *oldType = mFileDNA->getType(oldStruct[0]);
340 if (strncmp(oldType,s,szs)==0)
341 {
342 return;
343 }
344 }
345
346
347 int len = mFileDNA->getLength(strc[0]);
348
349 for (int i=0; i<dataChunk.nr; i++)
350 {
351 swapStruct(dataChunk.dna_nr, data,ignoreEndianFlag);
352 data+=len;
353 }
354 }
355
356 void bFile::swapLen(char *dataPtr)
357 {
358 const bool VOID_IS_8 = ((sizeof(void*)==8));
359 if (VOID_IS_8)
360 {
361 if (mFlags &FD_BITS_VARIES)
362 {
363 bChunkPtr4*c = (bChunkPtr4*) dataPtr;
364 if ((c->code & 0xFFFF)==0)
365 c->code >>=16;
366 SWITCH_INT(c->len);
367 SWITCH_INT(c->dna_nr);
368 SWITCH_INT(c->nr);
369 } else
370 {
371 bChunkPtr8* c = (bChunkPtr8*) dataPtr;
372 if ((c->code & 0xFFFF)==0)
373 c->code >>=16;
374 SWITCH_INT(c->len);
375 SWITCH_INT(c->dna_nr);
376 SWITCH_INT(c->nr);
377
378 }
379 } else
380 {
381 if (mFlags &FD_BITS_VARIES)
382 {
383 bChunkPtr8*c = (bChunkPtr8*) dataPtr;
384 if ((c->code & 0xFFFF)==0)
385 c->code >>=16;
386 SWITCH_INT(c->len);
387 SWITCH_INT(c->dna_nr);
388 SWITCH_INT(c->nr);
389
390 } else
391 {
392 bChunkPtr4* c = (bChunkPtr4*) dataPtr;
393 if ((c->code & 0xFFFF)==0)
394 c->code >>=16;
395 SWITCH_INT(c->len);
396
397 SWITCH_INT(c->dna_nr);
398 SWITCH_INT(c->nr);
399
400 }
401 }
402
403 }
404
405
406 void bFile::swapDNA(char* ptr)
407 {
408 bool swap = ((mFlags & FD_ENDIAN_SWAP)!=0);
409
410 int offset = (mFlags & FD_FILE_64)? 24 : 20;
411 char* data = &ptr[offset];
412
413 // void bDNA::init(char *data, int len, bool swap)
414 int *intPtr=0;short *shtPtr=0;
415 char *cp = 0;int dataLen =0;
416 intPtr = (int*)data;
417
418 /*
419 SDNA (4 bytes) (magic number)
420 NAME (4 bytes)
421 <nr> (4 bytes) amount of names (int)
422 <string>
423 <string>
424 */
425
426 if (strncmp(data, "SDNA", 4)==0)
427 {
428 // skip ++ NAME
429 intPtr++;
430 intPtr++;
431 } else
432 {
433
434 if (strncmp(data+4, "SDNA", 4)==0)
435 {
436 // skip ++ NAME
437 intPtr++;
438 intPtr++;
439 intPtr++;
440 }
441 }
442
443
444
445
446 // Parse names
447 if (swap)
448 dataLen = ChunkUtils::swapInt(*intPtr);
449 else
450 dataLen = *intPtr;
451
452 *intPtr = ChunkUtils::swapInt(*intPtr);
453 intPtr++;
454
455 cp = (char*)intPtr;
456 int i;
457 for ( i=0; i<dataLen; i++)
458 {
459 while (*cp)cp++;
460 cp++;
461 }
462
463
464 cp = btAlignPointer(cp,4);
465
466
467 /*
468 TYPE (4 bytes)
469 <nr> amount of types (int)
470 <string>
471 <string>
472 */
473
474 intPtr = (int*)cp;
475 assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
476
477 if (swap)
478 dataLen = ChunkUtils::swapInt(*intPtr);
479 else
480 dataLen = *intPtr;
481
482 *intPtr = ChunkUtils::swapInt(*intPtr);
483
484 intPtr++;
485
486 cp = (char*)intPtr;
487 for ( i=0; i<dataLen; i++)
488 {
489 while (*cp)cp++;
490 cp++;
491 }
492
493 cp = btAlignPointer(cp,4);
494
495 /*
496 TLEN (4 bytes)
497 <len> (short) the lengths of types
498 <len>
499 */
500
501 // Parse type lens
502 intPtr = (int*)cp;
503 assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
504
505
506 shtPtr = (short*)intPtr;
507 for ( i=0; i<dataLen; i++, shtPtr++)
508 {
509 //??????if (swap)
510 shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
511 }
512
513 if (dataLen & 1)
514 shtPtr++;
515
516 /*
517 STRC (4 bytes)
518 <nr> amount of structs (int)
519 <typenr>
520 <nr_of_elems>
521 <typenr>
522 <namenr>
523 <typenr>
524 <namenr>
525 */
526
527 intPtr = (int*)shtPtr;
528 cp = (char*)intPtr;
529 assert(strncmp(cp, "STRC", 4)==0);
530 intPtr++;
531
532 if (swap)
533 dataLen = ChunkUtils::swapInt(*intPtr);
534 else
535 dataLen = *intPtr;
536
537 *intPtr = ChunkUtils::swapInt(*intPtr);
538
539 intPtr++;
540
541
542 shtPtr = (short*)intPtr;
543 for ( i=0; i<dataLen; i++)
544 {
545
546 //if (swap)
547 {
548 int len = shtPtr[1];
549
550 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
551 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
552
553 shtPtr+= 2;
554
555 for (int a=0; a<len; a++, shtPtr+=2)
556 {
557 shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
558 shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
559 }
560 }
561 // else
562 // shtPtr+= (2*shtPtr[1])+2;
563 }
564
565 }
566
567 void bFile::writeFile(const char* fileName)
568 {
569 FILE* f = fopen(fileName,"wb");
570 fwrite(mFileBuffer,1,mFileLen,f);
571 fclose(f);
572 }
573
574 void bFile::preSwap()
575 {
576
577 //const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
578 //FD_ENDIAN_SWAP
579 //byte 8 determines the endianness of the file, little (v) versus big (V)
580 int littleEndian= 1;
581 littleEndian= ((char*)&littleEndian)[0];
582
583
584 if (mFileBuffer[8]=='V')
585 {
586 mFileBuffer[8]='v';
587 }
588 else
589 {
590 mFileBuffer[8]='V';
591 }
592
593
594
595
596
597
598 mDataStart = 12;
599
600 char *dataPtr = mFileBuffer+mDataStart;
601
602 bChunkInd dataChunk;
603 dataChunk.code = 0;
604 bool ignoreEndianFlag = true;
605
606 //we always want to swap here
607
608 int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
609 //dataPtr += ChunkUtils::getOffset(mFlags);
610 char *dataPtrHead = 0;
611
612 while (1)
613 {
614 // one behind
615 if (dataChunk.code == SDNA || dataChunk.code==DNA1 || dataChunk.code == TYPE || dataChunk.code == TLEN || dataChunk.code==STRC)
616 {
617
618 swapDNA(dataPtr);
619 break;
620 } else
621 {
622 //if (dataChunk.code == DNA1) break;
623 dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
624
625 swapLen(dataPtr);
626 if (dataChunk.dna_nr>=0)
627 {
628 swap(dataPtrHead, dataChunk,ignoreEndianFlag);
629 } else
630 {
631 //printf("unknown chunk\n");
632 }
633 }
634
635 // next please!
636 dataPtr += seek;
637
638 seek = getNextBlock(&dataChunk, dataPtr, mFlags);
639 if (seek < 0)
640 break;
641 }
642
643 if (mFlags & FD_ENDIAN_SWAP)
644 {
645 mFlags &= ~FD_ENDIAN_SWAP;
646 } else
647 {
648 mFlags |= FD_ENDIAN_SWAP;
649 }
650
651
652
653 }
654
655
656 // ----------------------------------------------------- //
657 char* bFile::readStruct(char *head, bChunkInd& dataChunk)
658 {
659 bool ignoreEndianFlag = false;
660
661 if (mFlags & FD_ENDIAN_SWAP)
662 swap(head, dataChunk, ignoreEndianFlag);
663
664
665
666 if (!mFileDNA->flagEqual(dataChunk.dna_nr))
667 {
668 // Ouch! need to rebuild the struct
669 short *oldStruct,*curStruct;
670 char *oldType, *newType;
671 int oldLen, curLen, reverseOld;
672
673
674 oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
675 oldType = mFileDNA->getType(oldStruct[0]);
676
677 oldLen = mFileDNA->getLength(oldStruct[0]);
678
679 if ((mFlags&FD_BROKEN_DNA)!=0)
680 {
681 if ((strcmp(oldType,"btQuantizedBvhNodeData")==0)&&oldLen==20)
682 {
683 return 0;
684 }
685 if ((strcmp(oldType,"btShortIntIndexData")==0))
686 {
687 int allocLen = 2;
688 char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
689 memset(dataAlloc, 0, (dataChunk.nr*allocLen)+1);
690 short* dest = (short*) dataAlloc;
691 const short* src = (short*) head;
692 for (int i=0;i<dataChunk.nr;i++)
693 {
694 dest[i] = src[i];
695 if (mFlags &FD_ENDIAN_SWAP)
696 {
697 SWITCH_SHORT(dest[i]);
698 }
699 }
700 addDataBlock(dataAlloc);
701 return dataAlloc;
702 }
703 }
704
705
706
708 if (strcmp("Link",oldType)!=0)
709 {
710 reverseOld = mMemoryDNA->getReverseType(oldType);
711
712 if ((reverseOld!=-1))
713 {
714 // make sure it's here
715 //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
716
717 //
718 curStruct = mMemoryDNA->getStruct(reverseOld);
719 newType = mMemoryDNA->getType(curStruct[0]);
720 curLen = mMemoryDNA->getLength(curStruct[0]);
721
722
723
724 // make sure it's the same
725 assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
726
727
728 numallocs++;
729 // numBlocks * length
730
731 int allocLen = (curLen);
732 char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
733 memset(dataAlloc, 0, (dataChunk.nr*allocLen));
734
735 // track allocated
736 addDataBlock(dataAlloc);
737
738 char *cur = dataAlloc;
739 char *old = head;
740 for (int block=0; block<dataChunk.nr; block++)
741 {
742 bool fixupPointers = true;
743 parseStruct(cur, old, dataChunk.dna_nr, reverseOld, fixupPointers);
744 mLibPointers.insert(old,(bStructHandle*)cur);
745
746 cur += curLen;
747 old += oldLen;
748 }
749 return dataAlloc;
750 }
751 } else
752 {
753 //printf("Link found\n");
754 }
755 } else
756 {
757 //#define DEBUG_EQUAL_STRUCTS
758 #ifdef DEBUG_EQUAL_STRUCTS
759 short *oldStruct;
760 char *oldType;
761 oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
762 oldType = mFileDNA->getType(oldStruct[0]);
763 printf("%s equal structure, just memcpy\n",oldType);
764 #endif //
765 }
766
767
768 char *dataAlloc = new char[(dataChunk.len)+1];
769 memset(dataAlloc, 0, dataChunk.len+1);
770
771
772 // track allocated
773 addDataBlock(dataAlloc);
774
775 memcpy(dataAlloc, head, dataChunk.len);
776 return dataAlloc;
777
778 }
779
780
781 // ----------------------------------------------------- //
782 void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers)
783 {
784 if (old_dna == -1) return;
785 if (new_dna == -1) return;
786
787 //disable this, because we need to fixup pointers/ListBase
788 if (0)//mFileDNA->flagEqual(old_dna))
789 {
790 short *strc = mFileDNA->getStruct(old_dna);
791 int len = mFileDNA->getLength(strc[0]);
792
793 memcpy(strcPtr, dtPtr, len);
794 return;
795 }
796
797 // Ok, now build the struct
798 char *memType, *memName, *cpc, *cpo;
799 short *fileStruct, *filePtrOld, *memoryStruct, *firstStruct;
800 int elementLength, size, revType, old_nr, new_nr, fpLen;
801 short firstStructType;
802
803
804 // File to memory lookup
805 memoryStruct = mMemoryDNA->getStruct(new_dna);
806 fileStruct = mFileDNA->getStruct(old_dna);
807 firstStruct = fileStruct;
808
809
810 filePtrOld = fileStruct;
811 firstStructType = mMemoryDNA->getStruct(0)[0];
812
813 // Get number of elements
814 elementLength = memoryStruct[1];
815 memoryStruct+=2;
816
817 cpc = strcPtr; cpo = 0;
818 for (int ele=0; ele<elementLength; ele++, memoryStruct+=2)
819 {
820 memType = mMemoryDNA->getType(memoryStruct[0]);
821 memName = mMemoryDNA->getName(memoryStruct[1]);
822
823
824 size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]);
825 revType = mMemoryDNA->getReverseType(memoryStruct[0]);
826
827 if (revType != -1 && memoryStruct[0]>=firstStructType && memName[0] != '*')
828 {
829 cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld);
830 if (cpo)
831 {
832 int arrayLen = mFileDNA->getArraySizeNew(filePtrOld[1]);
833 old_nr = mFileDNA->getReverseType(memType);
834 new_nr = revType;
835 fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]);
836 if (arrayLen==1)
837 {
838 parseStruct(cpc, cpo, old_nr, new_nr,fixupPointers);
839 } else
840 {
841 char* tmpCpc = cpc;
842 char* tmpCpo = cpo;
843
844 for (int i=0;i<arrayLen;i++)
845 {
846 parseStruct(tmpCpc, tmpCpo, old_nr, new_nr,fixupPointers);
847 tmpCpc += size/arrayLen;
848 tmpCpo += fpLen/arrayLen;
849 }
850 }
851 cpc+=size;
852 cpo+=fpLen;
853 }
854 else
855 cpc+=size;
856 }
857 else
858 {
859 getMatchingFileDNA(fileStruct, memName, memType, cpc, dtPtr,fixupPointers);
860 cpc+=size;
861 }
862
863 }
864 }
865
866
867 // ----------------------------------------------------- //
868 static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData)
869 {
870 #define getEle(value, current, type, cast, size, ptr)\
871 if (strcmp(current, type)==0)\
872 {\
873 value = (*(cast*)ptr);\
874 ptr += size;\
875 }
876
877 #define setEle(value, current, type, cast, size, ptr)\
878 if (strcmp(current, type)==0)\
879 {\
880 (*(cast*)ptr) = (cast)value;\
881 ptr += size;\
882 }
883 double value = 0.0;
884
885 for (int i=0; i<arrayLen; i++)
886 {
887 getEle(value, old, "char", char, sizeof(char), oldPtr);
888 setEle(value, cur, "char", char, sizeof(char), curData);
889 getEle(value, old, "short", short, sizeof(short), oldPtr);
890 setEle(value, cur, "short", short, sizeof(short), curData);
891 getEle(value, old, "ushort", unsigned short, sizeof(unsigned short), oldPtr);
892 setEle(value, cur, "ushort", unsigned short, sizeof(unsigned short), curData);
893 getEle(value, old, "int", int, sizeof(int), oldPtr);
894 setEle(value, cur, "int", int, sizeof(int), curData);
895 getEle(value, old, "long", int, sizeof(int), oldPtr);
896 setEle(value, cur, "long", int, sizeof(int), curData);
897 getEle(value, old, "float", float, sizeof(float), oldPtr);
898 setEle(value, cur, "float", float, sizeof(float), curData);
899 getEle(value, old, "double", double, sizeof(double), oldPtr);
900 setEle(value, cur, "double", double, sizeof(double), curData);
901 }
902 }
903
904
905 // ----------------------------------------------------- //
906 void bFile::swapData(char *data, short type, int arraySize,bool ignoreEndianFlag)
907 {
908 if (ignoreEndianFlag || (mFlags &FD_ENDIAN_SWAP))
909 {
910 if (type == 2 || type == 3)
911 {
912 short *sp = (short*)data;
913 for (int i=0; i<arraySize; i++)
914 {
915 sp[0] = ChunkUtils::swapShort(sp[0]);
916 sp++;
917 }
918 }
919 if (type>3 && type <8)
920 {
921 char c;
922 char *cp = data;
923 for (int i=0; i<arraySize; i++)
924 {
925 c = cp[0];
926 cp[0] = cp[3];
927 cp[3] = c;
928 c = cp[1];
929 cp[1] = cp[2];
930 cp[2] = c;
931 cp+=4;
932 }
933 }
934 }
935 }
936
937
938
939 void bFile::safeSwapPtr(char *dst, const char *src)
940 {
941 int ptrFile = mFileDNA->getPointerSize();
942 int ptrMem = mMemoryDNA->getPointerSize();
943
944 if (!src && !dst)
945 return;
946
947
948 if (ptrFile == ptrMem)
949 {
950 memcpy(dst, src, ptrMem);
951 }
952 else if (ptrMem==4 && ptrFile==8)
953 {
954 btPointerUid* oldPtr = (btPointerUid*)src;
955 btPointerUid* newPtr = (btPointerUid*)dst;
956
957 if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
958 {
959 //Bullet stores the 32bit unique ID in both upper and lower part of 64bit pointers
960 //so it can be used to distinguish between .blend and .bullet
961 newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
962 } else
963 {
964 //deal with pointers the Blender .blend style way, see
965 //readfile.c in the Blender source tree
966 long64 longValue = *((long64*)src);
967 //endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros
968 if (mFlags & FD_ENDIAN_SWAP)
969 SWITCH_LONGINT(longValue);
970 *((int*)dst) = (int)(longValue>>3);
971 }
972
973 }
974 else if (ptrMem==8 && ptrFile==4)
975 {
976 btPointerUid* oldPtr = (btPointerUid*)src;
977 btPointerUid* newPtr = (btPointerUid*)dst;
978 if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
979 {
980 newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
981 newPtr->m_uniqueIds[1] = 0;
982 } else
983 {
984 *((long64*)dst)= *((int*)src);
985 }
986 }
987 else
988 {
989 printf ("%d %d\n", ptrFile,ptrMem);
990 assert(0 && "Invalid pointer len");
991 }
992
993
994 }
995
996
997 // ----------------------------------------------------- //
998 void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers)
999 {
1000 // find the matching memory dna data
1001 // to the file being loaded. Fill the
1002 // memory with the file data...
1003
1004 int len = dna_addr[1];
1005 dna_addr+=2;
1006
1007 for (int i=0; i<len; i++, dna_addr+=2)
1008 {
1009 const char* type = mFileDNA->getType(dna_addr[0]);
1010 const char* name = mFileDNA->getName(dna_addr[1]);
1011
1012
1013
1014 int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]);
1015
1016 if ((mFlags&FD_BROKEN_DNA)!=0)
1017 {
1018 if ((strcmp(type,"short")==0)&&(strcmp(name,"int")==0))
1019 {
1020 eleLen = 0;
1021 }
1022 }
1023
1024 if (strcmp(lookupName, name)==0)
1025 {
1026 //int arrayLenold = mFileDNA->getArraySize((char*)name.c_str());
1027 int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]);
1028 //assert(arrayLenold == arrayLen);
1029
1030 if (name[0] == '*')
1031 {
1032 // cast pointers
1033 int ptrFile = mFileDNA->getPointerSize();
1034 int ptrMem = mMemoryDNA->getPointerSize();
1035 safeSwapPtr(strcData,data);
1036
1037 if (fixupPointers)
1038 {
1039 if (arrayLen > 1)
1040 {
1041 //void **sarray = (void**)strcData;
1042 //void **darray = (void**)data;
1043
1044 char *cpc, *cpo;
1045 cpc = (char*)strcData;
1046 cpo = (char*)data;
1047
1048 for (int a=0; a<arrayLen; a++)
1049 {
1050 safeSwapPtr(cpc, cpo);
1051 m_pointerFixupArray.push_back(cpc);
1052 cpc += ptrMem;
1053 cpo += ptrFile;
1054 }
1055 }
1056 else
1057 {
1058 if (name[1] == '*')
1059 m_pointerPtrFixupArray.push_back(strcData);
1060 else
1061 m_pointerFixupArray.push_back(strcData);
1062 }
1063 }
1064 else
1065 {
1066 // printf("skipped %s %s : %x\n",type.c_str(),name.c_str(),strcData);
1067 }
1068
1069 }
1070
1071 else if (strcmp(type, lookupType)==0)
1072 memcpy(strcData, data, eleLen);
1073 else
1074 getElement(arrayLen, lookupType, type, data, strcData);
1075
1076 // --
1077 return;
1078 }
1079 data+=eleLen;
1080 }
1081 }
1082
1083
1084 // ----------------------------------------------------- //
1085 char* bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos)
1086 {
1087 short *old = firstStruct;//mFileDNA->getStruct(old_nr);
1088 int elementLength = old[1];
1089 old+=2;
1090
1091 for (int i=0; i<elementLength; i++, old+=2)
1092 {
1093 char* type = mFileDNA->getType(old[0]);
1094 char* name = mFileDNA->getName(old[1]);
1095 int len = mFileDNA->getElementSize(old[0], old[1]);
1096
1097 if (strcmp(lookupName, name)==0)
1098 {
1099 if (strcmp(type, lookupType)==0)
1100 {
1101 if (foundPos)
1102 *foundPos = old;
1103 return data;
1104 }
1105 return 0;
1106 }
1107 data+=len;
1108 }
1109 return 0;
1110 }
1111
1112
1113 // ----------------------------------------------------- //
1114 void bFile::swapStruct(int dna_nr, char *data,bool ignoreEndianFlag)
1115 {
1116 if (dna_nr == -1) return;
1117
1118 short *strc = mFileDNA->getStruct(dna_nr);
1119 //short *firstStrc = strc;
1120
1121 int elementLen= strc[1];
1122 strc+=2;
1123
1124 short first = mFileDNA->getStruct(0)[0];
1125
1126 char *buf = data;
1127 for (int i=0; i<elementLen; i++, strc+=2)
1128 {
1129 char *type = mFileDNA->getType(strc[0]);
1130 char *name = mFileDNA->getName(strc[1]);
1131
1132 int size = mFileDNA->getElementSize(strc[0], strc[1]);
1133 if (strc[0] >= first && name[0]!='*')
1134 {
1135 int old_nr = mFileDNA->getReverseType(type);
1136 int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
1137 if (arrayLen==1)
1138 {
1139 swapStruct(old_nr,buf,ignoreEndianFlag);
1140 } else
1141 {
1142 char* tmpBuf = buf;
1143 for (int i=0;i<arrayLen;i++)
1144 {
1145 swapStruct(old_nr,tmpBuf,ignoreEndianFlag);
1146 tmpBuf+=size/arrayLen;
1147 }
1148 }
1149 }
1150 else
1151 {
1152 //int arrayLenOld = mFileDNA->getArraySize(name);
1153 int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
1154 //assert(arrayLenOld == arrayLen);
1155 swapData(buf, strc[0], arrayLen,ignoreEndianFlag);
1156 }
1157 buf+=size;
1158 }
1159 }
1160
1161 void bFile::resolvePointersMismatch()
1162 {
1163 // printf("resolvePointersStructMismatch\n");
1164
1165 int i;
1166
1167 for (i=0;i< m_pointerFixupArray.size();i++)
1168 {
1169 char* cur = m_pointerFixupArray.at(i);
1170 void** ptrptr = (void**) cur;
1171 void* ptr = *ptrptr;
1172 ptr = findLibPointer(ptr);
1173 if (ptr)
1174 {
1175 //printf("Fixup pointer!\n");
1176 *(ptrptr) = ptr;
1177 } else
1178 {
1179 // printf("pointer not found: %x\n",cur);
1180 }
1181 }
1182
1183
1184 for (i=0; i<m_pointerPtrFixupArray.size(); i++)
1185 {
1186 char* cur= m_pointerPtrFixupArray.at(i);
1187 void** ptrptr = (void**)cur;
1188
1189 bChunkInd *block = m_chunkPtrPtrMap.find(*ptrptr);
1190 if (block)
1191 {
1192 int ptrMem = mMemoryDNA->getPointerSize();
1193 int ptrFile = mFileDNA->getPointerSize();
1194
1195
1196 int blockLen = block->len / ptrFile;
1197
1198 void *onptr = findLibPointer(*ptrptr);
1199 if (onptr)
1200 {
1201 char *newPtr = new char[blockLen * ptrMem];
1202 addDataBlock(newPtr);
1203 memset(newPtr, 0, blockLen * ptrMem);
1204
1205 void **onarray = (void**)onptr;
1206 char *oldPtr = (char*)onarray;
1207
1208 int p = 0;
1209 while (blockLen-- > 0)
1210 {
1211 btPointerUid dp = {{0}};
1212 safeSwapPtr((char*)dp.m_uniqueIds, oldPtr);
1213
1214 void **tptr = (void**)(newPtr + p * ptrMem);
1215 *tptr = findLibPointer(dp.m_ptr);
1216
1217 oldPtr += ptrFile;
1218 ++p;
1219 }
1220
1221 *ptrptr = newPtr;
1222 }
1223 }
1224 }
1225 }
1226
1227
1229 void bFile::resolvePointersChunk(const bChunkInd& dataChunk, int verboseMode)
1230 {
1231 bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1232
1233 short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
1234 short oldLen = fileDna->getLength(oldStruct[0]);
1235 //char* structType = fileDna->getType(oldStruct[0]);
1236
1237 char* cur = (char*)findLibPointer(dataChunk.oldPtr);
1238 for (int block=0; block<dataChunk.nr; block++)
1239 {
1240 resolvePointersStructRecursive(cur,dataChunk.dna_nr, verboseMode,1);
1241 cur += oldLen;
1242 }
1243 }
1244
1245
1246 int bFile::resolvePointersStructRecursive(char *strcPtr, int dna_nr, int verboseMode,int recursion)
1247 {
1248
1249 bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1250
1251 char* memType;
1252 char* memName;
1253 short firstStructType = fileDna->getStruct(0)[0];
1254
1255
1256 char* elemPtr= strcPtr;
1257
1258 short int* oldStruct = fileDna->getStruct(dna_nr);
1259
1260 int elementLength = oldStruct[1];
1261 oldStruct+=2;
1262
1263 int totalSize = 0;
1264
1265 for (int ele=0; ele<elementLength; ele++, oldStruct+=2)
1266 {
1267
1268 memType = fileDna->getType(oldStruct[0]);
1269 memName = fileDna->getName(oldStruct[1]);
1270
1271
1272
1273 int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
1274 if (memName[0] == '*')
1275 {
1276 if (arrayLen > 1)
1277 {
1278 void **array= (void**)elemPtr;
1279 for (int a=0; a<arrayLen; a++)
1280 {
1281 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1282 {
1283 for (int i=0;i<recursion;i++)
1284 {
1285 printf(" ");
1286 }
1287 //skip the *
1288 printf("<%s type=\"pointer\"> ",&memName[1]);
1289 printf("%p ", array[a]);
1290 printf("</%s>\n",&memName[1]);
1291 }
1292
1293 array[a] = findLibPointer(array[a]);
1294 }
1295 }
1296 else
1297 {
1298 void** ptrptr = (void**) elemPtr;
1299 void* ptr = *ptrptr;
1300 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1301 {
1302 for (int i=0;i<recursion;i++)
1303 {
1304 printf(" ");
1305 }
1306 printf("<%s type=\"pointer\"> ",&memName[1]);
1307 printf("%p ", ptr);
1308 printf("</%s>\n",&memName[1]);
1309 }
1310 ptr = findLibPointer(ptr);
1311
1312 if (ptr)
1313 {
1314 // printf("Fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
1315 *(ptrptr) = ptr;
1316 if (memName[1] == '*' && ptrptr && *ptrptr)
1317 {
1318 // This will only work if the given **array is continuous
1319 void **array= (void**)*(ptrptr);
1320 void *np= array[0];
1321 int n=0;
1322 while (np)
1323 {
1324 np= findLibPointer(array[n]);
1325 if (np) array[n]= np;
1326 n++;
1327 }
1328 }
1329 } else
1330 {
1331 // printf("Cannot fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
1332 }
1333 }
1334 } else
1335 {
1336 int revType = fileDna->getReverseType(oldStruct[0]);
1337 if (oldStruct[0]>=firstStructType) //revType != -1 &&
1338 {
1339 char cleanName[MAX_STRLEN];
1340 getCleanName(memName,cleanName);
1341
1342 int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
1343 int byteOffset = 0;
1344
1345 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1346 {
1347 for (int i=0;i<recursion;i++)
1348 {
1349 printf(" ");
1350 }
1351
1352 if (arrayLen>1)
1353 {
1354 printf("<%s type=\"%s\" count=%d>\n",cleanName,memType, arrayLen);
1355 } else
1356 {
1357 printf("<%s type=\"%s\">\n",cleanName,memType);
1358 }
1359 }
1360
1361 for (int i=0;i<arrayLen;i++)
1362 {
1363 byteOffset += resolvePointersStructRecursive(elemPtr+byteOffset,revType, verboseMode,recursion+1);
1364 }
1365 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1366 {
1367 for (int i=0;i<recursion;i++)
1368 {
1369 printf(" ");
1370 }
1371 printf("</%s>\n",cleanName);
1372 }
1373 } else
1374 {
1375 //export a simple type
1376 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1377 {
1378
1379 if (arrayLen>MAX_ARRAY_LENGTH)
1380 {
1381 printf("too long\n");
1382 } else
1383 {
1384 //printf("%s %s\n",memType,memName);
1385
1386 bool isIntegerType = (strcmp(memType,"char")==0) || (strcmp(memType,"int")==0) || (strcmp(memType,"short")==0);
1387
1388 if (isIntegerType)
1389 {
1390 const char* newtype="int";
1391 int dbarray[MAX_ARRAY_LENGTH];
1392 int* dbPtr = 0;
1393 char* tmp = elemPtr;
1394 dbPtr = &dbarray[0];
1395 if (dbPtr)
1396 {
1397 char cleanName[MAX_STRLEN];
1398 getCleanName(memName,cleanName);
1399
1400 int i;
1401 getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
1402 for (i=0;i<recursion;i++)
1403 printf(" ");
1404 if (arrayLen==1)
1405 printf("<%s type=\"%s\">",cleanName,memType);
1406 else
1407 printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen);
1408 for (i=0;i<arrayLen;i++)
1409 printf(" %d ",dbPtr[i]);
1410 printf("</%s>\n",cleanName);
1411 }
1412 } else
1413 {
1414 const char* newtype="double";
1415 double dbarray[MAX_ARRAY_LENGTH];
1416 double* dbPtr = 0;
1417 char* tmp = elemPtr;
1418 dbPtr = &dbarray[0];
1419 if (dbPtr)
1420 {
1421 int i;
1422 getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
1423 for (i=0;i<recursion;i++)
1424 printf(" ");
1425 char cleanName[MAX_STRLEN];
1426 getCleanName(memName,cleanName);
1427
1428 if (arrayLen==1)
1429 {
1430 printf("<%s type=\"%s\">",memName,memType);
1431 }
1432 else
1433 {
1434 printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen);
1435 }
1436 for (i=0;i<arrayLen;i++)
1437 printf(" %f ",dbPtr[i]);
1438 printf("</%s>\n",cleanName);
1439 }
1440 }
1441 }
1442
1443 }
1444 }
1445 }
1446
1447 int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]);
1448 totalSize += size;
1449 elemPtr+=size;
1450
1451 }
1452
1453 return totalSize;
1454 }
1455
1456
1458 void bFile::resolvePointers(int verboseMode)
1459 {
1460 bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1461
1462 //char *dataPtr = mFileBuffer+mDataStart;
1463
1464 if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES))
1465 {
1466 resolvePointersMismatch();
1467 }
1468
1469 {
1470
1471 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1472 {
1473 printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
1474 int numitems = m_chunks.size();
1475 printf("<bullet_physics version=%d itemcount = %d>\n", btGetVersion(), numitems);
1476 }
1477 for (int i=0;i<m_chunks.size();i++)
1478 {
1479 const bChunkInd& dataChunk = m_chunks.at(i);
1480
1481 if (!mFileDNA || fileDna->flagEqual(dataChunk.dna_nr))
1482 {
1483 //dataChunk.len
1484 short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
1485 char* oldType = fileDna->getType(oldStruct[0]);
1486
1487 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1488 printf(" <%s pointer=%p>\n",oldType,dataChunk.oldPtr);
1489
1490 resolvePointersChunk(dataChunk, verboseMode);
1491
1492 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1493 printf(" </%s>\n",oldType);
1494 } else
1495 {
1496 //printf("skipping mStruct\n");
1497 }
1498 }
1499 if (verboseMode & FD_VERBOSE_EXPORT_XML)
1500 {
1501 printf("</bullet_physics>\n");
1502 }
1503 }
1504
1505
1506 }
1507
1508
1509 // ----------------------------------------------------- //
1510 void* bFile::findLibPointer(void *ptr)
1511 {
1512
1513 bStructHandle** ptrptr = getLibPointers().find(ptr);
1514 if (ptrptr)
1515 return *ptrptr;
1516 return 0;
1517 }
1518
1519
1520 void bFile::updateOldPointers()
1521 {
1522 int i;
1523
1524 for (i=0;i<m_chunks.size();i++)
1525 {
1526 bChunkInd& dataChunk = m_chunks[i];
1527 dataChunk.oldPtr = findLibPointer(dataChunk.oldPtr);
1528 }
1529 }
1530 void bFile::dumpChunks(bParse::bDNA* dna)
1531 {
1532 int i;
1533
1534 for (i=0;i<m_chunks.size();i++)
1535 {
1536 bChunkInd& dataChunk = m_chunks[i];
1537 char* codeptr = (char*)&dataChunk.code;
1538 char codestr[5] = {codeptr[0],codeptr[1],codeptr[2],codeptr[3],0};
1539
1540 short* newStruct = dna->getStruct(dataChunk.dna_nr);
1541 char* typeName = dna->getType(newStruct[0]);
1542 printf("%3d: %s ",i,typeName);
1543
1544 printf("code=%s ",codestr);
1545
1546 printf("ptr=%p ",dataChunk.oldPtr);
1547 printf("len=%d ",dataChunk.len);
1548 printf("nr=%d ",dataChunk.nr);
1549 if (dataChunk.nr!=1)
1550 {
1551 printf("not 1\n");
1552 }
1553 printf("\n");
1554
1555
1556
1557
1558 }
1559
1560 #if 0
1561 IDFinderData ifd;
1562 ifd.success = 0;
1563 ifd.IDname = NULL;
1564 ifd.just_print_it = 1;
1565 for (i=0; i<bf->m_blocks.size(); ++i)
1566 {
1567 BlendBlock* bb = bf->m_blocks[i];
1568 printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]", bb->tag, bb,bf->types[bb->type_index].name,bb->m_array_entries_.size());
1569 block_ID_finder(bb, bf, &ifd);
1570 printf("\n");
1571 }
1572 #endif
1573
1574 }
1575
1576
1577 void bFile::writeChunks(FILE* fp, bool fixupPointers)
1578 {
1579 bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1580
1581 for (int i=0;i<m_chunks.size();i++)
1582 {
1583 bChunkInd& dataChunk = m_chunks.at(i);
1584
1585 // Ouch! need to rebuild the struct
1586 short *oldStruct,*curStruct;
1587 char *oldType, *newType;
1588 int curLen, reverseOld;
1589
1590 oldStruct = fileDna->getStruct(dataChunk.dna_nr);
1591 oldType = fileDna->getType(oldStruct[0]);
1592 //int oldLen = fileDna->getLength(oldStruct[0]);
1594 reverseOld = mMemoryDNA->getReverseType(oldType);
1595
1596
1597 if ((reverseOld!=-1))
1598 {
1599 // make sure it's here
1600 //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
1601 //
1602 curStruct = mMemoryDNA->getStruct(reverseOld);
1603 newType = mMemoryDNA->getType(curStruct[0]);
1604 // make sure it's the same
1605 assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
1606
1607
1608 curLen = mMemoryDNA->getLength(curStruct[0]);
1609 dataChunk.dna_nr = reverseOld;
1610 if (strcmp("Link",oldType)!=0)
1611 {
1612 dataChunk.len = curLen * dataChunk.nr;
1613 } else
1614 {
1615 // printf("keep length of link = %d\n",dataChunk.len);
1616 }
1617
1618 //write the structure header
1619 fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
1620
1621
1622
1623 short int* curStruct1;
1624 curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr);
1625 assert(curStruct1 == curStruct);
1626
1627 char* cur = fixupPointers ? (char*)findLibPointer(dataChunk.oldPtr) : (char*)dataChunk.oldPtr;
1628
1629 //write the actual contents of the structure(s)
1630 fwrite(cur,dataChunk.len,1,fp);
1631 } else
1632 {
1633 printf("serious error, struct mismatch: don't write\n");
1634 }
1635 }
1636
1637 }
1638
1639
1640 // ----------------------------------------------------- //
1641 int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
1642 {
1643 bool swap = false;
1644 bool varies = false;
1645
1646 if (flags &FD_ENDIAN_SWAP)
1647 swap = true;
1648 if (flags &FD_BITS_VARIES)
1649 varies = true;
1650
1651 if (VOID_IS_8)
1652 {
1653 if (varies)
1654 {
1655 bChunkPtr4 head;
1656 memcpy(&head, dataPtr, sizeof(bChunkPtr4));
1657
1658
1659 bChunkPtr8 chunk;
1660
1661 chunk.code = head.code;
1662 chunk.len = head.len;
1663 chunk.m_uniqueInts[0] = head.m_uniqueInt;
1664 chunk.m_uniqueInts[1] = 0;
1665 chunk.dna_nr = head.dna_nr;
1666 chunk.nr = head.nr;
1667
1668 if (swap)
1669 {
1670 if ((chunk.code & 0xFFFF)==0)
1671 chunk.code >>=16;
1672
1673 SWITCH_INT(chunk.len);
1674 SWITCH_INT(chunk.dna_nr);
1675 SWITCH_INT(chunk.nr);
1676 }
1677
1678
1679 memcpy(dataChunk, &chunk, sizeof(bChunkInd));
1680 }
1681 else
1682 {
1683 bChunkPtr8 c;
1684 memcpy(&c, dataPtr, sizeof(bChunkPtr8));
1685
1686 if (swap)
1687 {
1688 if ((c.code & 0xFFFF)==0)
1689 c.code >>=16;
1690
1691 SWITCH_INT(c.len);
1692 SWITCH_INT(c.dna_nr);
1693 SWITCH_INT(c.nr);
1694 }
1695
1696 memcpy(dataChunk, &c, sizeof(bChunkInd));
1697 }
1698 }
1699 else
1700 {
1701 if (varies)
1702 {
1703 bChunkPtr8 head;
1704 memcpy(&head, dataPtr, sizeof(bChunkPtr8));
1705
1706
1707 bChunkPtr4 chunk;
1708 chunk.code = head.code;
1709 chunk.len = head.len;
1710
1711 if (head.m_uniqueInts[0]==head.m_uniqueInts[1])
1712 {
1713 chunk.m_uniqueInt = head.m_uniqueInts[0];
1714 } else
1715 {
1716 long64 oldPtr =0;
1717 memcpy(&oldPtr, &head.m_uniqueInts[0], 8);
1718 if (swap)
1719 SWITCH_LONGINT(oldPtr);
1720 chunk.m_uniqueInt = (int)(oldPtr >> 3);
1721 }
1722
1723
1724 chunk.dna_nr = head.dna_nr;
1725 chunk.nr = head.nr;
1726
1727 if (swap)
1728 {
1729 if ((chunk.code & 0xFFFF)==0)
1730 chunk.code >>=16;
1731
1732 SWITCH_INT(chunk.len);
1733 SWITCH_INT(chunk.dna_nr);
1734 SWITCH_INT(chunk.nr);
1735 }
1736
1737 memcpy(dataChunk, &chunk, sizeof(bChunkInd));
1738 }
1739 else
1740 {
1741 bChunkPtr4 c;
1742 memcpy(&c, dataPtr, sizeof(bChunkPtr4));
1743
1744 if (swap)
1745 {
1746 if ((c.code & 0xFFFF)==0)
1747 c.code >>=16;
1748
1749 SWITCH_INT(c.len);
1750 SWITCH_INT(c.dna_nr);
1751 SWITCH_INT(c.nr);
1752 }
1753 memcpy(dataChunk, &c, sizeof(bChunkInd));
1754 }
1755 }
1756
1757 if (dataChunk->len < 0)
1758 return -1;
1759
1760 #if 0
1761 print ("----------");
1762 print (dataChunk->code);
1763 print (dataChunk->len);
1764 print (dataChunk->old);
1765 print (dataChunk->dna_nr);
1766 print (dataChunk->nr);
1767 #endif
1768 return (dataChunk->len+ChunkUtils::getOffset(flags));
1769 }
1770
1771
1772
1773 //eof
bParse::bChunkPtr8::len
int len
Definition: bChunk.h:52
btAlignedObjectArray::push_back
void push_back(const T &_Val)
Definition: btAlignedObjectArray.h:274
bParse::bFile::resolvePointersChunk
void resolvePointersChunk(const bChunkInd &dataChunk, int verboseMode)
this loop only works fine if the Blender DNA structure of the file matches the headerfiles ...
Definition: bFile.cpp:1229
setEle
#define setEle(value, current, type, cast, size, ptr)
bDNA.h
bParse::bFile::m_pointerPtrFixupArray
btAlignedObjectArray< char * > m_pointerPtrFixupArray
Definition: bFile.h:67
bParse::bFile::getNextBlock
int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
Definition: bFile.cpp:1641
btPointerUid::m_uniqueIds
int m_uniqueIds[2]
Definition: btSerializer.h:138
bParse::bDNA::getArraySizeNew
int getArraySizeNew(short name)
Definition: bDNA.h:41
bParse::FD_FILEDNA_IS_MEMDNA
Definition: bFile.h:37
bParse::bChunkPtr4::code
int code
Definition: bChunk.h:37
bParse::bChunkInd::nr
int nr
Definition: bChunk.h:68
bParse::bFile::mMemoryDNA
bDNA * mMemoryDNA
Definition: bFile.h:64
bParse::bDNA::lessThan
bool lessThan(bDNA *other)
Definition: bDNA.cpp:44
bParse::bFile::readStruct
char * readStruct(char *head, class bChunkInd &chunk)
Definition: bFile.cpp:657
bParse::bFile::parseData
virtual void parseData()=0
btHashMap::find
const Value * find(const Key &key) const
Definition: btHashMap.h:434
bParse::bFile::parseInternal
virtual void parseInternal(int verboseMode, char *memDna, int memDnaLength)
Definition: bFile.cpp:203
getElement
static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData)
Definition: bFile.cpp:868
bParse::bChunkInd::len
int len
Definition: bChunk.h:66
bParse::bChunkInd
Definition: bChunk.h:62
size
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
btAlignedObjectArray::at
const T & at(int n) const
Definition: btAlignedObjectArray.h:160
bParse::bDNA::getName
char * getName(int ind)
Definition: bDNA.cpp:50
bParse::bFile::addDataBlock
virtual void addDataBlock(char *dataBlock)=0
bParse::bFile::mFileBuffer
char * mFileBuffer
Definition: bFile.h:55
btPointerUid::m_ptr
void * m_ptr
Definition: btSerializer.h:137
bParse::bChunkInd::dna_nr
int dna_nr
Definition: bChunk.h:68
bParse::bFile::swapDNA
void swapDNA(char *ptr)
Definition: bFile.cpp:406
SDNA
#define SDNA
Definition: bDefines.h:111
bParse::FD_VERSION_VARIES
Definition: bFile.h:34
bParse::bDNA::dumpTypeDefinitions
void dumpTypeDefinitions()
Definition: bDNA.cpp:531
bParse::bChunkPtr8::m_uniqueInts
int m_uniqueInts[2]
Definition: bChunk.h:56
bParse::bFile::dumpChunks
void dumpChunks(bDNA *dna)
Definition: bFile.cpp:1530
TYPE
#define TYPE
Definition: bDefines.h:112
btAlignedAllocator.h
bParse::FD_FILE_64
Definition: bFile.h:32
bParse::bFile::resolvePointersStructRecursive
int resolvePointersStructRecursive(char *strcPtr, int old_dna, int verboseMode, int recursion)
Definition: bFile.cpp:1246
STRC
#define STRC
Definition: bDefines.h:114
bFile.h
bParse::bChunkPtr4::m_uniqueInt
int m_uniqueInt
Definition: bChunk.h:41
bParse::bChunkPtr4
Definition: bChunk.h:33
bParse::bFile::bFile
bFile(const char *filename, const char headerString[7])
Definition: bFile.cpp:55
bParse::FD_BROKEN_DNA
Definition: bFile.h:36
bParse::bDNA::initCmpFlags
void initCmpFlags(bDNA *memDNA)
Definition: bDNA.cpp:172
SIZEOFBLENDERHEADER
#define SIZEOFBLENDERHEADER
Definition: bFile.cpp:27
bParse::bFile::swapLen
void swapLen(char *dataPtr)
Definition: bFile.cpp:356
bParse::bChunkPtr8::code
int code
Definition: bChunk.h:52
bParse::bStructHandle
Definition: bCommon.h:33
DNA1
#define DNA1
Definition: bDefines.h:107
bParse::ChunkUtils::swapInt
static int swapInt(int inte)
Definition: bChunk.cpp:37
SWITCH_LONGINT
#define SWITCH_LONGINT(a)
Definition: bDefines.h:131
bParse::bFile::preSwap
void preSwap()
Definition: bFile.cpp:574
bParse::bChunkPtr8::dna_nr
int dna_nr
Definition: bChunk.h:58
bParse::FD_ENDIAN_SWAP
Definition: bFile.h:31
MAX_STRLEN
#define MAX_STRLEN
Definition: bFile.cpp:30
bParse::FD_OK
Definition: bFile.h:29
bParse::bChunkPtr4::nr
int nr
Definition: bChunk.h:44
bParse::bChunkInd::oldPtr
void * oldPtr
Definition: bChunk.h:67
bParse::bChunkPtr8
Definition: bChunk.h:48
bParse::VOID_IS_8
const bool VOID_IS_8
Definition: bChunk.h:89
btPointerUid
Definition: btSerializer.h:133
bParse::bFile::m_pointerFixupArray
btAlignedObjectArray< char * > m_pointerFixupArray
Definition: bFile.h:66
bParse::FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS
Definition: bFile.h:43
bParse::bDNA::getNumNames
int getNumNames() const
Definition: bDNA.h:53
bParse::bChunkInd::code
int code
Definition: bChunk.h:66
bParse::bFile::resolvePointers
void resolvePointers(int verboseMode)
Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory ...
Definition: bFile.cpp:1458
bParse::bDNA::getPointerSize
int getPointerSize()
Definition: bDNA.cpp:133
bParse::bFile::swapStruct
void swapStruct(int dna_nr, char *data, bool ignoreEndianFlag)
Definition: bFile.cpp:1114
btHashMap::insert
void insert(const Key &key, const Value &value)
Definition: btHashMap.h:274
bParse::bFile::parseStruct
void parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers)
Definition: bFile.cpp:782
bParse::bFile::mFlags
int mFlags
Definition: bFile.h:77
SWITCH_INT
#define SWITCH_INT(a)
Definition: bDefines.h:118
btGetVersion
int btGetVersion()
Definition: btScalar.h:30
bParse::bFile::safeSwapPtr
void safeSwapPtr(char *dst, const char *src)
Definition: bFile.cpp:939
btMinMax.h
getCleanName
const char * getCleanName(const char *memName, char *buffer)
Definition: bFile.cpp:32
bParse::bFile::parseHeader
virtual void parseHeader()
Definition: bFile.cpp:131
bParse::FD_DOUBLE_PRECISION
Definition: bFile.h:35
bChunk.h
bParse::bFile::writeFile
void writeFile(const char *fileName)
Definition: bFile.cpp:567
bParse::bFile::mFileLen
int mFileLen
Definition: bFile.h:56
btAlignedObjectArray::size
int size() const
return the number of elements in the array
Definition: btAlignedObjectArray.h:155
bCommon.h
bParse::bFile::~bFile
virtual ~bFile()
Definition: bFile.cpp:113
TLEN
#define TLEN
Definition: bDefines.h:113
bParse::bFile::mDataStart
int mDataStart
Definition: bFile.h:62
bParse::bChunkPtr8::nr
int nr
Definition: bChunk.h:58
bParse::bFile::getLibPointers
bPtrMap & getLibPointers()
Definition: bFile.h:137
bParse::bFile::mVersion
int mVersion
Definition: bFile.h:57
getEle
#define getEle(value, current, type, cast, size, ptr)
bParse::FD_INVALID
Definition: bFile.h:28
bParse::bFile::m_chunks
btAlignedObjectArray< bChunkInd > m_chunks
Definition: bFile.h:69
bParse::bFile::setFileDNA
virtual void setFileDNA(int verboseMode, char *buffer, int len)
Definition: bFile.cpp:191
bParse::FD_VERBOSE_EXPORT_XML
Definition: bFile.h:42
bParse
Definition: btBulletWorldImporter.h:29
bParse::bDNA
Definition: bDNA.h:32
bParse::bDNA::getStruct
short * getStruct(int ind)
Definition: bDNA.cpp:66
bDefines.h
numallocs
int numallocs
Definition: bFile.cpp:52
bParse::bFile::getMatchingFileDNA
void getMatchingFileDNA(short *old, const char *lookupName, const char *lookupType, char *strcData, char *data, bool fixupPointers)
Definition: bFile.cpp:998
bParse::bDNA::init
void init(char *data, int len, bool swap=false)
Definition: bDNA.cpp:349
bParse::bDNA::flagEqual
bool flagEqual(int dna_nr)
Definition: bDNA.cpp:118
bParse::bChunkPtr4::len
int len
Definition: bChunk.h:38
bParse::FD_BITS_VARIES
Definition: bFile.h:33
btAlignPointer
T * btAlignPointer(T *unalignedPtr, size_t alignment)
align a pointer to the provided alignment, upwards
Definition: btScalar.h:792
bParse::bFile::findLibPointer
void * findLibPointer(void *ptr)
Definition: bFile.cpp:1510
bParse::bFile::swapData
void swapData(char *data, short type, int arraySize, bool ignoreEndianFlag)
Definition: bFile.cpp:906
bParse::bFile::m_headerString
char m_headerString[7]
Definition: bFile.h:52
bParse::bDNA::getElementSize
int getElementSize(short type, short name)
Definition: bDNA.h:46
bParse::bFile::getFileElement
char * getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos)
Definition: bFile.cpp:1085
bParse::ChunkUtils::swapShort
static short swapShort(short sht)
Definition: bChunk.cpp:30
bParse::bFile::mFileDNA
bDNA * mFileDNA
Definition: bFile.h:63
bParse::bFile::swap
void swap(char *head, class bChunkInd &ch, bool ignoreEndianFlag)
Definition: bFile.cpp:327
btMin
const T & btMin(const T &a, const T &b)
Definition: btMinMax.h:23
bParse::bChunkPtr4::dna_nr
int dna_nr
Definition: bChunk.h:43
bParse::bFile::mLibPointers
bPtrMap mLibPointers
Definition: bFile.h:60
SWITCH_SHORT
#define SWITCH_SHORT(a)
Definition: bDefines.h:125
bParse::bFile::ok
bool ok()
Definition: bFile.cpp:186
bParse::bFile::updateOldPointers
void updateOldPointers()
Definition: bFile.cpp:1520
long64
#define long64
Definition: bChunk.h:20
bParse::bDNA::getReverseType
int getReverseType(short type)
Definition: bDNA.cpp:82
bParse::bFile::m_chunkPtrPtrMap
btHashMap< btHashPtr, bChunkInd > m_chunkPtrPtrMap
Definition: bFile.h:70
bParse::bDNA::getLength
short getLength(int ind)
Definition: bDNA.cpp:74
bParse::bFile::mOwnsBuffer
bool mOwnsBuffer
Definition: bFile.h:54
MAX_ARRAY_LENGTH
#define MAX_ARRAY_LENGTH
Definition: bFile.cpp:28
bParse::bDNA::getType
char * getType(int ind)
Definition: bDNA.cpp:58
bParse::ChunkUtils::getOffset
static int getOffset(int flags)
Definition: bChunk.cpp:51
btSerializer.h
bParse::bFile::resolvePointersMismatch
void resolvePointersMismatch()
Definition: bFile.cpp:1161