CDefHandler.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. #include "../stdafx.h"
  2. #include "SDL.h"
  3. #include "CDefHandler.h"
  4. #include <sstream>
  5. #include "CLodHandler.h"
  6. #include "../lib/VCMI_Lib.h"
  7. /*
  8. * CDefHandler.cpp, part of VCMI engine
  9. *
  10. * Authors: listed in file AUTHORS in main folder
  11. *
  12. * License: GNU General Public License v2.0 or later
  13. * Full text of license available in license.txt file, in main folder
  14. *
  15. */
  16. static long long pow(long long a, int b)
  17. {
  18. if (!b) return 1;
  19. long c = a;
  20. while (--b)
  21. a*=c;
  22. return a;
  23. }
  24. CDefHandler::CDefHandler()
  25. {
  26. //FDef = NULL;
  27. RWEntries = NULL;
  28. notFreeImgs = false;
  29. }
  30. CDefHandler::~CDefHandler()
  31. {
  32. //if (FDef)
  33. //delete [] FDef;
  34. if (RWEntries)
  35. delete [] RWEntries;
  36. if (notFreeImgs)
  37. return;
  38. for (size_t i=0; i<ourImages.size(); ++i)
  39. {
  40. if (ourImages[i].bitmap)
  41. {
  42. SDL_FreeSurface(ourImages[i].bitmap);
  43. ourImages[i].bitmap=NULL;
  44. }
  45. }
  46. }
  47. CDefEssential::~CDefEssential()
  48. {
  49. for(size_t i=0; i < ourImages.size(); ++i)
  50. SDL_FreeSurface(ourImages[i].bitmap);
  51. }
  52. void CDefHandler::openDef(std::string name)
  53. {
  54. int i,j, totalInBlock;
  55. char Buffer[13];
  56. BMPPalette palette[256];
  57. defName=name;
  58. int andame;
  59. std::ifstream * is = new std::ifstream();
  60. is -> open(name.c_str(),std::ios::binary);
  61. is->seekg(0,std::ios::end); // na koniec
  62. andame = is->tellg(); // read length
  63. is->seekg(0,std::ios::beg); // wracamy na poczatek
  64. unsigned char * FDef = new unsigned char[andame]; // allocate memory
  65. is->read((char*)FDef, andame); // read map file to buffer
  66. is->close();
  67. delete is;
  68. i = 0;
  69. DEFType = readNormalNr(i,4,FDef); i+=4;
  70. width = readNormalNr(i,4,FDef); i+=4;
  71. height = readNormalNr(i,4,FDef); i+=4;
  72. i=0xc;
  73. totalBlocks = readNormalNr(i,4,FDef); i+=4;
  74. i=0x10;
  75. for (int it=0;it<256;it++)
  76. {
  77. palette[it].R = FDef[i++];
  78. palette[it].G = FDef[i++];
  79. palette[it].B = FDef[i++];
  80. palette[it].F = 0;
  81. }
  82. i=0x310;
  83. totalEntries=0;
  84. for (int z=0; z<totalBlocks; z++)
  85. {
  86. i+=4;
  87. totalInBlock = readNormalNr(i,4,FDef); i+=4;
  88. for (j=SEntries.size(); j<totalEntries+totalInBlock; j++)
  89. SEntries.push_back(SEntry());
  90. i+=8;
  91. for (j=0; j<totalInBlock; j++)
  92. {
  93. for (int k=0;k<13;k++) Buffer[k]=FDef[i+k];
  94. i+=13;
  95. SEntries[totalEntries+j].name=Buffer;
  96. }
  97. for (j=0; j<totalInBlock; j++)
  98. {
  99. SEntries[totalEntries+j].offset = readNormalNr(i,4,FDef);
  100. i+=4;
  101. }
  102. //totalEntries+=totalInBlock;
  103. for(int hh=0; hh<totalInBlock; ++hh)
  104. {
  105. SEntries[totalEntries].group = z;
  106. ++totalEntries;
  107. }
  108. }
  109. for(j=0; j<SEntries.size(); ++j)
  110. {
  111. SEntries[j].name = SEntries[j].name.substr(0, SEntries[j].name.find('.')+4);
  112. }
  113. for(size_t i=0; i < SEntries.size(); ++i)
  114. {
  115. Cimage nimg;
  116. nimg.bitmap = getSprite(i, FDef, palette);
  117. nimg.imName = SEntries[i].name;
  118. nimg.groupNumber = SEntries[i].group;
  119. ourImages.push_back(nimg);
  120. }
  121. delete [] FDef;
  122. FDef = NULL;
  123. }
  124. void CDefHandler::openFromMemory(unsigned char *table, std::string name)
  125. {
  126. int i,j, totalInBlock;
  127. BMPPalette palette[256];
  128. defName=name;
  129. i = 0;
  130. DEFType = readNormalNr(i,4,table); i+=4;
  131. width = readNormalNr(i,4,table); i+=4;
  132. height = readNormalNr(i,4,table); i+=4;
  133. i=0xc;
  134. totalBlocks = readNormalNr(i,4,table); i+=4;
  135. i=0x10;
  136. for (int it=0;it<256;it++)
  137. {
  138. palette[it].R = table[i++];
  139. palette[it].G = table[i++];
  140. palette[it].B = table[i++];
  141. palette[it].F = 0;
  142. }
  143. i=0x310;
  144. totalEntries=0;
  145. for (int z=0; z<totalBlocks; z++)
  146. {
  147. int unknown1 = readNormalNr(i,4,table); i+=4; //TODO use me
  148. totalInBlock = readNormalNr(i,4,table); i+=4;
  149. for (j=SEntries.size(); j<totalEntries+totalInBlock; j++)
  150. SEntries.push_back(SEntry());
  151. int unknown2 = readNormalNr(i,4,table); //TODO use me
  152. i+=4;
  153. int unknown3 = readNormalNr(i,4,table); //TODO use me
  154. i+=4;
  155. for (j=0; j<totalInBlock; j++)
  156. {
  157. char Buffer[13];
  158. memcpy(Buffer, &table[i], 12);
  159. Buffer[12] = 0;
  160. SEntries[totalEntries+j].name=Buffer;
  161. i+=13;
  162. }
  163. for (j=0; j<totalInBlock; j++)
  164. {
  165. SEntries[totalEntries+j].offset = readNormalNr(i,4,table);
  166. int unknown4 = readNormalNr(i,4,table); //TODO use me
  167. i+=4;
  168. }
  169. //totalEntries+=totalInBlock;
  170. for(int hh=0; hh<totalInBlock; ++hh)
  171. {
  172. SEntries[totalEntries].group = z;
  173. ++totalEntries;
  174. }
  175. }
  176. for(j=0; j<SEntries.size(); ++j)
  177. {
  178. SEntries[j].name = SEntries[j].name.substr(0, SEntries[j].name.find('.')+4);
  179. }
  180. RWEntries = new unsigned int[height];
  181. for(size_t i=0; i < SEntries.size(); ++i)
  182. {
  183. Cimage nimg;
  184. nimg.bitmap = getSprite(i, table, palette);
  185. nimg.imName = SEntries[i].name;
  186. nimg.groupNumber = SEntries[i].group;
  187. ourImages.push_back(nimg);
  188. }
  189. }
  190. unsigned char * CDefHandler::writeNormalNr (int nr, int bytCon)
  191. {
  192. //int tralalalatoniedziala = 2*9+100-4*bytCon;
  193. //unsigned char * ret = new unsigned char[bytCon];
  194. unsigned char * ret = NULL;
  195. for(int jj=0; jj<100; ++jj)
  196. {
  197. ret = (unsigned char*)calloc(1, bytCon);
  198. if(ret!=NULL)
  199. break;
  200. }
  201. long long amp = pow((long long int)256,bytCon-1);
  202. for (int i=bytCon-1; i>=0;i--)
  203. {
  204. int test2 = nr/(amp);
  205. ret[i]=test2;
  206. nr -= (nr/(amp))*amp;
  207. amp/=256;
  208. }
  209. return ret;
  210. }
  211. void CDefHandler::expand(unsigned char N,unsigned char & BL, unsigned char & BR)
  212. {
  213. BL = (N & 0xE0) >> 5;
  214. BR = N & 0x1F;
  215. }
  216. int CDefHandler::readNormalNr (int pos, int bytCon, const unsigned char * str, bool cyclic)
  217. {
  218. int ret=0;
  219. int amp=1;
  220. if (str)
  221. {
  222. for (int i=0; i<bytCon; i++)
  223. {
  224. ret+=str[pos+i]*amp;
  225. amp*=256;
  226. }
  227. }
  228. //else
  229. //{
  230. // for (int i=0; i<bytCon; i++)
  231. // {
  232. // ret+=FDef[pos+i]*amp;
  233. // amp*=256;
  234. // }
  235. //}
  236. if(cyclic && bytCon<4 && ret>=amp/2)
  237. {
  238. ret = ret-amp;
  239. }
  240. return ret;
  241. }
  242. void CDefHandler::print (std::ostream & stream, int nr, int bytcon)
  243. {
  244. unsigned char * temp = writeNormalNr(nr,bytcon);
  245. for (int i=0;i<bytcon;i++)
  246. stream << char(temp[i]);
  247. free(temp);
  248. }
  249. SDL_Surface * CDefHandler::getSprite (int SIndex, unsigned char * FDef, BMPPalette * palette)
  250. {
  251. SDL_Surface * ret=NULL;
  252. long BaseOffset,
  253. SpriteWidth, SpriteHeight, //format sprite'a
  254. LeftMargin, RightMargin, TopMargin,BottomMargin,
  255. i, add, FullHeight,FullWidth,
  256. TotalRowLength, // dlugosc przeczytanego segmentu
  257. RowAdd;//, NextSpriteOffset; //TODO use me
  258. unsigned char SegmentType;//, BL, BR; //TODO use me
  259. i=BaseOffset=SEntries[SIndex].offset;
  260. int prSize=readNormalNr(i,4,FDef);i+=4; //TODO use me
  261. int defType2 = readNormalNr(i,4,FDef);i+=4;
  262. FullWidth = readNormalNr(i,4,FDef);i+=4;
  263. FullHeight = readNormalNr(i,4,FDef);i+=4;
  264. SpriteWidth = readNormalNr(i,4,FDef);i+=4;
  265. SpriteHeight = readNormalNr(i,4,FDef);i+=4;
  266. LeftMargin = readNormalNr(i,4,FDef);i+=4;
  267. TopMargin = readNormalNr(i,4,FDef);i+=4;
  268. RightMargin = FullWidth - SpriteWidth - LeftMargin;
  269. BottomMargin = FullHeight - SpriteHeight - TopMargin;
  270. //if(LeftMargin + RightMargin < 0)
  271. // SpriteWidth += LeftMargin + RightMargin; //ugly construction... TODO: check how to do it nicer
  272. if(LeftMargin<0)
  273. SpriteWidth+=LeftMargin;
  274. if(RightMargin<0)
  275. SpriteWidth+=RightMargin;
  276. // Note: this looks bogus because we allocate only FullWidth, not FullWidth+add
  277. add = 4 - FullWidth%4;
  278. if (add==4)
  279. add=0;
  280. ret = SDL_CreateRGBSurface(SDL_SWSURFACE, FullWidth, FullHeight, 8, 0, 0, 0, 0);
  281. //int tempee2 = readNormalNr(0,4,((unsigned char *)tempee.c_str()));
  282. int BaseOffsetor = BaseOffset = i;
  283. for(int i=0; i<256; ++i)
  284. {
  285. SDL_Color pr;
  286. pr.r = palette[i].R;
  287. pr.g = palette[i].G;
  288. pr.b = palette[i].B;
  289. pr.unused = palette[i].F;
  290. (*(ret->format->palette->colors+i))=pr;
  291. }
  292. int ftcp=0;
  293. // If there's a margin anywhere, just blank out the whole surface.
  294. if (TopMargin > 0 || BottomMargin > 0 || LeftMargin > 0 || RightMargin > 0) {
  295. memset(((char *)ret->pixels), 0, FullHeight*FullWidth);
  296. }
  297. // Skip top margin
  298. if (TopMargin > 0)
  299. ftcp += TopMargin*(FullWidth+add);
  300. switch(defType2)
  301. {
  302. case 0:
  303. {
  304. for (int i=0;i<SpriteHeight;i++)
  305. {
  306. if (LeftMargin>0)
  307. ftcp += LeftMargin;
  308. memcpy((char*)(ret->pixels)+ftcp, &FDef[BaseOffset], SpriteWidth);
  309. ftcp += SpriteWidth;
  310. BaseOffset += SpriteWidth;
  311. if (RightMargin>0)
  312. ftcp += RightMargin;
  313. }
  314. }
  315. break;
  316. case 1:
  317. {
  318. memcpy(RWEntries, FDef+BaseOffset, SpriteHeight*sizeof(int));
  319. BaseOffset += sizeof(int) * SpriteHeight;
  320. for (int i=0;i<SpriteHeight;i++)
  321. {
  322. BaseOffset=BaseOffsetor+RWEntries[i];
  323. if (LeftMargin>0)
  324. ftcp += LeftMargin;
  325. TotalRowLength=0;
  326. do
  327. {
  328. unsigned int SegmentLength;
  329. SegmentType=FDef[BaseOffset++];
  330. SegmentLength=FDef[BaseOffset++] + 1;
  331. if (SegmentType==0xFF)
  332. {
  333. for (int k=0;k<SegmentLength;k++)
  334. {
  335. ((char*)(ret->pixels))[ftcp++]=FDef[BaseOffset+k];
  336. if ((TotalRowLength+k)>=SpriteWidth)
  337. break;
  338. }
  339. BaseOffset+=SegmentLength;
  340. TotalRowLength+=SegmentLength;
  341. }
  342. else
  343. {
  344. memset((char*)(ret->pixels)+ftcp, SegmentType, SegmentLength);
  345. ftcp += SegmentLength;
  346. TotalRowLength += SegmentLength;
  347. }
  348. }while(TotalRowLength<SpriteWidth);
  349. RowAdd=SpriteWidth-TotalRowLength;
  350. if (RightMargin>0)
  351. ftcp += RightMargin;
  352. if (add>0)
  353. ftcp += add+RowAdd;
  354. }
  355. }
  356. break;
  357. case 2:
  358. {
  359. for (int i=0;i<SpriteHeight;i++)
  360. {
  361. BaseOffset=BaseOffsetor+i*2*(SpriteWidth/32);
  362. RWEntries[i] = readNormalNr(BaseOffset,2,FDef);
  363. }
  364. BaseOffset = BaseOffsetor+RWEntries[0];
  365. for (int i=0;i<SpriteHeight;i++)
  366. {
  367. //BaseOffset = BaseOffsetor+RWEntries[i];
  368. if (LeftMargin>0)
  369. ftcp += LeftMargin;
  370. TotalRowLength=0;
  371. do
  372. {
  373. SegmentType=FDef[BaseOffset++];
  374. unsigned char code = SegmentType / 32;
  375. unsigned char value = (SegmentType & 31) + 1;
  376. if(code==7)
  377. {
  378. memcpy((char*)(ret->pixels)+ftcp, &FDef[BaseOffset], value);
  379. ftcp += value;
  380. BaseOffset += value;
  381. }
  382. else
  383. {
  384. memset((char*)(ret->pixels)+ftcp, code, value);
  385. ftcp += value;
  386. }
  387. TotalRowLength+=value;
  388. } while(TotalRowLength<SpriteWidth);
  389. if (RightMargin>0)
  390. ftcp += RightMargin;
  391. RowAdd=SpriteWidth-TotalRowLength;
  392. if (add>0)
  393. ftcp += add+RowAdd;
  394. }
  395. }
  396. break;
  397. case 3:
  398. {
  399. for (int i=0;i<SpriteHeight;i++)
  400. {
  401. BaseOffset=BaseOffsetor+i*2*(SpriteWidth/32);
  402. RWEntries[i] = readNormalNr(BaseOffset,2,FDef);
  403. }
  404. for (int i=0;i<SpriteHeight;i++)
  405. {
  406. BaseOffset = BaseOffsetor+RWEntries[i];
  407. if (LeftMargin>0)
  408. ftcp += LeftMargin;
  409. TotalRowLength=0;
  410. do
  411. {
  412. SegmentType=FDef[BaseOffset++];
  413. unsigned char code = SegmentType / 32;
  414. unsigned char value = (SegmentType & 31) + 1;
  415. if(code==7)
  416. {
  417. for(int h=0; h<value; ++h)
  418. {
  419. if(h<-LeftMargin)
  420. continue;
  421. if(h+TotalRowLength>=SpriteWidth)
  422. break;
  423. ((char*)(ret->pixels))[ftcp++]=FDef[BaseOffset++];
  424. }
  425. }
  426. else
  427. {
  428. for(int h=0; h<value; ++h)
  429. {
  430. if(h<-LeftMargin)
  431. continue;
  432. if(h+TotalRowLength>=SpriteWidth)
  433. break;
  434. ((char*)(ret->pixels))[ftcp++]=code;
  435. }
  436. }
  437. TotalRowLength+=( LeftMargin>=0 ? value : value+LeftMargin );
  438. }while(TotalRowLength<SpriteWidth);
  439. if (RightMargin>0)
  440. ftcp += RightMargin;
  441. RowAdd=SpriteWidth-TotalRowLength;
  442. if (add>0)
  443. ftcp += add+RowAdd;
  444. }
  445. }
  446. break;
  447. default:
  448. throw std::string("Unknown sprite format.");
  449. break;
  450. }
  451. SDL_Color ttcol = ret->format->palette->colors[0];
  452. Uint32 keycol = SDL_MapRGBA(ret->format, ttcol.r, ttcol.b, ttcol.g, ttcol.unused);
  453. SDL_SetColorKey(ret, SDL_SRCCOLORKEY, keycol);
  454. return ret;
  455. };
  456. CDefEssential * CDefHandler::essentialize()
  457. {
  458. CDefEssential * ret = new CDefEssential;
  459. ret->ourImages = ourImages;
  460. notFreeImgs = true;
  461. return ret;
  462. }
  463. CDefHandler * CDefHandler::giveDef(std::string defName)
  464. {
  465. unsigned char * data = spriteh->giveFile(defName);
  466. if(!data)
  467. throw "bad def name!";
  468. CDefHandler * nh = new CDefHandler();
  469. nh->openFromMemory(data, defName);
  470. nh->alphaTransformed = false;
  471. delete [] data;
  472. return nh;
  473. }
  474. CDefEssential * CDefHandler::giveDefEss(std::string defName)
  475. {
  476. CDefEssential * ret;
  477. CDefHandler * temp = giveDef(defName);
  478. ret = temp->essentialize();
  479. delete temp;
  480. return ret;
  481. }