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