Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "GameExe.h"#include "File_IO.h"#include "DirIO.h"/*** Add Exe** Adds an exe name available*/int CGameExe::AddExe(CyString exe){// search if it already existsint count = 0;for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() ){if ( node->Data()->sExe.Compare(exe) )return count;--count;}// not found, we need to addSGameExe *sExe = new SGameExe;sExe->sExe = exe;sExe->iName = 0;sExe->iFlags = 0;sExe->iMaxPatch = 1;sExe->iAddonTo = 0;m_lExe.push_back(sExe);return m_lExe.size() - 1;}/*** Find Exe** Find an exe and return its position in the file** Argument: exe, String - name of the exe file to find*/int CGameExe::FindExe(CyString exe){int count = 0;for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() ){if ( node->Data()->sExe.Compare(exe) )return count;++count;}return -1;}SGameExe *CGameExe::GetGameExe(CyString exe){int e = FindExe(exe);if ( e < 0 ) return NULL;return m_lExe[e];}int CGameExe::FindVersion(int exe, int size, CyString *fVersion){if ( fVersion )*fVersion = -1.0;if ( exe < 0 )return -1;SGameExe *gameExe = m_lExe[exe];if ( !gameExe )return -1;int count = 0;for ( CListNode<SGameExeVersion> *node = gameExe->lVersions.Front(); node; node = node->next() ){// check each size of a watchfor ( CListNode<int> *iNode = node->Data()->lSize.Front(); iNode; iNode = iNode->next() ){int checkSize = *iNode->Data();if ( checkSize == size ){*fVersion = node->Data()->fVersion;return count;}}++count;}return -1;}int CGameExe::FindVersion(CyString exe, int size, CyString *fVersion){int iExe = this->FindExe(exe);if ( iExe < 0 )return -1;int iVersion = this->FindVersion(iExe, size, fVersion);if ( iVersion < 0 )return -2 - iExe;return -1;}CyString CGameExe::GetModKey(int game){if ( game < 0 )return NullString;SGameExe *sExe = m_lExe[game];if ( !sExe )return NullString;return sExe->sModKey;}void CGameExe::ParseExe(CyString line){// get the exe fileCyString exe = line.GetToken(":", 1, 1);int iExe = this->AddExe(exe);SGameExe *sExe = m_lExe[iExe];sExe->iMaxPatch = line.GetToken(":", 2, 2).ToInt();sExe->iFlags = this->ParseFlags(line.GetToken(":", 3, 3));sExe->sModKey = line.GetToken(":", 4, 4);// get the nameCyString gameName = line.GetToken(":", 5, 5);this->_SetExeName(&sExe->sName, &sExe->iName, gameName);// get mydocssExe->sMyDoc = line.GetToken(":", 6, 6);// now get the versionsint pos = EXE_VERSIONPOS;int namestart = EXE_VERSION_NAMESTART;int sizestart = EXE_VERSION_SIZESTART;if ( sExe->iFlags & EXEFLAG_ADDON ) {++pos;++namestart;++sizestart;sExe->sAddon = line.GetToken(":", EXE_VERSIONPOS, EXE_VERSIONPOS);if ( sExe->sAddon.IsIn("!") ) {sExe->iAddonTo = this->FindExe(sExe->sAddon.GetToken("!", 2, 2));sExe->sAddon = sExe->sAddon.GetToken("!", 1, 1);}}int iVersions = line.GetToken(":", pos, pos).ToInt();int i;for ( i = 0; i < iVersions; i++ ){SGameExeVersion *sGameVersion = new SGameExeVersion;sGameVersion->iName = 0;sGameVersion->fVersion = line.GetToken(":", namestart + (i * 2), namestart + (i * 2)).GetToken(" ", 1, 1).ToFloat();CyString sSize = line.GetToken(":", sizestart + (i * 2), sizestart + (i * 2));// multiple versions available, we need to split them upif ( sSize.IsIn("!") ){int max = 0;CyString *sizes = sSize.SplitToken('!', &max);if ( sizes && max ){for ( int j = 0; j < max; j++ ){int *size = new int;(*size) = sizes[j].ToInt();if ( *size )sGameVersion->lSize.push_back(size);}CLEANSPLIT(sizes, max);}}else{int *size = new int;(*size) = sSize.ToInt();if ( *size )sGameVersion->lSize.push_back(size);}if ( !sGameVersion->lSize.empty() ){// finally, add the version namesthis->_SetExeName(&sGameVersion->sName, &sGameVersion->iName, line.GetToken(":", namestart + (i * 2), namestart + (i * 2)));sExe->lVersions.push_back(sGameVersion);}}}int CGameExe::ParseFlags(CyString flags){int max;CyString *sFlags = flags.SplitToken("|", &max);if ( !sFlags || !max )return EXEFLAG_NONE;int f = 0;for ( int i = 0; i < max; i++ ){CyString str = sFlags[i];if ( str.Compare("TC_TEXT") )f |= EXEFLAG_TCTEXT;else if ( str.Compare("NO_XOR") )f |= EXEFLAG_NOXOR;else if ( str.Compare("ADDON") )f |= EXEFLAG_ADDON;else if ( str.Compare("MYDOCLOG") )f |= EXEFLAG_MYDOCLOG;else if ( str.Compare("NOSAVESUBDIR") )f |= EXEFLAG_NOSAVESUBDIR;else{if ( str.IsNumber() )f |= str.ToInt();}}CLEANSPLIT(sFlags, max);return f;}void CGameExe::_SetExeName(CyString *sName, int *iName, CyString n){if ( n.IsIn("!") ){CyString gameNum = n.GetToken("!", 1, 1);n = n.GetToken("!", 2, 2);if ( gameNum.IsNumber() )*iName = gameNum.ToInt();else*sName = gameNum;}if ( n.IsNumber() )*iName = n.ToInt();else*sName = n;}void CGameExe::Reset(){for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() ){for ( CListNode<SGameExeVersion> *vNode = node->Data()->lVersions.Front(); vNode; vNode = vNode->next() )vNode->Data()->lSize.MemoryClear();node->Data()->lVersions.MemoryClear();}m_lExe.MemoryClear();}bool CGameExe::ReadFile(CyString file){FILE *id = fopen(file.c_str(), "rb");if ( !id )return false;CyString line;while ( !feof(id) ){line.GetEndOfLine(id, NULL, false);if ( line.Empty() )continue;CyString lineNoSpace = line;lineNoSpace.RemoveFirstSpace();if ( lineNoSpace.Empty() )continue;if ( lineNoSpace.Left(1) == "/" )continue;this->ParseExe(line);}fclose(id);return true;}CyString CGameExe::GetGameRunExe(CyString dir){CDirIO Dir(dir);int count = 0;for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() ){SGameExe *exe = node->Data();if ( Dir.Exists(exe->sExe) )return dir + "/" + exe->sExe;if ( !exe->sAddon.Empty() ) {if ( Dir.TopDir().Compare(exe->sAddon) )return this->GetGameDir(dir) + "/" + exe->sExe;}++count;}return NullString;}CyString CGameExe::GetGameName(CyString gameExe){int gameType = this->GetGameType(gameExe);CyString gameName = ExtractGameName(gameExe);if ( gameName.Empty() )gameName = this->GetGameNameFromType(gameType);if ( gameName.Empty() )return NullString;// no versionCyString fVersion;CyString versionName;if ( this->GetGameVersionName(gameExe, &versionName) ){if ( !versionName.Empty() )return gameName + " V" + versionName;elsereturn gameName;}CyString sGameVersion = this->GetGameVersionFromType(gameType, this->GetGameVersion(gameExe, &fVersion), fVersion);if ( sGameVersion.Empty() ){if ( !fVersion.Empty() )return gameName + " V" + fVersion;elsereturn gameName;}// return the name and the versionreturn gameName + " " + sGameVersion;}int CGameExe::GetGameAddons(CyString dir, CyStringList &exes){int count = 0;CDirIO Dir(dir);for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() ){SGameExe *exe = node->Data();if ( !(exe->iFlags & EXEFLAG_ADDON) )continue;if ( Dir.Exists(exe->sExe) ) {if ( Dir.Exists(exe->sAddon) ) {exes.PushBack(exe->sExe, exe->sAddon);++count;}}}return count;}CyString CGameExe::GetAddonDir(CyString dir){int gameType = this->GetGameType(dir);if ( gameType != -1 ) {return m_lExe[gameType]->sAddon;}return "";}CyString CGameExe::GetProperDir(CyString dir){CDirIO Dir(dir);int gameType = this->GetGameType(dir);if ( gameType != -1 ) {if ( !m_lExe[gameType]->sAddon.Empty() ) {if ( CDirIO(dir).IsFile() )return CFileIO(dir).GetDir() + "/" + m_lExe[gameType]->sAddon;return Dir.Dir(m_lExe[gameType]->sAddon);}}return dir;}int CGameExe::GetGameFlags(int game){if ( game == -1 )return 0;SGameExe *exe = m_lExe[game];if ( !exe )return 0;return exe->iFlags;}int CGameExe::GetMaxPatch(int game){if ( game == -1 )return 0;SGameExe *exe = m_lExe[game];if ( !exe )return 0;return exe->iMaxPatch;}CyString CGameExe::GetGameNameFromType(int type){if ( type == -1 )return NullString;SGameExe *exe = m_lExe[type];if ( !exe )return NullString;return exe->sName;}CyString CGameExe::GetGameVersionFromType(int game, int gameVersion, CyString fGameVersion){SGameExe *exe = m_lExe[game];if ( !exe )return NullString;SGameExeVersion *version = exe->lVersions[gameVersion];if ( !version ){if ( !fGameVersion.Empty() )return fGameVersion;return NullString;}return version->sName;}CyString CGameExe::GetGameDir(CyString dir){CDirIO Dir(dir);for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() ){SGameExe *exe = node->Data();if ( CDirIO(dir).IsFile() ) {if ( CFileIO(dir).GetFilename().Compare(exe->sExe) )return CFileIO(dir).GetDir();}else {if ( Dir.Exists(exe->sExe) )return dir;// check for addon dirif ( !exe->sAddon.Empty() ) {CyString top = Dir.TopDir();if ( exe->sAddon.Compare(Dir.TopDir()) )return Dir.Back();}}}return dir;}int CGameExe::GetGameType(CyString gameExe){CDirIO Dir(gameExe);int count = 0;for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() ){SGameExe *exe = node->Data();if ( CDirIO(gameExe).IsFile() ) {if ( CFileIO(gameExe).GetFilename().Compare(exe->sExe) )return count;}else {if ( Dir.Exists(exe->sExe) )return count;// check for addon dirif ( !exe->sAddon.Empty() ) {CyString top = Dir.TopDir();if ( exe->sAddon.Compare(Dir.TopDir()) )return count;}}++count;}return -1;}CyString CGameExe::ExtractGameName(CyString gameDir){CDirIO Dir(gameDir);CyString textFileName;if ( Dir.Exists("t") && Dir.Exists("t/0002.pck") )textFileName = "t/0002.pck";else if ( Dir.Exists("t") && Dir.Exists("t/440002.pck") )textFileName = "t/440002.pck";else if ( Dir.Exists("t") && Dir.Exists("t/0002-L044.pck") )textFileName = "t/0002-L044.pck";CyString sName;if ( !textFileName.Empty() ){CFileIO File(Dir.File(textFileName));size_t fileSize;char *fileData = File.ReadToData(&fileSize);if ( fileData && fileSize){size_t newFileSize;unsigned char *pckData = UnPCKData((unsigned char *)fileData, fileSize, &newFileSize);if ( pckData ){if ( newFileSize ){pckData[newFileSize -1] = '\0';CyString data((char *)pckData);int startpage = data.FindPos("<page id=\"1910\"");if ( startpage >= 0 ){int start = data.FindPos("<t id=\"1216\">", startpage);if ( start >= 0 ){start += 14;int end = data.FindPos("</t>", start);end++;CyString text = data.Mid(start, end - start);end = text.FindPos("\\n");if ( end >= 0 )sName = text.Left(end);}}}delete pckData;}}}return sName;}bool CGameExe::GetGameVersionName(CyString gameExe, CyString *versionName){int gameType = this->GetGameType(gameExe);if ( gameType == -1 )return false;CyString gameDir = gameExe;gameExe = this->GetGameDir(gameExe) + "/" + m_lExe[gameType]->sExe;int size = (int)CFileIO(gameExe).GetFilesize();CyString fVersion;int version = this->FindVersion(gameType, size, &fVersion);// not matched version// lets read the text fileif ( version != -1 ){(*versionName) = this->GetGameVersionFromType(gameType, version, fVersion);return true;}CDirIO Dir(gameDir);CyString textFileName;if ( Dir.Exists("t") && Dir.Exists("t/0002.pck") )textFileName = "t/0002.pck";else if ( Dir.Exists("t") && Dir.Exists("t/440002.pck") )textFileName = "t/440002.pck";else if ( Dir.Exists("t") && Dir.Exists("t/0002-L044.pck") )textFileName = "t/0002-L044.pck";if ( !textFileName.Empty() ){CyString sVersion;CFileIO File(Dir.File(textFileName));size_t fileSize;char *fileData = File.ReadToData(&fileSize);if ( fileData && fileSize){size_t newFileSize;unsigned char *pckData = UnPCKData((unsigned char *)fileData, fileSize, &newFileSize);if ( pckData ){if ( newFileSize ){pckData[newFileSize -1] = '\0';CyString data((char *)pckData);int startpage = data.FindPos("<page id=\"1910\"");if ( startpage >= 0 ){int start = data.FindPos("<t id=\"1216\">", startpage);if ( start >= 0 ){start += 15;int end = data.FindPos("</t>", start);end++;CyString text = data.Mid(start, end - start);int pos = text.FindPos("Version ");if ( pos >= 0 ){pos += 9;end = text.FindPos(", ", pos);if ( end >= 0 )sVersion = text.Mid(pos, (end + 1) - pos);}}if ( sVersion.Empty() ){int start = data.FindPos("<t id=\"1216\">", startpage);if ( start >= 0 ){start += 15;int end = data.FindPos("</t>", start);end++;CyString text = data.Mid(start, end - start);int pos = text.FindPos("ver=");if ( pos >= 0 ){pos += 5;end = text.FindPos("&", pos);if ( end >= 0 )sVersion = text.Mid(pos, (end + 1) - pos);}}}}}delete pckData;}}if ( !sVersion.Empty() ){// lets match the version(*versionName) = sVersion;float fVersion = sVersion.ToFloat();SGameExe *gameExe = m_lExe[gameType];if ( gameExe ){int count = 0;int lower = -1;for ( CListNode<SGameExeVersion> *node = gameExe->lVersions.Front(); node; node = node->next() ){if ( node->Data()->fVersion == fVersion ){(*versionName) = node->Data()->sName;return true;}++count;}version = lower;}}}return true;}int CGameExe::GetGameVersion(CyString gameExe, CyString *a_fVersion){int gameType = this->GetGameType(gameExe);if ( gameType == -1 )return -1;CyString gameDir = gameExe;if ( !m_lExe[gameType]->sAddon.Empty() )gameExe = CDirIO(gameExe).Back() + "/" + m_lExe[gameType]->sExe;elsegameExe = gameExe + "/" + m_lExe[gameType]->sExe;int size = (int)CFileIO(gameExe).GetFilesize();int version = this->FindVersion(gameType, size, a_fVersion);// not matched version// lets read the text fileif ( version == -1 ){CDirIO Dir(gameDir);CyString textFileName;if ( Dir.Exists("t") && Dir.Exists("t/0002.pck") )textFileName = "t/0002.pck";else if ( Dir.Exists("t") && Dir.Exists("t/440002.pck") )textFileName = "t/440002.pck";else if ( Dir.Exists("t") && Dir.Exists("t/0002-L044.pck") )textFileName = "t/0002-L044.pck";if ( !textFileName.Empty() ){CyString sVersion;CFileIO File(Dir.File(textFileName));size_t fileSize;char *fileData = File.ReadToData(&fileSize);if ( fileData && fileSize){size_t newFileSize;unsigned char *pckData = UnPCKData((unsigned char *)fileData, fileSize, &newFileSize);if ( pckData ){if ( newFileSize ){pckData[newFileSize -1] = '\0';CyString data((char *)pckData);int start = data.FindPos("<t id=\"10000\">");if ( start >= 0 ){start += 15;int end = data.FindPos("</t>", start);end++;CyString text = data.Mid(start, end - start);int pos = text.FindPos("ver=");if ( pos >= 0 ){pos += 5;end = text.FindPos("&", pos);if ( end >= 0 )sVersion = text.Mid(pos, (end + 1) - pos);}}}delete pckData;}}if ( !sVersion.Empty() ){// lets match the versionCyString fVersion = sVersion;if ( a_fVersion )*a_fVersion = fVersion;SGameExe *gameExe = m_lExe[gameType];if ( gameExe ){int count = 0;int lower = -1;for ( CListNode<SGameExeVersion> *node = gameExe->lVersions.Front(); node; node = node->next() ){if ( fVersion.CompareVersion(node->Data()->fVersion) == COMPARE_OLDER )lower = count;if ( fVersion.CompareVersion(node->Data()->fVersion) == COMPARE_SAME )return count;++count;}version = lower;}}}}return version;}int CGameExe::ConvertGameType(int gametype, int *version){int count = 0, game = 0;switch ( gametype ){case 1:*version = 0;return 1;case 2:*version = 0;return 2;case 3:*version = 1;return 2;case 4:*version = 0;return 3;case 5:*version = 1;return 3;case 6:*version = 2;return 3;}for ( CListNode<SGameExe> *node = m_lExe.Front(); node; node = node->next() ){++count;++game;SGameExe *exe = node->Data();// found the game type, the version is 0, which is any versionif ( count == gametype ){*version = 0;return game;}int v = 0;for ( CListNode<SGameExeVersion> *vNode = exe->lVersions.Front(); vNode; vNode = vNode->next() ){++count;++v;if ( count == gametype ){*version = v;return game;}}}// not found ?? just set to all versions*version = 0;return 0;}