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