Rev 329 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*SPKInstall V1.00 Created by Cycrow (Matthew Gravestock)*/// Main Spk File Library Include#ifdef _WIN32#include <spk.h>#include <StringList.h>#else#include "../spk/spk.h"#endif#include <time.h>#ifdef _WIN32#include <windows.h>#include <direct.h>#include <shlobj.h>#endif#include <Package/InstallText.h>#include "Utils/CommandLine.h"#define BETA 1class CProgressConsole : public CProgressInfo{public:CProgressConsole() : CProgressInfo(){m_iCount = 0;m_fNextPercent = 0.0f;}void Finish(bool newline = true){for ( int i = m_iCount; i < 20; i++ )printf ( "*" );if ( newline )printf ( "\n");m_fNextPercent = 0.0f;m_iCount = 0;}protected:virtual void ProgressUpdated ( const long cur, const long max ){float percent = ((float)cur / (float)max) * 100.0f;if ( m_bDoHalf ){percent /= 2.0f;if ( m_bSecondHalf )percent += 50.0f;else if ( percent > 50.0f )percent = 50.0f;}if ( (percent - m_fNextPercent) >= 5.0f ){printf ( "*" );m_fNextPercent += 5.0f;++m_iCount;}}virtual void DoingFile ( C_File *file ){}private:float m_fNextPercent;int m_iCount;};#define FLAGS L"[-voctm][--dir:destination][--lang:langid]"Utils::WString g_dir;bool g_debug = false;bool g_force = false;int g_indent = 0;/*Func: GetInputDesc: Gets an input from the user, ie, any settings required to be typed in*/Utils::WString GetInput (){// g_read = true;Utils::WString line;char c = getchar();while ( (c != '\n') && (c != '\0') ){line += Utils::WString(c);c = getchar();}return line;}bool OpenDestination(Utils::CommandLine& cmd, const Utils::WString& destination){Utils::WString endMessage;wprintf(L" |0 100|\n\n");wprintf(L" - Reading game directory ");CProgressConsole progress;auto& packages = cmd.packages();if (packages.read(destination, &progress)){packages.UpdatePackages();packages.ReadGameLanguage(false);progress.Finish(false);Utils::WString gameName = packages.getGameName();if (packages.GetLanguage() || !gameName.empty()){wprintf(L"\n\t");if (!gameName.empty())wprintf(L"Game: %s ", gameName.c_str());if (packages.GetLanguage())wprintf(L"(Language: %d)", packages.GetLanguage());}wprintf(L"\n");packages.AssignPackageNumbers();return true;}else{wprintf(L"ERROR!\n");wprintf(L"\nFailed to open destination directory: %s\n", destination.c_str());exit(1);}return false;}bool CloseDestination(Utils::CommandLine& cmd, bool isPrepare){CProgressConsole progress;Utils::WStringList lErrors;if (isPrepare)wprintf(L" - Preparing game directory ");elsewprintf(L" - Closing game directory ");if (cmd.packages().closeDir(&lErrors, &progress, true))progress.Finish();else{wprintf(L"ERROR!\n");exit(1);}cmd.packages().RestoreFakePatch();wprintf(L"\nDone!\n");return true;}void PrintSyntax(const Utils::WString &cmd){wprintf(L"Syntax: %s %s <command> [arguments]\n", cmd.c_str(), FLAGS );wprintf(L"\nCommands:\n" );wprintf(L" list\n\t- Lists installed packages\n");wprintf(L" info <package#>\n\t- Info about an installed package, use id number from list\n");wprintf(L" install <file>\n\t- Installs a package file\n" );wprintf(L" uninstall <package#>\n\t- Uninstalls a package, use id number from list\n" );wprintf(L" enable <package#>\n\t- Enables an installed package\n" );wprintf(L" disable <package#>\n\t- Disables an installed package\n" );wprintf(L" removeuninstall\n\t- Removes uninstall scripts\n" );wprintf(L" removeshared\n\t- Removes unused sharded files\n" );wprintf(L"\nSwitchs:\n");wprintf(L" --dir:<directory>\n\tChange destination directory, otherwise uses current\n\n" );wprintf(L" --lang:<language>\n\tSets the language id for text file renaming\n\totheriwse reads game lang.dat\n\n");wprintf(L"\nFlags:\n");wprintf(L" -v (--verbose)\n\tTurns on verbose mode\n\n");wprintf(L" -o (--override)\n\tOverride install warnings\n\tIE. allows you to install older scripts\n\n");wprintf(L" -t (--textrename)\n\tForces text file renaming for installed packages\n\n");wprintf(L" -c (enablechild)\n\tAuto Enabled all children when parent is enabled\n\n");wprintf(L" -m (forcemod)\n\tForces a mod enabled even if theres one already enabled\n\n");}void DisplayPackage(CBaseFile *p, int indent, int language){Utils::WString version = p->version();if ( version.lower()[0] != 'v' )version.prepend(L"v");printf ( " [%5d] ", p->GetNum() + 1 );if ( indent > g_indent ){printf (" \\->");}for ( int i = 0; i < indent; i++ )printf("\t");g_indent = indent;if ( !p->IsEnabled() )printf("[D] ");wprintf(L"%s %s by %s", p->name(language).c_str(), version.c_str(), p->author().c_str());switch (p->GetType()){case TYPE_XSP:wprintf(L" (Ship)");break;case TYPE_SPK:{CSpkFile* spk = dynamic_cast<CSpkFile*>(p);wprintf(L" (%s)", spk->scriptTypeString(language).c_str());break;}}wprintf(L"\n");}void DoAllChildren(CPackages *packages, CBaseFile *p, CLinkList<CBaseFile> *doneList, int indent){CLinkList<CBaseFile> children;if ( packages->GetChildPackages(p, &children) ){for ( CBaseFile *child = children.First(); p; p = children.Next() ){DisplayPackage(child, indent, packages->GetLanguage());doneList->push_back(child);DoAllChildren(packages, child, doneList, indent + 1);}}}void ListPackages(CPackages *packages){CProgressConsole progress;CLinkList<CBaseFile> doneList;g_indent = 0;wprintf(L"\nPackages:\n");for ( CBaseFile *p = packages->PackageList()->First(); p; p = packages->PackageList()->Next() ){// already done?if ( doneList.FindData(p) )continue;if ( p->GetType() != TYPE_SPK )continue;DisplayPackage(p, 0, packages->GetLanguage());doneList.push_back(p);// find all childrenDoAllChildren(packages, p, &doneList, 1);}wprintf(L"\n");}size_t SplitArguments(char **argv, int argc, int start, Utils::WStringList *argList){for ( int i = start; i < argc; i++ ){Utils::WString arg = argv[i];if (!arg.empty())argList->pushBack(arg);}return argList->size();}bool GetAllFiles(const Utils::CommandLine& cmd, int start, Utils::WStringList &files, const Utils::WString &ext, bool showError){for (int i = start; i < cmd.argCount(); i++){if (cmd.arg(i).containsAny(L"?*")){CFileIO File(cmd.fullFilename(cmd.arg(i)));if (File.dirIO().exists()){Utils::WStringList fileList;if (File.dirIO().dirList(fileList, Utils::WString::Null(), File.filename(), true)){for (auto itr = fileList.begin(); itr != fileList.end(); itr++){// check if the file existsif (CFileIO::Exists((*itr)->str))files.pushBack((*itr)->str);}}}}else{// check if the file existsif (CFileIO::Exists(cmd.fullFilename(cmd.arg(i)))){files.pushBack(cmd.fullFilename(cmd.arg(i)));continue;}// otherwise, try to append extension to the filenameif (!ext.empty()){if (CFileIO(cmd.fullFilename(cmd.arg(i))).extension().lower() != ext.lower()){Utils::WString filename = cmd.fullFilename(cmd.arg(i)) + L"." + ext;if (CFileIO::Exists(filename)){files.pushBack(filename);continue;}}}if (showError)wprintf(L"Error: Unable to find package file %s\n", cmd.arg(i).c_str());}}return !files.empty();}Utils::WString InstallPackage(Utils::CommandLine &cmd, const Utils::WString &destination, Utils::WStringList *errors, CPackages *packages, bool disabled){if (cmd.argCount() < 2){wprintf(L"Syntax: %s [flags] install <file>\n\tInstalls a package to the destination\n", cmd.cmdName().c_str());return Utils::WString::Null();}CProgressConsole progress;int error;Utils::WStringList files;if(!GetAllFiles(cmd, 1, files, L"spk", true)){wprintf(L"Error: No package files specified to install\n");return Utils::WString::Null();}if (!OpenDestination(cmd, destination))return Utils::WString::Null();CLinkList<CBaseFile> lPackages;// open the package fileprintf ( " - Opening Package \n" );for (auto itr = files.begin(); itr != files.end(); itr++){CFileIO spkFile((*itr)->str);if(spkFile.filename().length() > 30 )wprintf(L" %28s.. ", spkFile.filename().left(28).c_str() );elsewprintf(L" %30s ", spkFile.filename().c_str() );CLinkList<CBaseFile> lPackageList;CBaseFile *package = packages->openPackage(spkFile.fullFilename(), &error, &progress);// multi packagesif ( !package && error == INSTALLERR_NOMULTI ){if ( !packages->openMultiPackage(spkFile.fullFilename(), &lPackageList, &error, &progress)){printf ( "Error!\n");continue;}progress.Finish();}else if ( package ){progress.Finish();lPackageList.push_back(package);}else{printf ( "ERROR! " );switch ( error ){case INSTALLERR_OLD:printf ( "File is in old format no longer supported" );break;case INSTALLERR_NOEXIST:printf ( "file doesn't exist" );break;case INSTALLERR_INVALID:printf ( "Invalid package file" );break;case INSTALLERR_NOSHIP:printf ( "Ship Packages are currently not supported" );break;case INSTALLERR_VERSION:printf ( "Package file was created in a newer version, unable to open" );break;}printf ( "\n");continue;}for ( CListNode<CBaseFile> *pNode = lPackageList.Front(); pNode; pNode = pNode->next() ){CBaseFile *package = pNode->Data();// compare versionsUtils::WString packageName = package->getFullPackageName(packages->GetLanguage());int checkFlags = IC_ALL;int check = packages->PrepareInstallPackage(package, (disabled) ? true : !package->IsEnabled(), false, checkFlags);switch (check){case INSTALLCHECK_OLDVERSION:wprintf(L"Newer version of \"%s\" already installed", packageName.c_str() );if ( !g_force ){printf ( ", Unable to install older, use -o to force installation\n" );continue;}else{printf ( ", Overriding install\n" );if ( packages->PrepareInstallPackage(package, disabled, true) != INSTALLCHECK_OK )continue;break;}break;// wait for the rest to be addedcase INSTALLCHECK_WRONGGAME:wprintf ( L"ERROR! \"%s\" Wrong Game (Requires: %s)", packageName.c_str(), packages->getGameTypesString(package, false).c_str() );if ( g_force ){printf ( " [FORCED]\n" );if ( packages->PrepareInstallPackage(package, disabled, true) != INSTALLCHECK_OK )continue;}else{printf("\n");continue;}break;case INSTALLCHECK_WRONGVERSION:wprintf ( L"ERROR! \"%s\" Wrong Game Version (Requires: %s)\n", packageName.c_str(), packages->getGameVersionString(package).c_str() );if ( g_force ){printf ( " [FORCED]\n" );if ( packages->PrepareInstallPackage(package, disabled, true) != INSTALLCHECK_OK )continue;}else{printf("\n");continue;}break;}if ( package->installText()->any() ){Utils::WString installtext = packages->getInstallBeforeText(package);if ( !installtext.empty() ){installtext = installtext.stripHtml();wprintf(L"Installing %s: %s\n", packageName.c_str(), installtext.c_str() );printf ( "Do you want to continue with the install? " );if ( g_force )printf ( "(FORCED)\n" );else{Utils::WString input = GetInput().lower();if ( input != "y" && input != "yes" ){printf ( "\nInstallion aborted!!\n\n" );packages->RemovePreparedInstall(package);continue;}}}}lPackages.push_back(package);}}// is there any that couldn't installCLinkList<CBaseFile> lCheckPackages;if ( packages->CheckPreparedInstallRequired(&lCheckPackages) ){printf ( "\nError! Some packages are missing dependacies:\n" );for ( CListNode<CBaseFile> *pNode = lCheckPackages.Front(); pNode; pNode = pNode->next() ){CSpkFile *spk = (CSpkFile *)pNode->Data();wprintf(L"\t%s V%s by %s, Requires:\n", spk->name(packages->GetLanguage()).c_str(), spk->version().c_str(), spk->author().c_str());if(!spk->otherName().empty())wprintf(L"\t\t%s by %s\n", spk->otherName().c_str(), spk->otherAuthor().c_str());for (auto lNode = spk->GetNeededLibraries()->Front(); lNode; lNode = lNode->next())wprintf(L"\t\t%s by %s (Minimum Version: %s)\n", lNode->Data()->sName.c_str(), lNode->Data()->sAuthor.c_str(), lNode->Data()->sMinVersion.c_str());}}// no packages will be installedif ( packages->GetNumPackagesInQueue() < 1 )return Utils::WString::Null();// install the package fileprintf ( " - Installing " );CLinkList<CBaseFile> erroredPackages;if ( packages->installPreparedPackages(errors, &progress, &erroredPackages) )progress.Finish();else{printf ( "ERROR!\n" );CloseDestination(cmd, false);return Utils::WString::Null();}// delete any errored packagesfor ( CListNode<CBaseFile> *pNode = erroredPackages.Front(); pNode; pNode = pNode->next() ){lPackages.remove(pNode->Data());pNode->DeleteData();}CloseDestination(cmd, true);// now display the packagesUtils::WString retStr = L"Packages Installed:\n";for ( CListNode<CBaseFile> *pNode = lPackages.Front(); pNode; pNode = pNode->next() ){CBaseFile *package = pNode->Data();retStr += L" <> ";retStr += package->getFullPackageName(packages->GetLanguage());retStr += L"\n";if ( !packages->getInstallAfterText(package).empty() ){Utils::WString afterText = packages->getInstallAfterText(package).stripHtml();afterText = afterText.findReplace(L"\n", L"\n\t");retStr += L"\t";retStr += afterText;retStr += L"\n";}}return retStr;}CBaseFile *FindPackage(int packageNum, const CPackages *packages){for(auto node = packages->packageList()->Front(); node; node = node->next()){if (node->Data() && node->Data()->GetNum() == (packageNum - 1))return node->Data();}return nullptr;}bool UninstallPackage(int uninstallNum, Utils::WStringList *errors, CPackages *packages, Utils::WString &endMessage){CBaseFile *p = FindPackage(uninstallNum, packages);if ( !p )return false;// lets check for the uninstall textUtils::WString uText = packages->getUninstallBeforeText(p).stripHtml();if (!uText.empty()){wprintf(L"Uninstalling: %s\n", uText.c_str() );printf ( "Do you wish to continue with the uninstall? " );if ( g_force )printf ( "(FORCED)\n" );else{Utils::WString input = GetInput().lower();if ( input != "y" && input != "yes" ){printf ( "\nUninstallation has been aborted!!\n" );return false;}}}CProgressConsole progress;endMessage = L"Uninstalled: " + p->getFullPackageName(packages->GetLanguage());// add the uninstall after textuText = packages->getUninstallAfterText(p).stripHtml();if (!uText.empty()){endMessage += L"\n\n";endMessage += uText;endMessage += L"\n";}printf ( " - Unistalling " );packages->PrepareUninstallPackage(p);if ( packages->uninstallPreparedPackages(errors, &progress) ){progress.Finish();}else{endMessage = L"";printf ( "ERROR!\n" );return false;}return true;}bool EnablePackage(int uninstallNum, Utils::WStringList *errors, CPackages *packages, Utils::WString &endMessage){CBaseFile *p = FindPackage(uninstallNum, packages);if ( !p )return false;CProgressConsole progress;endMessage = L"Enabled: " + p->getFullPackageName(packages->GetLanguage());printf ( " - Enabling " );if ( packages->enablePackage(p, errors, &progress) ){progress.Finish();}else{int error = packages->GetError();endMessage = "";printf ( "ERROR! " );if ( error == PKERR_NOPARENT )printf ( "Parent package is disabled" );printf ( "\n" );return false;}return true;}bool DisablePackage(int uninstallNum, Utils::WStringList *errors, CPackages *packages, Utils::WString &endMessage){CBaseFile *p = FindPackage(uninstallNum, packages);if ( !p )return false;CProgressConsole progress;endMessage = L"Disabled: " + p->getFullPackageName(packages->GetLanguage());printf ( " - Disabling " );if ( packages->disablePackage(p, errors, &progress) ){progress.Finish();}else{endMessage = L"";printf ( "ERROR!\n" );return false;}return true;}void RemoveUninstallScripts(CPackages *packages, Utils::WStringList *errors){CProgressConsole progress;printf ( " - Removing uninstall scripts " );packages->removeUninstallScripts(errors, &progress);progress.Finish();}void RemoveUnusedShared(CPackages *packages, Utils::WStringList *errors){CProgressConsole progress;printf ( " - Removing unused shared files " );packages->removeUnusedSharedFiles(errors, &progress);progress.Finish();}void PrintDebug(Utils::WStringList *errors){if ( !g_debug )return;if (errors && errors->size())printf ( "\n");for(auto itr = errors->begin(); itr != errors->end(); itr++){int errornum = (*itr)->data.toInt();//Check this?//Utils::WString rest = (*itr)->str.tokens(L" ", 2);Utils::WString rest = (*itr)->str;Utils::WString err = FormatErrorString(errornum, rest);wprintf(L" * %s\n", err.c_str());}if (errors && errors->size())printf ( "\n");}void ShowInfo(const Utils::CommandLine& cmd){int package = Utils::WString(cmd.arg(1)).toInt();CBaseFile* p = FindPackage(package, &cmd.packages());if (!p){wprintf(L"Error: Unable to find package #%d\n", package);return;}wprintf(L"\n============================\n");wprintf(L"Package #%d: %s\n", package, p->name(cmd.packages().language()).c_str());wprintf(L"\t%15s: %s\n", L"Author", p->author().c_str());wprintf(L"\t%15s: %s\n", L"Version", p->version().c_str());wprintf(L"\t%15s: %s\n", L"Description", p->description().c_str());if (p->GetType() == TYPE_SPK){CSpkFile* spk = dynamic_cast<CSpkFile*>(p);wprintf(L"\t%15s: %s\n", L"Type", spk->scriptTypeString(cmd.packages().language()).c_str());}else if (p->GetType() == TYPE_XSP)wprintf(L"\t%15s: %s\n", L"Type", L"Ship");wprintf(L"\t%15s: %s\n", L"Status", p->isEnabled() ? L"Enabled" : L"Disabled");if (p->anyDependacies()){wprintf(L"\t%15s:\n", L"Dependancies");for (auto needed = p->GetNeededLibraries()->First(); needed; needed = p->GetNeededLibraries()->Next())wprintf(L"\t\t%s by %s (Min Version: %s)", needed->sName.c_str(), needed->sAuthor.c_str(), needed->sMinVersion.c_str());}wprintf(L"\n============================\n\b");}void Pause(){#ifdef _DEBUGchar pause;scanf ( "%s", &pause );#endif}int ParseCommandSwitchs(wchar_t c, Utils::WString &destination, CPackages *packages, int start, int *arg, char **argv){switch ( c ){case L'o':g_force = true;break;case L'v':g_debug = true;break;case L'd':destination = argv[*arg];destination = destination.findReplace("\\", "/");++(*arg);++start;break;case L't':packages->SetRenameText(true);break;case L'l':packages->SetLanguage(Utils::WString(argv[*arg]).toInt());++(*arg);++start;break;case L'c':packages->SetAutoEnable(true);break;case L'm':packages->SetForceModInstall(true);break;}return start;}/*TODO:Additional FeaturesPatch ModsUpdate Packages*//*Main entry point to program*/int main ( int argc, char **argv ){// display program header to command promptprintf ( "\nSPKInstall V1.00 (SPK Library Version %.2f) 31/05/2025 Created by Cycrow\n\n", GetLibraryVersion() );Utils::CommandLine cmd(argc, argv, true);// not enough arguments, display the syntax and exitif (cmd.argCount() < 1 ){PrintSyntax(cmd.cmdName());Pause();exit ( 1 );}Utils::WString destination = cmd.cmdDir();Utils::WStringList lErrors;// do the flags and switchs// get the destination directoryif(cmd.hasSwitch(L"dir"))destination = cmd.switchData(L"dir").findReplace("\\", "/");else if (cmd.hasSwitch(L"directory"))destination = cmd.switchData(L"directory").findReplace("\\", "/");else if (cmd.hasSwitch(L"destination"))destination = cmd.switchData(L"destination").findReplace("\\", "/");// get the game languageauto& packages = cmd.packages();if (cmd.hasSwitch(L"lang"))packages.SetLanguage(cmd.switchData(L"lang").toInt());else if (cmd.hasSwitch(L"language"))packages.SetLanguage(cmd.switchData(L"language").toInt());// check for verbose modeg_debug = cmd.hasSwitch(L"verbose") || cmd.hasFlag('v');g_force = cmd.hasSwitch(L"override") || cmd.hasFlag('o');if (cmd.hasSwitch(L"textrename") || cmd.hasFlag('t'))packages.SetRenameText(true);if (cmd.hasSwitch(L"enablechild") || cmd.hasFlag('c'))packages.SetAutoEnable(true);if (cmd.hasSwitch(L"forcemod") || cmd.hasFlag('m'))packages.SetForceModInstall(true);int start = 2;/*// check for switchswhile ( command[0] == '-' ){if ( argc < (start + 1) ){PrintSyntax(cmd);Pause();exit ( 1 );}++start;// single long commandsint arg = 2;if ( command.left(2) == L"--" ){Utils::WString cmd = command.right(-2);cmd.toLower();char c = 0;if ( cmd == L"override" )c = 'o';else if ( cmd == L"verbose" )c = 'v';else if ( cmd == L"directory" )c = 'd';else if ( cmd == L"textrename" )c = 't';else if ( cmd == L"enablechild" )c = 'c';else if ( cmd == L"language" )c = 'l';else if ( cmd == L"forcemod" )c = 'm';if ( c )start = ParseCommandSwitchs(c, destination, &packages, start, &arg, argv);}else{// now parse argumentsfor ( int i = 1; i < (int)command.length(); i++ )start = ParseCommandSwitchs(command[i], destination, &packages, start, &arg, argv);}if ( argc < start ){PrintSyntax(cmd);exit( 1 );}command = argv[start - 1];}*/// check for valid commandUtils::WString command = cmd.arg(0).toLower();if (command.Compare(L"list")){if (OpenDestination(cmd, destination)){ListPackages(&packages);CloseDestination(cmd, false);}}else if (command.Compare(L"info")){if (cmd.argCount() < 2){wprintf(L"Syntax: %s [flags] info <package#>\n\tDisplays info about an installed package\n", cmd.cmdName().c_str());wprintf(L"\tUse the <list> command to get the package number to use");}else{if (OpenDestination(cmd, destination)){ShowInfo(cmd);CloseDestination(cmd, false);}}}else if (command.Compare(L"install")){Utils::WString aftertext = InstallPackage(cmd, destination, &lErrors, &packages, false);PrintDebug(&lErrors);if (!aftertext.empty())wprintf(L"\n%s\n", aftertext.c_str());}else if (command.Compare(L"uninstall")){if (cmd.argCount() < 2){wprintf(L"Syntax: %s [flags] uninstall <package#>\n\tUninstalls a package, package# is from the /l list command\n", cmd.cmdName().c_str());Pause();exit(1);}else{if (OpenDestination(cmd, destination)){bool prepare = UninstallPackage(Utils::WString(cmd.arg(1)).toInt(), &lErrors, &packages, command);PrintDebug(&lErrors);if (prepare)CloseDestination(cmd, true);elsepackages.RestoreFakePatch();}}}else if (command.Compare(L"enable")){if (cmd.argCount() < 2){wprintf(L"Syntax: %s [flags] enable <package#>\n\tEnables an installed package thats been disabled\n", cmd.cmdName().c_str());Pause();exit(1);}else{if (OpenDestination(cmd, destination)){bool prepare = EnablePackage(Utils::WString(cmd.arg(1)).toInt(), &lErrors, &packages, command);PrintDebug(&lErrors);if (prepare)CloseDestination(cmd, true);elsepackages.RestoreFakePatch();}}}if ( command[0] == '/' ){wchar_t c = command[1];bool disabled = false;Utils::WString checkCmd = command.lower();if ( checkCmd == L"/install" )c = L'i';else if ( checkCmd == L"/installdisable" ){c = L'i';disabled = true;}else if ( checkCmd == L"/uninstall" )c = L'u';else if ( checkCmd == L"/enable" )c = L'e';else if ( checkCmd == L"/disable" )c = L'd';else if ( checkCmd == L"/list" )c = L'l';else if ( checkCmd == L"/removeshared" )c = L's';else if ( checkCmd == L"/removeunisntall" )c = L'r';if ( c == L'i' || c == L'l' || c == L'u' || c == L'e' || c == L'd' || c == L'r' || c == L's' ){Utils::WString endMessage;wprintf(L" |0 100|\n\n");wprintf(L" - Reading game directory ");CProgressConsole progress;if ( packages.read(destination, &progress) ){packages.UpdatePackages();packages.ReadGameLanguage(false);progress.Finish(false);Utils::WString gameName = packages.getGameName();if ( packages.GetLanguage() || !gameName.empty()){printf ( "\n\t" );if ( !gameName.empty() )wprintf ( L"Game: %s ", gameName.c_str());if ( packages.GetLanguage() )printf ( "(Language: %d)", packages.GetLanguage() );}printf ( "\n" );}else{printf ( "ERROR!\n" );exit(1);}bool prepare = false;packages.AssignPackageNumbers();Utils::WStringList lArguments;SplitArguments(argv, argc, start, &lArguments);switch ( c ){case 'u':if ( argc <= start )wprintf(L"Syntax: %s [flags] /u <package#>\n\tUninstalls a package, package# is from the /l list command\n", cmd.cmdName().c_str() );else{prepare = UninstallPackage(Utils::WString(argv[start]).toInt(), &lErrors, &packages, endMessage);PrintDebug(&lErrors);}break;case 'e':if ( argc <= start )wprintf(L"Syntax: %s [flags] /u <package#>\n\tEnabled an installed package thats been disabled\n", cmd.cmdName().c_str() );else{prepare = EnablePackage(Utils::WString(argv[start]).toInt(), &lErrors, &packages, endMessage);PrintDebug(&lErrors);}break;case 'd':if ( argc <= start )wprintf(L"Syntax: %s [flags] /u <package#>\n\tDisabled an installed package\n", cmd.cmdName().c_str() );else{prepare = DisablePackage(Utils::WString(argv[start]).toInt(), &lErrors, &packages, endMessage);PrintDebug(&lErrors);}break;case 'l':ListPackages(&packages);break;case 'r':RemoveUninstallScripts(&packages, &lErrors);endMessage = "Removed all unused uninstall scripts";break;case 's':RemoveUnusedShared(&packages, &lErrors);endMessage = "Removed all unused shared files";break;}if ( prepare ){lErrors.clear();printf ( " - Preparing game directory " );if ( packages.closeDir(&lErrors, &progress, true) )progress.Finish();else{printf ( "ERROR!\n" );Pause();exit(1);}PrintDebug(&lErrors);}elsepackages.RestoreFakePatch();printf ( "\nDone!\n" );if ( !endMessage.empty() )wprintf(L"\n%s\n", endMessage.c_str() );}elseprintf ( "Unknown Command: %c\n", c );}Pause();return 0;}