25 #include <boost/bind.hpp>
31 #include "vfs/raw/rawdata.h"
32 #include "util/base/exception.h"
33 #include "util/log/logger.h"
38 static Logger _log(LM_FO_LOADERS);
41 :
VFSSource(vfs), m_datpath(file), m_data(vfs->open(file)), m_filelist() {
43 FL_LOG(_log,
LMsg(
"MFFalloutDAT2")
44 <<
"loading: " << file
45 <<
" filesize: " << m_data->getDataLength());
47 m_data->setIndex(m_data->getDataLength() - 8);
48 uint32_t fileListLength = m_data->read32Little();
49 uint32_t archiveSize = m_data->read32Little();
51 FL_LOG(_log,
LMsg(
"MFFalloutDAT2")
52 <<
"FileListLength: " << fileListLength
53 <<
" ArchiveSize: " << archiveSize);
55 if (archiveSize != m_data->getDataLength())
56 throw InvalidFormat(
"size mismatch");
58 m_data->setIndex( archiveSize - fileListLength - 8);
59 m_filecount = m_data->read32Little();
60 m_currentIndex = m_data->getCurrentIndex();
62 FL_LOG(_log,
LMsg(
"MFFalloutDAT2 FileCount: ") << m_filecount);
66 m_timer.setInterval(0);
67 m_timer.setCallback( boost::bind( &DAT2::readFileEntry,
this) );
71 void DAT2::readFileEntry()
const {
72 assert( m_filecount != 0);
76 unsigned int load_per_cycle = 50;
77 if( load_per_cycle > m_filecount )
78 load_per_cycle = m_filecount;
79 m_filecount -= load_per_cycle;
82 IndexSaver isaver(m_data.get());
85 m_data->setIndex(m_currentIndex);
87 while( load_per_cycle-- ) {
88 uint32_t namelen = m_data->read32Little();
89 info.name = fixPath(m_data->readString(namelen));
91 info.type = m_data->read8();
92 info.unpackedLength = m_data->read32Little();
93 info.packedLength = m_data->read32Little();
94 info.offset = m_data->read32Little();
96 m_filelist.insert(std::make_pair(info.name, info));
98 m_currentIndex = m_data->getCurrentIndex();
101 if( m_filecount == 0 ) {
102 FL_LOG(_log, LMsg(
"MFFalloutDAT2, All file entries in '") << m_datpath <<
"' loaded.");
113 return findFileEntry(name) != m_filelist.end();
117 type_filelist::const_iterator i = findFileEntry(name);
118 if (i == m_filelist.end()) {
119 throw NotFound(name);
124 DAT2::type_filelist::const_iterator DAT2::findFileEntry(
const std::string& path)
const {
130 std::string name = path;
133 if (name.find(
"./") == 0) {
137 type_filelist::const_iterator i = m_filelist.find(name);
141 if ( m_filecount && i == m_filelist.end()) {
142 FL_LOG(_log, LMsg(
"MFFalloutDAT2")
143 <<
"Missing '" << name
144 <<
"' in partially(" << m_filecount <<
") loaded "<< m_datpath);
145 while( m_filecount && i == m_filelist.end()) {
147 i = m_filelist.find(name);
155 return list(pathstr,
false);
159 return list(pathstr,
true);
162 std::set<std::string> DAT2::list(
const std::string& pathstr,
bool dirs)
const {
163 std::set<std::string> list;
164 std::string path = pathstr;
169 while( m_filecount ) {
174 if (path.find(
"./") == 0) {
178 int lastIndex = path.size() - 1;
179 if ((lastIndex != -1) && path[lastIndex] !=
'/') {
183 type_filelist::const_iterator end = m_filelist.end();
184 for (type_filelist::const_iterator i = m_filelist.begin(); i != end; ++i) {
185 const std::string& file = i->first;
186 if (file.find(path) == 0) {
187 std::string cleanedfile = file.substr(path.size(), file.size());
188 bool isdir = cleanedfile.find(
'/') != std::string::npos;
191 cleanedfile = cleanedfile.substr(0, cleanedfile.find(
'/'));
192 if (cleanedfile.find(
'/') != cleanedfile.rfind(
'/')) {
199 list.insert(cleanedfile);