Subversion Repositories spk

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
/*
2
 SPKInstall V1.00 Created by Cycrow (Matthew Gravestock)
3
*/
4
 
5
// Main Spk File Library Include
6
#ifdef _WIN32
7
#include <spk.h>
8
#else
9
#include "../spk/spk.h"
10
#endif
11
#include <time.h>
12
 
13
#ifdef _WIN32
14
#include <windows.h>
15
#include <direct.h>
16
#include <shlobj.h>
17
#endif
18
 
19
#define BETA 1
20
 
21
class CProgressConsole : public CProgressInfo
22
{
23
public:
24
	CProgressConsole() : CProgressInfo()
25
	{
26
		m_iCount = 0;
27
		m_fNextPercent = 0.0f;
28
	}
29
 
30
	void Finish(bool newline = true)
31
	{
32
		for ( int i = m_iCount; i < 20; i++ )
33
			printf ( "*" );
34
		if ( newline )
35
			printf ( "\n");
36
		m_fNextPercent = 0.0f;
37
		m_iCount = 0;
38
	}
39
 
40
protected:
41
	virtual void ProgressUpdated ( const long cur, const long max )
42
	{
43
		float percent = ((float)cur / (float)max) * 100.0f;
44
		if ( m_bDoHalf )
45
		{
46
			percent /= 2.0f;
47
			if ( m_bSecondHalf )
48
				percent += 50.0f;
49
			else if ( percent > 50.0f )
50
				percent = 50.0f;
51
		}
52
		if ( (percent - m_fNextPercent) >= 5.0f )
53
		{
54
			printf ( "*" );
55
			m_fNextPercent += 5.0f;
56
			++m_iCount;
57
		}
58
	}
59
	virtual void DoingFile ( C_File *file )
60
	{
61
	}
62
 
63
private:
64
	float m_fNextPercent;
65
	int   m_iCount;
66
};
67
 
68
#define FLAGS "[-voctm][-d destination][-l langid]"
69
 
70
CyString	g_dir;
71
bool	g_debug = false;
72
bool	g_force = false;
73
int		g_indent = 0;
74
/*
75
	Func:	GetInput
76
	Desc:	Gets an input from the user, ie, any settings required to be typed in
77
*/
78
CyString GetInput ()
79
{
80
//	g_read = true;
81
 
82
	CyString line;
83
	char c = getchar();
84
 
85
	while ( (c != '\n') && (c != '\0') )
86
	{
87
		line += c;
88
		c = getchar();
89
	}
90
 
91
	return line;
92
}
93
 
94
void PrintSyntax ( CyString cmd )
95
{
96
	printf ( "Syntax: %s %s </command> [arguments]\n", cmd.c_str(), FLAGS );
97
	printf ( "\nCommands:\n" );
98
	printf ( "   /list\n\t- Lists installed packages\n" );
99
	printf ( "   /install <file>\n\t- Installs a package file\n" );
100
	printf ( "   /uninstall <package#>\n\t- Uninstalls a package, use id number from list\n" );
101
	printf ( "   /enable <package#>\n\t- Enables an installed package\n" );
102
	printf ( "   /disable <package#>\n\t- Disables an installed package\n" );
103
	printf ( "   /removeuninstall\n\t- Removes uninstall scripts\n" );
104
	printf ( "   /removeshared\n\t- Removes unused sharded files\n" );
105
	printf ( "\nSwitchs:\n" );
106
	printf ( "   -d (--directory) [directory]\n\tChange destination directory, otherwise uses current\n\n" );
107
	printf ( "   -v (--verbose)\n\tTurns on verbose mode\n\n" );
108
	printf ( "   -o (--override)\n\tOverride install warnings\n\tIE. allows you to install older scripts\n\n" );
109
	printf ( "   -t (--textrename)\n\tForces text file renaming for installed packages\n\n" );
110
	printf ( "   -l (--language) <language>\n\tSets the language id for text file renaming\n\totheriwse reads game lang.dat\n\n" );
111
	printf ( "   -c (--enablechild)\n\tAuto Enabled all children when parent is enabled\n\n" );
112
	printf ( "   -m (--forcemod\n\tForces a mod enabled even if theres one already enabled\n\n" );
113
}
114
 
115
void DisplayPackage(CBaseFile *p, int indent, int language)
116
{
117
	CyString version = p->GetVersion();
118
	if ( version.lower()[0] != 'v' )
119
		version.Prepend("v");
120
 
121
	printf ( "  [%5d] ", p->GetNum() + 1 );
122
 
123
	if ( indent > g_indent )
124
	{
125
		printf (" \\->");
126
	}
127
	for ( int i = 0; i < indent; i++ )
128
		printf("\t");
129
 
130
	g_indent = indent;
131
 
132
	if ( !p->IsEnabled() )
133
		printf("[D] ");
134
 
135
	printf ( "%s %s by %s\n", p->GetLanguageName(language).c_str(), version.c_str(), p->GetAuthor().c_str() );
136
}
137
 
138
void DoAllChildren(CPackages *packages, CBaseFile *p, CLinkList<CBaseFile> *doneList, int indent)
139
{
140
	CLinkList<CBaseFile> children;
141
	if ( packages->GetChildPackages(p, &children) )
142
	{
143
		for ( CBaseFile *child = children.First(); p; p = children.Next() )
144
		{
145
			DisplayPackage(child, indent, packages->GetLanguage());
146
			doneList->push_back(child);
147
 
148
			DoAllChildren(packages, child, doneList, indent + 1);
149
		}
150
	}
151
}
152
 
153
void ListPackages(CPackages *packages)
154
{
155
	CProgressConsole progress;
156
 
157
	CLinkList<CBaseFile> doneList;
158
 
159
	g_indent = 0;
160
	printf ( "\nPackages:\n" );
161
	for ( CBaseFile *p = packages->PackageList()->First(); p; p = packages->PackageList()->Next() )
162
	{
163
		// already done?
164
		if ( doneList.FindData(p) )
165
			continue;
166
 
167
		if ( p->GetType() != TYPE_SPK )
168
			continue;
169
 
170
		DisplayPackage(p, 0, packages->GetLanguage());
171
		doneList.push_back(p);
172
 
173
		// find all children
174
		DoAllChildren(packages, p, &doneList, 1);
175
	}
176
}
177
 
178
int SplitArguments(char **argv, int argc, int start, CyStringList *argList)
179
{
180
	for ( int i = start; i < argc; i++ )
181
	{
182
		CyString arg = argv[i];
183
		if ( !arg.Empty() )
184
			argList->PushBack(arg);
185
	}
186
 
187
	return argList->Count();
188
}
189
 
190
CyString InstallPackage(CyStringList *lArguments, CyStringList *errors, CPackages *packages, bool disabled)
191
{
192
	CProgressConsole progress;
193
 
194
	int error;
195
 
196
	if ( !lArguments || !lArguments->Count() )
197
		return NullString;
198
 
199
	// append spk on the end
200
	for ( SStringList *node = lArguments->Head(); node; node = node->next )
201
	{
202
		if ( !CFileIO(node->str).Exists() )
203
		{
204
			if ( CFileIO(node->str).GetFileExtension().lower() != "spk" )
205
				node->str += ".spk";
206
		}
207
	}
208
 
209
	CLinkList<CBaseFile> lPackages;
210
 
211
	// open the package file
212
	printf ( "  - Opening Package                \n" );
213
	for ( SStringList *node = lArguments->Head(); node; node = node->next )
214
	{
215
		CyString spkFilename = node->str;
216
 
217
		if ( spkFilename.Length() > 30 )
218
			printf ( "    ..%28s ", spkFilename.Right(28).c_str() );
219
		else
220
			printf ( "    %30s ", spkFilename.Right(30).c_str() );
221
 
222
		CLinkList<CBaseFile> lPackageList;
223
		CBaseFile *package = packages->OpenPackage(spkFilename, &error, &progress);
224
 
225
		// multi packages
226
		if ( !package && error == INSTALLERR_NOMULTI )
227
		{
228
			if ( !packages->OpenMultiPackage(spkFilename, &lPackageList, &error, &progress) )
229
			{
230
				printf ( "Error!\n");
231
				continue;
232
			}
233
			progress.Finish();
234
		}
235
 
236
		else if ( package )
237
		{
238
			progress.Finish();
239
			lPackageList.push_back(package);
240
		}
241
		else
242
		{
243
			printf ( "ERROR!  " );
244
			switch ( error )
245
			{
246
				case INSTALLERR_OLD:
247
					printf ( "File is in old format no longer supported" );
248
					break;
249
				case INSTALLERR_NOEXIST:
250
					printf ( "file doesn't exist" );
251
					break;
252
				case INSTALLERR_INVALID:
253
					printf ( "Invalid package file" );
254
					break;
255
				case INSTALLERR_NOSHIP:
256
					printf ( "Ship Packages are currently not supported" );
257
					break;
258
				case INSTALLERR_VERSION:
259
					printf ( "Package file was created in a newer version, unable to open" );
260
					break;
261
			}
262
			printf ( "\n");
263
			continue;
264
		}
265
 
266
		for ( CListNode<CBaseFile> *pNode = lPackageList.Front(); pNode; pNode = pNode->next() )
267
		{
268
			CBaseFile *package = pNode->Data();
269
 
270
			// compare versions
271
			CyString packageName = package->GetFullPackageName(packages->GetLanguage());
272
 
273
			int checkFlags = IC_ALL;
274
			int check = packages->PrepareInstallPackage(package, (disabled) ? true : !package->IsEnabled(), false, checkFlags);
275
 
276
			switch (check)
277
			{
278
				case INSTALLCHECK_OLDVERSION:
279
					printf ( "Newer version of \"%s\" already installed", packageName.c_str() );
280
					if ( !g_force )
281
					{
282
						printf ( ", Unable to install older, use -o to force installation\n" );
283
						continue;
284
					}
285
					else
286
					{
287
						printf ( ", Overriding install\n" );
288
						if ( packages->PrepareInstallPackage(package, disabled, true) != INSTALLCHECK_OK )
289
							continue;
290
						break;
291
					}
292
					break;
293
					// wait for the rest to be added
294
				case INSTALLCHECK_WRONGGAME:
295
					printf ( "ERROR! \"%s\" Wrong Game (Requires: %s)", packageName.c_str(), packages->GetGameTypesString(package, false).c_str() );
296
					if ( g_force )
297
					{
298
						printf ( " [FORCED]\n" );
299
						if ( packages->PrepareInstallPackage(package, disabled, true) != INSTALLCHECK_OK )
300
							continue;
301
					}
302
					else
303
					{
304
						printf("\n");
305
						continue;
306
					}
307
					break;
308
 
309
				case INSTALLCHECK_WRONGVERSION:
310
					printf ( "ERROR! \"%s\" Wrong Game Version (Requires: %s)\n", packageName.c_str(), packages->GetGameVersionString(package).c_str() );
311
					if ( g_force )
312
					{
313
						printf ( " [FORCED]\n" );
314
						if ( packages->PrepareInstallPackage(package, disabled, true) != INSTALLCHECK_OK )
315
							continue;
316
					}
317
					else
318
					{
319
						printf("\n");
320
						continue;
321
					}
322
					break;
323
			}
324
 
325
			if ( package->IsThereInstallText() )
326
			{
327
				CyString installtext = packages->GetInstallBeforeText(package);
328
				if ( !installtext.Empty() )
329
				{
330
					installtext.StripHTML();
331
					printf ( "Installing %s: %s\n", packageName.c_str(), installtext.c_str() );
332
					printf ( "Do you want to continue with the install? " );
333
 
334
					if ( g_force )
335
						printf ( "(FORCED)\n" );
336
					else
337
					{
338
						CyString input = GetInput().ToLower();
339
 
340
						if ( input != "y" && input != "yes" )
341
						{
342
							printf ( "\nInstallion aborted!!\n\n" );
343
							packages->RemovePreparedInstall(package);
344
							continue;
345
						}
346
					}
347
				}
348
			}
349
 
350
			lPackages.push_back(package);
351
		}
352
	}
353
 
354
	// is there any that couldn't install
355
	CLinkList<CBaseFile> lCheckPackages;
356
	if ( packages->CheckPreparedInstallRequired(&lCheckPackages) )
357
	{
358
		printf ( "\nError! Some packages are missing dependacies:\n" );
359
		for ( CListNode<CBaseFile> *pNode = lCheckPackages.Front(); pNode; pNode = pNode->next() )
360
		{
361
			CSpkFile *spk = (CSpkFile *)pNode->Data();
362
			printf ( "\t%s V%s by %s (Requires: %s by %s)\n", spk->GetLanguageName(packages->GetLanguage()).c_str(), spk->GetVersion().c_str(), spk->GetAuthor().c_str(), spk->GetOtherName().c_str(), spk->GetOtherAuthor().c_str());
363
		}
364
	}
365
 
366
	// no packages will be installed
367
	if ( packages->GetNumPackagesInQueue() < 1 )
368
		return NullString;
369
 
370
	// install the package file
371
	printf ( "  - Installing                     " );
372
	CLinkList<CBaseFile> erroredPackages;
373
	if ( packages->InstallPreparedPackages(errors, &progress, &erroredPackages) )
374
		progress.Finish();
375
	else
376
	{
377
		printf ( "ERROR!\n" );
378
		return NullString;
379
	}
380
 
381
	// delete any errored packages
382
	for ( CListNode<CBaseFile> *pNode = erroredPackages.Front(); pNode; pNode = pNode->next() )
383
	{
384
		lPackages.remove(pNode->Data());
385
		pNode->DeleteData();
386
	}
387
 
388
	// now display the packages
389
	CyString retStr = "Packages Installed:\n";
390
	for ( CListNode<CBaseFile> *pNode = lPackages.Front(); pNode; pNode = pNode->next() )
391
	{
392
		CBaseFile *package = pNode->Data();
393
 
394
		retStr += "  <> ";
395
		retStr += package->GetFullPackageName(packages->GetLanguage());
396
		retStr += "\n";
397
 
398
		if ( !packages->GetInstallAfterText(package).Empty() )
399
		{
400
			CyString afterText = packages->GetInstallAfterText(package).StripHTML();
401
			afterText = afterText.FindReplace("\n", "\n\t");
402
			retStr += "\t";
403
			retStr += afterText;
404
			retStr += "\n";
405
		}
406
	}
407
 
408
	return retStr;
409
}
410
 
411
CBaseFile *FindPackage(int packageNum, CPackages *packages)
412
{
413
	for ( CBaseFile *p = packages->PackageList()->First(); p; p = packages->PackageList()->Next() )
414
	{
415
		if ( p->GetNum() == (packageNum - 1) )
416
			return p;
417
	}
418
 
419
	return 0;
420
}
421
 
422
bool UninstallPackage(int uninstallNum, CyStringList *errors, CPackages *packages, CyString *endMessage)
423
{
424
	CBaseFile *p = FindPackage(uninstallNum, packages);
425
	if ( !p )
426
		return false;
427
 
428
	// lets check for the uninstall text
429
	CyString uText = packages->GetUninstallBeforeText(p).StripHTML();
430
	if ( !uText.Empty() )
431
	{
432
		printf ( "Uninstalling: %s\n", uText.c_str() );
433
		printf ( "Do you wish to continue with the uninstall? " );
434
		if ( g_force )
435
			printf ( "(FORCED)\n" );
436
		else
437
		{
438
			CyString input = GetInput().ToLower();
439
			if ( input != "y" && input != "yes" )
440
			{
441
				printf ( "\nUninstallation has been aborted!!\n" );
442
				return false;
443
			}
444
		}
445
	}
446
 
447
	CProgressConsole progress;
448
 
449
	(*endMessage) = CyString("Uninstalled: ") + p->GetFullPackageName(packages->GetLanguage());
450
	// add the uninstall after text
451
	uText = packages->GetUninstallAfterText(p).StripHTML();
452
	if ( !uText.Empty() )
453
	{
454
		(*endMessage) += "\n\n";
455
		(*endMessage) += uText;
456
		(*endMessage) += "\n";
457
	}
458
 
459
	printf ( "  - Unistalling                    " );
460
	packages->PrepareUninstallPackage(p);
461
	if ( packages->UninstallPreparedPackages(errors, &progress) )
462
	{
463
		progress.Finish();
464
	}
465
	else
466
	{
467
		(*endMessage) = "";
468
		printf ( "ERROR!\n" );
469
		return false;
470
	}
471
 
472
 
473
	return true;
474
}
475
 
476
bool EnablePackage(int uninstallNum, CyStringList *errors, CPackages *packages, CyString *endMessage)
477
{
478
	CBaseFile *p = FindPackage(uninstallNum, packages);
479
	if ( !p )
480
		return false;
481
 
482
	CProgressConsole progress;
483
 
484
	(*endMessage) = CyString("Enabled: ") + p->GetFullPackageName(packages->GetLanguage());
485
 
486
	printf ( "  - Enabling                       " );
487
	if ( packages->EnablePackage(p, errors, &progress) )
488
	{
489
		progress.Finish();
490
	}
491
	else
492
	{
493
		int error = packages->GetError();
494
		(*endMessage) = "";
495
		printf ( "ERROR! " );
496
		if ( error == PKERR_NOPARENT )
497
			printf ( "Parent package is disabled" );
498
		printf ( "\n" );
499
		return false;
500
	}
501
	return true;
502
}
503
 
504
bool DisablePackage(int uninstallNum, CyStringList *errors, CPackages *packages, CyString *endMessage)
505
{
506
	CBaseFile *p = FindPackage(uninstallNum, packages);
507
	if ( !p )
508
		return false;
509
 
510
	CProgressConsole progress;
511
 
512
	(*endMessage) = CyString("Disabled: ") + p->GetFullPackageName(packages->GetLanguage());
513
 
514
	printf ( "  - Disabling                      " );
515
	if ( packages->DisablePackage(p, errors, &progress) )
516
	{
517
		progress.Finish();
518
	}
519
	else
520
	{
521
		(*endMessage) = "";
522
		printf ( "ERROR!\n" );
523
		return false;
524
	}
525
	return true;
526
}
527
 
528
void RemoveUninstallScripts(CPackages *packages, CyStringList *errors)
529
{
530
	CProgressConsole progress;
531
	printf ( "  - Removing uninstall scripts     " );
532
	packages->RemoveUninstallScripts(errors, &progress);
533
	progress.Finish();
534
}
535
 
536
void RemoveUnusedShared(CPackages *packages, CyStringList *errors)
537
{
538
	CProgressConsole progress;
539
	printf ( "  - Removing unused shared files   " );
540
	packages->RemoveUnusedSharedFiles(errors, &progress);
541
	progress.Finish();
542
}
543
 
544
 
545
void PrintDebug(CyStringList *errors)
546
{
547
	if ( !g_debug )
548
		return;
549
 
550
	if ( errors && errors->Count() )
551
		printf ( "\n");
552
 
553
	for ( SStringList *str = errors->Head(); str; str = str->next )
554
	{
555
		int errornum = str->str.ToInt();
556
		CyString rest = str->str.GetToken(" ", 2);
557
 
558
		CyString err = FormatErrorString(errornum, rest);
559
		printf ( "  * %s\n", err.c_str() );
560
	}
561
 
562
	if ( errors && errors->Count() )
563
		printf ( "\n");
564
}
565
 
566
 
567
 
568
 
569
void Pause()
570
{
571
#ifdef _DEBUG
572
	char pause;
573
	scanf ( "%s", &pause );
574
#endif
575
}
576
 
577
 
578
int ParseCommandSwitchs(char c, CyString *destination, CPackages *packages, int start, int *arg, char **argv)
579
{
580
	switch ( c )
581
	{
582
		case 'o':
583
			g_force = true;
584
			break;
585
		case 'v':
586
			g_debug = true;
587
			break;
588
		case 'd':
589
			*destination = argv[*arg];
590
			*destination = destination->FindReplace("\\", "/");
591
			++(*arg);
592
			++start;
593
			break;
594
		case 't':
595
			packages->SetRenameText(true);
596
			break;
597
		case 'l':
598
			packages->SetLanguage(CyString(argv[*arg]).ToInt());
599
			++(*arg);
600
			++start;
601
			break;
602
		case 'c':
603
			packages->SetAutoEnable(true);
604
			break;
605
		case 'm':
606
			packages->SetForceModInstall(true);
607
			break;
608
	}
609
 
610
	return start;
611
}
612
 
613
/*
614
TODO:
615
Additional Features
616
	Patch Mods
617
	Update Packages
618
*/
619
 
620
/*
621
	Main entry point to program
622
*/
623
int main ( int argc, char **argv )
624
{
625
 	// display program header to command prompt
626
	printf ( "\nSPKInstall V0.90 (SPK Library Version %.2f) 18/10/2009 Created by Cycrow\n\n", GetLibraryVersion() );
627
 
628
	// parse the cmd name
629
	CyString cmd (argv[0]);
630
 
631
	cmd = cmd.FindReplace ( "\\", "/" );
632
	g_dir = cmd.GetToken ( 0, cmd.NumToken('/') - 1, '/' );
633
	cmd = cmd.GetToken ( cmd.NumToken('/'), '/' );
634
 
635
	if ( g_dir.Empty() )
636
	{
637
	    #ifdef _WIN32
638
		g_dir = CyString(_getcwd(NULL, 0));
639
		#else
640
		g_dir = CyString(getcwd(NULL, 0));
641
		#endif
642
		if ( g_dir.Empty() )
643
			g_dir = "./";
644
	}
645
 
646
	// not enough arguments, display the syntax and exit
647
	if ( argc < 2 )
648
	{
649
		PrintSyntax(cmd);
650
		Pause();
651
		exit ( 1 );
652
	}
653
 
654
	CyString destination = g_dir;
655
	CyStringList errors;
656
 
657
	// get the command flag
658
	CyString command(argv[1]);
659
	command = command.lower();
660
 
661
	CPackages packages;
662
	CyString myDoc = g_dir;
663
#ifdef _WIN32
664
	TCHAR pszPath[MAX_PATH];
665
	if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, pszPath)))
666
		myDoc = (char *)pszPath;
667
#endif
668
	packages.Startup(g_dir, g_dir, myDoc);
669
 
670
	int start = 2;
671
	// check for switchs
672
	while ( command[0] == '-' )
673
	{
674
		if ( argc < (start + 1) )
675
		{
676
			PrintSyntax(cmd);
677
			Pause();
678
			exit ( 1 );
679
		}
680
		++start;
681
 
682
		// single long commands
683
		int arg = 2;
684
		if ( command.Left(2) == "--" )
685
		{
686
			CyString cmd = command.Right(-2);
687
			cmd = cmd.ToLower();
688
 
689
			char c = 0;
690
			if ( cmd == "override" )
691
				c = 'o';
692
			else if ( cmd == "verbose" )
693
				c = 'v';
694
			else if ( cmd == "directory" )
695
				c = 'd';
696
			else if ( cmd == "textrename" )
697
				c = 't';
698
			else if ( cmd == "enablechild" )
699
				c = 'c';
700
			else if ( cmd == "language" )
701
				c = 'l';
702
			else if ( cmd == "forcemod" )
703
				c = 'm';
704
 
705
			if ( c )
706
				start = ParseCommandSwitchs(c, &destination, &packages, start, &arg, argv);
707
		}
708
		else
709
		{
710
			// now parse arguments
711
			for ( int i = 1; i < (int)command.Length(); i++ )
712
				start = ParseCommandSwitchs(command[i], &destination, &packages, start, &arg, argv);
713
		}
714
 
715
		if ( argc < start )
716
		{
717
			PrintSyntax(cmd);
718
			exit( 1 );
719
		}
720
		command = argv[start - 1];
721
	}
722
 
723
	if ( command[0] == '/' )
724
	{
725
		char c = command[1];
726
 
727
		bool disabled = false;
728
 
729
		CyString checkCmd = command.ToLower();
730
		if ( checkCmd == "/install" )
731
			c = 'i';
732
		else if ( checkCmd == "/installdisable" )
733
		{
734
			c = 'i';
735
			disabled = true;
736
		}
737
		else if ( checkCmd == "/uninstall" )
738
			c = 'u';
739
		else if ( checkCmd == "/enable" )
740
			c = 'e';
741
		else if ( checkCmd == "/disable" )
742
			c = 'd';
743
		else if ( checkCmd == "/list" )
744
			c = 'l';
745
		else if ( checkCmd == "/removeshared" )
746
			c = 's';
747
		else if ( checkCmd == "/removeunisntall" )
748
			c = 'r';
749
 
750
		if ( c == 'i' || c == 'l' || c == 'u' || c == 'e' || c == 'd' || c == 'r' || c == 's' )
751
		{
752
			CyString endMessage;
753
 
754
			printf ( "                                   |0              100|\n\n");
755
			printf ( "  - Reading game directory         " );
756
 
757
			CProgressConsole progress;
758
 
759
			if ( packages.Read(destination, &progress) )
760
			{
761
				packages.UpdatePackages();
762
				packages.ReadGameLanguage(false);
763
				progress.Finish(false);
764
 
765
				CyString gameName = packages.GetGameName();
766
				if ( packages.GetLanguage() || !gameName.Empty())
767
				{
768
					printf ( "\n\t" );
769
					if ( !gameName.Empty() )
770
						printf ( "Game: %s ", gameName.c_str());
771
					if ( packages.GetLanguage() )
772
						printf ( "(Language: %d)", packages.GetLanguage() );
773
				}
774
				printf ( "\n" );
775
			}
776
			else
777
			{
778
				printf ( "ERROR!\n" );
779
				exit(1);
780
			}
781
 
782
			bool prepare = false;
783
 
784
			packages.AssignPackageNumbers();
785
 
786
			CyStringList lArguments;
787
			SplitArguments(argv, argc, start, &lArguments);
788
 
789
			switch ( c )
790
			{
791
				case 'i':
792
					if ( argc <= start )
793
						printf ( "Syntax: %s [flags] /i <file>\n\tInstalls a package to the destination\n", cmd.c_str() );
794
					else
795
					{
796
						CyString aftertext = InstallPackage(&lArguments, &errors, &packages, disabled);
797
						if ( !aftertext.Empty() )
798
						{
799
							prepare = true;
800
							endMessage = aftertext;
801
						}
802
						PrintDebug(&errors);
803
					}
804
					break;
805
 
806
				case 'u':
807
					if ( argc <= start )
808
						printf ( "Syntax: %s [flags] /u <package#\n\tUninstalls a package, package# is from the /l list command\n", cmd.c_str() );
809
					else
810
					{
811
						prepare = UninstallPackage(CyString(argv[start]).ToInt(), &errors, &packages, &endMessage);
812
						PrintDebug(&errors);
813
					}
814
					break;
815
 
816
				case 'e':
817
					if ( argc <= start )
818
						printf ( "Syntax: %s [flags] /u <package#\n\tEnabled an installed package thats been disabled\n", cmd.c_str() );
819
					else
820
					{
821
						prepare = EnablePackage(CyString(argv[start]).ToInt(), &errors, &packages, &endMessage);
822
						PrintDebug(&errors);
823
					}
824
					break;
825
 
826
				case 'd':
827
					if ( argc <= start )
828
						printf ( "Syntax: %s [flags] /u <package#\n\tDisabled an installed package\n", cmd.c_str() );
829
					else
830
					{
831
						prepare = DisablePackage(CyString(argv[start]).ToInt(), &errors, &packages, &endMessage);
832
						PrintDebug(&errors);
833
					}
834
					break;
835
 
836
				case 'l':
837
					ListPackages(&packages);
838
					break;
839
 
840
				case 'r':
841
					RemoveUninstallScripts(&packages, &errors);
842
					endMessage = "Removed all unused uninstall scripts";
843
					break;
844
 
845
				case 's':
846
					RemoveUnusedShared(&packages, &errors);
847
					endMessage = "Removed all unused shared files";
848
					break;
849
			}
850
 
851
			if ( prepare )
852
			{
853
				errors.Clear();
854
				printf ( "  - Preparing game directory       " );
855
				if ( packages.CloseDir(&errors, &progress, true) )
856
					progress.Finish();
857
				else
858
				{
859
					printf ( "ERROR!\n" );
860
					Pause();
861
					exit(1);
862
				}
863
 
864
				PrintDebug(&errors);
865
			}
866
			else
867
				packages.RestoreFakePatch();
868
 
869
			printf ( "\nDone!\n" );
870
			if ( !endMessage.Empty() )
871
				printf ( "\n%s\n", endMessage.c_str() );
872
		}
873
		else
874
			printf ( "Unknown Command: %c\n", c );
875
	}
876
 
877
	Pause();
878
 
879
	return 0;
880
}