Subversion Repositories spk

Rev

Rev 35 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
 
2
#include "VirtualFileSystem.h"
3
#include "File_IO.h"
4
#include "CatFile.h"
35 cycrow 5
#include "XspFile.h"
1 cycrow 6
 
35 cycrow 7
namespace SPK {
8
 
1 cycrow 9
CVirtualFileSystem::CVirtualFileSystem()
10
{
11
	m_bLoaded = false;
35 cycrow 12
	m_pMap = new FileList;
13
	m_pModMap = new FileList;
14
 
15
	m_pTexts = new CTextDB();
16
	m_pModTexts = new CTextDB();
17
 
1 cycrow 18
	m_sAddon = "";
35 cycrow 19
 
20
	m_iLang = 0;
1 cycrow 21
}
22
 
23
CVirtualFileSystem::~CVirtualFileSystem(void)
24
{
35 cycrow 25
	if ( m_pMap )		delete m_pMap;
26
	if ( m_pModMap )	delete m_pModMap;
27
 
28
	if ( m_pTexts )		delete m_pTexts;
29
	if ( m_pModTexts )  delete m_pModTexts;
1 cycrow 30
}
31
 
35 cycrow 32
void CVirtualFileSystem::setLanguage(int iLang)
1 cycrow 33
{
35 cycrow 34
	m_iLang = iLang;
35
}
36
 
37
bool CVirtualFileSystem::LoadFilesystem(const Utils::String &dir, int maxPatch)
38
{
39
	return this->LoadFilesystem(dir, "", maxPatch);
40
}
41
 
42
bool CVirtualFileSystem::LoadFilesystem(const Utils::String &dir, const Utils::String &mod, int maxPatch)
43
{
1 cycrow 44
	m_sDir = dir;
45
 
35 cycrow 46
	this->_clear();
1 cycrow 47
 
48
	int number = 1;
35 cycrow 49
	while ( CFileIO(CyString(dir) + "/" + CyString::Number(number).PadNumber(2) + ".cat").Exists() )
1 cycrow 50
	{
51
		if ( maxPatch && maxPatch > number ) break;
35 cycrow 52
		CyString file = CyString(dir) + "/" + CyString::Number(number).PadNumber(2);
1 cycrow 53
		if ( !CFileIO(file + ".dat").Exists() )
54
			break;
55
 
56
		CCatFile cat;
57
		if ( cat.Open(file + ".cat", m_sAddon, CATREAD_JUSTCONTENTS, false) == CATERR_NONE )
58
		{
59
			for ( CListNode<SInCatFile> *c = cat.GetFiles()->Front(); c; c = c->next() )
60
			{
61
				(*m_pMap)[CFileIO(c->Data()->sFile).GetFullFilename().ToLower().c_str()] = CyString(file + ".cat").c_str();
62
				m_bLoaded = true;
63
			}
64
		}
65
		++number;
66
	}
67
 
35 cycrow 68
	// now add all the extracted data
1 cycrow 69
 
35 cycrow 70
	if ( !mod.empty() )
71
		this->addMod(mod);
72
 
1 cycrow 73
	return m_bLoaded;
74
}
75
 
35 cycrow 76
bool CVirtualFileSystem::loadMod(const Utils::String &mod)
1 cycrow 77
{
78
	bool loaded = false;
35 cycrow 79
 
80
	if ( !m_pModMap ) m_pModMap = new FileList;
81
 
1 cycrow 82
	CCatFile cat;
83
	if ( CCatFile::Opened(cat.Open(mod, m_sAddon, CATREAD_JUSTCONTENTS, false), false) )
84
	{
85
		for ( CListNode<SInCatFile> *c = cat.GetFiles()->Front(); c; c = c->next() )
86
		{
35 cycrow 87
			(*m_pModMap)[CFileIO(c->Data()->sFile).GetFullFilename().ToLower().c_str()] = mod.c_str();
88
			loaded = true;
89
		}
90
	}
91
 
92
	return loaded;
93
}
94
 
95
bool CVirtualFileSystem::addMod(const Utils::String &mod)
96
{
97
	bool loaded = false;
98
 
99
	if ( !m_pMap ) m_pMap = new FileList;
100
 
101
	CCatFile cat;
102
	if ( CCatFile::Opened(cat.Open(mod, m_sAddon, CATREAD_JUSTCONTENTS, false), false) )
103
	{
104
		for ( CListNode<SInCatFile> *c = cat.GetFiles()->Front(); c; c = c->next() )
105
		{
1 cycrow 106
			(*m_pMap)[CFileIO(c->Data()->sFile).GetFullFilename().ToLower().c_str()] = mod.c_str();
107
			loaded = true;
108
		}
109
	}
110
 
111
	return loaded;
112
}
113
 
35 cycrow 114
bool CVirtualFileSystem::textExists(int iLang, int iPage, int iID) const
1 cycrow 115
{
35 cycrow 116
	if ( m_pTexts ) {
117
		if ( m_pTexts->exists(iLang, iPage, iID) ) return m_pTexts->exists(iLang, iPage, iID);
118
	}
119
	if ( m_pModTexts ) {
120
		if ( m_pModTexts->exists(iLang, iPage, iID) ) return m_pModTexts->exists(iLang, iPage, iID);
121
	}
122
 
123
	return false;
1 cycrow 124
}
125
 
35 cycrow 126
Utils::String CVirtualFileSystem::findText(int iLang, int iPage, int iID) const
1 cycrow 127
{
35 cycrow 128
	if ( m_pTexts ) {
129
		if ( m_pTexts->exists(iLang, iPage, iID) ) return m_pTexts->get(iLang, iPage, iID);
130
	}
131
	if ( m_pModTexts ) {
132
		if ( m_pModTexts->exists(iLang, iPage, iID) ) return m_pModTexts->get(iLang, iPage, iID);
133
	}
1 cycrow 134
 
35 cycrow 135
	return Utils::String("ReadText") + (long)iPage + "-" + (long)iID;
136
}
137
Utils::String CVirtualFileSystem::findFile(const Utils::String &file)
138
{
139
	if ( m_pModMap && !m_pModMap->empty() ) {
140
		if ( !m_sAddon.empty() ) {
141
			FileListItr aitr = m_pModMap->find(CFileIO(m_sAddon + "/" + file).GetFullFilename().ToLower().c_str());
142
			if ( aitr == m_pModMap->end() ) aitr = m_pModMap->find(CFileIO(_convertExtension(m_sAddon + "/" + file)).GetFullFilename().ToLower().c_str());
143
			if ( aitr != m_pModMap->end() ) return aitr->second;
144
		}
145
		FileListItr itr = m_pModMap->find(CFileIO(file).GetFullFilename().ToLower().c_str());
146
		if ( itr == m_pModMap->end() ) itr = m_pModMap->find(CFileIO(_convertExtension(file)).GetFullFilename().ToLower().c_str());
147
		if ( itr != m_pModMap->end() ) return itr->second;
148
	}
149
	else if ( m_pMap && !m_pMap->empty() ) {
150
		if ( !m_sAddon.empty() ) {
151
			FileListItr aitr = m_pMap->find(CFileIO(m_sAddon + "/" + file).GetFullFilename().ToLower().c_str());
152
			if ( aitr == m_pMap->end() ) aitr = m_pMap->find(CFileIO(_convertExtension(m_sAddon + "/" + file)).GetFullFilename().ToLower().c_str());
153
			if ( aitr != m_pMap->end() ) return aitr->second;
154
		}
155
		FileListItr itr = m_pMap->find(CFileIO(file).GetFullFilename().ToLower().c_str());
156
		if ( itr == m_pMap->end() ) itr = m_pMap->find(CFileIO(_convertExtension(file)).GetFullFilename().ToLower().c_str());
157
		if ( itr != m_pMap->end() ) return itr->second;
158
	}
159
	return "";
160
}
161
 
162
bool CVirtualFileSystem::ExtractGameFile(const Utils::String &file, const Utils::String &to)
163
{
164
	Utils::String sIn = findFile(file);
165
	if ( sIn.empty() ) return false;
166
 
1 cycrow 167
	CCatFile catFile;
168
	if ( catFile.Open(sIn, m_sAddon, CATREAD_CATDECRYPT, false) == CATERR_NONE )
169
	{
170
		// check for the file
171
		if ( catFile.ExtractFile(file, to) )
172
			return true;
173
		if ( catFile.Error() == CATERR_INVALIDDEST || catFile.Error() == CATERR_CANTCREATEDIR )
174
		{
175
			if ( catFile.ExtractFile(file) )
176
				return true;
177
		}
178
	}
179
	return false;
180
}
181
 
35 cycrow 182
Utils::String CVirtualFileSystem::_convertExtension(const Utils::String &sFile)
183
{
184
	CFileIO File(sFile);
185
	if ( File.CheckFileExtension("pck") ) {
186
		return File.ChangeFileExtension("xml").ToString();
187
	}
188
	else if ( File.CheckFileExtension("xml") ) {
189
		return File.ChangeFileExtension("pck").ToString();
190
	}
191
	else if ( File.CheckFileExtension("pbb") ) {
192
		return File.ChangeFileExtension("bob").ToString();
193
	}
194
	else if ( File.CheckFileExtension("bob") ) {
195
		return File.ChangeFileExtension("pbb").ToString();
196
	}
197
	else if ( File.CheckFileExtension("pbd") ) {
198
		return File.ChangeFileExtension("bod").ToString();
199
	}
200
	else if ( File.CheckFileExtension("bod") ) {
201
		return File.ChangeFileExtension("pbd").ToString();
202
	}
203
 
204
	return sFile;
205
}
206
 
207
CyStringList *CVirtualFileSystem::GetTShipsEntries()
208
{
209
	if ( this->ExtractGameFile("types/tships.pck", "tships.txt") ) {
210
		CFileIO TShips("tships.txt");
211
		if ( TShips.Exists() )
212
		{
213
			CyStringList *lines = TShips.ReadLinesStr();
214
			if ( lines )
215
			{
216
				// remove any commands, blank lines, and start
217
				// and put the id as the data
218
				int entries = -1;
219
				for ( SStringList *str = lines->Head(); str; str = str->next )
220
				{
221
					str->str.RemoveFirstSpace();
222
					str->str.RemoveChar(9);
223
					str->str.RemoveChar('\r');
224
					str->str.RemoveChar('\n');
225
					if ( str->str.Empty() )
226
					{
227
						str->remove = true;
228
						continue;
229
					}
230
 
231
					if ( str->str[0] == '/' )
232
					{
233
						str->remove = true;
234
						continue;
235
					}
236
 
237
					if ( entries == -1 )
238
					{
239
						entries = str->str.GetToken(";", 2, 2).ToInt();
240
						str->remove = true;
241
						continue;
242
					}
243
 
244
					// hopefully we now have a valid tships line
245
					int num = -1;
246
					while ( str->data.Empty() )
247
						str->data = str->str.GetToken(";", num--, (num + 2));
248
				}
249
			}
250
			// remove the tmp file
251
			TShips.Remove();
252
 
253
			if ( lines )
254
				lines->RemoveMarked();
255
			return lines;
256
		}
257
	}
258
 
259
	return NULL;
260
}
261
 
262
C_File *CVirtualFileSystem::extractGameFileToPackage(CBaseFile *pPackage, const Utils::String &sFile, FileType iFileType)
263
{
264
	return this->extractGameFileToPackage(pPackage, sFile, iFileType, sFile);
265
}
266
 
267
C_File *CVirtualFileSystem::extractGameFileToPackage(CBaseFile *pPackage, const Utils::String &sFile, FileType iFileType, const Utils::String &sTo)
268
{
269
 
270
	if ( this->ExtractGameFile(sFile, "tmp") ) {
271
		CFileIO File("tmp");
272
 
273
		C_File *f = pPackage->AddFile(CFileIO(sTo).GetFilename(), CFileIO(sTo).GetDir(), iFileType);
274
		if ( f ) {
275
			if ( f->ReadFromFile("tmp") ) {
276
				File.Remove();
277
				return f;
278
			}
279
		}
280
 
281
		File.Remove();
282
	}
283
 
284
	return NULL;
285
}
286
 
287
Utils::String CVirtualFileSystem::getTShipsEntry(const Utils::String &sId)
288
{
289
	CyStringList *ships = this->GetTShipsEntries();
290
	if ( ships )
291
	{
292
		SStringList *node = ships->FindData(CyString(sId).upper());
293
		if ( node )
294
			return node->str.ToString();
295
	}
296
	return "";
297
}
298
 
299
void CVirtualFileSystem::extractTexts(CXspFile *pPackage, int textId)
300
{
301
	//TODO: check for better finding of files in map
302
	for ( FileListItr itr = m_pMap->begin(); itr != m_pMap->end(); ++itr ) {
303
		Utils::String str = itr->first;
304
 
305
		if ( !m_sAddon.empty() ) {
306
			if ( !str.left(m_sAddon.length() + 3).Compare(m_sAddon + "/t/") && !str.left(m_sAddon.length() + 3).Compare(m_sAddon + "\\t\\") )
307
				continue;
308
		}
309
		else {
310
			if ( !str.left(2).Compare("t\\") && !str.left(2).Compare("t/") && !str.left(8).Compare("addon\t\\") && !str.left(8).Compare("addon/t/") )
311
				continue;
312
		}
313
 
314
		if ( this->ExtractGameFile(str, "tmp") ) {
315
			pPackage->AddTextFromFile("tmp", textId);
316
			CFileIO("tmp").Remove();
317
		}
318
	}
319
}
320
 
321
void CVirtualFileSystem::updateTexts(int iFromPage, int iToPage)
322
{
323
	this->_updateTexts(iFromPage, iToPage, m_pMap, m_pTexts);
324
}
325
void CVirtualFileSystem::updateTexts(int iPage)
326
{
327
	this->_updateTexts(iPage, iPage, m_pMap, m_pTexts);
328
}
329
void CVirtualFileSystem::updateModTexts(int iFromPage, int iToPage)
330
{
331
	this->_updateTexts(iFromPage, iToPage, m_pModMap, m_pModTexts);
332
}
333
void CVirtualFileSystem::updateModTexts(int iPage)
334
{
335
	this->_updateTexts(iPage, iPage, m_pModMap, m_pModTexts);
336
}
337
 
338
void CVirtualFileSystem::_clear()
339
{
340
	m_bLoaded = false;
341
 
342
	if ( m_pMap ) delete m_pMap;
343
	m_pMap = new FileList;
344
	if ( m_pModMap ) delete m_pModMap;
345
	m_pModMap = new FileList;
346
}
347
 
348
void CVirtualFileSystem::_updateTexts(int iFromPage, int iToPage, FileList *pFileList, CTextDB *pTextList)
349
{
350
	// read all text files
351
	for ( FileListItr itr = pFileList->begin(); itr != pFileList->end(); ++itr ) {
352
		Utils::String str = itr->first;
353
 
354
		if ( !m_sAddon.empty() ) {
355
			if ( !str.left(m_sAddon.length() + 3).Compare(m_sAddon + "/t/") && !str.left(m_sAddon.length() + 3).Compare(m_sAddon + "\\t\\") )
356
				continue;
357
		}
358
		else {
359
			if ( !str.left(2).Compare("t\\") && !str.left(2).Compare("t/") )
360
				continue;
361
		}
362
 
363
		if ( this->ExtractGameFile(str, "tmp") ) {
364
			// add all texts into the map, id=(pageid, tid) data=text
365
			Utils::String baseFile = CFileIO(str).GetBaseName().ToString();
366
			int lang = (baseFile.isin("-L")) ? baseFile.right(3) : baseFile.truncate(-4);
367
 
368
			if ( m_iLang && lang != m_iLang ) continue;
369
			// open the text file to add
370
			pTextList->parseTextFile(iFromPage, iToPage, "tmp", lang);
371
		}
372
	}
373
}
374
 
375
void CVirtualFileSystem::clearMods()
376
{
377
	if ( m_pTexts ) delete m_pTexts;
378
	m_pTexts = new CTextDB();
379
	if ( m_pModTexts ) delete m_pModTexts;
380
	m_pModTexts = new CTextDB();
381
}
382
 
383
bool CVirtualFileSystem::loadShipData(CyStringList *list)
384
{
385
	bool ret = false;
386
 
387
	if ( this->ExtractGameFile("types/TShips.pck", "tmp") ) {
388
		CFileIO File("tmp");
389
		CyStringList *lines = File.ReadLinesStr();
390
		if ( lines )
391
		{
392
			bool readFirst = false;
393
			for ( SStringList *str = lines->Head(); str; str = str->next )
394
			{
395
				if ( str->str.Empty() )
396
					continue;
397
				str->str.RemoveChar('\r');
398
				str->str.RemoveChar(9);
399
				str->str.RemoveFirstSpace();
400
				if ( str->str.Empty() )
401
					continue;
402
				if ( str->str[0] == '/' || str->str[0] == '#' )
403
					continue;
404
 
405
				if ( !readFirst )
406
					readFirst = true;
407
				else
408
				{
409
					CyString t = str->str.GetToken(";", -2);
410
					while ( t.Right(1) == ";" )
411
						t.Truncate((int)t.Length() - 1);
412
					list->PushBack(t, str->str);
413
				}
414
			}
415
 
416
			delete lines;
417
			ret = true;
418
		}
419
 
420
		File.Remove();
421
	}
422
 
423
	return ret;
424
}
425
 
426
 
427
} //NAMESPACE