Rev 294 | Rev 307 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*SPKTool V1.00 Created by Cycrow (Matthew Gravestock)*/// Main Spk File Library Include#ifdef _WIN32#include <spk.h>#include <MultiSpkFile.h>#include <spkcmdprogress.h>#else#include "../spk/spk.h"#include "../spk/MultiSpkFile.h"#include "../spk/spkcmdprogress.h"#endif// Multi Spk File format, required if using Multi Spk files// Displays 7Zip compression progress to the command line#include <time.h>#ifdef _WIN32#include <windows.h>#include <direct.h>#include <shlobj.h>#endifUtils::WString g_dir;bool g_read;class CFileProgress : public CProgressInfo{private:Utils::WString _display;CBaseFile *_package;CPackages *_packages;public:CFileProgress(CPackages *packages, CBaseFile *package, const Utils::WString &display) :_display(display),_packages(packages),_package(package){}protected:void ProgressUpdated(const long cur, const long max){}void DoingFile(C_File *file){Utils::WString game;if (!file->game() || file->game() == GAME_ALLNEW)game = L"All Games";else if (_packages){for (unsigned int i = 0; i < 31; ++i){if (file->game() & (1 << i)){Utils::WString g = _packages->GetGameExe()->gameNameFromType(i - 1);if (!g.empty()){if (game.empty())game = g;elsegame = game + L", " + g;}}}}if(game.empty())wprintf(L"%s: %s\n", _display.c_str(), file->getNameDirectory(_package).c_str());elsewprintf(L"%s: %s [%s]\n", _display.c_str(), file->getNameDirectory(_package).c_str(), game.c_str());}};/*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;wchar_t c = getchar();while ( (c != L'\n') && (c != L'\0') ){line += c;c = getchar();}return line;}/*Func: PrintSyntaxArgs: String cmd - The command name to be displayedDesc: Displays the syntax for the program*/void PrintSyntax(const Utils::WString &cmd){wprintf(L"Syntax: %s <command>\n", cmd.c_str() );wprintf(L"Commands:\n" );wprintf(L"\t-v <spkfile>\n\t--view <spkfile>\n\t\tViews the contents of a spk file\n\n" );wprintf(L"\t-e <spkfile> [destination]\n\t--extractall <spkfile> [destination]\n\t\tExtracts all the files to the destination directory [or current if no destiantion is set]\n\n" );wprintf(L"\t-x <spkfile> <type> <file> [destination]\n\t--extract <spkfile> <type> <file> [destination]\n\t\tExtracts a single file of <type> to destination directory\n\n" );wprintf(L"\t-x <multispkfile> <file> [destination]\n\t--extractspk <multispkfile> <spkfile> [destination]\n\t\tExtracts a single spk file from a Multi-Spk Package\n\n" );wprintf(L"\t-c <spkfile>\n\t--create\n\t\tCreates a new spk file\n\n" );wprintf(L"\t-a <spkfile> <type> <filename>\n\t--append <spkfile> <type> <filename>\n\t\tAppends a file to the package of set <type>\n\n" );wprintf(L"\t-r <spkfile> <type> <filename>\n\t--remove <spkfile> <type> <filename>\n\t\tRemoves a file from the package of set <type>\n\n" );wprintf(L"\t-r <multispkfile> <filename>\n\t--removespk <multispkfile> <filename>\n\t\tRemoves a spk file from the Multi-SPK package\n\n" );wprintf(L"\t-m <spkfile> <spkfile>\n\t--mergemulti <spkfile> <spkfile>\n\t\tMerges spk files together, the second file will be merged into the first\n\n" );wprintf(L"\t-n <multispkfile>\n\t--createmulti\n\t\tCreates a multi spk file, and adds the spkfiles in\n\n" );wprintf(L"\t-s <multispkfile> [destination]\n\t--splitmulti <multispkfile> [destination]\n\t\tSplits a Multi-SPK file up, saves all the spk files to Destination\n\n" );wprintf(L"\t--set <setting> [value]\n\t\tChanges the settings of the script\n\n" );wprintf(L"\t--convertxsp <oldxsp> [newxsp]\n\t\tConverts an old XSP file into the new format\n\n");wprintf(L"\t--createscript <packagescript>\n\t\tCreates a spk file from a packager script\n\n");wprintf(L"\t--verifyscript <packagescript>\n\t\tChecks a packager script is valid without creating the resulting file\n\n");wprintf(L"\t--generatescript <package> [packagescript]\n\t\tCreates a packager script (.sps) from a spk file\n\n");wprintf(L"\t--extractship <modfile> <xspfile> [shipid]\n\t\tCreates an XSP ship file from a mod package\n\n");wprintf(L"\t--generateupdatefile <package>\n\t\tCreates an update file for the spk/xsp file\n\n");wprintf(L"\t--packagelist <filenames>\n\t\tThis will generate the update file to allow downloading packages from a server.\n\n");// printf ( "\t--convertxspwizard <oldxsp> [newxsp]\n\t\tConverts an old XSP file into the new format\n\n");}void Settings(const Utils::WString &filename, const Utils::WString &settings, int argc, char **argv, const Utils::WString &cmd){if ( settings.Compare(L"author") ){if ( argc < 5 ){wprintf(L"Syntax: %s -set <spkfile> Author <authorname>\n\tSets the authors name of the package\n", cmd.c_str() );return;}}else{wprintf(L"Error! Unknown settings: %s\n", settings.c_str());return;}// first chekc if file even existsFILE *id = _wfopen(filename.c_str(), L"rb+");if ( !id ){wprintf(L"Error: File, %s, doesn't exist\n", filename.c_str() );return;}fclose ( id );int check = CSpkFile::CheckFile(filename);if ( check == SPKFILE_SINGLE ){CSpkFile spkfile;wprintf(L"* Opening SPK File, %s...\n", filename.c_str());if ( !spkfile.readFile(filename, SPKREAD_ALL)){wprintf(L"Failed to open the spk files, %s\n", filename.c_str() );return;}// now do the settingsif ( settings.Compare(L"author") ){spkfile.setAuthor(Utils::WString::FromString(argv[4]));wprintf(L"Settings Author to: %s\n", spkfile.author().c_str());}spkfile.writeFile(filename);printf ( "\nSPK file has been written sucessfully\n" );}elsewprintf(L"File, %s, is not a valid SPK file\n", filename.c_str() );}void SetRating (const Utils::WString &filename, int ease, int changing, int rec ){if ( ease > 5 )ease = 5;if ( changing > 5 )changing = 5;if ( changing > 5 )changing = 5;FILE *id = _wfopen(filename.c_str(), L"rb+");if ( !id ){wprintf(L"Error: File, %s, doesn't exist\n", filename.c_str() );return;}fclose ( id );int check = CSpkFile::CheckFile(filename);if ( check == SPKFILE_SINGLE ){CSpkFile spkfile;wprintf(L"* Opening SPK File, %s...\n", filename.c_str() );if ( !spkfile.readFile(filename, SPKREAD_ALL)){wprintf(L"Failed to open the spk files, %s\n", filename.c_str() );return;}wprintf(L"File Format Version: %.2f\n", spkfile.fileVersion());wprintf(L"Assigning Ease Of Use:\t\t%d\nAssigning Game Changing:\t%d\nAssigning Recommended:\t\t%d\n", ease, changing, rec);spkfile.setEaseOfUse(ease);spkfile.setGameChanging(changing);spkfile.setRecommended(rec);spkfile.writeFile(filename);wprintf(L"\nSPK file has been written sucessfully\n" );}elsewprintf(L"File, %s, is not a valid SPK file\n", filename.c_str() );}Utils::WString GetTerranConflictDir(){while ( true ){printf ( "\nPlease enter the directory for terran conflict: ");Utils::WString dir = GetInput();if ( dir.empty() )return Utils::WString::Null();// check if the directory existsif ( CFileIO::Exists(dir + L"/x3tc.exe") )return dir;wprintf(L"\nTerran Conflict installation doesn't exist: %s\n\n", dir.c_str());}return Utils::WString::Null();}void ConvertXsp(const Utils::WString &filename, const Utils::WString &tofile, bool wizard){// first chekc if file even existsFILE *id = _wfopen (filename.c_str(), L"rb+" );if ( !id ){wprintf(L"Error: File, %s, doesn't exist\n", filename.c_str() );return;}fclose ( id );// check its not a new format alreadyint check = CSpkFile::CheckFile(filename);if ( check == SPKFILE_INVALID && CFileIO(filename).isFileExtension(L"xsp") ){wprintf(L"* Converting XSP File, %s... ", filename.c_str() );CXspFile xspFile;if ( !xspFile.convertOld(filename) ){wprintf(L"[ERROR]\n\nFailed to convert old xsp file, %s\n", filename.c_str() );return;}printf ( "[DONE]\n");Utils::WString dir;printf ("Do you want to create weapon masks for Terran conflict? ");Utils::WString input = GetInput();if ( input.Compare(L"y") || input.Compare(L"yes") ){dir = GetTerranConflictDir();if (!dir.empty()){}}wprintf(L"* Writing XSP File, %s... ", tofile.c_str());// now we need to save itif ( !xspFile.writeFile(tofile) )wprintf(L"[ERROR]\n\nFailed to write file to, %s\n", tofile.c_str() );elsewprintf(L"[DONE]\n\nFile: %s, has been converted to, %s\n", filename.c_str(), tofile.c_str() );}elsewprintf(L"Error: File, %s, is not an old style XSP file\n", filename.c_str() );}void ExtractShip(const Utils::WString &catfile, const Utils::WString &to, Utils::WString shipid){if ( !CFileIO::Exists(catfile) ){wprintf(L"Error: Mod File, %s, does not exist\n", catfile.c_str());return;}CVirtualFileSystem *pVfs = new CVirtualFileSystem();if ( !pVfs->loadMod(catfile) ) {wprintf(L"Error: Unable to read mod file, %s\n", catfile.c_str());delete pVfs;return;}Utils::WStringList *ships = pVfs->getTShipsEntries();if ( !ships ){wprintf(L"Error: Failed to read %s::types\\TShips.pck\n", catfile.c_str());delete pVfs;return;}// now get the ship line to extractUtils::WString tShipsLine;if (shipid.empty()){// no ship id, lets get oneUtils::WString ids[2];int i = 0;int id = 0;for ( Utils::WStringNode *str = ships->first(); str; str = ships->next() ){ids[i++] = str->data;if ( i >= 2 ){wprintf(L"[%3d][%30s]\t[%3d][%30s]\n", id - 1, ids[0].c_str(), id, ids[1].c_str());for ( i = 0; i < 2; i++ )ids[i] = L"";i = 0;}++id;}if ( i == 1 )wprintf(L"[%3d][%30s]\n", id, ids[0].c_str());printf("Enter ID to use > ");shipid = GetInput();if ( shipid.isNumber() )tShipsLine = ships->get(shipid.toInt())->str;elsetShipsLine = ships->findData(shipid, true);}elseships->findData(shipid, true);if ( tShipsLine.empty() ){wprintf(L"Error, %s is not a valid ship id to use\n", shipid.c_str());delete pVfs;return;}// now we have the tships to use, lets start to extract the shipwprintf(L"Extracting ship from %s, Ship=%s\n", catfile.c_str(), tShipsLine.token(L";", -2).c_str());CXspFile ship;if ( ship.extractShip(pVfs, tShipsLine.token(L";", -2).toString(), 0)){printf ( "Ship has been successfully extracted\n" );printf("\t- Models:\t %d\n", ship.countFiles(FILETYPE_SHIPMODEL));printf("\t- Textures:\t %d\n", ship.countFiles(FILETYPE_SHIPOTHER));printf("\t- Dummies:\t %d\n", ship.GetDummies()->size());printf("\t- Components:\t %d\n", ship.GetComponents()->size());printf("\t- Bodies:\t %d\n", ship.getBodies().size());printf("\t- Cockpits:\t %d\n", ship.GetCockpits()->size());printf("\t- Text Entries:\t %d\n", ship.GetTexts()->size());printf("\nEnter the name for the ship: ");ship.setName(GetInput().toString());printf("Enter the author for the ship: ");ship.setAuthor(GetInput().toString());printf("Enter the version for the ship: V");ship.setVersion(GetInput().toString());printf("Enter the description for the ship: ");ship.setDescription(GetInput().toString());struct tm *currDate;char dateString[100];time_t now = time(NULL);currDate = localtime( &now );strftime(dateString, sizeof dateString, "%d/%m/%Y", currDate);ship.setCreationDate(Utils::WString::FromString(dateString));wprintf(L"\nWriting file: %s...\n", to.c_str());if ( ship.writeFile(to) )wprintf(L"Ship file has been created: %s\n", to.c_str());elsewprintf(L"Error: Unable to write ship file, %s\n", to.c_str());}elsewprintf(L"Error: Unable to extract the ship\n");delete pVfs;}Utils::WString GetGameName(int game){switch(game){case GAME_X2:return L"X2: The Threat";case GAME_X3:return L"X3: Reunion";case GAME_X3TC:return L"X3: Terran Conflict";case GAME_X3AP:return L"X3: Albion Prelude";case GAME_X3FL:return L"X3: Farnham's Legacy";}return L"Unknown";}void DisplayVersion(const Utils::WString &filename){// first chekc if file even existsFILE *id = _wfopen(filename.c_str(), L"rb+");if ( !id ){wprintf(L"Error: File, %s, doesn't exist\n", filename.c_str());return;}fclose ( id );bool read = false;CBaseFile *pBaseFile = NULL;int check = CSpkFile::CheckFile ( filename );if ( check == SPKFILE_BASE ){pBaseFile = new CBaseFile();wprintf(L"* Opening SPK File, %s...\n", filename.c_str() );if ( !pBaseFile->readFile(filename, SPKREAD_NODATA)){wprintf(L"Failed to open the spk files, %s\n", filename.c_str() );return;}read = true;}else if ( check == SPKFILE_SINGLE ){pBaseFile = (CBaseFile *)new CSpkFile();wprintf(L"* Opening SPK File, %s...\n", filename.c_str() );if ( !pBaseFile->readFile(filename, SPKREAD_NODATA)){wprintf(L"Failed to open the spk files, %s\n", filename.c_str() );return;}read = true;}else if ( check == SPKFILE_SINGLESHIP ){pBaseFile = (CBaseFile *)new CXspFile();wprintf(L"* Opening XSP File, %s...\n", filename.c_str() );if ( !pBaseFile->readFile(filename, SPKREAD_NODATA)){wprintf(L"Failed to open the xsp files, %s\n", filename.c_str() );return;}read = true;}// otherwise its an old ship fileelse if ( CFileIO(filename).isFileExtension(L"xsp") ){wprintf(L"* Converting XSP File, %s...\n", filename.c_str() );pBaseFile = new CXspFile;if ( !((CXspFile *)pBaseFile)->convertOld(filename) ){delete pBaseFile;pBaseFile = NULL;wprintf(L"Failed to convert old xsp file, %s\n", filename.c_str() );return;}check = SPKFILE_SINGLESHIP;read = true;}if ( pBaseFile && read){CPackages p;p.startup(L".", L".", L".");CSpkFile *pSpkFile = NULL;CXspFile *pXspFile = NULL;if ( check == SPKFILE_SINGLE )pSpkFile = (CSpkFile *)pBaseFile;elsepXspFile = (CXspFile *)pBaseFile;wprintf(L"File Format Version: %.2f\n", pBaseFile->fileVersion());Utils::WString sType;if ( check == SPKFILE_SINGLESHIP )sType = L"Ship";elsesType = L"Package";wprintf(L"%s Name: %s\n", sType.c_str(), pBaseFile->name().c_str() );if ( !pBaseFile->email().empty() )wprintf(L"%s Author: %s (%s)\n", sType.c_str(), pBaseFile->author().c_str(), pBaseFile->email().c_str() );elsewprintf(L"%s Author: %s\n", sType.c_str(), pBaseFile->author().c_str() );if ( !pBaseFile->version().empty() ) wprintf(L"%s Version: %s\n", sType.c_str(), pBaseFile->version().c_str() );//for gameprintf("For Games: ");if ( !pBaseFile->AnyGameCompatability() )printf("All");elsewprintf(L"%s", p.getGameTypesString(pBaseFile, true).c_str());printf("\n");if ( pXspFile ){wprintf(L"Ship Display Name: %s\n", pXspFile->shipName(44).c_str());if ( pXspFile->IsExistingShip() )wprintf(L"Ship ID: %s (Replace Existing Ship)\n", pXspFile->shipID().c_str() );elsewprintf(L"Ship ID: %s\n", pXspFile->shipID().c_str() );if ( pXspFile->anyShipyards() ){printf ( "Add To Shipyards:\n" );for (unsigned long i = 1; i <= GetMaxShipyards(); i *= 2 ){if ( pXspFile->isShipyard(static_cast<ShipyardRace>(i)) )wprintf(L"\t%s\n", GetShipyardName(static_cast<ShipyardRace>(i)).c_str());}}for ( SWeaponMask *text = pXspFile->GetLaserMasks()->First(); text; text = pXspFile->GetLaserMasks()->Next() )wprintf(L"Laser Mask, Game: %s, Mask: %d\n", GetGameName(text->iGame).c_str(), text->iMask);for ( SWeaponMask *text = pXspFile->GetMissileMasks()->First(); text; text = pXspFile->GetMissileMasks()->Next() )wprintf(L"Missile Mask, Game: %s, Mask: %d\n", GetGameName(text->iGame).c_str(), text->iMask);if ( pXspFile->GetOriginalDescription() )wprintf(L"Use Existing Text, ID: %d\n", pXspFile->GetOriginalDescription());if ( pXspFile->AnyTexts() ){for ( SText *text = pXspFile->GetTexts()->First(); text; text = pXspFile->GetTexts()->Next() ){wprintf(L"Ship Text, Language: %d\n", text->iId);if ( !text->sName.empty() )wprintf(L"\tName: %s\n", text->sName.c_str());if ( !text->sDesc.empty() )wprintf(L"\tDescription: %s\n", text->sDesc.c_str());}}if ( pXspFile->AnyComponents() ){wprintf(L"Component Entries:\n" );for ( SComponent *c = pXspFile->GetComponents()->First(); c; c = pXspFile->GetComponents()->Next() )wprintf(L"\t%s\n\t\t%s\n\t\t\t%s\n", c->sSection.c_str(), c->sSection2.c_str(), c->sData.c_str());}if ( pXspFile->AnyDummies() ){wprintf(L"Dummy Entries:\n" );for ( SDummy *d = pXspFile->GetDummies()->First(); d; d = pXspFile->GetDummies()->Next() )wprintf(L"\t%s\n\t\t%s\n", d->sSection.c_str(), d->sData.c_str());}if ( pXspFile->AnyCockpits() ){wprintf(L"Cockpit Entries:\n" );for ( SCockpit *c = pXspFile->GetCockpits()->First(); c; c = pXspFile->GetCockpits()->Next() )wprintf(L"\t%s\n", c->sCockpit.c_str());}if ( pXspFile->anyCutData() ){wprintf(L"CutData Entries [%d]:\n", pXspFile->getCutData().size() );for(auto itr = pXspFile->getCutData().begin(); itr != pXspFile->getCutData().end(); itr++)wprintf(L"\t%s\n", (*itr)->str.c_str());}}if ( !pBaseFile->creationDate().empty() ) wprintf(L"Creation Date: %s\n", pBaseFile->creationDate().c_str() );if ( !pBaseFile->description().empty() ) wprintf(L"Description: %s\n", pBaseFile->description().c_str() );if ( pSpkFile ){if ( pSpkFile->IsLibrary() )printf ( "Script Type: Library\n" );else if ( pSpkFile->IsPatch() )printf ( "Script Type: Patch Mod\n" );else if ( pSpkFile->IsCustomStart() )printf ( "Script Type: Custom Start\n" );else if ( pSpkFile->IsPackageUpdate() )printf ( "Script Type: Package Update\n" );else if ( !pSpkFile->scriptTypeString(44).empty() )wprintf(L"Script Type: %s\n", pSpkFile->scriptTypeString(44).c_str() );if ( !pSpkFile->GetWaresList()->empty() ){for ( CListNode<SWares> * wNode = pSpkFile->GetWaresList()->Front(); wNode; wNode = wNode->next() ){SWares *w = wNode->Data();wprintf (L"Ware: (%c) %s\n", w->cType, CSpkFile::GetWareText(w, 44).c_str() );Utils::WString desc = CSpkFile::GetWareDesc(w, 44);if (!desc.empty())wprintf(L"\tDescription: %s\n", desc.c_str() );}}}if ( !pBaseFile->forumLink().empty() ) wprintf(L"Forum Link: %s\n", pBaseFile->forumLink().c_str() );if ( !pBaseFile->webSite().empty() ) wprintf(L"Web Site Address: %s\n", pBaseFile->webSite().c_str() );if ( !pBaseFile->webAddress().empty() ) wprintf(L"Update Address: %s\n", pBaseFile->webAddress().c_str() );if ( pBaseFile->anyWebMirrors() ){printf("Update Mirror Addresses:\n");for (size_t i = 0; i < pBaseFile->getMaxWebMirrors(); i++ )wprintf(L"\t%s\n", pBaseFile->getWebMirror(i).c_str());}if ( pSpkFile ){if ( (!pSpkFile->otherName().empty()) && (!pSpkFile->otherAuthor().empty()) )wprintf(L"Script is a child to the mod: %s by %s\n", pSpkFile->otherName().c_str(), pSpkFile->otherAuthor().c_str() );}if ( pBaseFile->AnyDependacies() ){printf ( "Required Dependacies:\n" );for ( SNeededLibrary *needed = pBaseFile->GetNeededLibraries()->First(); needed; needed = pBaseFile->GetNeededLibraries()->Next() )wprintf(L"\t%s by %s (Minimum Version=%s)\n", needed->sName.c_str(), needed->sAuthor.c_str(), needed->sMinVersion.c_str() );}if ( pBaseFile->easeOfUse() != -1 ) printf ( "Ease Of Use Rating: %d\n", pBaseFile->easeOfUse() );if ( pBaseFile->gameChanging() != -1 ) printf ( "Game Changing Rating: %d\n", pBaseFile->gameChanging() );if ( pBaseFile->recommended() != -1 ) printf ( "Recommendation Rating: %d\n", pBaseFile->recommended() );if (pBaseFile->icon())wprintf(L"Icon File Found, Type: %s, Size: %s\n", pBaseFile->iconExt().c_str(), pBaseFile->icon()->dataSizeString().c_str() );if ( pBaseFile->GetFileList()->size() ){printf("\nListing files in package:\n");CLinkList<C_File> *list = pBaseFile->GetFileList();for (unsigned int game = 0; game < 31; ++game){bool heading = true;for (C_File *file = list->First(); file; file = list->Next()){bool display = false;if (game == 0 && (!file->game() || file->game() == GAME_ALLNEW))display = true;if (game > 0 && file->game() & (1 << game))display = true;if (display){if (heading){Utils::WString sGame = p.GetGameExe()->gameNameFromType(game - 1);wprintf(L"\tGame: %s\n", sGame.c_str());heading = false;}wprintf(L"\t\t%s (%s) Size: %s\n", file->getNameDirectory(pBaseFile).c_str(), file->fileTypeString().c_str(), file->dataSizeString().c_str());}}}}elseprintf ( "\nThere are currently no files in the package\n" );}else if ( check == SPKFILE_MULTI ){CMultiSpkFile spkfile;wprintf(L"* Opening Multi-SPK file, %s...\n", filename.c_str() );if ( !pBaseFile->readFile(filename, false)){wprintf(L"Error: Failed to open the Multi-SPK file, %s\n", filename.c_str() );return;}wprintf(L"Multi Package Name: %s\n", spkfile.name().c_str() );wprintf(L"Selection Mode: " );if (spkfile.isSelection ())wprintf(L"On\n" );elsewprintf(L"Off\n" );CLinkList<SMultiSpkFile> *list = spkfile.GetFileList();for ( SMultiSpkFile *ms = list->First(); ms; ms = list->Next() ){wprintf(L"File, %s:\n", ms->sName.c_str() );wprintf(L"\tSize: %s\n", SPK::GetSizeString (ms->lSize).c_str() );if ( (!ms->sScriptName.empty()) && (!ms->sScriptAuthor.empty()) )wprintf(L"\tScript: %s %s by %s\n", ms->sScriptName.c_str(), ms->sScriptVersion.c_str(), ms->sScriptAuthor.c_str() );wprintf(L"\tDefault Install: " );if ( ms->bOn )wprintf(L"Yes\n" );elsewprintf(L"No\n" );}}elsewprintf(L"File, %s, is not a valid SPK file\n", filename.c_str() );if ( pBaseFile )delete pBaseFile;}void AppendFile (const Utils::WString &sfile, const Utils::WString &type, const Utils::WString &addfile ){int t = GetFileTypeFromString(type);if ( t == -1 ){wprintf(L"The file type \"%s\" is invalid\n", type.c_str());return;}int check = CSpkFile::CheckFile(sfile);CBaseFile *pBaseFile = 0;if ( check == SPKFILE_SINGLE )pBaseFile = new CSpkFile();else if ( check == SPKFILE_SINGLESHIP )pBaseFile = new CXspFile();else if ( check == SPKFILE_BASE )pBaseFile = new CBaseFile();if ( !pBaseFile ){wprintf(L"Error: Invalid file format, unable to open\n");return;}wprintf(L"Opening File, %s... ", sfile.c_str());if ( !pBaseFile->readFile(sfile)){wprintf(L"(Error)\nUnable to open the file, %s\n", sfile.c_str());return;}wprintf(L"(Done)\n" );MyProgress progress(0);wprintf(L"Adding file %s to package\n\t>", addfile.c_str() );if ( pBaseFile->appendFile(addfile, t, 0, false, Utils::WString::Null(), &progress)){progress.PrintDone();wprintf(L"< (Done)\n");pBaseFile->writeFile(sfile);wprintf(L"\nFile has been written sucessfully\n");}elsewprintf(L"< (Error)\n");}void RemoveFile(const Utils::WString &sfile, const Utils::WString &type, const Utils::WString &addfile){FILE *id = _wfopen(sfile.c_str(), L"rb+");if ( !id ){wprintf(L"Error: File, %s, doesn't exist\n", sfile.c_str() );return;}if ( addfile.empty() ){wprintf(L"Error: Remove filename is invalid\n" );return;}FileType t = GetFileTypeFromString(type);if (t == FileType::FILETYPE_UNKNOWN){wprintf(L"The file type \"%s\" is invalid\n", type.c_str() );return;}int check = CSpkFile::CheckFile(sfile);CBaseFile *pBaseFile = 0;if ( check == SPKFILE_SINGLE )pBaseFile = new CSpkFile();else if ( check == SPKFILE_SINGLESHIP )pBaseFile = new CXspFile();else if ( check == SPKFILE_BASE )pBaseFile = new CBaseFile();if ( pBaseFile ){wprintf(L"Opening File, %s... ", sfile.c_str());if ( !pBaseFile->readFile(sfile)){wprintf(L"(Error)\nUnable to open the file, %s\n", sfile.c_str());return;}wprintf(L"(Done)\n");wprintf(L"Removing file, %s, from Package\n", addfile.c_str());if(pBaseFile->removeFile(addfile, t)){wprintf(L"File, %s, has been remove from package\n", addfile.c_str() );pBaseFile->writeFile(sfile);wprintf(L"File has been written to disk successfully\n" );}elsewprintf(L"Unable to remove the file, %s, from the package\n", addfile.c_str());}else if ( check == SPKFILE_MULTI ){CMultiSpkFile spkfile;wprintf(L"Opening Multi-SPK file, %s...", sfile.c_str());if ( !spkfile.readFile(sfile)){wprintf(L"(Error)\nUnable to open the Multi-SPK file, %s\n", sfile.c_str());return;}wprintf(L"(Done)\n");const SMultiSpkFile *ms = spkfile.findFile(type);if ( !ms ){wprintf(L"Unable to find the file \"%s\" in the package\n", type.c_str());return;}wprintf(L"Removing file, %s, from Package\n", addfile.c_str());if (!spkfile.removeFile(ms)){wprintf(L"Error: Unable to remove file, %s, from package\n", type.c_str());return;}wprintf(L"Writing SPK File, %s... ", sfile.c_str());if (spkfile.writeFile(sfile))wprintf(L"(Done)\n");elsewprintf(L"(Error)\n");}elsewprintf(L"Error: Invalid file format, unable to open\n");}void CreateMultiFile (const Utils::WString &filename){wprintf(L"* Creating new Multi-SPK File, %s\n\n", filename.c_str());FILE *id = _wfopen(filename.c_str(), L"rb+");if ( id ){fclose ( id );wprintf(L"* File already exists, unable to create\n");return;}id = _wfopen(filename.c_str(), L"wb");if ( !id ){wprintf(L"* Unable to open file for writing\n");return;}fclose(id);_wremove(filename.c_str());CMultiSpkFile spkfile;Utils::WString sInput;wprintf(L"Enter Multi-Spk Package Name: ");spkfile.setName(GetInput());while ( true ){wprintf(L"\nDo you want users to select scripts to install? (Y/N): " );Utils::WString i = GetInput();i = i.upper();if ( i == L"Y" )spkfile.setSelection(true);if ( (i == L"Y") || (i == L"N") )break;}while ( true ){wprintf(L"\nEnter Spk File to add (Enter \"0\" to finish): " );sInput = GetInput();if ( sInput == L"0" )break;// check if file can be openedFILE *id2 = _wfopen(sInput.c_str(), L"rb+");if ( !id2 )wprintf(L"Error: Unable to open SPK file %s\n", sInput.c_str() );else{fclose(id2);if ( !spkfile.addFile(sInput))wprintf(L"Error: Unable to add SPK file to package\n");elsewprintf(L"File Added to package (%s)\n", sInput.c_str());}}if ( spkfile.numFiles() < 1 )wprintf(L"\nError: You have added no files, you must add at least one file to create a package\n");else{wprintf(L"Writing MultiSpk file... ");if ( spkfile.writeFile(filename))wprintf(L"(Done)\n" );elsewprintf(L"(Error)\n" );}}void CreateFile(const Utils::WString &filename){wprintf(L"* Creating new SPK File, %s\n\n", filename.c_str());FILE *id = _wfopen(filename.c_str(), L"rb+");if ( id ){fclose(id);wprintf(L"* File already exists, unable to create\n");return;}id = _wfopen(filename.c_str(), L"wb");if ( !id ){wprintf(L"* Unable to open file for writing\n");return;}fclose(id);_wremove(filename.c_str());CSpkFile spkfile;wprintf(L"Enter Script Name: ");spkfile.setName(GetInput());wprintf(L"Enter Script Author: ");spkfile.setAuthor(GetInput());wprintf(L"Enter Script Version: ");spkfile.setVersion(GetInput());wprintf(L"Enter Script Description: ");spkfile.setDescription(GetInput());struct tm *currDate;char dateString[100];time_t now = time(NULL);currDate = localtime( &now );strftime(dateString, sizeof dateString, "%d %m %Y", currDate);spkfile.setCreationDate(Utils::WString::FromString(dateString));spkfile.writeFile(filename, NULL);wprintf(L"SPK file has been written to disk: %s\n", filename.c_str() );}void ExtractFiles (const Utils::WString &sfile, const Utils::WString &dir, int game ){// First checks if the file exists by opening itFILE *id = _wfopen(sfile.c_str(), L"rb+");if ( !id ){wprintf(L"Error: File, %s, doesn't exist\n", sfile.c_str() );return;}fclose ( id );CPackages packages;packages.startup(L".", L".", L".");int check = CSpkFile::CheckFile ( sfile );// extracts a file from single packages fileif ( check == SPKFILE_SINGLE || check == SPKFILE_BASE || check == SPKFILE_SINGLESHIP ){// creates the spkfile objectCBaseFile *pBaseFile = 0;if ( check == SPKFILE_SINGLE )pBaseFile = (CBaseFile *)new CSpkFile();else if ( check == SPKFILE_SINGLESHIP )pBaseFile = (CBaseFile *)new CXspFile();elsepBaseFile = new CBaseFile();wprintf(L"Opening File, %s... ", sfile.c_str());// reads the file into memory// the SPKREAD_NODATA flag causes it to just read the settings, and skips the file dataif ( !pBaseFile->readFile(sfile, SPKREAD_NODATA)){wprintf(L"(Error)\nUnable to open the file, %s\n", sfile.c_str() );return;}wprintf(L"(Done)\n");if(game == 0)wprintf(L"Extracting all files from archive...\n\n");elsewprintf(L"Extracting %s files from archive...\n\n", packages.GetGameExe()->gameNameFromType(game - 1).c_str());CFileProgress info(&packages, pBaseFile, "Extracting");if (packages.extractAll(pBaseFile, dir, game, true, &info) )wprintf(L"\n(Done)\nFiles have been extracted successfully\n");elsewprintf(L"\n(Error)\nThere was a problem extracting the files\n");}elsewprintf(L"Invalid package file, %s\n", sfile.c_str());}/*Func: AppendMultiFileArgs: String toFile - The spk file to append ontoString addfile - The spk file to appendDesc: Appends a spk file into a Multi-Spk ArchiveIf toFile is a single spk file, it will be converted to a Multi-Spk Fileif addfile is a Multi-Spk file, all files from it will be appended*/void AppendMultiFile(const Utils::WString &toFile, const Utils::WString &addfile){// create destination objectCMultiSpkFile spkfile;// checks the destinationint checkto = CSpkFile::CheckFile(toFile);// if the destination is a single file, then convert it to a Multi-Spk packageif ( checkto == SPKFILE_SINGLE ){// adds the single file to the Multi-Spk object// Add file also reads it into memoryif ( !spkfile.addFile(toFile)){wprintf(L"Error: Unable to create Multi-Spk file\n");return;}}else{// if its already a multispk file, then simply open it and read it to memoryif ( !spkfile.readFile(toFile)){wprintf(L"Error: Unable to open Multi-Spk file, %s\n", toFile.c_str());return;}}// now add the file into the Multi-Spk Object// the AddFile function will handle both single and Multi-Spk files// So you dont need to test what the appending file isif ( spkfile.addFile(addfile)){// if it added correctly, then simply write the new Multi-Spk Object to diskwprintf(L"File, %s, has been added to Multi-Spk Package\n", addfile.c_str());wprintf(L"Saving Multi-Spk File: %s... ", toFile.c_str());if ( spkfile.writeFile(toFile))wprintf(L"(Done)\n");elsewprintf(L"(Error)\n");}elsewprintf(L"Error: Unable to add files, %s, to Multi-Spk Package\n", addfile.c_str());}/*Func: ExtractFileArgs: String sfile - the spk file to read fromString type - the type of the file to findString addfile - The filename to extractString dir - The directory to extract toDesc: Finds and extracts a file from a Spk Package*/void ExtractFile (const Utils::WString &sfile, const Utils::WString &type, const Utils::WString &addfile, const Utils::WString &dir){// First checks if the file exists by opening itFILE *id = _wfopen(sfile.c_str(), L"rb+");if ( !id ){wprintf(L"Error: File, %s, doesn't exist\n", sfile.c_str());return;}fclose ( id );// now check the type of file it is, using the static function CheckFile(filename).// This will return the type of file// SPK_INVALID - Invalid file format, wont be able to open// SPK_SINGLE - A Single spk package file// SPK_MULTI - A Multi-Spk Archive// SPK_BASE - A Base File// SPK_SINGLESHIP - A Ship fileint check = CSpkFile::CheckFile ( sfile );// extracts a file from single packages fileif ( check == SPKFILE_SINGLE || check == SPKFILE_BASE || check == SPKFILE_SINGLESHIP ){// first get the file type is valid// converts the string type into its filetype flagFileType t = GetFileTypeFromString(type);// incorrect text type, display the errorif (t == FileType::FILETYPE_UNKNOWN){wprintf(L"The file type \"%s\" is invalid\n", type.c_str());return;}// creates the spkfile objectCBaseFile *pBaseFile = 0;if ( check == SPKFILE_SINGLE )pBaseFile = (CBaseFile *)new CSpkFile();else if ( check == SPKFILE_SINGLESHIP )pBaseFile = (CBaseFile *)new CXspFile();elsepBaseFile = new CBaseFile();wprintf(L"Opening File, %s... ", sfile.c_str());// reads the file into memory// the SPKREAD_NODATA flag causes it to just read the settings, and skips the file dataif ( !pBaseFile->readFile(sfile, SPKREAD_NODATA)){wprintf(L"(Error)\nUnable to open the file, %s\n", sfile.c_str());return;}// No read all the file data into memory// This can be done all together in the ReadFile function// Doing it seperatly allows you to save time if an error occurs, so you dont have to wait for it to read the whole thingpBaseFile->ReadAllFilesToMemory ();wprintf(L"(Done)\n");// uses the FindFile function to find the selected file in the archive// requires the filename, type and custom directory (only for Extra File Type)C_File *f = pBaseFile->findFile(addfile, t);if ( !f ){wprintf(L"Unable to find the file \"%s\" in the package\n", addfile.c_str());return;}// creates the directory so it can be extractedCDirIO Dir(dir);if ( !Dir.create(f->getDirectory(pBaseFile)) ){wprintf(L"Unable to create the directory \"%s\" to extract into\n", dir.c_str());return;}// sets up the progress pointer// if it uses 7zip, the progress will be displayed in the command promptMyProgress progress(0);wprintf(L"Extracting the file from package\n\t>");// Extracts the file to the specified directoryif ( !pBaseFile->extractFile(f, dir, true, &progress))wprintf(L"< (Error)\nUnable to extract the file\n");else{progress.PrintDone ();wprintf(L"< (Done)\nFile has been extracted successfully\n");}}// the file is a Multi-Spk File, extracts a single spk file from the archiveelse if ( check == SPKFILE_MULTI ){// creates MultiSpkFile objectCMultiSpkFile spkfile;wprintf(L"Opening Multi-SPK file, %s...", sfile.c_str());// reads the MultiSpkFile into memoryif ( !spkfile.readFile(sfile)){wprintf(L"(Error)\nUnable to open the Multi-SPK file, %s\n", sfile.c_str());return;}wprintf(L"(Done)\n");// searchs the archive for a matching fileconst SMultiSpkFile *ms = spkfile.findFile(type);if ( !ms ){wprintf(L"Unable to find the file \"%s\" in the package\n", type.c_str());return;}// extracts the file from the archive, to the given directorywprintf(L"Extracting SPK file, %s, from package... ", ms->sName.c_str());if (spkfile.extractFile(ms, addfile))wprintf(L"(Done)\n");elsewprintf(L"(Error)\n");}elsewprintf(L"Error: Invalid file format, unable to open\n");}/*Func: SplitMultiArgs: String filename - the filename of the multispk file to openString dest - The destination directory to extract the files toDesc: Splits a multi-spk file into its seperate spk files*/void SplitMulti(const Utils::WString &filename, const Utils::WString &dest){// Check the file type, Must return SPKFILE_MULTI, otherwise its not a Multi-Spk Packagesif ( CSpkFile::CheckFile(filename) != SPKFILE_MULTI ){wprintf(L"Error: The file is not a Multi-Spk packages\n");return;}wprintf(L"Spliting Multi-SPK File to, %s... ", dest.c_str());// create the MultiSpkFile objectCMultiSpkFile spkfile;// Splits the files to the destinationif ( !spkfile.splitMulti(filename, dest)){wprintf(L"(Error)\nUnable to split Multi-SPK package, %s\n", filename.c_str());return;}wprintf(L"(Done)\n");}Utils::WString GetAsk(const Utils::WString &command){wprintf(L"(ASK) Enter the value for, %s: ", command.c_str());return GetInput();}void GenerateUpdateList(int argc, char **argv){Utils::WString currentDir = CFileIO(Utils::WString::FromString(argv[0])).dir();CDirIO Dir(currentDir);Utils::WStringList list;for (int i = 2; i < argc; ++i){Utils::WString file(argv[i]);if (CFileIO::Exists(file))list.pushBack(file, L"file");else if (CFileIO::Exists(Dir.file(file)))list.pushBack(Dir.file(file), L"file");else if (CDirIO::Exists(file))list.pushBack(file, L"dir");else if (CDirIO::Exists(Dir.dir(file)))list.pushBack(Dir.dir(file), L"dir");elselist.pushBack(file, L"pattern");}if (list.empty())wprintf(L"unable to find any packages");else{Utils::WStringList fileList;for (auto itr = list.begin(); itr != list.end(); itr++){Utils::WString file = (*itr)->str;Utils::WString data = (*itr)->data;if (data == L"file")fileList.pushBack(file);else if (data == L"dir"){CDirIO dir(file);Utils::WStringList d;if (dir.dirList(d)){for (auto itr2 = d.begin(); itr2 != d.end(); itr2++){Utils::WString ext = CFileIO((*itr2)->str).extension().lower();if(ext == L"xsp" || ext == L"spk")fileList.pushBack(dir.file((*itr2)->str));}}}else if (data == L"pattern"){CFileIO f(file);CDirIO dir(f.dir());if (!dir.exists())dir = CDirIO(Dir.dir(dir.dir()));Utils::WStringList d;if (dir.dirList(d, Utils::WString::Null(), f.filename())){for (auto itr2 = d.begin(); itr2 != d.end(); itr2++){Utils::WString ext = CFileIO((*itr2)->str).extension().lower();if (ext == L"xsp" || ext == L"spk")fileList.pushBack(dir.file((*itr2)->str));}}}}if (fileList.empty())wprintf(L"unable to find any packages");else{CPackages packages;Utils::WStringList filedata;for (auto itr = fileList.begin(); itr != fileList.end(); itr++){wprintf(L"Reading file: %s\n", (*itr)->str.c_str());int error = 0;CBaseFile *p = packages.openPackage((*itr)->str.toString(), &error, 0, SPKREAD_NODATA);if (!p){printf("\tERROR!\n");continue;}wprintf(L"\tData extracted: %s %s by %s\n", p->name().c_str(), p->version().c_str(), p->author().c_str());if (!p->creationDate().empty())wprintf(L"\t\tCreated: %s\n", p->creationDate().c_str());if(!p->description().empty())wprintf(L"\t\t%s\n", p->description().c_str());filedata.pushBack(CPackages::FormatAvailablePackageData(p));delete p;}if (filedata.empty())wprintf(L"unable to find any packages");else{Utils::WString dest = Dir.file(L"xpackagedata.dat");if (CFileIO(dest).writeFile(&filedata))wprintf(L"web update file, xpackagedata.dat, generated");elsewprintf(L"unable to write update file");}}}}void GenerateUpdateFile(const Utils::WString &spkfile){if (!CFileIO::Exists(spkfile)){wprintf(L"Error: The package file, %s, does not exist", spkfile.c_str());return;}int check = CSpkFile::CheckFile(spkfile);if ( check == SPKFILE_MULTI ){wprintf(L"Error: Multi-Package files currently not supported\n");return;}else if ( check == SPKFILE_OLD ){wprintf(L"Error: unable to read old format spk file, try spkconvert first\n");return;}else if ( check == SPKFILE_INVALID ){wprintf(L"Error: %s doesn't appear to be a valid package file\n", spkfile.c_str());return;}CPackages p;int error;CBaseFile *package = p.openPackage(spkfile, &error, 0, SPKREAD_NODATA);if ( !package ){wprintf(L"Error: unable to open package file, %s, Error=%d\n", spkfile.c_str(), error);return;}Utils::WString file = package->createUpdateFile(CFileIO(spkfile).dir());if ( file.empty() )wprintf(L"Error: unable to create update file for: %s, Directory=%s\n", spkfile.c_str(), CFileIO(spkfile).dir().c_str());elsewprintf(L"Update file: %s has been created for package, %s\n", file.c_str(), spkfile.c_str());delete package;}void GeneratePackagerScript(const Utils::WString &spkfile, Utils::WString toFile, int game){if (!CFileIO::Exists(spkfile)){wprintf(L"Error: The package file, %s, does not exist", spkfile.c_str());return;}int check = CSpkFile::CheckFile(spkfile);if ( check == SPKFILE_MULTI ){wprintf(L"Error: Cant generate a script from a multi-spk file\n");return;}else if ( check == SPKFILE_OLD ){wprintf(L"Error: unable to read old format spk file, try spkconvert first\n");return;}else if ( check == SPKFILE_INVALID ){wprintf(L"Error: %s doesn't appear to be a spk file\n", spkfile.c_str());return;}CPackages p;p.startup(L".", L".", L".");int error;CBaseFile *package = p.openPackage(spkfile, &error, 0, SPKREAD_NODATA);if ( !package ){wprintf(L"Error: unable to open package files, %s, Error=%d\n", spkfile.c_str(), error);return;}Utils::WStringList list;if ( !p.generatePackagerScript(package, true, &list, game) ){wprintf(L"Error: Unable to generate packager script\n");return;}if ( toFile.empty() )toFile = CFileIO(spkfile).GetDirIO().file(package->name() + L"_" + package->author() + L".sps");// save package fileif ( CFileIO(toFile).writeFile(&list) )wprintf(L"Packager script, %s, has been geenrated\n", toFile.c_str());elsewprintf(L"Error: unable to write packager script, %s\n", toFile.c_str());delete package;}/*Func: LoadPackagerScriptArgs: String filename - The filename of the packager script to loadDesc: Loads the packager scripts and creates a spk/xsp file from it*/void LoadPackagerScript(const Utils::WString &filename, bool verify){if ( !CFileIO::Exists(filename) ){wprintf(L"Error: The packager script, %s, does not exist", filename.c_str());return;}Utils::WString myDoc;#ifdef _WIN32TCHAR pszPath[MAX_PATH];if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, pszPath))){myDoc = (char *)pszPath;}#endifif ( verify )wprintf(L"Verifying Packager Script: %s\n", filename.c_str());CPackages p;p.startup(L".", L".", myDoc);Utils::WStringList malformed, unknown;Utils::WString curDir = CFileIO(filename).dir();if ( curDir.empty() ) curDir = L"./";Utils::WStringList variables;variables.pushBack(L"$PATH", curDir);CFileProgress info(&p, NULL, "Adding File");CBaseFile *package = p.loadPackagerScript(filename, -1, (verify) ? NULL : &GetAsk, &malformed, &unknown, &variables, &info);printf("\n");if ( verify ){if ( !malformed.empty() ){printf("Malformed Lines (%d):\n", malformed.size());for(auto itr = malformed.begin(); itr != malformed.end(); itr++)wprintf(L"\t(Line %3d) %s\n", (*itr)->data.toInt(), (*itr)->str.c_str());}if ( !unknown.empty() ){printf("Unknown Commands (%d):\n", unknown.size());for (auto itr = unknown.begin(); itr != unknown.end(); itr++)wprintf(L"\t* Command: %s = %s\n", (*itr)->str.c_str(), (*itr)->data.c_str());}}if ( !package ){if ( verify )printf("Error: There are errors in the packager script which prevents it from being created\n");elsewprintf(L"Error: Unable to create package, from script: %s\n", filename.c_str());}else{Utils::WString saveto = package->filename();saveto = saveto.findReplace(L"$DEFAULTDIR", curDir + L"/");saveto = saveto.findReplace(L"$PATH", curDir);saveto = saveto.findReplace(L"\\", L"/");saveto = saveto.findReplace(L"//", L"/");if ( !saveto.right(4).Compare(L".spk") && package->GetType() != TYPE_XSP )saveto += L".spk";else if ( !saveto.right(4).Compare(L".xsp") && package->GetType() == TYPE_XSP )saveto += L".xsp";wprintf(L"Saving file to: %s\n", CFileIO(saveto).fullFilename().c_str());if ( verify )printf("Package can be created from this script\n");else{// write scriptif ( package->writeFile(saveto.toString()) ){if ( package->AutoGenerateUpdateFile() )package->createUpdateFile(CFileIO(saveto).dir());wprintf(L"Package: %s was created\n", saveto.c_str());}elseprintf("Error! There was a problem writing the package\n");}saveto = package->exportFilename();if ( !saveto.empty() ) {saveto = saveto.findReplace(L"$DEFAULTDIR", curDir + L"/");saveto = saveto.findReplace(L"$PATH", curDir);saveto = saveto.findReplace(L"\\", L"/");saveto = saveto.findReplace(L"//", L"/");wprintf(L"Exporting file to: %s\n", CFileIO(saveto).fullFilename().c_str());if ( verify )printf("Package can be exported from this script\n");else{// exportif ( package->saveToArchive(saveto.toString(), 0, p.GetGameExe())) {if ( package->IsAnyGameInPackage() ) {for ( int i = 0; i < p.GetGameExe()->numGames(); i++ ) {if ( package->IsGameInPackage(i + 1) ) {Utils::WString exportFile = CFileIO(saveto).dir() + L"/" + CFileIO(saveto).baseName() + L"_" + CBaseFile::ConvertGameToString(i + 1) + L"." + CFileIO(saveto).extension();package->saveToArchive(exportFile.toString(), i + 1, p.GetGameExe());}}}wprintf(L"Package: %s was exported\n", saveto.c_str());}elseprintf("Error! There was a problem exporting the package\n");}}}}/*Main entry point to program*/int main ( int argc, char **argv ){// display program header to command promptprintf ( "\nSPKTool V1.50 (SPK File Version %.2f) 14/02/2021 Created by Cycrow\n\n", (float)FILEVERSION );// parse the cmd nameUtils::WString cmd (argv[0]);cmd = cmd.findReplace(L"\\", L"/");g_dir = cmd.tokens(L"/", 1, cmd.countToken(L"/") - 1);cmd = cmd.token(L"/", cmd.countToken(L"/"));g_read = false;// not enough arguments, display the syntax and exitif ( argc < 2 ){PrintSyntax ( cmd.toString() );exit ( 1 );}Utils::WString fileTypes;for ( int i = 0; i < FILETYPE_MAX; i++ ){Utils::WString sT = GetFileTypeString(i);if ( !sT.empty() ){if ( fileTypes.empty() )fileTypes = sT;else{fileTypes += L", ";fileTypes += sT;}}}// get the command flagUtils::WString command(argv[1]);// display the contents of the spk fileif ( command == L"-v" || command == L"--view" || command == L"--version"){if ( argc < 3 )wprintf(L"Syntax: %s -v <spkfile>\n\tWill open and display the contents of the spkfile\n", cmd.c_str() );elseDisplayVersion(argv[2]);}// creates a new spk fileelse if ( command == L"-c" || command == L"--create" ){if ( argc < 3 )wprintf(L"Syntax:\n\t%s -c <spkfile>\n\t%s --create <spkfile>\n\t\tThis will create a new SPK file and allow you to set some basic settings for the file\n", cmd.c_str(), cmd.c_str() );elseCreateFile ( argv[2] );}// appends a file onto the spk archiveelse if ( command == L"-a" || command == L"--append" ){if ( argc < 4 )wprintf(L"Syntax:\n\t%s -a <spkfile> <type> <filename>\n\t%s --append <spkfile> <type> <filename>\n\t\tThis will append the file into the archive and compress it according to the files default compression\n\t<type> = %s\n", cmd.c_str(), cmd.c_str(), fileTypes.c_str() );else{Utils::WString arg4;if ( argc > 4 )arg4 = argv[4];AppendFile ( argv[2], argv[3], arg4 );}}// removes a file from the spk archiveelse if ( command == L"-r" || command == L"--remove" || command == L"--removespk" ){if ( argc < 4 ){wprintf(L"Syntax:\n\t%s -r <spkfile> <type> <filename>\n\t%s --remove <spkfile> <type> <filename\n\t\tThis will remove a file from the archive\n\t<type> = %s\n", cmd.c_str(), cmd.c_str(), fileTypes.c_str() );wprintf(L"\t%s -r <multispkfile> <filename>\n\t%s --removespk <multispkfile> <filename>\n\t\tThis will remove a spk file from the Multi-SPK package\n", cmd.c_str(), cmd.c_str() );}else{Utils::WString arg4;if ( argc > 4 )arg4 = argv[4];RemoveFile ( argv[2], argv[3], arg4 );}}// extracts a file from a spk fileelse if ( command == L"--extractspk" ){if ( argc < 4 )wprintf(L"Syntax:\n\t%s --extractspk <multispkfile> <filename> [destination]\n\tThis will extract a spk file from the Multi-Spk package and save it to the destination path\n", cmd.c_str() );else{Utils::WString arg4;if ( argc > 4 )arg4 = argv[3];ExtractFile(argv[2], argv[3], arg4, Utils::WString::Null());}}else if ( command == L"-x" || command == L"--extract"){if ( argc < 4 ){wprintf(L"Syntax:\n\t%s -x <spkfile> <type> <filename> [destination]\n\tThis will extract a file from the package and save it to the corect path in <directory>\n\t<type> = %s\n", cmd.c_str(), fileTypes.c_str() );wprintf(L"\t%s -x <multispkfile> <filename> [destination]\n\tThis will extract a spk file from the Multi-Spk package and save it to the destination path\n", cmd.c_str() );}else{Utils::WString arg5, arg4;if ( argc > 5 )arg5 = argv[5];if ( argc > 4 )arg4 = argv[4];ExtractFile(argv[2], argv[3], arg4, arg5);}}// extracts all the files from an archiveelse if ( command == L"-e" || command == L"--extractall" ){if ( argc < 3 )wprintf(L"Syntax:\n\t%s -e <spkfile> [destination]\n\t--extractall <spkfile> <game> [destination]\n\t\tThis will extract all files of a set game into the destination directory\n\n\t\tGame = 0 will extract all files", cmd.c_str() );else{Utils::WString arg4;if ( argc > 4 )arg4 = argv[4];ExtractFiles(argv[2], arg4, CBaseFile::GetGameFromString(argv[3]));}}// creates a multispk archiveelse if ( command == L"-n" || command == L"--createmulti" ){if ( argc < 3 )wprintf(L"Syntax:\n\t%s -n <multispkfile>\n\t%s --createmulti <multispkfile>\n\t\tThis will create a multispk file and allow you to add spk files to it\n", cmd.c_str(), cmd.c_str() );elseCreateMultiFile ( argv[2] );}// merges 2 multi-spk archives together, or appends a single spk file into a multi-spk fileelse if ( command == L"-m" || command == L"--mergemulti" ){if ( argc < 4 )wprintf(L"Syntax:\n\t%s -m <spkfile1> <spkfile2>\n\t%s --mergemulti <spkfile1> <spkfile2>\n\t\tThis will add spkfile2 into spkfile1, if spkfile1 is a normal SPK file, it will be saved into a Multi-Spk file\nspkfile2 can also be a Multi-Spk file, all files within it will be added\n", cmd.c_str(), cmd.c_str() );elseAppendMultiFile ( argv[2], argv[3] );}// splits the multi-spk file, exracts all spk fileselse if ( command == L"-s" || command == L"--splitmulti" ){if ( argc < 3 )wprintf(L"Syntax: %s -s <multispkfile> [destination]\n\tSplits the Multi-SPK file and saves each spk file to the destiantion directory\n", cmd.c_str() );else{Utils::WString arg3;if ( argc > 3 )arg3 = argv[3];SplitMulti ( argv[2], arg3 );}}else if ( command == L"--set" ){if ( argc < 4 )wprintf(L"Syntax: %s --set <spkfile> <setting> [values]\n\tSets various settings in the package\n", cmd.c_str() );elseSettings(argv[2], argv[3], argc, argv, cmd);}else if ( command == L"--setrating" ){if ( argc < 6 )wprintf(L"Syntax: %s --setrating <spkfile> <easeofuse> <gamechanging> <recommended>\n\tSets the rating of the spk package\n", cmd.c_str() );elseSetRating(argv[2], Utils::WString(argv[3]).toInt(), Utils::WString(argv[4]).toInt(), Utils::WString(argv[5]).toInt());}else if ( command == L"--convertxsp" || command == L"--convertxspwizard" ){if ( argc < 3 )wprintf(L"Syntax: %s %s <xspfile> [newxspfile]\n\tConverts an old format xsp file to work with the new format\n", cmd.c_str(), command.c_str() );else{Utils::WString arg3;if ( argc > 3 )arg3 = argv[3];ConvertXsp(Utils::WString::FromString(argv[2]), arg3, (command == L"--convertxspwizard") ? true : false);}}else if ( command == L"--createscript" ){if ( argc < 3 )wprintf(L"Syntax:\n\t%s --createscript <packagerscript>\n\t\tThis will create a spk/xsp file from a packager script\n", cmd.c_str() );elseLoadPackagerScript ( argv[2], false );}else if ( command == L"--generatescript" ){if ( argc < 3 )wprintf(L"Syntax:\n\t%s --generatescript <package> [packagerscript]\n\t\tThis will generate a packager script file from a spk/xsp file.\n", cmd.c_str() );else{if ( argc < 4 )GeneratePackagerScript ( argv[2], "", 0);elseGeneratePackagerScript ( argv[2], argv[3], 0);}}else if ( command == L"--verifyscript" ){if ( argc < 3 )wprintf(L"Syntax:\n\t%s --verifyscript <packagerscript>\n\t\tThis will read a packager script and check its correct without creating the resulting spk/xsp file\n", cmd.c_str() );elseLoadPackagerScript ( argv[2], true );}else if ( command == L"--extractship" ){if ( argc < 4 )wprintf(L"Syntax:\n\t%s --extractship <modfile> <xspfile> [shipid]\n\t\tThis will create an xsp ship file by extracting from a mod file\n", cmd.c_str() );else{if ( argc < 5 )ExtractShip ( argv[2], argv[3], L"" );elseExtractShip ( argv[2], argv[3], argv[4] );}}else if (command == L"--generateupdatefile"){if (argc < 3)wprintf(L"Syntax:\n\t%s --generateupdatefile <package>\n\t\tThis will generate the update file to allow auto updates for a package\n", cmd.c_str());elseGenerateUpdateFile(argv[2]);}else if (command == L"--packagelist"){if (argc < 3)wprintf(L"Syntax:\n\t%s --packagelist <filenames>\n\t\tThis will generate the update file to allow downloading packages from a server.\n", cmd.c_str());elseGenerateUpdateList(argc, argv);}// not a valid switch, display syntaxelsePrintSyntax(cmd);#ifdef _DEBUGchar pause;scanf ( "%s", &pause );#endifreturn 0;}