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),
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  cp = btAlignPointer(cp,4);
464 
465 
466  /*
467  TYPE (4 bytes)
468  <nr> amount of types (int)
469  <string>
470  <string>
471  */
472 
473  intPtr = (int*)cp;
474  assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
475 
476  if (swap)
477  dataLen = ChunkUtils::swapInt(*intPtr);
478  else
479  dataLen = *intPtr;
480 
481  *intPtr = ChunkUtils::swapInt(*intPtr);
482 
483  intPtr++;
484 
485  cp = (char*)intPtr;
486  for ( i=0; i<dataLen; i++)
487  {
488  while (*cp)cp++;
489  cp++;
490  }
491 
492  cp = btAlignPointer(cp,4);
493 
494  /*
495  TLEN (4 bytes)
496  <len> (short) the lengths of types
497  <len>
498  */
499 
500  // Parse type lens
501  intPtr = (int*)cp;
502  assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
503 
504 
505  shtPtr = (short*)intPtr;
506  for ( i=0; i<dataLen; i++, shtPtr++)
507  {
508  //??????if (swap)
509  shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
510  }
511 
512  if (dataLen & 1)
513  shtPtr++;
514 
515  /*
516  STRC (4 bytes)
517  <nr> amount of structs (int)
518  <typenr>
519  <nr_of_elems>
520  <typenr>
521  <namenr>
522  <typenr>
523  <namenr>
524  */
525 
526  intPtr = (int*)shtPtr;
527  cp = (char*)intPtr;
528  assert(strncmp(cp, "STRC", 4)==0);
529  intPtr++;
530 
531  if (swap)
532  dataLen = ChunkUtils::swapInt(*intPtr);
533  else
534  dataLen = *intPtr;
535 
536  *intPtr = ChunkUtils::swapInt(*intPtr);
537 
538  intPtr++;
539 
540 
541  shtPtr = (short*)intPtr;
542  for ( i=0; i<dataLen; i++)
543  {
544 
545  //if (swap)
546  {
547  int len = shtPtr[1];
548 
549  shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
550  shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
551 
552  shtPtr+= 2;
553 
554  for (int a=0; a<len; a++, shtPtr+=2)
555  {
556  shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
557  shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
558  }
559  }
560 // else
561 // shtPtr+= (2*shtPtr[1])+2;
562  }
563 
564 }
565 
566 void bFile::writeFile(const char* fileName)
567 {
568  FILE* f = fopen(fileName,"wb");
569  fwrite(mFileBuffer,1,mFileLen,f);
570  fclose(f);
571 }
572 
574 {
575 
576  const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
577  //FD_ENDIAN_SWAP
578  //byte 8 determines the endianness of the file, little (v) versus big (V)
579  int littleEndian= 1;
580  littleEndian= ((char*)&littleEndian)[0];
581 
582 
583  if (mFileBuffer[8]=='V')
584  {
585  mFileBuffer[8]='v';
586  }
587  else
588  {
589  mFileBuffer[8]='V';
590  }
591 
592 
593 
594 
595 
596 
597  mDataStart = 12;
598 
599  char *dataPtr = mFileBuffer+mDataStart;
600 
601  bChunkInd dataChunk;
602  dataChunk.code = 0;
603  bool ignoreEndianFlag = true;
604 
605  //we always want to swap here
606 
607  int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
608  //dataPtr += ChunkUtils::getOffset(mFlags);
609  char *dataPtrHead = 0;
610 
611  while (1)
612  {
613  // one behind
614  if (dataChunk.code == SDNA || dataChunk.code==DNA1 || dataChunk.code == TYPE || dataChunk.code == TLEN || dataChunk.code==STRC)
615  {
616 
617  swapDNA(dataPtr);
618  break;
619  } else
620  {
621  //if (dataChunk.code == DNA1) break;
622  dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
623 
624  swapLen(dataPtr);
625  if (dataChunk.dna_nr>=0)
626  {
627  swap(dataPtrHead, dataChunk,ignoreEndianFlag);
628  } else
629  {
630  //printf("unknown chunk\n");
631  }
632  }
633 
634  // next please!
635  dataPtr += seek;
636 
637  seek = getNextBlock(&dataChunk, dataPtr, mFlags);
638  if (seek < 0)
639  break;
640  }
641 
642  if (mFlags & FD_ENDIAN_SWAP)
643  {
644  mFlags &= ~FD_ENDIAN_SWAP;
645  } else
646  {
648  }
649 
650 
651 
652 }
653 
654 
655 // ----------------------------------------------------- //
656 char* bFile::readStruct(char *head, bChunkInd& dataChunk)
657 {
658  bool ignoreEndianFlag = false;
659 
660  if (mFlags & FD_ENDIAN_SWAP)
661  swap(head, dataChunk, ignoreEndianFlag);
662 
663 
664 
665  if (!mFileDNA->flagEqual(dataChunk.dna_nr))
666  {
667  // Ouch! need to rebuild the struct
668  short *oldStruct,*curStruct;
669  char *oldType, *newType;
670  int oldLen, curLen, reverseOld;
671 
672 
673  oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
674  oldType = mFileDNA->getType(oldStruct[0]);
675 
676  oldLen = mFileDNA->getLength(oldStruct[0]);
677 
678  if ((mFlags&FD_BROKEN_DNA)!=0)
679  {
680  if ((strcmp(oldType,"btQuantizedBvhNodeData")==0)&&oldLen==20)
681  {
682  return 0;
683  }
684  if ((strcmp(oldType,"btShortIntIndexData")==0))
685  {
686  int allocLen = 2;
687  char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
688  memset(dataAlloc, 0, (dataChunk.nr*allocLen)+1);
689  short* dest = (short*) dataAlloc;
690  const short* src = (short*) head;
691  for (int i=0;i<dataChunk.nr;i++)
692  {
693  dest[i] = src[i];
694  if (mFlags &FD_ENDIAN_SWAP)
695  {
696  SWITCH_SHORT(dest[i]);
697  }
698  }
699  addDataBlock(dataAlloc);
700  return dataAlloc;
701  }
702  }
703 
704 
705 
707  if (strcmp("Link",oldType)!=0)
708  {
709  reverseOld = mMemoryDNA->getReverseType(oldType);
710 
711  if ((reverseOld!=-1))
712  {
713  // make sure it's here
714  //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
715 
716  //
717  curStruct = mMemoryDNA->getStruct(reverseOld);
718  newType = mMemoryDNA->getType(curStruct[0]);
719  curLen = mMemoryDNA->getLength(curStruct[0]);
720 
721 
722 
723  // make sure it's the same
724  assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
725 
726 
727  numallocs++;
728  // numBlocks * length
729 
730  int allocLen = (curLen);
731  char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
732  memset(dataAlloc, 0, (dataChunk.nr*allocLen));
733 
734  // track allocated
735  addDataBlock(dataAlloc);
736 
737  char *cur = dataAlloc;
738  char *old = head;
739  for (int block=0; block<dataChunk.nr; block++)
740  {
741  bool fixupPointers = true;
742  parseStruct(cur, old, dataChunk.dna_nr, reverseOld, fixupPointers);
743  mLibPointers.insert(old,(bStructHandle*)cur);
744 
745  cur += curLen;
746  old += oldLen;
747  }
748  return dataAlloc;
749  }
750  } else
751  {
752  //printf("Link found\n");
753  }
754  } else
755  {
756 //#define DEBUG_EQUAL_STRUCTS
757 #ifdef DEBUG_EQUAL_STRUCTS
758  short *oldStruct;
759  char *oldType;
760  oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
761  oldType = mFileDNA->getType(oldStruct[0]);
762  printf("%s equal structure, just memcpy\n",oldType);
763 #endif //
764  }
765 
766 
767  char *dataAlloc = new char[(dataChunk.len)+1];
768  memset(dataAlloc, 0, dataChunk.len+1);
769 
770 
771  // track allocated
772  addDataBlock(dataAlloc);
773 
774  memcpy(dataAlloc, head, dataChunk.len);
775  return dataAlloc;
776 
777 }
778 
779 
780 // ----------------------------------------------------- //
781 void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers)
782 {
783  if (old_dna == -1) return;
784  if (new_dna == -1) return;
785 
786  //disable this, because we need to fixup pointers/ListBase
787  if (0)//mFileDNA->flagEqual(old_dna))
788  {
789  short *strc = mFileDNA->getStruct(old_dna);
790  int len = mFileDNA->getLength(strc[0]);
791 
792  memcpy(strcPtr, dtPtr, len);
793  return;
794  }
795 
796  // Ok, now build the struct
797  char *memType, *memName, *cpc, *cpo;
798  short *fileStruct, *filePtrOld, *memoryStruct, *firstStruct;
799  int elementLength, size, revType, old_nr, new_nr, fpLen;
800  short firstStructType;
801 
802 
803  // File to memory lookup
804  memoryStruct = mMemoryDNA->getStruct(new_dna);
805  fileStruct = mFileDNA->getStruct(old_dna);
806  firstStruct = fileStruct;
807 
808 
809  filePtrOld = fileStruct;
810  firstStructType = mMemoryDNA->getStruct(0)[0];
811 
812  // Get number of elements
813  elementLength = memoryStruct[1];
814  memoryStruct+=2;
815 
816  cpc = strcPtr; cpo = 0;
817  for (int ele=0; ele<elementLength; ele++, memoryStruct+=2)
818  {
819  memType = mMemoryDNA->getType(memoryStruct[0]);
820  memName = mMemoryDNA->getName(memoryStruct[1]);
821 
822 
823  size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]);
824  revType = mMemoryDNA->getReverseType(memoryStruct[0]);
825 
826  if (revType != -1 && memoryStruct[0]>=firstStructType && memName[0] != '*')
827  {
828  cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld);
829  if (cpo)
830  {
831  int arrayLen = mFileDNA->getArraySizeNew(filePtrOld[1]);
832  old_nr = mFileDNA->getReverseType(memType);
833  new_nr = revType;
834  fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]);
835  if (arrayLen==1)
836  {
837  parseStruct(cpc, cpo, old_nr, new_nr,fixupPointers);
838  } else
839  {
840  char* tmpCpc = cpc;
841  char* tmpCpo = cpo;
842 
843  for (int i=0;i<arrayLen;i++)
844  {
845  parseStruct(tmpCpc, tmpCpo, old_nr, new_nr,fixupPointers);
846  tmpCpc += size/arrayLen;
847  tmpCpo += fpLen/arrayLen;
848  }
849  }
850  cpc+=size;
851  cpo+=fpLen;
852  }
853  else
854  cpc+=size;
855  }
856  else
857  {
858  getMatchingFileDNA(fileStruct, memName, memType, cpc, dtPtr,fixupPointers);
859  cpc+=size;
860  }
861 
862  }
863 }
864 
865 
866 // ----------------------------------------------------- //
867 static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData)
868 {
869 #define getEle(value, current, type, cast, size, ptr)\
870  if (strcmp(current, type)==0)\
871  {\
872  value = (*(cast*)ptr);\
873  ptr += size;\
874  }
875 
876 #define setEle(value, current, type, cast, size, ptr)\
877  if (strcmp(current, type)==0)\
878  {\
879  (*(cast*)ptr) = (cast)value;\
880  ptr += size;\
881  }
882  double value = 0.0;
883 
884  for (int i=0; i<arrayLen; i++)
885  {
886  getEle(value, old, "char", char, sizeof(char), oldPtr);
887  setEle(value, cur, "char", char, sizeof(char), curData);
888  getEle(value, old, "short", short, sizeof(short), oldPtr);
889  setEle(value, cur, "short", short, sizeof(short), curData);
890  getEle(value, old, "ushort", unsigned short, sizeof(unsigned short), oldPtr);
891  setEle(value, cur, "ushort", unsigned short, sizeof(unsigned short), curData);
892  getEle(value, old, "int", int, sizeof(int), oldPtr);
893  setEle(value, cur, "int", int, sizeof(int), curData);
894  getEle(value, old, "long", int, sizeof(int), oldPtr);
895  setEle(value, cur, "long", int, sizeof(int), curData);
896  getEle(value, old, "float", float, sizeof(float), oldPtr);
897  setEle(value, cur, "float", float, sizeof(float), curData);
898  getEle(value, old, "double", double, sizeof(double), oldPtr);
899  setEle(value, cur, "double", double, sizeof(double), curData);
900  }
901 }
902 
903 
904 // ----------------------------------------------------- //
905 void bFile::swapData(char *data, short type, int arraySize,bool ignoreEndianFlag)
906 {
907  if (ignoreEndianFlag || (mFlags &FD_ENDIAN_SWAP))
908  {
909  if (type == 2 || type == 3)
910  {
911  short *sp = (short*)data;
912  for (int i=0; i<arraySize; i++)
913  {
914  sp[0] = ChunkUtils::swapShort(sp[0]);
915  sp++;
916  }
917  }
918  if (type>3 && type <8)
919  {
920  char c;
921  char *cp = data;
922  for (int i=0; i<arraySize; i++)
923  {
924  c = cp[0];
925  cp[0] = cp[3];
926  cp[3] = c;
927  c = cp[1];
928  cp[1] = cp[2];
929  cp[2] = c;
930  cp+=4;
931  }
932  }
933  }
934 }
935 
936 
937 
938 void bFile::safeSwapPtr(char *dst, const char *src)
939 {
940  int ptrFile = mFileDNA->getPointerSize();
941  int ptrMem = mMemoryDNA->getPointerSize();
942 
943  if (!src && !dst)
944  return;
945 
946 
947  if (ptrFile == ptrMem)
948  {
949  memcpy(dst, src, ptrMem);
950  }
951  else if (ptrMem==4 && ptrFile==8)
952  {
953  btPointerUid* oldPtr = (btPointerUid*)src;
954  btPointerUid* newPtr = (btPointerUid*)dst;
955 
956  if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
957  {
958  //Bullet stores the 32bit unique ID in both upper and lower part of 64bit pointers
959  //so it can be used to distinguish between .blend and .bullet
960  newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
961  } else
962  {
963  //deal with pointers the Blender .blend style way, see
964  //readfile.c in the Blender source tree
965  long64 longValue = *((long64*)src);
966  //endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros
967  if (mFlags & FD_ENDIAN_SWAP)
968  SWITCH_LONGINT(longValue);
969  *((int*)dst) = (int)(longValue>>3);
970  }
971 
972  }
973  else if (ptrMem==8 && ptrFile==4)
974  {
975  btPointerUid* oldPtr = (btPointerUid*)src;
976  btPointerUid* newPtr = (btPointerUid*)dst;
977  if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
978  {
979  newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
980  newPtr->m_uniqueIds[1] = 0;
981  } else
982  {
983  *((long64*)dst)= *((int*)src);
984  }
985  }
986  else
987  {
988  printf ("%d %d\n", ptrFile,ptrMem);
989  assert(0 && "Invalid pointer len");
990  }
991 
992 
993 }
994 
995 
996 // ----------------------------------------------------- //
997 void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers)
998 {
999  // find the matching memory dna data
1000  // to the file being loaded. Fill the
1001  // memory with the file data...
1002 
1003  int len = dna_addr[1];
1004  dna_addr+=2;
1005 
1006  for (int i=0; i<len; i++, dna_addr+=2)
1007  {
1008  const char* type = mFileDNA->getType(dna_addr[0]);
1009  const char* name = mFileDNA->getName(dna_addr[1]);
1010 
1011 
1012 
1013  int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]);
1014 
1015  if ((mFlags&FD_BROKEN_DNA)!=0)
1016  {
1017  if ((strcmp(type,"short")==0)&&(strcmp(name,"int")==0))
1018  {
1019  eleLen = 0;
1020  }
1021  }
1022 
1023  if (strcmp(lookupName, name)==0)
1024  {
1025  //int arrayLenold = mFileDNA->getArraySize((char*)name.c_str());
1026  int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]);
1027  //assert(arrayLenold == arrayLen);
1028 
1029  if (name[0] == '*')
1030  {
1031  // cast pointers
1032  int ptrFile = mFileDNA->getPointerSize();
1033  int ptrMem = mMemoryDNA->getPointerSize();
1034  safeSwapPtr(strcData,data);
1035 
1036  if (fixupPointers)
1037  {
1038  if (arrayLen > 1)
1039  {
1040  //void **sarray = (void**)strcData;
1041  //void **darray = (void**)data;
1042 
1043  char *cpc, *cpo;
1044  cpc = (char*)strcData;
1045  cpo = (char*)data;
1046 
1047  for (int a=0; a<arrayLen; a++)
1048  {
1049  safeSwapPtr(cpc, cpo);
1051  cpc += ptrMem;
1052  cpo += ptrFile;
1053  }
1054  }
1055  else
1056  {
1057  if (name[1] == '*')
1059  else
1060  m_pointerFixupArray.push_back(strcData);
1061  }
1062  }
1063  else
1064  {
1065 // printf("skipped %s %s : %x\n",type.c_str(),name.c_str(),strcData);
1066  }
1067 
1068  }
1069 
1070  else if (strcmp(type, lookupType)==0)
1071  memcpy(strcData, data, eleLen);
1072  else
1073  getElement(arrayLen, lookupType, type, data, strcData);
1074 
1075  // --
1076  return;
1077  }
1078  data+=eleLen;
1079  }
1080 }
1081 
1082 
1083 // ----------------------------------------------------- //
1084 char* bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos)
1085 {
1086  short *old = firstStruct;//mFileDNA->getStruct(old_nr);
1087  int elementLength = old[1];
1088  old+=2;
1089 
1090  for (int i=0; i<elementLength; i++, old+=2)
1091  {
1092  char* type = mFileDNA->getType(old[0]);
1093  char* name = mFileDNA->getName(old[1]);
1094  int len = mFileDNA->getElementSize(old[0], old[1]);
1095 
1096  if (strcmp(lookupName, name)==0)
1097  {
1098  if (strcmp(type, lookupType)==0)
1099  {
1100  if (foundPos)
1101  *foundPos = old;
1102  return data;
1103  }
1104  return 0;
1105  }
1106  data+=len;
1107  }
1108  return 0;
1109 }
1110 
1111 
1112 // ----------------------------------------------------- //
1113 void bFile::swapStruct(int dna_nr, char *data,bool ignoreEndianFlag)
1114 {
1115  if (dna_nr == -1) return;
1116 
1117  short *strc = mFileDNA->getStruct(dna_nr);
1118  //short *firstStrc = strc;
1119 
1120  int elementLen= strc[1];
1121  strc+=2;
1122 
1123  short first = mFileDNA->getStruct(0)[0];
1124 
1125  char *buf = data;
1126  for (int i=0; i<elementLen; i++, strc+=2)
1127  {
1128  char *type = mFileDNA->getType(strc[0]);
1129  char *name = mFileDNA->getName(strc[1]);
1130 
1131  int size = mFileDNA->getElementSize(strc[0], strc[1]);
1132  if (strc[0] >= first && name[0]!='*')
1133  {
1134  int old_nr = mFileDNA->getReverseType(type);
1135  int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
1136  if (arrayLen==1)
1137  {
1138  swapStruct(old_nr,buf,ignoreEndianFlag);
1139  } else
1140  {
1141  char* tmpBuf = buf;
1142  for (int i=0;i<arrayLen;i++)
1143  {
1144  swapStruct(old_nr,tmpBuf,ignoreEndianFlag);
1145  tmpBuf+=size/arrayLen;
1146  }
1147  }
1148  }
1149  else
1150  {
1151  //int arrayLenOld = mFileDNA->getArraySize(name);
1152  int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
1153  //assert(arrayLenOld == arrayLen);
1154  swapData(buf, strc[0], arrayLen,ignoreEndianFlag);
1155  }
1156  buf+=size;
1157  }
1158 }
1159 
1161 {
1162 // printf("resolvePointersStructMismatch\n");
1163 
1164  int i;
1165 
1166  for (i=0;i< m_pointerFixupArray.size();i++)
1167  {
1168  char* cur = m_pointerFixupArray.at(i);
1169  void** ptrptr = (void**) cur;
1170  void* ptr = *ptrptr;
1171  ptr = findLibPointer(ptr);
1172  if (ptr)
1173  {
1174  //printf("Fixup pointer!\n");
1175  *(ptrptr) = ptr;
1176  } else
1177  {
1178 // printf("pointer not found: %x\n",cur);
1179  }
1180  }
1181 
1182 
1183  for (i=0; i<m_pointerPtrFixupArray.size(); i++)
1184  {
1185  char* cur= m_pointerPtrFixupArray.at(i);
1186  void** ptrptr = (void**)cur;
1187 
1188  bChunkInd *block = m_chunkPtrPtrMap.find(*ptrptr);
1189  if (block)
1190  {
1191  int ptrMem = mMemoryDNA->getPointerSize();
1192  int ptrFile = mFileDNA->getPointerSize();
1193 
1194 
1195  int blockLen = block->len / ptrFile;
1196 
1197  void *onptr = findLibPointer(*ptrptr);
1198  if (onptr)
1199  {
1200  char *newPtr = new char[blockLen * ptrMem];
1201  addDataBlock(newPtr);
1202  memset(newPtr, 0, blockLen * ptrMem);
1203 
1204  void **onarray = (void**)onptr;
1205  char *oldPtr = (char*)onarray;
1206 
1207  int p = 0;
1208  while (blockLen-- > 0)
1209  {
1210  btPointerUid dp = {{0}};
1211  safeSwapPtr((char*)dp.m_uniqueIds, oldPtr);
1212 
1213  void **tptr = (void**)(newPtr + p * ptrMem);
1214  *tptr = findLibPointer(dp.m_ptr);
1215 
1216  oldPtr += ptrFile;
1217  ++p;
1218  }
1219 
1220  *ptrptr = newPtr;
1221  }
1222  }
1223  }
1224 }
1225 
1226 
1228 void bFile::resolvePointersChunk(const bChunkInd& dataChunk, int verboseMode)
1229 {
1230  bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1231 
1232  short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
1233  short oldLen = fileDna->getLength(oldStruct[0]);
1234  //char* structType = fileDna->getType(oldStruct[0]);
1235 
1236  char* cur = (char*)findLibPointer(dataChunk.oldPtr);
1237  for (int block=0; block<dataChunk.nr; block++)
1238  {
1239  resolvePointersStructRecursive(cur,dataChunk.dna_nr, verboseMode,1);
1240  cur += oldLen;
1241  }
1242 }
1243 
1244 
1245 int bFile::resolvePointersStructRecursive(char *strcPtr, int dna_nr, int verboseMode,int recursion)
1246 {
1247 
1248  bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1249 
1250  char* memType;
1251  char* memName;
1252  short firstStructType = fileDna->getStruct(0)[0];
1253 
1254 
1255  char* elemPtr= strcPtr;
1256 
1257  short int* oldStruct = fileDna->getStruct(dna_nr);
1258 
1259  int elementLength = oldStruct[1];
1260  oldStruct+=2;
1261 
1262  int totalSize = 0;
1263 
1264  for (int ele=0; ele<elementLength; ele++, oldStruct+=2)
1265  {
1266 
1267  memType = fileDna->getType(oldStruct[0]);
1268  memName = fileDna->getName(oldStruct[1]);
1269 
1270 
1271 
1272  int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
1273  if (memName[0] == '*')
1274  {
1275  if (arrayLen > 1)
1276  {
1277  void **array= (void**)elemPtr;
1278  for (int a=0; a<arrayLen; a++)
1279  {
1280  if (verboseMode & FD_VERBOSE_EXPORT_XML)
1281  {
1282  for (int i=0;i<recursion;i++)
1283  {
1284  printf(" ");
1285  }
1286  //skip the *
1287  printf("<%s type=\"pointer\"> ",&memName[1]);
1288  printf("%d ", array[a]);
1289  printf("</%s>\n",&memName[1]);
1290  }
1291 
1292  array[a] = findLibPointer(array[a]);
1293  }
1294  }
1295  else
1296  {
1297  void** ptrptr = (void**) elemPtr;
1298  void* ptr = *ptrptr;
1299  if (verboseMode & FD_VERBOSE_EXPORT_XML)
1300  {
1301  for (int i=0;i<recursion;i++)
1302  {
1303  printf(" ");
1304  }
1305  printf("<%s type=\"pointer\"> ",&memName[1]);
1306  printf("%d ", ptr);
1307  printf("</%s>\n",&memName[1]);
1308  }
1309  ptr = findLibPointer(ptr);
1310 
1311  if (ptr)
1312  {
1313  // printf("Fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
1314  *(ptrptr) = ptr;
1315  if (memName[1] == '*' && ptrptr && *ptrptr)
1316  {
1317  // This will only work if the given **array is continuous
1318  void **array= (void**)*(ptrptr);
1319  void *np= array[0];
1320  int n=0;
1321  while (np)
1322  {
1323  np= findLibPointer(array[n]);
1324  if (np) array[n]= np;
1325  n++;
1326  }
1327  }
1328  } else
1329  {
1330  // printf("Cannot fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
1331  }
1332  }
1333  } else
1334  {
1335  int revType = fileDna->getReverseType(oldStruct[0]);
1336  if (oldStruct[0]>=firstStructType) //revType != -1 &&
1337  {
1338  char cleanName[MAX_STRLEN];
1339  getCleanName(memName,cleanName);
1340 
1341  int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
1342  int byteOffset = 0;
1343 
1344  if (verboseMode & FD_VERBOSE_EXPORT_XML)
1345  {
1346  for (int i=0;i<recursion;i++)
1347  {
1348  printf(" ");
1349  }
1350 
1351  if (arrayLen>1)
1352  {
1353  printf("<%s type=\"%s\" count=%d>\n",cleanName,memType, arrayLen);
1354  } else
1355  {
1356  printf("<%s type=\"%s\">\n",cleanName,memType);
1357  }
1358  }
1359 
1360  for (int i=0;i<arrayLen;i++)
1361  {
1362  byteOffset += resolvePointersStructRecursive(elemPtr+byteOffset,revType, verboseMode,recursion+1);
1363  }
1364  if (verboseMode & FD_VERBOSE_EXPORT_XML)
1365  {
1366  for (int i=0;i<recursion;i++)
1367  {
1368  printf(" ");
1369  }
1370  printf("</%s>\n",cleanName);
1371  }
1372  } else
1373  {
1374  //export a simple type
1375  if (verboseMode & FD_VERBOSE_EXPORT_XML)
1376  {
1377 
1378  if (arrayLen>MAX_ARRAY_LENGTH)
1379  {
1380  printf("too long\n");
1381  } else
1382  {
1383  //printf("%s %s\n",memType,memName);
1384 
1385  bool isIntegerType = (strcmp(memType,"char")==0) || (strcmp(memType,"int")==0) || (strcmp(memType,"short")==0);
1386 
1387  if (isIntegerType)
1388  {
1389  const char* newtype="int";
1390  int dbarray[MAX_ARRAY_LENGTH];
1391  int* dbPtr = 0;
1392  char* tmp = elemPtr;
1393  dbPtr = &dbarray[0];
1394  if (dbPtr)
1395  {
1396  char cleanName[MAX_STRLEN];
1397  getCleanName(memName,cleanName);
1398 
1399  int i;
1400  getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
1401  for (i=0;i<recursion;i++)
1402  printf(" ");
1403  if (arrayLen==1)
1404  printf("<%s type=\"%s\">",cleanName,memType);
1405  else
1406  printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen);
1407  for (i=0;i<arrayLen;i++)
1408  printf(" %d ",dbPtr[i]);
1409  printf("</%s>\n",cleanName);
1410  }
1411  } else
1412  {
1413  const char* newtype="double";
1414  double dbarray[MAX_ARRAY_LENGTH];
1415  double* dbPtr = 0;
1416  char* tmp = elemPtr;
1417  dbPtr = &dbarray[0];
1418  if (dbPtr)
1419  {
1420  int i;
1421  getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
1422  for (i=0;i<recursion;i++)
1423  printf(" ");
1424  char cleanName[MAX_STRLEN];
1425  getCleanName(memName,cleanName);
1426 
1427  if (arrayLen==1)
1428  {
1429  printf("<%s type=\"%s\">",memName,memType);
1430  }
1431  else
1432  {
1433  printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen);
1434  }
1435  for (i=0;i<arrayLen;i++)
1436  printf(" %f ",dbPtr[i]);
1437  printf("</%s>\n",cleanName);
1438  }
1439  }
1440  }
1441 
1442  }
1443  }
1444  }
1445 
1446  int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]);
1447  totalSize += size;
1448  elemPtr+=size;
1449 
1450  }
1451 
1452  return totalSize;
1453 }
1454 
1455 
1457 void bFile::resolvePointers(int verboseMode)
1458 {
1459  bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1460 
1461  //char *dataPtr = mFileBuffer+mDataStart;
1462 
1463  if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES))
1464  {
1466  }
1467 
1468  {
1469 
1470  if (verboseMode & FD_VERBOSE_EXPORT_XML)
1471  {
1472  printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
1473  int numitems = m_chunks.size();
1474  printf("<bullet_physics version=%d itemcount = %d>\n", btGetVersion(), numitems);
1475  }
1476  for (int i=0;i<m_chunks.size();i++)
1477  {
1478  const bChunkInd& dataChunk = m_chunks.at(i);
1479 
1480  if (!mFileDNA || fileDna->flagEqual(dataChunk.dna_nr))
1481  {
1482  //dataChunk.len
1483  short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
1484  char* oldType = fileDna->getType(oldStruct[0]);
1485 
1486  if (verboseMode & FD_VERBOSE_EXPORT_XML)
1487  printf(" <%s pointer=%d>\n",oldType,dataChunk.oldPtr);
1488 
1489  resolvePointersChunk(dataChunk, verboseMode);
1490 
1491  if (verboseMode & FD_VERBOSE_EXPORT_XML)
1492  printf(" </%s>\n",oldType);
1493  } else
1494  {
1495  //printf("skipping mStruct\n");
1496  }
1497  }
1498  if (verboseMode & FD_VERBOSE_EXPORT_XML)
1499  {
1500  printf("</bullet_physics>\n");
1501  }
1502  }
1503 
1504 
1505 }
1506 
1507 
1508 // ----------------------------------------------------- //
1509 void* bFile::findLibPointer(void *ptr)
1510 {
1511 
1512  bStructHandle** ptrptr = getLibPointers().find(ptr);
1513  if (ptrptr)
1514  return *ptrptr;
1515  return 0;
1516 }
1517 
1518 
1520 {
1521  int i;
1522 
1523  for (i=0;i<m_chunks.size();i++)
1524  {
1525  bChunkInd& dataChunk = m_chunks[i];
1526  dataChunk.oldPtr = findLibPointer(dataChunk.oldPtr);
1527  }
1528 }
1530 {
1531  int i;
1532 
1533  for (i=0;i<m_chunks.size();i++)
1534  {
1535  bChunkInd& dataChunk = m_chunks[i];
1536  char* codeptr = (char*)&dataChunk.code;
1537  char codestr[5] = {codeptr[0],codeptr[1],codeptr[2],codeptr[3],0};
1538 
1539  short* newStruct = dna->getStruct(dataChunk.dna_nr);
1540  char* typeName = dna->getType(newStruct[0]);
1541  printf("%3d: %s ",i,typeName);
1542 
1543  printf("code=%s ",codestr);
1544 
1545  printf("ptr=%p ",dataChunk.oldPtr);
1546  printf("len=%d ",dataChunk.len);
1547  printf("nr=%d ",dataChunk.nr);
1548  if (dataChunk.nr!=1)
1549  {
1550  printf("not 1\n");
1551  }
1552  printf("\n");
1553 
1554 
1555 
1556 
1557  }
1558 
1559 #if 0
1560  IDFinderData ifd;
1561  ifd.success = 0;
1562  ifd.IDname = NULL;
1563  ifd.just_print_it = 1;
1564  for (i=0; i<bf->m_blocks.size(); ++i)
1565  {
1566  BlendBlock* bb = bf->m_blocks[i];
1567  printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]", bb->tag, bb,bf->types[bb->type_index].name,bb->m_array_entries_.size());
1568  block_ID_finder(bb, bf, &ifd);
1569  printf("\n");
1570  }
1571 #endif
1572 
1573 }
1574 
1575 
1576 void bFile::writeChunks(FILE* fp, bool fixupPointers)
1577 {
1578  bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
1579 
1580  for (int i=0;i<m_chunks.size();i++)
1581  {
1582  bChunkInd& dataChunk = m_chunks.at(i);
1583 
1584  // Ouch! need to rebuild the struct
1585  short *oldStruct,*curStruct;
1586  char *oldType, *newType;
1587  int curLen, reverseOld;
1588 
1589  oldStruct = fileDna->getStruct(dataChunk.dna_nr);
1590  oldType = fileDna->getType(oldStruct[0]);
1591  //int oldLen = fileDna->getLength(oldStruct[0]);
1593  reverseOld = mMemoryDNA->getReverseType(oldType);
1594 
1595 
1596  if ((reverseOld!=-1))
1597  {
1598  // make sure it's here
1599  //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
1600  //
1601  curStruct = mMemoryDNA->getStruct(reverseOld);
1602  newType = mMemoryDNA->getType(curStruct[0]);
1603  // make sure it's the same
1604  assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
1605 
1606 
1607  curLen = mMemoryDNA->getLength(curStruct[0]);
1608  dataChunk.dna_nr = reverseOld;
1609  if (strcmp("Link",oldType)!=0)
1610  {
1611  dataChunk.len = curLen * dataChunk.nr;
1612  } else
1613  {
1614 // printf("keep length of link = %d\n",dataChunk.len);
1615  }
1616 
1617  //write the structure header
1618  fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
1619 
1620 
1621 
1622  short int* curStruct1;
1623  curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr);
1624  assert(curStruct1 == curStruct);
1625 
1626  char* cur = fixupPointers ? (char*)findLibPointer(dataChunk.oldPtr) : (char*)dataChunk.oldPtr;
1627 
1628  //write the actual contents of the structure(s)
1629  fwrite(cur,dataChunk.len,1,fp);
1630  } else
1631  {
1632  printf("serious error, struct mismatch: don't write\n");
1633  }
1634  }
1635 
1636 }
1637 
1638 
1639 // ----------------------------------------------------- //
1640 int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
1641 {
1642  bool swap = false;
1643  bool varies = false;
1644 
1645  if (flags &FD_ENDIAN_SWAP)
1646  swap = true;
1647  if (flags &FD_BITS_VARIES)
1648  varies = true;
1649 
1650  if (VOID_IS_8)
1651  {
1652  if (varies)
1653  {
1654  bChunkPtr4 head;
1655  memcpy(&head, dataPtr, sizeof(bChunkPtr4));
1656 
1657 
1658  bChunkPtr8 chunk;
1659 
1660  chunk.code = head.code;
1661  chunk.len = head.len;
1662  chunk.m_uniqueInts[0] = head.m_uniqueInt;
1663  chunk.m_uniqueInts[1] = 0;
1664  chunk.dna_nr = head.dna_nr;
1665  chunk.nr = head.nr;
1666 
1667  if (swap)
1668  {
1669  if ((chunk.code & 0xFFFF)==0)
1670  chunk.code >>=16;
1671 
1672  SWITCH_INT(chunk.len);
1673  SWITCH_INT(chunk.dna_nr);
1674  SWITCH_INT(chunk.nr);
1675  }
1676 
1677 
1678  memcpy(dataChunk, &chunk, sizeof(bChunkInd));
1679  }
1680  else
1681  {
1682  bChunkPtr8 c;
1683  memcpy(&c, dataPtr, sizeof(bChunkPtr8));
1684 
1685  if (swap)
1686  {
1687  if ((c.code & 0xFFFF)==0)
1688  c.code >>=16;
1689 
1690  SWITCH_INT(c.len);
1691  SWITCH_INT(c.dna_nr);
1692  SWITCH_INT(c.nr);
1693  }
1694 
1695  memcpy(dataChunk, &c, sizeof(bChunkInd));
1696  }
1697  }
1698  else
1699  {
1700  if (varies)
1701  {
1702  bChunkPtr8 head;
1703  memcpy(&head, dataPtr, sizeof(bChunkPtr8));
1704 
1705 
1706  bChunkPtr4 chunk;
1707  chunk.code = head.code;
1708  chunk.len = head.len;
1709 
1710  if (head.m_uniqueInts[0]==head.m_uniqueInts[1])
1711  {
1712  chunk.m_uniqueInt = head.m_uniqueInts[0];
1713  } else
1714  {
1715  long64 oldPtr =0;
1716  memcpy(&oldPtr, &head.m_uniqueInts[0], 8);
1717  if (swap)
1718  SWITCH_LONGINT(oldPtr);
1719  chunk.m_uniqueInt = (int)(oldPtr >> 3);
1720  }
1721 
1722 
1723  chunk.dna_nr = head.dna_nr;
1724  chunk.nr = head.nr;
1725 
1726  if (swap)
1727  {
1728  if ((chunk.code & 0xFFFF)==0)
1729  chunk.code >>=16;
1730 
1731  SWITCH_INT(chunk.len);
1732  SWITCH_INT(chunk.dna_nr);
1733  SWITCH_INT(chunk.nr);
1734  }
1735 
1736  memcpy(dataChunk, &chunk, sizeof(bChunkInd));
1737  }
1738  else
1739  {
1740  bChunkPtr4 c;
1741  memcpy(&c, dataPtr, sizeof(bChunkPtr4));
1742 
1743  if (swap)
1744  {
1745  if ((c.code & 0xFFFF)==0)
1746  c.code >>=16;
1747 
1748  SWITCH_INT(c.len);
1749  SWITCH_INT(c.dna_nr);
1750  SWITCH_INT(c.nr);
1751  }
1752  memcpy(dataChunk, &c, sizeof(bChunkInd));
1753  }
1754  }
1755 
1756  if (dataChunk->len < 0)
1757  return -1;
1758 
1759 #if 0
1760  print ("----------");
1761  print (dataChunk->code);
1762  print (dataChunk->len);
1763  print (dataChunk->old);
1764  print (dataChunk->dna_nr);
1765  print (dataChunk->nr);
1766 #endif
1767  return (dataChunk->len+ChunkUtils::getOffset(flags));
1768 }
1769 
1770 
1771 
1772 //eof
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:1228
#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:1640
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
char * readStruct(char *head, class bChunkInd &chunk)
Definition: bFile.cpp:656
virtual void parseData()=0
const Value * find(const Key &key) const
Definition: btHashMap.h:419
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:867
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
const T & at(int n) const
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:530
int m_uniqueInts[2]
Definition: bChunk.h:56
void dumpChunks(bDNA *dna)
Definition: bFile.cpp:1529
#define TYPE
Definition: bDefines.h:112
int resolvePointersStructRecursive(char *strcPtr, int old_dna, int verboseMode, int recursion)
Definition: bFile.cpp:1245
#define STRC
Definition: bDefines.h:114
bFile(const char *filename, const char headerString[7])
Definition: bFile.cpp:55
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:573
#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
int getNumNames() const
Definition: bDNA.h:53
void resolvePointers(int verboseMode)
Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory ...
Definition: bFile.cpp:1457
int getPointerSize()
Definition: bDNA.cpp:133
void swapStruct(int dna_nr, char *data, bool ignoreEndianFlag)
Definition: bFile.cpp:1113
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:781
int mFlags
Definition: bFile.h:77
#define SWITCH_INT(a)
Definition: bDefines.h:118
int btGetVersion()
Definition: btScalar.h:34
void safeSwapPtr(char *dst, const char *src)
Definition: bFile.cpp:938
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:566
int mFileLen
Definition: bFile.h:56
int size() const
return the number of elements in the array
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:997
void init(char *data, int len, bool swap=false)
Definition: bDNA.cpp:349
virtual void writeChunks(FILE *fp, bool fixupPointers)
Definition: bFile.cpp:1576
bool flagEqual(int dna_nr)
Definition: bDNA.cpp:118
T * btAlignPointer(T *unalignedPtr, size_t alignment)
align a pointer to the provided alignment, upwards
Definition: btScalar.h:761
void * findLibPointer(void *ptr)
Definition: bFile.cpp:1509
void swapData(char *data, short type, int arraySize, bool ignoreEndianFlag)
Definition: bFile.cpp:905
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:1084
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:1519
#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:1160