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