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