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