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