CLodHandler.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. #define VCMI_DLL
  2. #include "../stdafx.h"
  3. #include "zlib.h"
  4. #include "CLodHandler.h"
  5. #include <sstream>
  6. #include <algorithm>
  7. #include <cctype>
  8. #include <cstring>
  9. #include <iostream>
  10. #include <fstream>
  11. #include "boost/filesystem/operations.hpp"
  12. #include <boost/algorithm/string.hpp>
  13. #include <boost/algorithm/string/replace.hpp>
  14. #include <boost/thread.hpp>
  15. #include <SDL_endian.h>
  16. #ifdef max
  17. #undef max
  18. #endif
  19. /*
  20. * CLodHandler.cpp, part of VCMI engine
  21. *
  22. * Authors: listed in file AUTHORS in main folder
  23. *
  24. * License: GNU General Public License v2.0 or later
  25. * Full text of license available in license.txt file, in main folder
  26. *
  27. */
  28. DLL_EXPORT int readNormalNr (int pos, int bytCon, const unsigned char * str)
  29. {
  30. int ret=0;
  31. int amp=1;
  32. if (str)
  33. {
  34. for (int i=0; i<bytCon; i++)
  35. {
  36. ret+=str[pos+i]*amp;
  37. amp<<=8;
  38. }
  39. }
  40. else return -1;
  41. return ret;
  42. }
  43. unsigned char * CLodHandler::giveFile(std::string defName, int * length)
  44. {
  45. std::transform(defName.begin(), defName.end(), defName.begin(), (int(*)(int))toupper);
  46. Entry * ourEntry = entries.znajdz(Entry(defName));
  47. if(!ourEntry) //nothing's been found
  48. {
  49. tlog1 << "Cannot find file: " << defName << std::endl;
  50. return NULL;
  51. }
  52. if(length) *length = ourEntry->realSize;
  53. mutex->lock();
  54. unsigned char * outp;
  55. if (ourEntry->offset<0) //file is in the sprites/ folder; no compression
  56. {
  57. int result;
  58. unsigned char * outp = new unsigned char[ourEntry->realSize];
  59. FILE * f = fopen((myDir + "/" + ourEntry->nameStr).c_str(), "rb");
  60. if (f) {
  61. result = fread(outp,1,ourEntry->realSize,f);
  62. fclose(f);
  63. } else
  64. result = -1;
  65. mutex->unlock();
  66. if(result<0) {
  67. tlog1<<"Error in file reading: " << myDir << "/" << ourEntry->nameStr << std::endl;
  68. delete[] outp;
  69. return NULL;
  70. } else
  71. return outp;
  72. }
  73. else if (ourEntry->size==0) //file is not compressed
  74. {
  75. outp = new unsigned char[ourEntry->realSize];
  76. LOD.seekg(ourEntry->offset, std::ios::beg);
  77. LOD.read((char*)outp, ourEntry->realSize);
  78. mutex->unlock();
  79. return outp;
  80. }
  81. else //we will decompress file
  82. {
  83. outp = new unsigned char[ourEntry->size];
  84. LOD.seekg(ourEntry->offset, std::ios::beg);
  85. LOD.read((char*)outp, ourEntry->size);
  86. mutex->unlock();
  87. unsigned char * decomp = NULL;
  88. int decRes = infs2(outp, ourEntry->size, ourEntry->realSize, decomp);
  89. delete[] outp;
  90. return decomp;
  91. }
  92. return NULL;
  93. }
  94. DLL_EXPORT int CLodHandler::infs2(unsigned char * in, int size, int realSize, unsigned char *& out, int wBits)
  95. {
  96. int ret;
  97. unsigned have;
  98. z_stream strm;
  99. out = new unsigned char [realSize];
  100. int latPosOut = 0;
  101. /* allocate inflate state */
  102. strm.zalloc = Z_NULL;
  103. strm.zfree = Z_NULL;
  104. strm.opaque = Z_NULL;
  105. strm.avail_in = 0;
  106. strm.next_in = Z_NULL;
  107. ret = inflateInit2(&strm, wBits);
  108. if (ret != Z_OK)
  109. return ret;
  110. int chunkNumber = 0;
  111. do
  112. {
  113. if(size < chunkNumber * NLoadHandlerHelp::fCHUNK)
  114. break;
  115. strm.avail_in = std::min(NLoadHandlerHelp::fCHUNK, size - chunkNumber * NLoadHandlerHelp::fCHUNK);
  116. if (strm.avail_in == 0)
  117. break;
  118. strm.next_in = in + chunkNumber * NLoadHandlerHelp::fCHUNK;
  119. /* run inflate() on input until output buffer not full */
  120. do
  121. {
  122. strm.avail_out = realSize - latPosOut;
  123. strm.next_out = out + latPosOut;
  124. ret = inflate(&strm, Z_NO_FLUSH);
  125. //assert(ret != Z_STREAM_ERROR); /* state not clobbered */
  126. bool breakLoop = false;
  127. switch (ret)
  128. {
  129. case Z_STREAM_END:
  130. breakLoop = true;
  131. break;
  132. case Z_NEED_DICT:
  133. ret = Z_DATA_ERROR; /* and fall through */
  134. case Z_DATA_ERROR:
  135. case Z_MEM_ERROR:
  136. (void)inflateEnd(&strm);
  137. return ret;
  138. }
  139. if(breakLoop)
  140. break;
  141. have = realSize - latPosOut - strm.avail_out;
  142. latPosOut += have;
  143. } while (strm.avail_out == 0);
  144. ++chunkNumber;
  145. /* done when inflate() says it's done */
  146. } while (ret != Z_STREAM_END);
  147. /* clean up and return */
  148. (void)inflateEnd(&strm);
  149. return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
  150. }
  151. void CLodHandler::extractFile(std::string FName, std::string name)
  152. {
  153. int len; //length of file to write
  154. unsigned char * outp = giveFile(name, &len);
  155. std::ofstream out;
  156. out.open(FName.c_str(), std::ios::binary);
  157. if(!out.is_open())
  158. {
  159. tlog1<<"Unable to create "<<FName<<std::endl;
  160. }
  161. else
  162. {
  163. out.write(reinterpret_cast<char*>(outp), len);
  164. out.close();
  165. }
  166. }
  167. void CLodHandler::init(std::string lodFile, std::string dirName)
  168. {
  169. myDir = dirName;
  170. std::string Ts;
  171. Uint32 temp;
  172. LOD.open(lodFile.c_str(), std::ios::in | std::ios::binary);
  173. if (!LOD.is_open()) {
  174. tlog1 << "Cannot open " << lodFile << std::endl;
  175. return;
  176. }
  177. LOD.seekg(8);
  178. LOD.read((char *)&temp, 4);
  179. totalFiles = SDL_SwapLE32(temp);
  180. LOD.seekg(0x5c, std::ios::beg);
  181. struct LodEntry *lodEntries = new struct LodEntry[totalFiles];
  182. LOD.read((char *)lodEntries, sizeof(struct LodEntry) * totalFiles);
  183. for (unsigned int i=0; i<totalFiles; i++)
  184. {
  185. Entry entry;
  186. entry.nameStr = lodEntries[i].filename;
  187. std::transform(entry.nameStr.begin(), entry.nameStr.end(),
  188. entry.nameStr.begin(), toupper);
  189. entry.offset= SDL_SwapLE32(lodEntries[i].offset);
  190. entry.realSize = SDL_SwapLE32(lodEntries[i].uncompressedSize);
  191. entry.size = SDL_SwapLE32(lodEntries[i].size);
  192. entries.push_back(entry);
  193. }
  194. delete [] lodEntries;
  195. boost::filesystem::directory_iterator enddir;
  196. if(boost::filesystem::exists(dirName))
  197. {
  198. for (boost::filesystem::directory_iterator dir(dirName);dir!=enddir;dir++)
  199. {
  200. if(boost::filesystem::is_regular(dir->status()))
  201. {
  202. std::string name = dir->path().leaf();
  203. std::transform(name.begin(), name.end(), name.begin(), (int(*)(int))toupper);
  204. boost::algorithm::replace_all(name,".BMP",".PCX");
  205. Entry * e = entries.znajdz(name);
  206. if(e) //file present in .lod - overwrite its entry
  207. {
  208. e->offset = -1;
  209. e->realSize = e->size = boost::filesystem::file_size(dir->path());
  210. }
  211. else //file not present in lod - add entry for it
  212. {
  213. Entry e2;
  214. e2.offset = -1;
  215. e2.nameStr = name;
  216. e2.realSize = e2.size = boost::filesystem::file_size(dir->path());
  217. entries.push_back(e2);
  218. }
  219. }
  220. }
  221. }
  222. else
  223. {
  224. tlog1<<"Warning: No "+dirName+"/ folder!"<<std::endl;
  225. }
  226. }
  227. std::string CLodHandler::getTextFile(std::string name)
  228. {
  229. int length=-1;
  230. unsigned char* data = giveFile(name,&length);
  231. if (!data) {
  232. tlog1<<"Fatal error. Missing game file. Aborting!"<<std::endl;
  233. exit(1);
  234. }
  235. std::string ret(data, data+length);
  236. delete [] data;
  237. return ret;
  238. }
  239. CLodHandler::CLodHandler()
  240. {
  241. mutex = new boost::mutex;
  242. totalFiles = 0;
  243. }
  244. CLodHandler::~CLodHandler()
  245. {
  246. delete mutex;
  247. }