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