summaryrefslogtreecommitdiff
path: root/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp')
-rw-r--r--thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp1739
1 files changed, 1739 insertions, 0 deletions
diff --git a/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp
new file mode 100644
index 0000000000..432f7fc2b4
--- /dev/null
+++ b/thirdparty/bullet/src/Bullet3Serialize/Bullet2FileLoader/b3File.cpp
@@ -0,0 +1,1739 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+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.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include "b3File.h"
+#include "b3Common.h"
+#include "b3Chunk.h"
+#include "b3DNA.h"
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "b3Defines.h"
+#include "Bullet3Serialize/Bullet2FileLoader/b3Serializer.h"
+#include "Bullet3Common/b3AlignedAllocator.h"
+#include "Bullet3Common/b3MinMax.h"
+
+#define B3_SIZEOFBLENDERHEADER 12
+#define MAX_ARRAY_LENGTH 512
+using namespace bParse;
+#define MAX_STRLEN 1024
+
+const char* getCleanName(const char* memName, char* buffer)
+{
+ int slen = strlen(memName);
+ assert(slen<MAX_STRLEN);
+ slen=b3Min(slen,MAX_STRLEN);
+ for (int i=0;i<slen;i++)
+ {
+ if (memName[i]==']'||memName[i]=='[')
+ {
+ buffer[i] = 0;//'_';
+ } else
+ {
+ buffer[i] = memName[i];
+ }
+ }
+ buffer[slen]=0;
+ return buffer;
+}
+
+
+
+// ----------------------------------------------------- //
+bFile::bFile(const char *filename, const char headerString[7])
+ : mOwnsBuffer(true),
+ mFileBuffer(0),
+ mFileLen(0),
+ mVersion(0),
+ mDataStart(0),
+ mFileDNA(0),
+ mMemoryDNA(0),
+ mFlags(FD_INVALID)
+{
+ for (int i=0;i<7;i++)
+ {
+ m_headerString[i] = headerString[i];
+ }
+
+ FILE *fp = fopen(filename, "rb");
+ if (fp)
+ {
+ fseek(fp, 0L, SEEK_END);
+ mFileLen = ftell(fp);
+ fseek(fp, 0L, SEEK_SET);
+
+ mFileBuffer = (char*)malloc(mFileLen+1);
+ int bytesRead;
+ bytesRead = fread(mFileBuffer, mFileLen, 1, fp);
+
+ fclose(fp);
+
+ //
+ parseHeader();
+
+ }
+}
+
+// ----------------------------------------------------- //
+bFile::bFile( char *memoryBuffer, int len, const char headerString[7])
+: mOwnsBuffer(false),
+ mFileBuffer(0),
+ mFileLen(0),
+ mVersion(0),
+ mDataStart(0),
+ mFileDNA(0),
+ mMemoryDNA(0),
+ mFlags(FD_INVALID)
+{
+ for (int i=0;i<7;i++)
+ {
+ m_headerString[i] = headerString[i];
+ }
+ mFileBuffer = memoryBuffer;
+ mFileLen = len;
+
+ parseHeader();
+
+}
+
+
+// ----------------------------------------------------- //
+bFile::~bFile()
+{
+ if (mOwnsBuffer && mFileBuffer)
+ {
+ free(mFileBuffer);
+ mFileBuffer = 0;
+ }
+
+
+ delete mMemoryDNA;
+ delete mFileDNA;
+}
+
+
+
+
+
+// ----------------------------------------------------- //
+void bFile::parseHeader()
+{
+ if (!mFileLen || !mFileBuffer)
+ return;
+
+ char *blenderBuf = mFileBuffer;
+ char header[B3_SIZEOFBLENDERHEADER+1] ;
+ memcpy(header, blenderBuf, B3_SIZEOFBLENDERHEADER);
+ header[B3_SIZEOFBLENDERHEADER]='\0';
+
+ if (strncmp(header, m_headerString, 6)!=0)
+ {
+ memcpy(header, m_headerString, B3_SIZEOFBLENDERHEADER);
+ return;
+ }
+
+ if (header[6] == 'd')
+ {
+ mFlags |= FD_DOUBLE_PRECISION;
+ }
+
+ char *ver = header+9;
+ mVersion = atoi(ver);
+ if (mVersion <= 241)
+ {
+ //printf("Warning, %d not fully tested : <= 242\n", mVersion);
+ }
+
+ int littleEndian= 1;
+ littleEndian= ((char*)&littleEndian)[0];
+
+ // swap ptr sizes...
+ if (header[7]=='-')
+ {
+ mFlags |= FD_FILE_64;
+ if (!VOID_IS_8)
+ mFlags |= FD_BITS_VARIES;
+ }
+ else if (VOID_IS_8) mFlags |= FD_BITS_VARIES;
+
+ // swap endian...
+ if (header[8]=='V')
+ {
+ if (littleEndian ==1)
+ mFlags |= FD_ENDIAN_SWAP;
+ }
+ else
+ if (littleEndian==0)
+ mFlags |= FD_ENDIAN_SWAP;
+
+
+ mFlags |= FD_OK;
+}
+
+// ----------------------------------------------------- //
+bool bFile::ok()
+{
+ return (mFlags &FD_OK)!=0;
+}
+
+// ----------------------------------------------------- //
+void bFile::parseInternal(int verboseMode, char* memDna,int memDnaLength)
+{
+ if ( (mFlags &FD_OK) ==0)
+ return;
+
+ char *blenderData = mFileBuffer;
+ bChunkInd dna;
+ dna.oldPtr = 0;
+
+ char *tempBuffer = blenderData;
+ for (int i=0; i<mFileLen; i++)
+ {
+ // looking for the data's starting position
+ // and the start of SDNA decls
+
+ if (!mDataStart && strncmp(tempBuffer, "REND", 4)==0)
+ mDataStart = i;
+
+ if (strncmp(tempBuffer, "DNA1", 4)==0)
+ {
+ // read the DNA1 block and extract SDNA
+ if (getNextBlock(&dna, tempBuffer, mFlags) > 0)
+ {
+ if (strncmp((tempBuffer + ChunkUtils::getOffset(mFlags)), "SDNANAME", 8) ==0)
+ dna.oldPtr = (tempBuffer + ChunkUtils::getOffset(mFlags));
+ else dna.oldPtr = 0;
+ }
+ else dna.oldPtr = 0;
+ }
+ // Some Bullet files are missing the DNA1 block
+ // In Blender it's DNA1 + ChunkUtils::getOffset() + SDNA + NAME
+ // In Bullet tests its SDNA + NAME
+ else if (strncmp(tempBuffer, "SDNANAME", 8) ==0)
+ {
+ dna.oldPtr = blenderData + i;
+ dna.len = mFileLen-i;
+
+ // Also no REND block, so exit now.
+ if (mVersion==276) break;
+ }
+
+ if (mDataStart && dna.oldPtr) break;
+ tempBuffer++;
+ }
+ if (!dna.oldPtr || !dna.len)
+ {
+ //printf("Failed to find DNA1+SDNA pair\n");
+ mFlags &= ~FD_OK;
+ return;
+ }
+
+
+ mFileDNA = new bDNA();
+
+
+ ///mFileDNA->init will convert part of DNA file endianness to current CPU endianness if necessary
+ mFileDNA->init((char*)dna.oldPtr, dna.len, (mFlags & FD_ENDIAN_SWAP)!=0);
+
+
+ if (mVersion==276)
+ {
+ int i;
+ for (i=0;i<mFileDNA->getNumNames();i++)
+ {
+ if (strcmp(mFileDNA->getName(i),"int")==0)
+ {
+ mFlags |= FD_BROKEN_DNA;
+ }
+ }
+ if ((mFlags&FD_BROKEN_DNA)!=0)
+ {
+ //printf("warning: fixing some broken DNA version\n");
+ }
+ }
+
+
+
+ if (verboseMode & FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS)
+ mFileDNA->dumpTypeDefinitions();
+
+ mMemoryDNA = new bDNA();
+ int littleEndian= 1;
+ littleEndian= ((char*)&littleEndian)[0];
+
+ mMemoryDNA->init(memDna,memDnaLength,littleEndian==0);
+
+
+
+
+ ///@todo we need a better version check, add version/sub version info from FileGlobal into memory DNA/header files
+ if (mMemoryDNA->getNumNames() != mFileDNA->getNumNames())
+ {
+ mFlags |= FD_VERSION_VARIES;
+ //printf ("Warning, file DNA is different than built in, performance is reduced. Best to re-export file with a matching version/platform");
+ }
+
+ // as long as it kept up to date it will be ok!!
+ if (mMemoryDNA->lessThan(mFileDNA))
+ {
+ //printf ("Warning, file DNA is newer than built in.");
+ }
+
+
+ mFileDNA->initCmpFlags(mMemoryDNA);
+
+ parseData();
+
+ resolvePointers(verboseMode);
+
+ updateOldPointers();
+
+
+}
+
+
+
+// ----------------------------------------------------- //
+void bFile::swap(char *head, bChunkInd& dataChunk, bool ignoreEndianFlag)
+{
+ char *data = head;
+ short *strc = mFileDNA->getStruct(dataChunk.dna_nr);
+
+
+
+ const char s[] = "SoftBodyMaterialData";
+ int szs = sizeof(s);
+ if (strncmp((char*)&dataChunk.code,"ARAY",4)==0)
+ {
+ short *oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
+ char *oldType = mFileDNA->getType(oldStruct[0]);
+ if (strncmp(oldType,s,szs)==0)
+ {
+ return;
+ }
+ }
+
+
+ int len = mFileDNA->getLength(strc[0]);
+
+ for (int i=0; i<dataChunk.nr; i++)
+ {
+ swapStruct(dataChunk.dna_nr, data,ignoreEndianFlag);
+ data+=len;
+ }
+}
+
+void bFile::swapLen(char *dataPtr)
+{
+ const bool VOID_IS_8 = ((sizeof(void*)==8));
+ if (VOID_IS_8)
+ {
+ if (mFlags &FD_BITS_VARIES)
+ {
+ bChunkPtr4*c = (bChunkPtr4*) dataPtr;
+ if ((c->code & 0xFFFF)==0)
+ c->code >>=16;
+ B3_SWITCH_INT(c->len);
+ B3_SWITCH_INT(c->dna_nr);
+ B3_SWITCH_INT(c->nr);
+ } else
+ {
+ bChunkPtr8* c = (bChunkPtr8*) dataPtr;
+ if ((c->code & 0xFFFF)==0)
+ c->code >>=16;
+ B3_SWITCH_INT(c->len);
+ B3_SWITCH_INT(c->dna_nr);
+ B3_SWITCH_INT(c->nr);
+
+ }
+ } else
+ {
+ if (mFlags &FD_BITS_VARIES)
+ {
+ bChunkPtr8*c = (bChunkPtr8*) dataPtr;
+ if ((c->code & 0xFFFF)==0)
+ c->code >>=16;
+ B3_SWITCH_INT(c->len);
+ B3_SWITCH_INT(c->dna_nr);
+ B3_SWITCH_INT(c->nr);
+
+ } else
+ {
+ bChunkPtr4* c = (bChunkPtr4*) dataPtr;
+ if ((c->code & 0xFFFF)==0)
+ c->code >>=16;
+ B3_SWITCH_INT(c->len);
+
+ B3_SWITCH_INT(c->dna_nr);
+ B3_SWITCH_INT(c->nr);
+
+ }
+ }
+
+}
+
+
+void bFile::swapDNA(char* ptr)
+{
+ bool swap = ((mFlags & FD_ENDIAN_SWAP)!=0);
+
+ char* data = &ptr[20];
+// void bDNA::init(char *data, int len, bool swap)
+ int *intPtr=0;short *shtPtr=0;
+ char *cp = 0;int dataLen =0;
+ //long nr=0;
+ intPtr = (int*)data;
+
+ /*
+ SDNA (4 bytes) (magic number)
+ NAME (4 bytes)
+ <nr> (4 bytes) amount of names (int)
+ <string>
+ <string>
+ */
+
+ if (strncmp(data, "SDNA", 4)==0)
+ {
+ // skip ++ NAME
+ intPtr++; intPtr++;
+ }
+
+
+
+ // Parse names
+ if (swap)
+ dataLen = ChunkUtils::swapInt(*intPtr);
+ else
+ dataLen = *intPtr;
+
+ *intPtr = ChunkUtils::swapInt(*intPtr);
+ intPtr++;
+
+ cp = (char*)intPtr;
+ int i;
+ for ( i=0; i<dataLen; i++)
+ {
+ while (*cp)cp++;
+ cp++;
+ }
+
+
+ cp = b3AlignPointer(cp,4);
+
+ /*
+ TYPE (4 bytes)
+ <nr> amount of types (int)
+ <string>
+ <string>
+ */
+
+ intPtr = (int*)cp;
+ assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+
+ if (swap)
+ dataLen = ChunkUtils::swapInt(*intPtr);
+ else
+ dataLen = *intPtr;
+
+ *intPtr = ChunkUtils::swapInt(*intPtr);
+
+ intPtr++;
+
+ cp = (char*)intPtr;
+ for ( i=0; i<dataLen; i++)
+ {
+ while (*cp)cp++;
+ cp++;
+ }
+
+ cp = b3AlignPointer(cp,4);
+
+ /*
+ TLEN (4 bytes)
+ <len> (short) the lengths of types
+ <len>
+ */
+
+ // Parse type lens
+ intPtr = (int*)cp;
+ assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+
+
+ shtPtr = (short*)intPtr;
+ for ( i=0; i<dataLen; i++, shtPtr++)
+ {
+ //??????if (swap)
+ shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+ }
+
+ if (dataLen & 1)
+ shtPtr++;
+
+ /*
+ STRC (4 bytes)
+ <nr> amount of structs (int)
+ <typenr>
+ <nr_of_elems>
+ <typenr>
+ <namenr>
+ <typenr>
+ <namenr>
+ */
+
+ intPtr = (int*)shtPtr;
+ cp = (char*)intPtr;
+ assert(strncmp(cp, "STRC", 4)==0);
+ intPtr++;
+
+ if (swap)
+ dataLen = ChunkUtils::swapInt(*intPtr);
+ else
+ dataLen = *intPtr;
+
+ *intPtr = ChunkUtils::swapInt(*intPtr);
+
+ intPtr++;
+
+
+ shtPtr = (short*)intPtr;
+ for ( i=0; i<dataLen; i++)
+ {
+
+ //if (swap)
+ {
+ int len = shtPtr[1];
+
+ shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
+ shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+
+ shtPtr+= 2;
+
+ for (int a=0; a<len; a++, shtPtr+=2)
+ {
+ shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
+ shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+ }
+ }
+// else
+// shtPtr+= (2*shtPtr[1])+2;
+ }
+
+}
+
+void bFile::writeFile(const char* fileName)
+{
+ FILE* f = fopen(fileName,"wb");
+ fwrite(mFileBuffer,1,mFileLen,f);
+ fclose(f);
+}
+
+void bFile::preSwap()
+{
+
+ //const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
+ //FD_ENDIAN_SWAP
+ //byte 8 determines the endianness of the file, little (v) versus big (V)
+ int littleEndian= 1;
+ littleEndian= ((char*)&littleEndian)[0];
+
+
+ if (mFileBuffer[8]=='V')
+ {
+ mFileBuffer[8]='v';
+ }
+ else
+ {
+ mFileBuffer[8]='V';
+ }
+
+
+
+
+
+
+ mDataStart = 12;
+
+ char *dataPtr = mFileBuffer+mDataStart;
+
+ bChunkInd dataChunk;
+ dataChunk.code = 0;
+ bool ignoreEndianFlag = true;
+
+ //we always want to swap here
+
+ int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+ //dataPtr += ChunkUtils::getOffset(mFlags);
+ char *dataPtrHead = 0;
+
+ while (1)
+ {
+ // one behind
+ if (dataChunk.code == B3_SDNA || dataChunk.code==B3_DNA1 || dataChunk.code == B3_TYPE || dataChunk.code == B3_TLEN || dataChunk.code==B3_STRC)
+ {
+
+ swapDNA(dataPtr);
+ break;
+ } else
+ {
+ //if (dataChunk.code == DNA1) break;
+ dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
+
+ swapLen(dataPtr);
+ if (dataChunk.dna_nr>=0)
+ {
+ swap(dataPtrHead, dataChunk,ignoreEndianFlag);
+ } else
+ {
+ //printf("unknown chunk\n");
+ }
+ }
+
+ // next please!
+ dataPtr += seek;
+
+ seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+ if (seek < 0)
+ break;
+ }
+
+ if (mFlags & FD_ENDIAN_SWAP)
+ {
+ mFlags &= ~FD_ENDIAN_SWAP;
+ } else
+ {
+ mFlags |= FD_ENDIAN_SWAP;
+ }
+
+
+
+}
+
+
+// ----------------------------------------------------- //
+char* bFile::readStruct(char *head, bChunkInd& dataChunk)
+{
+ bool ignoreEndianFlag = false;
+
+ if (mFlags & FD_ENDIAN_SWAP)
+ swap(head, dataChunk, ignoreEndianFlag);
+
+
+
+ if (!mFileDNA->flagEqual(dataChunk.dna_nr))
+ {
+ // Ouch! need to rebuild the struct
+ short *oldStruct,*curStruct;
+ char *oldType, *newType;
+ int oldLen, curLen, reverseOld;
+
+
+ oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
+ oldType = mFileDNA->getType(oldStruct[0]);
+
+ oldLen = mFileDNA->getLength(oldStruct[0]);
+
+ if ((mFlags&FD_BROKEN_DNA)!=0)
+ {
+ if ((strcmp(oldType,"b3QuantizedBvhNodeData")==0)&&oldLen==20)
+ {
+ return 0;
+ }
+ if ((strcmp(oldType,"b3ShortIntIndexData")==0))
+ {
+ int allocLen = 2;
+ char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
+ memset(dataAlloc, 0, (dataChunk.nr*allocLen)+1);
+ short* dest = (short*) dataAlloc;
+ const short* src = (short*) head;
+ for (int i=0;i<dataChunk.nr;i++)
+ {
+ dest[i] = src[i];
+ if (mFlags &FD_ENDIAN_SWAP)
+ {
+ B3_SWITCH_SHORT(dest[i]);
+ }
+ }
+ addDataBlock(dataAlloc);
+ return dataAlloc;
+ }
+ }
+
+
+
+ ///don't try to convert Link block data, just memcpy it. Other data can be converted.
+ if (strcmp("Link",oldType)!=0)
+ {
+ reverseOld = mMemoryDNA->getReverseType(oldType);
+
+ if ((reverseOld!=-1))
+ {
+ // make sure it's here
+ //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
+
+ //
+ curStruct = mMemoryDNA->getStruct(reverseOld);
+ newType = mMemoryDNA->getType(curStruct[0]);
+ curLen = mMemoryDNA->getLength(curStruct[0]);
+
+
+
+ // make sure it's the same
+ assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
+
+
+ // numBlocks * length
+
+ int allocLen = (curLen);
+ char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
+ memset(dataAlloc, 0, (dataChunk.nr*allocLen));
+
+ // track allocated
+ addDataBlock(dataAlloc);
+
+ char *cur = dataAlloc;
+ char *old = head;
+ for (int block=0; block<dataChunk.nr; block++)
+ {
+ bool fixupPointers = true;
+ parseStruct(cur, old, dataChunk.dna_nr, reverseOld, fixupPointers);
+ mLibPointers.insert(old,(bStructHandle*)cur);
+
+ cur += curLen;
+ old += oldLen;
+ }
+ return dataAlloc;
+ }
+ } else
+ {
+ //printf("Link found\n");
+ }
+ } else
+ {
+//#define DEBUG_EQUAL_STRUCTS
+#ifdef DEBUG_EQUAL_STRUCTS
+ short *oldStruct;
+ char *oldType;
+ oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
+ oldType = mFileDNA->getType(oldStruct[0]);
+ printf("%s equal structure, just memcpy\n",oldType);
+#endif //
+ }
+
+
+ char *dataAlloc = new char[(dataChunk.len)+1];
+ memset(dataAlloc, 0, dataChunk.len+1);
+
+
+ // track allocated
+ addDataBlock(dataAlloc);
+
+ memcpy(dataAlloc, head, dataChunk.len);
+ return dataAlloc;
+
+}
+
+
+// ----------------------------------------------------- //
+void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers)
+{
+ if (old_dna == -1) return;
+ if (new_dna == -1) return;
+
+ //disable this, because we need to fixup pointers/ListBase
+ if (0)//mFileDNA->flagEqual(old_dna))
+ {
+ short *strc = mFileDNA->getStruct(old_dna);
+ int len = mFileDNA->getLength(strc[0]);
+
+ memcpy(strcPtr, dtPtr, len);
+ return;
+ }
+
+ // Ok, now build the struct
+ char *memType, *memName, *cpc, *cpo;
+ short *fileStruct, *filePtrOld, *memoryStruct, *firstStruct;
+ int elementLength, size, revType, old_nr, new_nr, fpLen;
+ short firstStructType;
+
+
+ // File to memory lookup
+ memoryStruct = mMemoryDNA->getStruct(new_dna);
+ fileStruct = mFileDNA->getStruct(old_dna);
+ firstStruct = fileStruct;
+
+
+ filePtrOld = fileStruct;
+ firstStructType = mMemoryDNA->getStruct(0)[0];
+
+ // Get number of elements
+ elementLength = memoryStruct[1];
+ memoryStruct+=2;
+
+ cpc = strcPtr; cpo = 0;
+ for (int ele=0; ele<elementLength; ele++, memoryStruct+=2)
+ {
+ memType = mMemoryDNA->getType(memoryStruct[0]);
+ memName = mMemoryDNA->getName(memoryStruct[1]);
+
+
+ size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]);
+ revType = mMemoryDNA->getReverseType(memoryStruct[0]);
+
+ if (revType != -1 && memoryStruct[0]>=firstStructType && memName[0] != '*')
+ {
+ cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld);
+ if (cpo)
+ {
+ int arrayLen = mFileDNA->getArraySizeNew(filePtrOld[1]);
+ old_nr = mFileDNA->getReverseType(memType);
+ new_nr = revType;
+ fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]);
+ if (arrayLen==1)
+ {
+ parseStruct(cpc, cpo, old_nr, new_nr,fixupPointers);
+ } else
+ {
+ char* tmpCpc = cpc;
+ char* tmpCpo = cpo;
+
+ for (int i=0;i<arrayLen;i++)
+ {
+ parseStruct(tmpCpc, tmpCpo, old_nr, new_nr,fixupPointers);
+ tmpCpc += size/arrayLen;
+ tmpCpo += fpLen/arrayLen;
+ }
+ }
+ cpc+=size;
+ cpo+=fpLen;
+ }
+ else
+ cpc+=size;
+ }
+ else
+ {
+ getMatchingFileDNA(fileStruct, memName, memType, cpc, dtPtr,fixupPointers);
+ cpc+=size;
+ }
+
+ }
+}
+
+
+// ----------------------------------------------------- //
+static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData)
+{
+#define b3GetEle(value, current, type, cast, size, ptr)\
+ if (strcmp(current, type)==0)\
+ {\
+ value = (*(cast*)ptr);\
+ ptr += size;\
+ }
+
+#define b3SetEle(value, current, type, cast, size, ptr)\
+ if (strcmp(current, type)==0)\
+ {\
+ (*(cast*)ptr) = (cast)value;\
+ ptr += size;\
+ }
+ double value = 0.0;
+
+ for (int i=0; i<arrayLen; i++)
+ {
+ b3GetEle(value, old, "char", char, sizeof(char), oldPtr);
+ b3SetEle(value, cur, "char", char, sizeof(char), curData);
+ b3GetEle(value, old, "short", short, sizeof(short), oldPtr);
+ b3SetEle(value, cur, "short", short, sizeof(short), curData);
+ b3GetEle(value, old, "ushort", unsigned short, sizeof(unsigned short), oldPtr);
+ b3SetEle(value, cur, "ushort", unsigned short, sizeof(unsigned short), curData);
+ b3GetEle(value, old, "int", int, sizeof(int), oldPtr);
+ b3SetEle(value, cur, "int", int, sizeof(int), curData);
+ b3GetEle(value, old, "long", int, sizeof(int), oldPtr);
+ b3SetEle(value, cur, "long", int, sizeof(int), curData);
+ b3GetEle(value, old, "float", float, sizeof(float), oldPtr);
+ b3SetEle(value, cur, "float", float, sizeof(float), curData);
+ b3GetEle(value, old, "double", double, sizeof(double), oldPtr);
+ b3SetEle(value, cur, "double", double, sizeof(double), curData);
+ }
+}
+
+
+// ----------------------------------------------------- //
+void bFile::swapData(char *data, short type, int arraySize,bool ignoreEndianFlag)
+{
+ if (ignoreEndianFlag || (mFlags &FD_ENDIAN_SWAP))
+ {
+ if (type == 2 || type == 3)
+ {
+ short *sp = (short*)data;
+ for (int i=0; i<arraySize; i++)
+ {
+ sp[0] = ChunkUtils::swapShort(sp[0]);
+ sp++;
+ }
+ }
+ if (type>3 && type <8)
+ {
+ char c;
+ char *cp = data;
+ for (int i=0; i<arraySize; i++)
+ {
+ c = cp[0];
+ cp[0] = cp[3];
+ cp[3] = c;
+ c = cp[1];
+ cp[1] = cp[2];
+ cp[2] = c;
+ cp+=4;
+ }
+ }
+ }
+}
+
+
+
+void bFile::safeSwapPtr(char *dst, const char *src)
+{
+ int ptrFile = mFileDNA->getPointerSize();
+ int ptrMem = mMemoryDNA->getPointerSize();
+
+ if (!src && !dst)
+ return;
+
+
+ if (ptrFile == ptrMem)
+ {
+ memcpy(dst, src, ptrMem);
+ }
+ else if (ptrMem==4 && ptrFile==8)
+ {
+ b3PointerUid* oldPtr = (b3PointerUid*)src;
+ b3PointerUid* newPtr = (b3PointerUid*)dst;
+
+ if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
+ {
+ //Bullet stores the 32bit unique ID in both upper and lower part of 64bit pointers
+ //so it can be used to distinguish between .blend and .bullet
+ newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
+ } else
+ {
+ //deal with pointers the Blender .blend style way, see
+ //readfile.c in the Blender source tree
+ b3Long64 longValue = *((b3Long64*)src);
+ //endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros
+ if (mFlags & FD_ENDIAN_SWAP)
+ B3_SWITCH_LONGINT(longValue);
+ *((int*)dst) = (int)(longValue>>3);
+ }
+
+ }
+ else if (ptrMem==8 && ptrFile==4)
+ {
+ b3PointerUid* oldPtr = (b3PointerUid*)src;
+ b3PointerUid* newPtr = (b3PointerUid*)dst;
+ if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
+ {
+ newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
+ newPtr->m_uniqueIds[1] = 0;
+ } else
+ {
+ *((b3Long64*)dst)= *((int*)src);
+ }
+ }
+ else
+ {
+ printf ("%d %d\n", ptrFile,ptrMem);
+ assert(0 && "Invalid pointer len");
+ }
+
+
+}
+
+
+// ----------------------------------------------------- //
+void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers)
+{
+ // find the matching memory dna data
+ // to the file being loaded. Fill the
+ // memory with the file data...
+
+ int len = dna_addr[1];
+ dna_addr+=2;
+
+ for (int i=0; i<len; i++, dna_addr+=2)
+ {
+ const char* type = mFileDNA->getType(dna_addr[0]);
+ const char* name = mFileDNA->getName(dna_addr[1]);
+
+
+
+ int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]);
+
+ if ((mFlags&FD_BROKEN_DNA)!=0)
+ {
+ if ((strcmp(type,"short")==0)&&(strcmp(name,"int")==0))
+ {
+ eleLen = 0;
+ }
+ }
+
+ if (strcmp(lookupName, name)==0)
+ {
+ //int arrayLenold = mFileDNA->getArraySize((char*)name.c_str());
+ int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]);
+ //assert(arrayLenold == arrayLen);
+
+ if (name[0] == '*')
+ {
+ // cast pointers
+ int ptrFile = mFileDNA->getPointerSize();
+ int ptrMem = mMemoryDNA->getPointerSize();
+ safeSwapPtr(strcData,data);
+
+ if (fixupPointers)
+ {
+ if (arrayLen > 1)
+ {
+ //void **sarray = (void**)strcData;
+ //void **darray = (void**)data;
+
+ char *cpc, *cpo;
+ cpc = (char*)strcData;
+ cpo = (char*)data;
+
+ for (int a=0; a<arrayLen; a++)
+ {
+ safeSwapPtr(cpc, cpo);
+ m_pointerFixupArray.push_back(cpc);
+ cpc += ptrMem;
+ cpo += ptrFile;
+ }
+ }
+ else
+ {
+ if (name[1] == '*')
+ m_pointerPtrFixupArray.push_back(strcData);
+ else
+ m_pointerFixupArray.push_back(strcData);
+ }
+ }
+ else
+ {
+// printf("skipped %s %s : %x\n",type.c_str(),name.c_str(),strcData);
+ }
+
+ }
+
+ else if (strcmp(type, lookupType)==0)
+ memcpy(strcData, data, eleLen);
+ else
+ getElement(arrayLen, lookupType, type, data, strcData);
+
+ // --
+ return;
+ }
+ data+=eleLen;
+ }
+}
+
+
+// ----------------------------------------------------- //
+char* bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos)
+{
+ short *old = firstStruct;//mFileDNA->getStruct(old_nr);
+ int elementLength = old[1];
+ old+=2;
+
+ for (int i=0; i<elementLength; i++, old+=2)
+ {
+ char* type = mFileDNA->getType(old[0]);
+ char* name = mFileDNA->getName(old[1]);
+ int len = mFileDNA->getElementSize(old[0], old[1]);
+
+ if (strcmp(lookupName, name)==0)
+ {
+ if (strcmp(type, lookupType)==0)
+ {
+ if (foundPos)
+ *foundPos = old;
+ return data;
+ }
+ return 0;
+ }
+ data+=len;
+ }
+ return 0;
+}
+
+
+// ----------------------------------------------------- //
+void bFile::swapStruct(int dna_nr, char *data,bool ignoreEndianFlag)
+{
+ if (dna_nr == -1) return;
+
+ short *strc = mFileDNA->getStruct(dna_nr);
+ //short *firstStrc = strc;
+
+ int elementLen= strc[1];
+ strc+=2;
+
+ short first = mFileDNA->getStruct(0)[0];
+
+ char *buf = data;
+ for (int i=0; i<elementLen; i++, strc+=2)
+ {
+ char *type = mFileDNA->getType(strc[0]);
+ char *name = mFileDNA->getName(strc[1]);
+
+ int size = mFileDNA->getElementSize(strc[0], strc[1]);
+ if (strc[0] >= first && name[0]!='*')
+ {
+ int old_nr = mFileDNA->getReverseType(type);
+ int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
+ if (arrayLen==1)
+ {
+ swapStruct(old_nr,buf,ignoreEndianFlag);
+ } else
+ {
+ char* tmpBuf = buf;
+ for (int i=0;i<arrayLen;i++)
+ {
+ swapStruct(old_nr,tmpBuf,ignoreEndianFlag);
+ tmpBuf+=size/arrayLen;
+ }
+ }
+ }
+ else
+ {
+ //int arrayLenOld = mFileDNA->getArraySize(name);
+ int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
+ //assert(arrayLenOld == arrayLen);
+ swapData(buf, strc[0], arrayLen,ignoreEndianFlag);
+ }
+ buf+=size;
+ }
+}
+
+void bFile::resolvePointersMismatch()
+{
+// printf("resolvePointersStructMismatch\n");
+
+ int i;
+
+ for (i=0;i< m_pointerFixupArray.size();i++)
+ {
+ char* cur = m_pointerFixupArray.at(i);
+ void** ptrptr = (void**) cur;
+ void* ptr = *ptrptr;
+ ptr = findLibPointer(ptr);
+ if (ptr)
+ {
+ //printf("Fixup pointer!\n");
+ *(ptrptr) = ptr;
+ } else
+ {
+// printf("pointer not found: %x\n",cur);
+ }
+ }
+
+
+ for (i=0; i<m_pointerPtrFixupArray.size(); i++)
+ {
+ char* cur= m_pointerPtrFixupArray.at(i);
+ void** ptrptr = (void**)cur;
+
+ bChunkInd *block = m_chunkPtrPtrMap.find(*ptrptr);
+ if (block)
+ {
+ int ptrMem = mMemoryDNA->getPointerSize();
+ int ptrFile = mFileDNA->getPointerSize();
+
+
+ int blockLen = block->len / ptrFile;
+
+ void *onptr = findLibPointer(*ptrptr);
+ if (onptr)
+ {
+ char *newPtr = new char[blockLen * ptrMem];
+ addDataBlock(newPtr);
+ memset(newPtr, 0, blockLen * ptrMem);
+
+ void **onarray = (void**)onptr;
+ char *oldPtr = (char*)onarray;
+
+ int p = 0;
+ while (blockLen-- > 0)
+ {
+ b3PointerUid dp = {{0}};
+ safeSwapPtr((char*)dp.m_uniqueIds, oldPtr);
+
+ void **tptr = (void**)(newPtr + p * ptrMem);
+ *tptr = findLibPointer(dp.m_ptr);
+
+ oldPtr += ptrFile;
+ ++p;
+ }
+
+ *ptrptr = newPtr;
+ }
+ }
+ }
+}
+
+
+///this loop only works fine if the Blender DNA structure of the file matches the headerfiles
+void bFile::resolvePointersChunk(const bChunkInd& dataChunk, int verboseMode)
+{
+ bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+ short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+ short oldLen = fileDna->getLength(oldStruct[0]);
+ //char* structType = fileDna->getType(oldStruct[0]);
+
+ char* cur = (char*)findLibPointer(dataChunk.oldPtr);
+ for (int block=0; block<dataChunk.nr; block++)
+ {
+ resolvePointersStructRecursive(cur,dataChunk.dna_nr, verboseMode,1);
+ cur += oldLen;
+ }
+}
+
+
+int bFile::resolvePointersStructRecursive(char *strcPtr, int dna_nr, int verboseMode,int recursion)
+{
+
+ bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+ char* memType;
+ char* memName;
+ short firstStructType = fileDna->getStruct(0)[0];
+
+
+ char* elemPtr= strcPtr;
+
+ short int* oldStruct = fileDna->getStruct(dna_nr);
+
+ int elementLength = oldStruct[1];
+ oldStruct+=2;
+
+ int totalSize = 0;
+
+ for (int ele=0; ele<elementLength; ele++, oldStruct+=2)
+ {
+
+ memType = fileDna->getType(oldStruct[0]);
+ memName = fileDna->getName(oldStruct[1]);
+
+
+
+ int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
+ if (memName[0] == '*')
+ {
+ if (arrayLen > 1)
+ {
+ void **array= (void**)elemPtr;
+ for (int a=0; a<arrayLen; a++)
+ {
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ for (int i=0;i<recursion;i++)
+ {
+ printf(" ");
+ }
+ //skip the *
+ printf("<%s type=\"pointer\"> ",&memName[1]);
+ printf("%p ", array[a]);
+ printf("</%s>\n",&memName[1]);
+ }
+
+ array[a] = findLibPointer(array[a]);
+ }
+ }
+ else
+ {
+ void** ptrptr = (void**) elemPtr;
+ void* ptr = *ptrptr;
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ for (int i=0;i<recursion;i++)
+ {
+ printf(" ");
+ }
+ printf("<%s type=\"pointer\"> ",&memName[1]);
+ printf("%p ", ptr);
+ printf("</%s>\n",&memName[1]);
+ }
+ ptr = findLibPointer(ptr);
+
+ if (ptr)
+ {
+ // printf("Fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
+ *(ptrptr) = ptr;
+ if (memName[1] == '*' && ptrptr && *ptrptr)
+ {
+ // This will only work if the given **array is continuous
+ void **array= (void**)*(ptrptr);
+ void *np= array[0];
+ int n=0;
+ while (np)
+ {
+ np= findLibPointer(array[n]);
+ if (np) array[n]= np;
+ n++;
+ }
+ }
+ } else
+ {
+ // printf("Cannot fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
+ }
+ }
+ } else
+ {
+ int revType = fileDna->getReverseType(oldStruct[0]);
+ if (oldStruct[0]>=firstStructType) //revType != -1 &&
+ {
+ char cleanName[MAX_STRLEN];
+ getCleanName(memName,cleanName);
+
+ int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
+ int byteOffset = 0;
+
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ for (int i=0;i<recursion;i++)
+ {
+ printf(" ");
+ }
+
+ if (arrayLen>1)
+ {
+ printf("<%s type=\"%s\" count=%d>\n",cleanName,memType, arrayLen);
+ } else
+ {
+ printf("<%s type=\"%s\">\n",cleanName,memType);
+ }
+ }
+
+ for (int i=0;i<arrayLen;i++)
+ {
+ byteOffset += resolvePointersStructRecursive(elemPtr+byteOffset,revType, verboseMode,recursion+1);
+ }
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ for (int i=0;i<recursion;i++)
+ {
+ printf(" ");
+ }
+ printf("</%s>\n",cleanName);
+ }
+ } else
+ {
+ //export a simple type
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+
+ if (arrayLen>MAX_ARRAY_LENGTH)
+ {
+ printf("too long\n");
+ } else
+ {
+ //printf("%s %s\n",memType,memName);
+
+ bool isIntegerType = (strcmp(memType,"char")==0) || (strcmp(memType,"int")==0) || (strcmp(memType,"short")==0);
+
+ if (isIntegerType)
+ {
+ const char* newtype="int";
+ int dbarray[MAX_ARRAY_LENGTH];
+ int* dbPtr = 0;
+ char* tmp = elemPtr;
+ dbPtr = &dbarray[0];
+ if (dbPtr)
+ {
+ char cleanName[MAX_STRLEN];
+ getCleanName(memName,cleanName);
+
+ int i;
+ getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
+ for (i=0;i<recursion;i++)
+ printf(" ");
+ if (arrayLen==1)
+ printf("<%s type=\"%s\">",cleanName,memType);
+ else
+ printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen);
+ for (i=0;i<arrayLen;i++)
+ printf(" %d ",dbPtr[i]);
+ printf("</%s>\n",cleanName);
+ }
+ } else
+ {
+ const char* newtype="double";
+ double dbarray[MAX_ARRAY_LENGTH];
+ double* dbPtr = 0;
+ char* tmp = elemPtr;
+ dbPtr = &dbarray[0];
+ if (dbPtr)
+ {
+ int i;
+ getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
+ for (i=0;i<recursion;i++)
+ printf(" ");
+ char cleanName[MAX_STRLEN];
+ getCleanName(memName,cleanName);
+
+ if (arrayLen==1)
+ {
+ printf("<%s type=\"%s\">",memName,memType);
+ }
+ else
+ {
+ printf("<%s type=\"%s\" count=%d>",cleanName,memType,arrayLen);
+ }
+ for (i=0;i<arrayLen;i++)
+ printf(" %f ",dbPtr[i]);
+ printf("</%s>\n",cleanName);
+ }
+ }
+ }
+
+ }
+ }
+ }
+
+ int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]);
+ totalSize += size;
+ elemPtr+=size;
+
+ }
+
+ return totalSize;
+}
+
+
+///Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory structures
+void bFile::resolvePointers(int verboseMode)
+{
+ bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+ //char *dataPtr = mFileBuffer+mDataStart;
+
+ if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES))
+ {
+ resolvePointersMismatch();
+ }
+
+ {
+
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+ int numitems = m_chunks.size();
+ printf("<bullet_physics version=%d itemcount = %d>\n", b3GetVersion(), numitems);
+ }
+ for (int i=0;i<m_chunks.size();i++)
+ {
+ const bChunkInd& dataChunk = m_chunks.at(i);
+
+ if (!mFileDNA || fileDna->flagEqual(dataChunk.dna_nr))
+ {
+ //dataChunk.len
+ short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+ char* oldType = fileDna->getType(oldStruct[0]);
+
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ printf(" <%s pointer=%p>\n",oldType,dataChunk.oldPtr);
+
+ resolvePointersChunk(dataChunk, verboseMode);
+
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ printf(" </%s>\n",oldType);
+ } else
+ {
+ //printf("skipping mStruct\n");
+ }
+ }
+ if (verboseMode & FD_VERBOSE_EXPORT_XML)
+ {
+ printf("</bullet_physics>\n");
+ }
+ }
+
+
+}
+
+
+// ----------------------------------------------------- //
+void* bFile::findLibPointer(void *ptr)
+{
+
+ bStructHandle** ptrptr = getLibPointers().find(ptr);
+ if (ptrptr)
+ return *ptrptr;
+ return 0;
+}
+
+
+void bFile::updateOldPointers()
+{
+ int i;
+
+ for (i=0;i<m_chunks.size();i++)
+ {
+ bChunkInd& dataChunk = m_chunks[i];
+ dataChunk.oldPtr = findLibPointer(dataChunk.oldPtr);
+ }
+}
+void bFile::dumpChunks(bParse::bDNA* dna)
+{
+ int i;
+
+ for (i=0;i<m_chunks.size();i++)
+ {
+ bChunkInd& dataChunk = m_chunks[i];
+ char* codeptr = (char*)&dataChunk.code;
+ char codestr[5] = {codeptr[0],codeptr[1],codeptr[2],codeptr[3],0};
+
+ short* newStruct = dna->getStruct(dataChunk.dna_nr);
+ char* typeName = dna->getType(newStruct[0]);
+ printf("%3d: %s ",i,typeName);
+
+ printf("code=%s ",codestr);
+
+ printf("ptr=%p ",dataChunk.oldPtr);
+ printf("len=%d ",dataChunk.len);
+ printf("nr=%d ",dataChunk.nr);
+ if (dataChunk.nr!=1)
+ {
+ printf("not 1\n");
+ }
+ printf("\n");
+
+
+
+
+ }
+
+#if 0
+ IDFinderData ifd;
+ ifd.success = 0;
+ ifd.IDname = NULL;
+ ifd.just_print_it = 1;
+ for (i=0; i<bf->m_blocks.size(); ++i)
+ {
+ BlendBlock* bb = bf->m_blocks[i];
+ printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]", bb->tag, bb,bf->types[bb->type_index].name,bb->m_array_entries_.size());
+ block_ID_finder(bb, bf, &ifd);
+ printf("\n");
+ }
+#endif
+
+}
+
+
+void bFile::writeChunks(FILE* fp, bool fixupPointers)
+{
+ bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+ for (int i=0;i<m_chunks.size();i++)
+ {
+ bChunkInd& dataChunk = m_chunks.at(i);
+
+ // Ouch! need to rebuild the struct
+ short *oldStruct,*curStruct;
+ char *oldType, *newType;
+ int oldLen, curLen, reverseOld;
+
+ oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+ oldType = fileDna->getType(oldStruct[0]);
+ oldLen = fileDna->getLength(oldStruct[0]);
+ ///don't try to convert Link block data, just memcpy it. Other data can be converted.
+ reverseOld = mMemoryDNA->getReverseType(oldType);
+
+
+ if ((reverseOld!=-1))
+ {
+ // make sure it's here
+ //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
+ //
+ curStruct = mMemoryDNA->getStruct(reverseOld);
+ newType = mMemoryDNA->getType(curStruct[0]);
+ // make sure it's the same
+ assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
+
+
+ curLen = mMemoryDNA->getLength(curStruct[0]);
+ dataChunk.dna_nr = reverseOld;
+ if (strcmp("Link",oldType)!=0)
+ {
+ dataChunk.len = curLen * dataChunk.nr;
+ } else
+ {
+// printf("keep length of link = %d\n",dataChunk.len);
+ }
+
+ //write the structure header
+ fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
+
+
+
+ short int* curStruct1;
+ curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr);
+ assert(curStruct1 == curStruct);
+
+ char* cur = fixupPointers ? (char*)findLibPointer(dataChunk.oldPtr) : (char*)dataChunk.oldPtr;
+
+ //write the actual contents of the structure(s)
+ fwrite(cur,dataChunk.len,1,fp);
+ } else
+ {
+ printf("serious error, struct mismatch: don't write\n");
+ }
+ }
+
+}
+
+
+// ----------------------------------------------------- //
+int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
+{
+ bool swap = false;
+ bool varies = false;
+
+ if (flags &FD_ENDIAN_SWAP)
+ swap = true;
+ if (flags &FD_BITS_VARIES)
+ varies = true;
+
+ if (VOID_IS_8)
+ {
+ if (varies)
+ {
+ bChunkPtr4 head;
+ memcpy(&head, dataPtr, sizeof(bChunkPtr4));
+
+
+ bChunkPtr8 chunk;
+
+ chunk.code = head.code;
+ chunk.len = head.len;
+ chunk.m_uniqueInts[0] = head.m_uniqueInt;
+ chunk.m_uniqueInts[1] = 0;
+ chunk.dna_nr = head.dna_nr;
+ chunk.nr = head.nr;
+
+ if (swap)
+ {
+ if ((chunk.code & 0xFFFF)==0)
+ chunk.code >>=16;
+
+ B3_SWITCH_INT(chunk.len);
+ B3_SWITCH_INT(chunk.dna_nr);
+ B3_SWITCH_INT(chunk.nr);
+ }
+
+
+ memcpy(dataChunk, &chunk, sizeof(bChunkInd));
+ }
+ else
+ {
+ bChunkPtr8 c;
+ memcpy(&c, dataPtr, sizeof(bChunkPtr8));
+
+ if (swap)
+ {
+ if ((c.code & 0xFFFF)==0)
+ c.code >>=16;
+
+ B3_SWITCH_INT(c.len);
+ B3_SWITCH_INT(c.dna_nr);
+ B3_SWITCH_INT(c.nr);
+ }
+
+ memcpy(dataChunk, &c, sizeof(bChunkInd));
+ }
+ }
+ else
+ {
+ if (varies)
+ {
+ bChunkPtr8 head;
+ memcpy(&head, dataPtr, sizeof(bChunkPtr8));
+
+
+ bChunkPtr4 chunk;
+ chunk.code = head.code;
+ chunk.len = head.len;
+
+ if (head.m_uniqueInts[0]==head.m_uniqueInts[1])
+ {
+ chunk.m_uniqueInt = head.m_uniqueInts[0];
+ } else
+ {
+ b3Long64 oldPtr =0;
+ memcpy(&oldPtr, &head.m_uniqueInts[0], 8);
+ if (swap)
+ B3_SWITCH_LONGINT(oldPtr);
+ chunk.m_uniqueInt = (int)(oldPtr >> 3);
+ }
+
+
+ chunk.dna_nr = head.dna_nr;
+ chunk.nr = head.nr;
+
+ if (swap)
+ {
+ if ((chunk.code & 0xFFFF)==0)
+ chunk.code >>=16;
+
+ B3_SWITCH_INT(chunk.len);
+ B3_SWITCH_INT(chunk.dna_nr);
+ B3_SWITCH_INT(chunk.nr);
+ }
+
+ memcpy(dataChunk, &chunk, sizeof(bChunkInd));
+ }
+ else
+ {
+ bChunkPtr4 c;
+ memcpy(&c, dataPtr, sizeof(bChunkPtr4));
+
+ if (swap)
+ {
+ if ((c.code & 0xFFFF)==0)
+ c.code >>=16;
+
+ B3_SWITCH_INT(c.len);
+ B3_SWITCH_INT(c.dna_nr);
+ B3_SWITCH_INT(c.nr);
+ }
+ memcpy(dataChunk, &c, sizeof(bChunkInd));
+ }
+ }
+
+ if (dataChunk->len < 0)
+ return -1;
+
+#if 0
+ print ("----------");
+ print (dataChunk->code);
+ print (dataChunk->len);
+ print (dataChunk->old);
+ print (dataChunk->dna_nr);
+ print (dataChunk->nr);
+#endif
+ return (dataChunk->len+ChunkUtils::getOffset(flags));
+}
+
+
+
+//eof