CSndHandler.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #include "../stdafx.h"
  2. #include <fstream>
  3. #include "CSndHandler.h"
  4. #include <boost/iostreams/device/mapped_file.hpp>
  5. #include <SDL_endian.h>
  6. /*
  7. * CSndHandler.cpp, part of VCMI engine
  8. *
  9. * Authors: listed in file AUTHORS in main folder
  10. *
  11. * License: GNU General Public License v2.0 or later
  12. * Full text of license available in license.txt file, in main folder
  13. *
  14. */
  15. CMediaHandler::~CMediaHandler()
  16. {
  17. entries.clear();
  18. fimap.clear();
  19. mfile->close();
  20. delete mfile;
  21. }
  22. CMediaHandler::CMediaHandler(std::string fname)
  23. {
  24. try //c-tor of mapped_file_source throws exception on failure
  25. {
  26. mfile = new boost::iostreams::mapped_file_source(fname);
  27. } HANDLE_EXCEPTIONC(tlog1 << "Cannot open " << fname << std::endl)
  28. if (!mfile->is_open()) //just in case
  29. {
  30. tlog1 << "Cannot open " << fname << std::endl;
  31. throw std::string("Cannot open ")+fname;
  32. }
  33. }
  34. void CMediaHandler::extract(int index, std::string dstfile) //saves selected file
  35. {
  36. std::ofstream out(dstfile.c_str(),std::ios_base::binary);
  37. const char *data = mfile->data();
  38. out.write(&data[entries[index].offset], entries[index].size);
  39. out.close();
  40. }
  41. void CMediaHandler::extract(std::string srcfile, std::string dstfile, bool caseSens) //saves selected file
  42. {
  43. srcfile.erase(srcfile.find_last_of('.'));
  44. if (caseSens)
  45. {
  46. for (size_t i=0;i<entries.size();++i)
  47. {
  48. if (entries[i].name==srcfile)
  49. extract(i,dstfile);
  50. }
  51. }
  52. else
  53. {
  54. std::transform(srcfile.begin(),srcfile.end(),srcfile.begin(),tolower);
  55. for (size_t i=0;i<entries.size();++i)
  56. {
  57. if (entries[i].name==srcfile)
  58. {
  59. std::string por = entries[i].name;
  60. std::transform(por.begin(),por.end(),por.begin(),tolower);
  61. if (por==srcfile)
  62. extract(i,dstfile);
  63. }
  64. }
  65. }
  66. }
  67. #if 0
  68. // unused and not sure what it's supposed to do
  69. MemberFile CMediaHandler::getFile(std::string name)
  70. {
  71. MemberFile ret;
  72. std::transform(name.begin(),name.end(),name.begin(),tolower);
  73. for (size_t i=0;i<entries.size();++i)
  74. {
  75. if (entries[i].name==name)
  76. {
  77. std::string por = entries[i].name;
  78. std::transform(por.begin(),por.end(),por.begin(),tolower);
  79. if (por==name)
  80. {
  81. ret.length=entries[i].size;
  82. file.seekg(entries[i].offset,std::ios_base::beg);
  83. ret.ifs=&file;
  84. return ret;
  85. }
  86. }
  87. }
  88. return ret;
  89. }
  90. #endif
  91. const char * CMediaHandler::extract (int index, int & size)
  92. {
  93. size = entries[index].size;
  94. const char *data = mfile->data();
  95. return &data[entries[index].offset];
  96. }
  97. const char * CMediaHandler::extract (std::string srcName, int &size)
  98. {
  99. int index;
  100. srcName.erase(srcName.find_last_of('.'));
  101. std::map<std::string, int>::iterator fit;
  102. if ((fit = fimap.find(srcName)) != fimap.end())
  103. {
  104. index = fit->second;
  105. return this->extract(index, size);
  106. }
  107. size = 0;
  108. return NULL;
  109. }
  110. CSndHandler::CSndHandler(std::string fname) : CMediaHandler(fname)
  111. {
  112. const unsigned char *data = (const unsigned char *)mfile->data();
  113. unsigned int numFiles = SDL_SwapLE32(*(Uint32 *)&data[0]);
  114. struct soundEntry *se = (struct soundEntry *)&data[4];
  115. for (unsigned int i=0; i<numFiles; i++, se++)
  116. {
  117. Entry entry;
  118. // char *p;
  119. // Reassemble the filename, drop extension
  120. entry.name = se->filename;
  121. // entry.name += '.';
  122. // p = se->filename;
  123. // while(*p) p++;
  124. // p++;
  125. // entry.name += p;
  126. entry.offset = SDL_SwapLE32(se->offset);
  127. entry.size = SDL_SwapLE32(se->size);
  128. entries.push_back(entry);
  129. fimap[entry.name] = i;
  130. }
  131. }
  132. CVidHandler::CVidHandler(std::string fname) : CMediaHandler(fname)
  133. {
  134. const unsigned char *data = (const unsigned char *)mfile->data();
  135. unsigned int numFiles = SDL_SwapLE32(*(Uint32 *)&data[0]);
  136. struct videoEntry *ve = (struct videoEntry *)&data[4];
  137. for (unsigned int i=0; i<numFiles; i++, ve++)
  138. {
  139. Entry entry;
  140. entry.name = ve->filename;
  141. entry.offset = SDL_SwapLE32(ve->offset);
  142. entry.name.erase(entry.name.find_last_of('.'));
  143. // There is no size, so check where the next file is
  144. if (i == numFiles - 1) {
  145. entry.size = mfile->size() - entry.offset;
  146. } else {
  147. struct videoEntry *ve_next = ve+1;
  148. entry.size = SDL_SwapLE32(ve_next->offset) - entry.offset;
  149. }
  150. entries.push_back(entry);
  151. fimap[entry.name] = i;
  152. }
  153. }