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