#include "StdInc.h" #include #include #include "CSndHandler.h" /* * CSndHandler.cpp, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ /* Media file are kept in container files. We map these files in * memory, parse them and create an index of them to easily retrieve * the data+size of the objects. */ CMediaHandler::~CMediaHandler() { std::vector::iterator it; entries.clear(); fimap.clear(); for (it=mfiles.begin() ; it < mfiles.end(); it++ ) { (*it)->close(); delete *it; } } boost::iostreams::mapped_file_source *CMediaHandler::add_file(std::string fname, bool important /*= true*/) { boost::iostreams::mapped_file_source *mfile; try //c-tor of mapped_file_source throws exception on failure { mfile = new boost::iostreams::mapped_file_source(fname); if (!mfile->is_open()) //just in case throw std::runtime_error("Cannot open " + fname + ": !mfile->is_open()"); } catch(std::exception &e) { if(important) tlog1 << "Cannot open " << fname << ": " << e.what() << std::endl; throw; } mfiles.push_back(mfile); return mfile; } void CMediaHandler::extract(int index, std::string dstfile) //saves selected file { std::ofstream out(dstfile.c_str(),std::ios_base::binary); Entry &entry = entries[index]; out.write(entry.data, entry.size); out.close(); } void CMediaHandler::extract(std::string srcfile, std::string dstfile, bool caseSens) //saves selected file { srcfile.erase(srcfile.find_last_of('.')); if (caseSens) { for (size_t i=0;i::iterator fit; if ((fit = fimap.find(srcName)) != fimap.end()) { index = fit->second; return this->extract(index, size); } size = 0; return NULL; } void CSndHandler::add_file(std::string fname, bool important /*= true*/) { boost::iostreams::mapped_file_source *mfile = NULL; try { mfile = CMediaHandler::add_file(fname, important); } catch(...) { return; } const char *data = mfile->data(); ui32 numFiles = SDL_SwapLE32(*(Uint32 *)&data[0]); struct soundEntry *se = (struct soundEntry *)&data[4]; for (ui32 i=0; ifilename; entry.offset = SDL_SwapLE32(se->offset); entry.size = SDL_SwapLE32(se->size); entry.data = mfile->data() + entry.offset; entries.push_back(entry); fimap[entry.name] = i; } } void CVidHandler::add_file(std::string fname) { boost::iostreams::mapped_file_source *mfile = NULL; try { mfile = CMediaHandler::add_file(fname); } catch(...) { return; } if(mfile->size() < 48) { tlog1 << fname << " doesn't contain needed data!\n"; return; } const ui8 *data = (const ui8 *)mfile->data(); ui32 numFiles = SDL_SwapLE32(*(Uint32 *)&data[0]); struct videoEntry *ve = (struct videoEntry *)&data[4]; for (ui32 i=0; ifilename; entry.offset = SDL_SwapLE32(ve->offset); entry.name.erase(entry.name.find_last_of('.')); // There is no size, so check where the next file is if (i == numFiles - 1) { entry.size = mfile->size() - entry.offset; } else { struct videoEntry *ve_next = ve+1; entry.size = SDL_SwapLE32(ve_next->offset) - entry.offset; } entry.data = mfile->data() + entry.offset; entries.push_back(entry); fimap[entry.name] = i; } }