Subversion Repositories spk

Rev

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