GameDetector.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2003-2005 The Pentagram team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #include "pent_include.h"
00020 
00021 #include "GameDetector.h"
00022 #include "FileSystem.h"
00023 #include "GameInfo.h"
00024 #include "RawArchive.h"
00025 #include "md5.h"
00026 
00027 #include "gamemd5.h"
00028 
00029 bool GameDetector::detect(std::string path, GameInfo *info)
00030 {
00031         FileSystem* fs = FileSystem::get_instance();
00032         if (!fs->AddVirtualPath("@detect", path))
00033                 return false;
00034 
00035         IDataSource* ids;
00036 
00037 
00038         // Strategy: find eusecode.flx, fusecode.flx or gusecode.flx,
00039         // compute its MD5, and check it against our MD5 table.
00040         // Should that fail, try a manual check to at least identify the
00041         // game type and its language.
00042 
00043         ids = fs->ReadFile("@detect/usecode/eusecode.flx");
00044         if (!ids)
00045                 ids = fs->ReadFile("@detect/usecode/fusecode.flx");
00046         if (!ids)
00047                 ids = fs->ReadFile("@detect/usecode/gusecode.flx");
00048         if (!ids)
00049                 ids = fs->ReadFile("@detect/usecode/jusecode.flx");
00050         if (!ids)
00051                 return false; // all games have usecode
00052 
00053         Pentagram::md5_file(ids, info->md5, 0);
00054         delete ids;
00055 
00056         std::string md5s = info->getPrintableMD5();
00057 
00058         int i = 0;
00059         while (Pentagram::md5table[i].md5) {
00060                 if (md5s == Pentagram::md5table[i].md5) {
00061                         info->type = Pentagram::md5table[i].type;
00062                         info->language = Pentagram::md5table[i].language;
00063                         info->version = Pentagram::md5table[i].version;
00064                         return true;
00065                 }
00066                 i++;
00067         }
00068 
00069         perr << "MD5-based game autodetection failed (" << md5s << "). "
00070                  << std::endl << "Trying manual detection." << std::endl;
00071 
00072 
00073 
00074         // game type
00075         if (info->type == GameInfo::GAME_UNKNOWN) {
00076 
00077                 ids = fs->ReadFile("@detect/static/u8gumps.flx"); // random U8 file
00078                 if (ids) {
00079                         info->type = GameInfo::GAME_U8;
00080                         delete ids; ids = 0;
00081                 }
00082 
00083         }
00084 
00085         if (info->type == GameInfo::GAME_UNKNOWN) {
00086 
00087                 ids = fs->ReadFile("@detect/static/help1.dat"); // random remorse file
00088                 if (ids) {
00089                         info->type = GameInfo::GAME_REMORSE;
00090                         delete ids; ids = 0;
00091                 }
00092 
00093         }
00094 
00095         if (info->type == GameInfo::GAME_UNKNOWN) {
00096 
00097                 ids = fs->ReadFile("@detect/static/help1.bmp"); // random regret file
00098                 if (ids) {
00099                         info->type = GameInfo::GAME_REGRET;
00100                         delete ids; ids = 0;
00101                 }
00102 
00103         }
00104 
00105         //TODO: game version
00106         info->version = 999;
00107 
00108 
00109         // game language
00110 
00111         // detect using eusecode/fusecode/gusecode
00112         if (info->language == GameInfo::GAMELANG_UNKNOWN) {
00113                 ids = fs->ReadFile("@detect/usecode/eusecode.flx");
00114                 if (ids) {
00115                         if (info->type == GameInfo::GAME_U8) {
00116                                 // distinguish between english and spanish
00117                                 RawArchive* f = new RawArchive(ids);
00118                                 const char* buf = reinterpret_cast<const char*>((f->get_object_nodel(183)));
00119                                 unsigned int size = f->get_size(183);
00120                                 if (buf) {
00121                                         for (unsigned int i = 0; i + 9 < size; ++i) {
00122                                                 if (strncmp(buf+i, "tableware", 9) == 0) {
00123                                                         info->language = GameInfo::GAMELANG_ENGLISH;
00124                                                         break;
00125                                                 }
00126                                                 if (strncmp(buf+i, "vajilla", 7) == 0) {
00127                                                         info->language = GameInfo::GAMELANG_SPANISH;
00128                                                         break;
00129                                                 }
00130                                         }
00131                                 }
00132                                 delete f; ids = 0; // ids is deleted when f is deleted
00133                         }
00134 
00135                         // if still unsure, English
00136                         if (info->language == GameInfo::GAMELANG_UNKNOWN)
00137                                 info->language = GameInfo::GAMELANG_ENGLISH;
00138 
00139                         delete ids; ids = 0;
00140                 }
00141         }
00142         if (info->language == GameInfo::GAMELANG_UNKNOWN) {
00143                 ids = fs->ReadFile("@detect/usecode/fusecode.flx");
00144                 if (ids) {
00145                         info->language = GameInfo::GAMELANG_FRENCH;
00146                         delete ids; ids = 0;
00147                 }
00148         }
00149         if (info->language == GameInfo::GAMELANG_UNKNOWN) {
00150                 ids = fs->ReadFile("@detect/usecode/gusecode.flx");
00151                 if (ids) {
00152                         info->language = GameInfo::GAMELANG_GERMAN;
00153                         delete ids; ids = 0;
00154                 }
00155         }
00156         if (info->language == GameInfo::GAMELANG_UNKNOWN) {
00157                 ids = fs->ReadFile("@detect/usecode/jusecode.flx");
00158                 if (ids) {
00159                         info->language = GameInfo::GAMELANG_JAPANESE;
00160                         delete ids; ids = 0;
00161                 }
00162         }
00163 
00164         fs->RemoveVirtualPath("@detect");
00165 
00166         return (info->type != GameInfo::GAME_UNKNOWN &&
00167                         /* info->version != 0 && */
00168                         info->language != GameInfo::GAMELANG_UNKNOWN);
00169 }

Generated on Fri Jul 27 22:27:15 2007 for pentagram by  doxygen 1.4.7