Subversion Repositories spk

Rev

Rev 197 | Rev 233 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
#include "GameExe.h"
2
#include "File_IO.h"
3
#include "DirIO.h"
4
 
5
/**
6
 * Add Exe
7
 *
8
 * Adds an exe name available
9
 */
197 cycrow 10
int CGameExe::addExe(const Utils::WString &exe)
1 cycrow 11
{
12
	// search if it already exists
57 cycrow 13
	int iCount = this->_findExe(exe);
14
	if ( iCount != -1 ) return iCount;
1 cycrow 15
 
16
	// not found, we need to add
17
	SGameExe *sExe = new SGameExe;
18
	sExe->sExe = exe;
19
	sExe->iName = 0;
20
	sExe->iFlags = 0;
21
	sExe->iMaxPatch = 1;
22
	sExe->iAddonTo = 0;
57 cycrow 23
	sExe->iTextNum = 0;
1 cycrow 24
 
25
	m_lExe.push_back(sExe);
26
 
27
	return m_lExe.size() - 1;
28
}
29
 
30
/**
31
 * Find Exe
32
 *
33
 * Find an exe and return its position in the file
34
 *
35
 * Argument:	exe,	String - name of the exe file to find
36
 */
197 cycrow 37
int CGameExe::_findExe(const Utils::WString &exe) const
1 cycrow 38
{
121 cycrow 39
	CFileIO File(exe);
197 cycrow 40
	Utils::WString e = File.filename();
121 cycrow 41
 
1 cycrow 42
	int count = 0;
43
	for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() )
44
	{
121 cycrow 45
		if ( node->Data()->sExe.Compare(e) )
1 cycrow 46
			return count;
47
		++count;
48
	}
49
 
50
	return -1;
51
}
52
 
197 cycrow 53
SGameExe *CGameExe::gameExe(const Utils::WString &exe) const
1 cycrow 54
{
57 cycrow 55
	int e = this->_findExe(exe);
197 cycrow 56
	if ( e < 0 ) return nullptr;
121 cycrow 57
	return m_lExe.Get(e);
1 cycrow 58
}
59
 
197 cycrow 60
int CGameExe::_findVersion(int exe, int size, Utils::WString *fVersion) const
1 cycrow 61
{
57 cycrow 62
	if ( fVersion ) *fVersion = -1.0;
63
	if ( exe < 0 ) return -1;
1 cycrow 64
 
65
	SGameExe *gameExe = m_lExe[exe];
57 cycrow 66
	if ( !gameExe ) return -1;
1 cycrow 67
 
68
	int count = 0;
57 cycrow 69
	for ( CListNode<SGameExeVersion> *node = gameExe->lVersions.Front(); node; node = node->next() ) {
70
		for ( CListNode<int> *iNode = node->Data()->lSize.Front(); iNode; iNode = iNode->next() ) {
1 cycrow 71
			int checkSize = *iNode->Data();
57 cycrow 72
			if ( checkSize == size ) {
1 cycrow 73
				*fVersion = node->Data()->fVersion;
74
				return count;
75
			}
76
		}
77
 
78
		++count;
79
	}
80
 
81
	return -1;
82
}
83
 
197 cycrow 84
int CGameExe::findVersion(const Utils::WString &exe, int size, Utils::WString *fVersion)
1 cycrow 85
{
57 cycrow 86
	int iExe = this->_findExe(exe);
1 cycrow 87
	if ( iExe < 0 )
88
		return -1;
89
 
57 cycrow 90
	int iVersion = this->_findVersion(iExe, size, fVersion);
1 cycrow 91
	if ( iVersion < 0 )
92
		return -2 - iExe;
93
 
94
	return -1;
95
}
96
 
197 cycrow 97
Utils::WString CGameExe::getModKey(int game) const
1 cycrow 98
{
197 cycrow 99
	if ( game < 0 )	return L"";
1 cycrow 100
	SGameExe *sExe = m_lExe[game];
197 cycrow 101
	if ( !sExe ) return L"";
1 cycrow 102
 
103
	return sExe->sModKey;
104
}
105
 
197 cycrow 106
void CGameExe::getDirectoryData(GameDirectory *gameDir) const
125 cycrow 107
{
108
	if (!gameDir)
109
		return;
110
	if (CDirIO::Exists(gameDir->dir))
111
	{
197 cycrow 112
		gameDir->exe = this->gameRunExe(gameDir->dir);
125 cycrow 113
		if (CDirIO::Exists(gameDir->exe))
114
		{
115
			int id = _findExe(gameDir->exe);
116
			SGameExe *exe = m_lExe.Get(id);
117
			if (exe)
118
			{
119
				gameDir->addon = exe->sAddon;
120
				gameDir->name = exe->sName;
121
				if (exe->iFlags & EXEFLAG_MYDOCLOG)
122
					gameDir->logdir = exe->sMyDoc;
123
				else
124
					gameDir->logdir = gameDir->dir;
125
				gameDir->basename = exe->sName;
126
			}
127
 
197 cycrow 128
			this->getGameVersion(gameDir->exe, &gameDir->version);
129
			gameDir->name = this->gameName(gameDir->exe);
125 cycrow 130
		}
131
	}
132
}
133
 
134
 
197 cycrow 135
void CGameExe::parseExe(const Utils::WString &line)
1 cycrow 136
{
137
	// get the exe file
197 cycrow 138
	Utils::WString exe = line.token(L":", 1);
56 cycrow 139
	int iTextNum = -1;
197 cycrow 140
	if ( exe.contains(L"|") ) {
141
		iTextNum = exe.token(L"|", 2);
142
		exe = exe.token(L"|", 1);
56 cycrow 143
	}
144
 
197 cycrow 145
	int iExe = this->addExe(exe);
1 cycrow 146
 
147
	SGameExe *sExe = m_lExe[iExe];
197 cycrow 148
	sExe->iMaxPatch = line.token(L":", 2);
149
	sExe->iFlags = this->parseFlags(line.token(L":", 3));
150
	sExe->sModKey = line.token(L":", 4);
56 cycrow 151
	sExe->iTextNum = iTextNum;
1 cycrow 152
 
153
	// get the name
197 cycrow 154
	Utils::WString gameName = line.token(L":", 5);
155
	this->_setExeName(&sExe->sName, &sExe->iName, gameName);
1 cycrow 156
 
157
	// get mydocs
197 cycrow 158
	sExe->sMyDoc = line.token(L":", 6);
1 cycrow 159
 
160
	// now get the versions
161
	int pos = EXE_VERSIONPOS;
162
	int namestart = EXE_VERSION_NAMESTART;
163
	int sizestart = EXE_VERSION_SIZESTART;
164
 
165
	if ( sExe->iFlags & EXEFLAG_ADDON ) {
166
		++pos;
167
		++namestart;
168
		++sizestart;
197 cycrow 169
		sExe->sAddon = line.token(L":", EXE_VERSIONPOS);
170
		if ( sExe->sAddon.contains(L"!") ) {
171
			sExe->iAddonTo = this->_findExe(sExe->sAddon.token(L"!", 2));
172
			sExe->sAddon = sExe->sAddon.token(L"!", 1);
1 cycrow 173
		}
174
	}
175
 
197 cycrow 176
	int iVersions = line.token(L":", pos);
1 cycrow 177
	int i;
178
 
179
	for ( i = 0; i < iVersions; i++ )
180
	{
181
		SGameExeVersion *sGameVersion = new SGameExeVersion;
182
		sGameVersion->iName = 0;
197 cycrow 183
		sGameVersion->fVersion = line.token(L":", namestart + (i * 2)).token(L" ", 1);
1 cycrow 184
 
197 cycrow 185
		Utils::WString sSize = line.token(L":", sizestart + (i * 2));
1 cycrow 186
		// multiple versions available, we need to split them up
197 cycrow 187
		if ( sSize.contains(L"!") ) {
188
			std::vector<Utils::WString> sizes;
189
			if(sSize.tokenise(L"!", sizes))
190
			{
191
				for (size_t j = 0; j < sizes.size(); j++ ) 
192
				{
1 cycrow 193
					int *size = new int;
56 cycrow 194
					(*size) = sizes[j];
195
					if ( *size ) sGameVersion->lSize.push_back(size);
1 cycrow 196
				}
197
			}
198
		}
56 cycrow 199
		else {
1 cycrow 200
			int *size = new int;
56 cycrow 201
			(*size) = sSize;
202
			if ( *size ) sGameVersion->lSize.push_back(size);
1 cycrow 203
		}
204
 
56 cycrow 205
		if ( !sGameVersion->lSize.empty() )	{
1 cycrow 206
			// finally, add the version names
197 cycrow 207
			this->_setExeName(&sGameVersion->sName, &sGameVersion->iName, line.token(L":", namestart + (i * 2)));
1 cycrow 208
			sExe->lVersions.push_back(sGameVersion);
209
		}
210
	}
211
}
212
 
197 cycrow 213
int CGameExe::parseFlags(const Utils::WString &flags)
1 cycrow 214
{
197 cycrow 215
	std::vector<Utils::WString> sFlags;
216
	if (!flags.tokenise(L"|", sFlags))
217
		return EXEFLAG_NONE;
1 cycrow 218
 
219
	int f = 0;
197 cycrow 220
	for (size_t i = 0; i < sFlags.size(); i++) {
221
		Utils::WString str = sFlags[i];
222
		if ( str.Compare(L"TC_TEXT") )
1 cycrow 223
			f |= EXEFLAG_TCTEXT;
197 cycrow 224
		else if ( str.Compare(L"NO_XOR") )
1 cycrow 225
			f |= EXEFLAG_NOXOR;
197 cycrow 226
		else if ( str.Compare(L"ADDON") )
1 cycrow 227
			f |= EXEFLAG_ADDON;
197 cycrow 228
		else if ( str.Compare(L"MYDOCLOG") )
1 cycrow 229
			f |= EXEFLAG_MYDOCLOG;
197 cycrow 230
		else if ( str.Compare(L"NOSAVESUBDIR") )
1 cycrow 231
			f |= EXEFLAG_NOSAVESUBDIR;
56 cycrow 232
		else {
233
			if ( str.isNumber() )
234
				f |= (long)str;
1 cycrow 235
		}
236
	}
237
 
238
	return f;
239
}
240
 
197 cycrow 241
void CGameExe::_setExeName(Utils::WString *sName, int *iName, const Utils::WString &n)
1 cycrow 242
{
197 cycrow 243
	Utils::WString str = n;
244
	if ( n.contains(L"!") )
1 cycrow 245
	{
197 cycrow 246
		Utils::WString gameNum = str.token(L"!", 1);
247
		str = str.token(L"!", 2);
1 cycrow 248
 
56 cycrow 249
		if ( gameNum.isNumber() )
250
			*iName = gameNum;
1 cycrow 251
		else
252
			*sName = gameNum;
253
	}
254
 
56 cycrow 255
	if ( str.isNumber() )
256
		*iName = str;
1 cycrow 257
	else
56 cycrow 258
		*sName = str;
1 cycrow 259
}
260
 
261
void CGameExe::Reset()
262
{
263
	for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() )
264
	{
265
		for ( CListNode<SGameExeVersion> *vNode = node->Data()->lVersions.Front(); vNode; vNode = vNode->next() )
266
			vNode->Data()->lSize.MemoryClear();
267
		node->Data()->lVersions.MemoryClear();
268
	}
269
	m_lExe.MemoryClear();
270
}
271
 
197 cycrow 272
bool CGameExe::readFile(const Utils::WString &file)
1 cycrow 273
{
56 cycrow 274
	CFileIO File(file);
275
	if ( !File.startRead() ) return false;
1 cycrow 276
 
56 cycrow 277
	while ( !File.atEnd() ) {
197 cycrow 278
		Utils::WString line = File.readEndOfLine();
56 cycrow 279
		line.removeFirstSpace();
280
		if ( line.empty() ) continue;
281
		if ( line[0] == '/' ) continue;
197 cycrow 282
		this->parseExe(line);
1 cycrow 283
	}
56 cycrow 284
	File.close();
1 cycrow 285
	return true;
286
}
287
 
197 cycrow 288
Utils::WString CGameExe::gameRunExe(const Utils::WString &dir) const
1 cycrow 289
{
290
	CDirIO Dir(dir);
291
	int count = 0;
292
	for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() )
293
	{
294
		SGameExe *exe = node->Data();
121 cycrow 295
		if ( Dir.exists(exe->sExe) )
197 cycrow 296
			return dir + L"/" + exe->sExe;
56 cycrow 297
		if ( !exe->sAddon.empty() ) {
121 cycrow 298
			if ( Dir.topDir().Compare(exe->sAddon) )
197 cycrow 299
				return this->gameDir(dir) + L"/" + exe->sExe;
1 cycrow 300
		}
301
		++count;
302
	}
303
 
197 cycrow 304
	return L"";
1 cycrow 305
}
306
 
197 cycrow 307
Utils::WString CGameExe::gameBaseName(const Utils::WString &gameExe) const
1 cycrow 308
{
197 cycrow 309
	int gameType = this->getGameType(gameExe);
310
	Utils::WString gameDir = this->properDir(gameExe);
311
	Utils::WString gameName = this->extractGameName(gameDir);
312
	if (gameName.empty())	gameName = this->gameNameFromType(gameType);
1 cycrow 313
 
125 cycrow 314
	return gameName;
315
}
316
 
197 cycrow 317
Utils::WString CGameExe::gameName(const Utils::WString &gameExe) const
125 cycrow 318
{
197 cycrow 319
	Utils::WString gameName = gameBaseName(gameExe);
320
	if (gameName.empty()) return L"";
125 cycrow 321
 
1 cycrow 322
	// no version
197 cycrow 323
	Utils::WString fVersion;
324
	Utils::WString versionName;
1 cycrow 325
 
197 cycrow 326
	if ( this->getGameVersionName(gameExe, &versionName) ) 
125 cycrow 327
	{
56 cycrow 328
		if ( !versionName.empty() )
197 cycrow 329
			return gameName + L" V" + versionName;
1 cycrow 330
		else
331
			return gameName;
332
	}
333
 
197 cycrow 334
	int gameType = this->getGameType(gameExe);
335
	Utils::WString sGameVersion = this->gameVersionFromType(gameType, this->getGameVersion(gameExe, &fVersion), fVersion);
56 cycrow 336
	if ( sGameVersion.empty() )
1 cycrow 337
	{
56 cycrow 338
		if ( !fVersion.empty() )
197 cycrow 339
			return gameName + L" V" + fVersion;
1 cycrow 340
		else
341
			return gameName;
342
	}
343
 
344
	// return the name and the version
197 cycrow 345
	return gameName + L" " + sGameVersion;
1 cycrow 346
}
347
 
348
 
197 cycrow 349
int CGameExe::getGameAddons(const Utils::WString &dir, Utils::WStringList &exes) const
1 cycrow 350
{
351
	int count = 0;
352
 
353
	CDirIO Dir(dir);
354
 
355
	for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() )
356
	{
357
		SGameExe *exe = node->Data();
358
		if ( !(exe->iFlags & EXEFLAG_ADDON) )
359
			continue;
121 cycrow 360
		if ( Dir.exists(exe->sExe) ) {
361
			if ( Dir.exists(exe->sAddon) ) {			
362
				exes.pushBack(exe->sExe, exe->sAddon);
1 cycrow 363
				++count;
364
			}
365
		}
366
	}
367
 
368
	return count;
369
}
370
 
197 cycrow 371
Utils::WString CGameExe::addonDir(const Utils::WString &dir) const
1 cycrow 372
{
197 cycrow 373
	int gameType = this->getGameType(dir);
1 cycrow 374
	if ( gameType != -1 ) {
375
		return m_lExe[gameType]->sAddon;
376
	}
377
 
197 cycrow 378
	return L"";
1 cycrow 379
}
380
 
197 cycrow 381
bool CGameExe::isAddon(const Utils::WString &exe) const
1 cycrow 382
{
121 cycrow 383
	SGameExe *e = gameExe(exe);
384
	if (e && (e->iFlags & EXEFLAG_ADDON))
385
		return true;
386
 
387
	return false;
388
}
389
 
197 cycrow 390
int CGameExe::getTextID(const Utils::WString &dir) const
121 cycrow 391
{
392
	SGameExe *e = gameExe(dir);
393
	if (e)
394
		return e->iTextNum;
395
 
197 cycrow 396
	e = gameExe(this->gameRunExe(dir));
121 cycrow 397
	if (e)
398
		return e->iTextNum;
399
 
400
	return 0;
401
}
402
 
197 cycrow 403
Utils::WString CGameExe::properDir(const Utils::WString &dir) const
121 cycrow 404
{
1 cycrow 405
	CDirIO Dir(dir);
121 cycrow 406
 
197 cycrow 407
	int gameType = this->getGameType(dir);
1 cycrow 408
	if ( gameType != -1 ) {
56 cycrow 409
		if ( !m_lExe[gameType]->sAddon.empty() ) {
197 cycrow 410
			if ( CDirIO(dir).isFile() ) return this->gameDir(dir) + L"/" + m_lExe[gameType]->sAddon;
411
			return CDirIO(this->gameDir(dir)).dir(m_lExe[gameType]->sAddon);
1 cycrow 412
		}
413
	}
414
 
197 cycrow 415
	return CDirIO(dir).isFile() ? CFileIO(dir).dir() : dir;
1 cycrow 416
}
417
 
197 cycrow 418
int CGameExe::gameFlags(int game)
1 cycrow 419
{
420
	if ( game == -1 )
421
		return 0;
422
 
423
	SGameExe *exe = m_lExe[game];
424
	if ( !exe )
425
		return 0;
426
 
427
	return exe->iFlags;
428
}
429
 
197 cycrow 430
int CGameExe::maxPatch(int game)
1 cycrow 431
{
432
	if ( game == -1 )
433
		return 0;
434
 
435
	SGameExe *exe = m_lExe[game];
436
	if ( !exe )
437
		return 0;
438
 
439
	return exe->iMaxPatch;
440
}
441
 
197 cycrow 442
Utils::WString CGameExe::gameNameFromType(int type) const
1 cycrow 443
{
197 cycrow 444
	if ( type == -1 ) return L"";
1 cycrow 445
 
121 cycrow 446
	SGameExe *exe = m_lExe.Get(type);
197 cycrow 447
	if ( !exe ) return L"";
1 cycrow 448
 
449
	return exe->sName;
450
}
451
 
197 cycrow 452
Utils::WString CGameExe::gameVersionFromType(int game, int gameVersion, const Utils::WString &fGameVersion) const
1 cycrow 453
{
454
	SGameExe *exe = m_lExe[game];
197 cycrow 455
	if ( !exe ) return L"";
1 cycrow 456
 
457
	SGameExeVersion *version = exe->lVersions[gameVersion];
458
	if ( !version )
459
	{
56 cycrow 460
		if ( !fGameVersion.empty() ) return fGameVersion;
197 cycrow 461
		return L"";
1 cycrow 462
	}
463
 
464
	return version->sName;
465
}
466
 
197 cycrow 467
Utils::WString CGameExe::gameDir(const Utils::WString &dir) const
1 cycrow 468
{
469
	CDirIO Dir(dir);
470
 
471
	for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() )
472
	{
473
		SGameExe *exe = node->Data();
125 cycrow 474
		if ( CDirIO(dir).isFile() ) {
56 cycrow 475
			if ( CFileIO(dir).filename().Compare(exe->sExe) )
202 cycrow 476
				return CFileIO(dir).dir();
1 cycrow 477
		}
478
		else {
121 cycrow 479
			if ( Dir.exists(exe->sExe) ) return dir;
1 cycrow 480
			// check for addon dir
56 cycrow 481
			if ( !exe->sAddon.empty() ) {
197 cycrow 482
				if ( exe->sAddon.Compare(Dir.topDir()) )
483
					return Dir.back();
1 cycrow 484
			}
485
		}
486
	}
487
 
488
	return dir;
489
}
126 cycrow 490
 
197 cycrow 491
int CGameExe::findAddonType(const Utils::WString &addon) const
126 cycrow 492
{
493
	int i = 0;
494
	for (CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next())
495
	{
496
		SGameExe *exe = node->Data();
497
		if (exe->iFlags & EXEFLAG_ADDON)
498
		{
499
			if (exe->sAddon.Compare(addon))
500
				return i;
501
		}
502
		++i;
503
	}
504
 
505
	return -1;
506
}
507
 
197 cycrow 508
int CGameExe::getGameType(const Utils::WString &gameExe) const
1 cycrow 509
{
95 cycrow 510
	CDirIO Dir (gameExe);
1 cycrow 511
	int count = 0;
512
 
513
	for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() )
514
	{
515
		SGameExe *exe = node->Data();
125 cycrow 516
		if ( CDirIO(gameExe).isFile() ) {
56 cycrow 517
			if ( CFileIO(gameExe).filename().Compare(exe->sExe) )
1 cycrow 518
				return count;
519
		}
520
		else {
121 cycrow 521
			if ( Dir.exists(exe->sExe) )
1 cycrow 522
				return count;
523
			// check for addon dir
56 cycrow 524
			if ( !exe->sAddon.empty() ) {
197 cycrow 525
				if ( exe->sAddon.Compare(Dir.topDir()) )
1 cycrow 526
					return count;
527
			}
528
		}
529
		++count;
530
	}
531
 
532
	return -1;
533
}
534
 
197 cycrow 535
Utils::WString CGameExe::extractGameName(const Utils::WString &gameDir, Utils::WString *extra) const
1 cycrow 536
{
197 cycrow 537
	Utils::WString dir = this->properDir(gameDir);
121 cycrow 538
	CDirIO Dir(dir);
1 cycrow 539
 
197 cycrow 540
	Utils::WString sText = this->_extractTextData(this->_readTextFile(dir), 1910, 1216, this->getTextID(gameDir));
541
	if ( sText.empty() ) return L"";
542
	int end = sText.findPos(L"\\n");
160 cycrow 543
	if (end >= 0)
544
	{
545
		sText = sText.left(end);
197 cycrow 546
		sText = sText.findReplace(L"\\(", L"(").findReplace(L"\\)", L")");
1 cycrow 547
 
197 cycrow 548
		if (sText.contains(L"(") && sText.contains(L")"))
160 cycrow 549
		{
197 cycrow 550
			int pos = sText.findPos(L"(");
160 cycrow 551
			int endPos;
552
			for (endPos = sText.length() - 1; endPos > pos; pos--)
553
			{
554
				if (sText[endPos] == ')')
555
					break;
556
			}
197 cycrow 557
			Utils::WString e = sText.substr(pos, endPos);
160 cycrow 558
			sText = sText.findRemove(e).removeEndSpace();
559
			if (extra)
560
				(*extra) = e.mid(1, -1);
561
		}
562
 
563
		return sText;
564
	}
565
 
56 cycrow 566
	return "";
567
}
568
 
197 cycrow 569
Utils::WString CGameExe::_textFileName(const Utils::WString &sGameDir) const
56 cycrow 570
{
121 cycrow 571
	int lang = 44;
572
 
56 cycrow 573
	CDirIO Dir(sGameDir);
197 cycrow 574
	if (Dir.exists(L"t"))
121 cycrow 575
	{
197 cycrow 576
		if (Dir.exists(L"t/0002.pck")) return L"t/0002.pck";
577
		else if (Dir.exists(L"t/0002.xml")) return L"t/0002.xml";
578
		else if (Dir.exists(Utils::WString::Format(L"t/%d0002.pck", lang))) return Utils::WString::Format(L"t/%d0002.pck", lang);
579
		else if (Dir.exists(Utils::WString::Format(L"t/%d0002.xml", lang))) return Utils::WString::Format(L"t/%d0002.xml", lang);
580
		else if (Dir.exists(Utils::WString::Format(L"t/0002-L%03d.pck", lang))) return Utils::WString::Format(L"t/0002-L%03d.pck", lang);
581
		else if (Dir.exists(Utils::WString::Format(L"t/0002-L%03d.xml", lang))) return Utils::WString::Format(L"t/0002-L%03d.xml", lang);
121 cycrow 582
	}
197 cycrow 583
	return L"";
56 cycrow 584
}
585
 
197 cycrow 586
Utils::WString CGameExe::_readTextFile(const Utils::WString &sGameDir) const
56 cycrow 587
{
197 cycrow 588
	Utils::WString textFileName = _textFileName(sGameDir);
121 cycrow 589
	if ( !textFileName.empty() )
590
	{
197 cycrow 591
		Utils::WString sVersion;
56 cycrow 592
 
593
		CDirIO Dir(sGameDir);
160 cycrow 594
		CFileIO File(Dir.file(textFileName));
1 cycrow 595
		size_t fileSize;
56 cycrow 596
		unsigned char *fileData = File.readAll(&fileSize);
121 cycrow 597
		if ( fileData && fileSize) 
598
		{
196 cycrow 599
			if (CFileIO(textFileName).isFileExtension(L"pck"))
121 cycrow 600
			{
601
				size_t newFileSize;
602
				unsigned char *pckData = UnPCKData((unsigned char *)fileData, fileSize, &newFileSize);
603
				delete fileData;
604
				pckData[newFileSize - 1] = '\0';
197 cycrow 605
				Utils::WString Data((char *)pckData);
121 cycrow 606
				delete pckData;
607
				return Data;
608
			}
196 cycrow 609
			else if (CFileIO(textFileName).isFileExtension(L"xml"))
121 cycrow 610
			{
197 cycrow 611
				Utils::WString Data((char *)fileData);
121 cycrow 612
				delete fileData;
613
				return Data;
614
			}
56 cycrow 615
		}
616
	}
1 cycrow 617
 
197 cycrow 618
	return L"";
56 cycrow 619
}
1 cycrow 620
 
197 cycrow 621
Utils::WString CGameExe::_extractTextData(const Utils::WString &sData, long iPage, long iID, int iGameID) const
56 cycrow 622
{
197 cycrow 623
	Utils::WString sID = Utils::WString(L"<t id=\"") + iID + L"\">";
56 cycrow 624
 
121 cycrow 625
	if (iGameID > 0)
626
	{
197 cycrow 627
		Utils::WString sPage = Utils::WString(L"<page id=\"") + Utils::WString::Number(iGameID) + iPage + L"\"";
121 cycrow 628
 
629
		int startpage = sData.findPos(sPage);
630
		if (startpage >= 0) {
631
			int start = sData.findPos(sID, startpage);
632
			if (start >= 0) {
633
				start += sID.length();
197 cycrow 634
				int end = sData.findPos(L"</t>", start);
121 cycrow 635
				return sData.mid(start, end);
636
			}
1 cycrow 637
		}
638
	}
56 cycrow 639
 
121 cycrow 640
	{
197 cycrow 641
		Utils::WString sPage = Utils::WString(L"<page id=\"") + iPage + L"\"";
121 cycrow 642
 
643
		int startpage = sData.findPos(sPage);
644
		if (startpage >= 0) {
645
			int start = sData.findPos(sID, startpage);
646
			if (start >= 0) {
647
				start += sID.length();
197 cycrow 648
				int end = sData.findPos(L"</t>", start);
121 cycrow 649
				return sData.mid(start, end);
650
			}
651
		}
652
	}
653
 
197 cycrow 654
	return L"";
1 cycrow 655
}
656
 
197 cycrow 657
bool CGameExe::getGameVersionName(const Utils::WString &sGameExe, Utils::WString *versionName) const
1 cycrow 658
{
197 cycrow 659
	int gameType = this->getGameType(sGameExe);
1 cycrow 660
 
661
	if ( gameType == -1 )
662
		return false;
663
 
197 cycrow 664
	Utils::WString gameExe = this->gameDir(sGameExe) + L"/" + m_lExe[gameType]->sExe;
665
	Utils::WString gameDir = this->properDir(gameExe);
1 cycrow 666
	int size = (int)CFileIO(gameExe).GetFilesize();
667
 
197 cycrow 668
	Utils::WString fVersion;
57 cycrow 669
	int version = this->_findVersion(gameType, size, &fVersion);
1 cycrow 670
	// not matched version
671
	// lets read the text file
672
 
56 cycrow 673
	if ( version != -1 ) {
197 cycrow 674
		(*versionName) = this->gameVersionFromType(gameType, version, fVersion);
1 cycrow 675
		return true;
676
	}
677
 
197 cycrow 678
	Utils::WString sText = this->_extractTextData(this->_readTextFile(gameDir), 1910, 1216, this->getTextID(gameExe));
679
	Utils::WString sVersion = sText.between(L"Version ", L", ");
680
	if ( sVersion.empty() ) sVersion = sText.between(L"ver=", L"&amp");
1 cycrow 681
 
56 cycrow 682
	if ( !sVersion.empty() ) {
683
		// lets match the version
684
		(*versionName) = sVersion;
685
		float fVersion = sVersion;
686
		SGameExe *gameExe = m_lExe[gameType];
687
		if ( gameExe )
1 cycrow 688
		{
56 cycrow 689
			int count = 0;
690
			int lower = -1;
691
			for ( CListNode<SGameExeVersion> *node = gameExe->lVersions.Front(); node; node = node->next() )
1 cycrow 692
			{
56 cycrow 693
				if ( (float)node->Data()->fVersion == fVersion )
1 cycrow 694
				{
56 cycrow 695
					(*versionName) = node->Data()->sName;
696
					return true;
1 cycrow 697
				}
56 cycrow 698
				++count;
1 cycrow 699
			}
700
 
56 cycrow 701
			version = lower;
702
		}				
1 cycrow 703
	}
704
 
705
	return true;
706
}
707
 
197 cycrow 708
int CGameExe::getGameVersion(const Utils::WString &sGameExe, Utils::WString *a_fVersion) const
1 cycrow 709
{
197 cycrow 710
	Utils::WString gameExe = sGameExe;
56 cycrow 711
 
197 cycrow 712
	int gameType = this->getGameType(gameExe);
1 cycrow 713
 
714
	if ( gameType == -1 )
715
		return -1;
716
 
197 cycrow 717
	Utils::WString gameDir = gameExe;
56 cycrow 718
	if ( !m_lExe[gameType]->sAddon.empty() )
197 cycrow 719
		gameExe = CDirIO(gameExe).back() + L"/" + m_lExe[gameType]->sExe;
1 cycrow 720
	else
197 cycrow 721
		gameExe = gameExe + L"/" + m_lExe[gameType]->sExe;
196 cycrow 722
	int size = (int)CFileIO(gameExe).fileSize();
1 cycrow 723
 
57 cycrow 724
	int version = this->_findVersion(gameType, size, a_fVersion);
1 cycrow 725
 
197 cycrow 726
	Utils::WString sText = this->_extractTextData(this->_readTextFile(gameDir), 1910, 10000, this->getTextID(gameExe));
727
	Utils::WString sVersion = sText.between(L"ver=", L"&amp");
1 cycrow 728
 
56 cycrow 729
	if ( !sVersion.empty() )
730
	{
731
		// lets match the version
197 cycrow 732
		Utils::WString fVersion = sVersion;
56 cycrow 733
		if ( a_fVersion ) *a_fVersion = fVersion;
734
		SGameExe *gameExe = m_lExe[gameType];
735
		if ( gameExe ) {
736
			int count = 0;
737
			int lower = -1;
738
			for ( CListNode<SGameExeVersion> *node = gameExe->lVersions.Front(); node; node = node->next() )
1 cycrow 739
			{
56 cycrow 740
				if ( fVersion.compareVersion(node->Data()->fVersion) == COMPARE_OLDER )
741
					lower = count;
742
				if (  fVersion.compareVersion(node->Data()->fVersion) == COMPARE_SAME )
743
					return count;
744
				++count;
1 cycrow 745
			}
746
 
56 cycrow 747
			version = lower;
748
		}				
1 cycrow 749
	}
56 cycrow 750
 
1 cycrow 751
	return version;
752
}
753
 
197 cycrow 754
int CGameExe::convertGameType(int gametype, int *version)
1 cycrow 755
{
756
	int count = 0, game = 0;
757
 
758
	switch ( gametype )
759
	{
760
		case 1:
761
			*version = 0;
762
			return 1;
763
		case 2:
764
			*version = 0;
765
			return 2;
766
		case 3:
767
			*version = 1;
768
			return 2;
769
		case 4:
770
			*version = 0;
771
			return 3;
772
		case 5:
773
			*version = 1;
774
			return 3;
775
		case 6:
776
			*version = 2;
777
			return 3;
778
	}
779
 
780
	for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() )
781
	{
782
		++count;
783
		++game;
784
		SGameExe *exe = node->Data();
785
 
786
		// found the game type, the version is 0, which is any version
787
		if ( count == gametype )
788
		{
789
			*version = 0;
790
			return game;
791
		}
792
 
793
		int v = 0;
794
		for ( CListNode<SGameExeVersion> *vNode = exe->lVersions.Front(); vNode; vNode = vNode->next() )
795
		{
796
			++count;
797
			++v;
798
			if ( count == gametype )
799
			{
800
				*version = v;
801
				return game;
802
			}
803
		}
804
	}
805
 
806
	// not found ?? just set to all versions
807
	*version = 0;
808
	return 0;
126 cycrow 809
}
810
 
197 cycrow 811
SGameExe *CGameExe::game(int game) const
126 cycrow 812
{ 
813
	if (game >= 0 && game < m_lExe.size()) 
814
		return m_lExe.Get(game); 
815
	return NULL; 
816
}
127 cycrow 817
 
818
unsigned int CGameExe::gameCount() const
819
{
820
	return static_cast<unsigned int>(m_lExe.size());
821
}