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

Bullet Collision Detection & Physics Library

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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