Subversion Repositories spk

Rev

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