bFile.cpp 38 KB

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