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