00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020
00021 #include "GameInfo.h"
00022
00023 #include "IDataSource.h"
00024 #include "ODataSource.h"
00025 #include "util.h"
00026
00027
00028 struct GameTypeDesc {
00029 const char* shortname;
00030 const char* longname;
00031 };
00032 struct GameLangDesc {
00033 char letter;
00034 char usecodeletter;
00035 const char* name;
00036 };
00037
00038
00039 static GameTypeDesc gametypes[] = {
00040 { "", "" },
00041 { "ultima8", "Ultima VIII: Pagan" },
00042 { "remorse", "Crusader: No Remorse" },
00043 { "regret", "Crusader: No Regret" },
00044 { "pentmenu", "Pentagram Menu" },
00045 { 0, 0 }
00046 };
00047
00048
00049 static GameLangDesc gamelangs[] = {
00050 { 0, 0, "unknown" },
00051 { 'e', 'e', "English" },
00052 { 'f', 'f', "French" },
00053 { 'g', 'g', "German" },
00054 { 'e', 'e', "Spanish" },
00055 { 'e', 'j', "Japanese" },
00056 { 0, 0 }
00057 };
00058
00059
00060 GameInfo::GameInfo()
00061 : type(GAME_UNKNOWN), version(0), language(GAMELANG_UNKNOWN)
00062 {
00063 for (int i = 0; i < 16; ++i)
00064 md5[i] = 0;
00065 }
00066
00067 char GameInfo::getLanguageFileLetter() const
00068 {
00069 switch (type) {
00070 case GAME_U8:
00071 {
00072 unsigned int l = static_cast<unsigned int>(language);
00073 assert(l < (sizeof(gamelangs)/sizeof(gamelangs[0]))-1);
00074
00075 return gamelangs[l].letter;
00076 }
00077 case GAME_REMORSE:
00078 case GAME_REGRET:
00079 return 'e';
00080 default:
00081 return 0;
00082 }
00083 }
00084
00085 char GameInfo::getLanguageUsecodeLetter() const
00086 {
00087 switch (type) {
00088 case GAME_U8:
00089 {
00090 unsigned int l = static_cast<unsigned int>(language);
00091 assert(l < (sizeof(gamelangs)/sizeof(gamelangs[0]))-1);
00092
00093 return gamelangs[l].usecodeletter;
00094 }
00095 case GAME_REMORSE:
00096 case GAME_REGRET:
00097 return 'e';
00098 default:
00099 return 0;
00100 }
00101 }
00102
00103 std::string GameInfo::getLanguage() const
00104 {
00105 unsigned int l = static_cast<unsigned int>(language);
00106 assert(l < (sizeof(gamelangs)/sizeof(gamelangs[0]))-1);
00107
00108 return gamelangs[l].name;
00109 }
00110
00111 std::string GameInfo::getGameTitle() const
00112 {
00113 unsigned int t = static_cast<unsigned int>(type);
00114 assert(t < (sizeof(gametypes)/sizeof(gametypes[0]))-1);
00115
00116 return gametypes[t].longname;
00117 }
00118
00119 std::string GameInfo::getPrintableVersion() const
00120 {
00121 char buf[32];
00122 sprintf(buf, "%d.%02d", version/100, version%100);
00123 return buf;
00124 }
00125
00126 std::string GameInfo::getPrintDetails() const
00127 {
00128 std::string ret;
00129
00130 std::string title = getGameTitle();
00131 if (title == "") title = "Unknown";
00132
00133 ret = title + ", ";
00134
00135 std::string lang = getLanguage();
00136 if (lang == "") lang = "Unknown";
00137 ret += lang;
00138
00139 if (type != GAME_PENTAGRAM_MENU) {
00140
00141
00142 ret += ", version ";
00143 ret += getPrintableVersion();
00144
00145 ret += ", md5 ";
00146 ret += getPrintableMD5();
00147 }
00148
00149 return ret;
00150 }
00151
00152
00153 std::string GameInfo::getPrintableMD5() const
00154 {
00155 std::string ret;
00156
00157 char buf[33];
00158 for (int i = 0; i < 16; ++i) {
00159 sprintf(buf+2*i, "%02x", md5[i]);
00160 }
00161
00162 ret = buf;
00163
00164 return ret;
00165 }
00166
00167 bool GameInfo::match(GameInfo& other, bool ignoreMD5) const
00168 {
00169 if (type != other.type) return false;
00170 if (language != other.language) return false;
00171 if (version != other.version) return false;
00172
00173 if (ignoreMD5) return true;
00174
00175 return (std::memcmp(md5, other.md5, 16) == 0);
00176 }
00177
00178 void GameInfo::save(ODataSource* ods)
00179 {
00180 unsigned int l = static_cast<unsigned int>(language);
00181 assert(l < (sizeof(gamelangs)/sizeof(gamelangs[0]))-1);
00182 unsigned int t = static_cast<unsigned int>(type);
00183 assert(t < (sizeof(gametypes)/sizeof(gametypes[0]))-1);
00184
00185 std::string game = gametypes[t].shortname;
00186 std::string lang = gamelangs[l].name;
00187
00188 char buf[16];
00189 sprintf(buf, "%d", version);
00190 std::string ver = buf;
00191 std::string md5 = getPrintableMD5();
00192
00193 std::string d = game + "," + lang + "," + ver + "," + md5 + "\n";
00194 ods->write(d.c_str(), d.size());
00195 }
00196
00197 bool GameInfo::load(IDataSource* ids, uint32 version)
00198 {
00199 std::string s;
00200 std::vector<std::string> parts;
00201
00202 ids->readline(s);
00203 Pentagram::SplitString(s, ',', parts);
00204 if (parts.size() != 4) return false;
00205
00206 int i = 0;
00207 while (gametypes[i].shortname) {
00208 if (parts[0] == gametypes[i].shortname) {
00209 type = static_cast<GameType>(i);
00210 break;
00211 }
00212 i++;
00213 }
00214 if (!gametypes[i].shortname) return false;
00215
00216 i = 0;
00217 while (gamelangs[i].name) {
00218 if (parts[1] == gamelangs[i].name) {
00219 language = static_cast<GameLanguage>(i);
00220 break;
00221 }
00222 i++;
00223 }
00224 if (!gamelangs[i].name) return false;
00225
00226 this->version = std::strtol(parts[2].c_str(), 0, 0);
00227
00228 for (int i = 0; i < 16; ++i) {
00229 char buf[3];
00230 buf[0] = parts[3][2*i];
00231 buf[1] = parts[3][2*i+1];
00232 buf[2] = 0;
00233 long x = std::strtol(buf, 0, 16);
00234 md5[i] = static_cast<uint8>(x);
00235 }
00236
00237 return true;
00238 }