Ticket #8473: kyra-md5detect.patch
File kyra-md5detect.patch, 15.1 KB (added by , 19 years ago) |
---|
-
kyra/kyra.cpp
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvmcvs/kyra/kyra.cpp scummvm/kyra/kyra.cpp
old new 29 29 #include "common/config-manager.h" 30 30 #include "common/file.h" 31 31 #include "common/system.h" 32 #include "common/md5.h" 32 33 33 34 #include "sound/mixer.h" 34 35 #include "sound/mididrv.h" … … 48 49 49 50 using namespace Kyra; 50 51 52 enum { 53 // We only compute MD5 of the first megabyte of our data files. 54 kMD5FileSizeLimit = 1024 * 1024 55 }; 56 57 // Kyra MD5 detection brutally ripped from the Gobliins engine. 51 58 struct KyraGameSettings { 52 59 const char *name; 53 60 const char *description; 61 byte id; 54 62 uint32 features; 55 const char *detectName; 63 const char *md5sum; 64 const char *checkFile; 56 65 GameSettings toGameSettings() const { 57 66 GameSettings dummy = { name, description, features }; 58 67 return dummy; 59 68 } 60 69 }; 61 70 62 static const KyraGameSettings kyra_settings[] = { 63 { "kyra1", "Legend of Kyrandia (Floppy)", GF_FLOPPY | GF_KYRA1, "INTRO.SND" }, 64 { "kyra1cd", "Legend of Kyrandia (CD)", GF_TALKIE | GF_KYRA1, "CHAPTER1.VRM" }, 65 { "kyra1demo", "Legend of Kyrandia (Demo)", GF_DEMO | GF_FLOPPY | GF_KYRA1, "DEMO1.WSA" }, 66 // { "kyra2", "Hand of Fate (Floppy)", GF_FLOPPY | GF_KYRA2, 0 }, 67 // { "kyra2cd", "Hand of Fate (CD)", GF_TALKIE | GF_KYRA2, "AUDIO.PAK" }, 68 // { "kyra3", "Malcolm's Revenge", GF_TALKIE | GF_KYRA3, "K3INTRO0.VQA" }, 69 { 0, 0, 0, 0 } 71 static const KyraGameSettings kyra_games[] = { 72 { "kyra1", "Legend of Kyrandia (Floppy, English)", GI_KYRA1, GF_ENGLISH | GF_FLOPPY | GF_KYRA1, 73 "796e44863dd22fa635b042df1bf16673", "GEMCUT.EMC" }, 74 { "kyra1", "Legend of Kyrandia (Floppy, French)", GI_KYRA1, GF_FRENCH | GF_FLOPPY | GF_KYRA1, 75 "abf8eb360e79a6c2a837751fbd4d3d24", "GEMCUT.EMC" }, 76 { "kyra1", "Legend of Kyrandia (Floppy, German)", GI_KYRA1, GF_GERMAN | GF_FLOPPY | GF_KYRA1, 77 "82aea70ef26f41fa963dfae270994e49", "GEMCUT.EMC"}, 78 { "kyra1", "Legend of Kyrandia (CD)", GI_KYRA1, GF_ENGLISH | GF_TALKIE | GF_KYRA1, 79 "fac399fe62f98671e56a005c5e94e39f", "GEMCUT.PAK" }, 80 { "kyra1", "Legend of Kyrandia (Demo)", GI_KYRA1, GF_DEMO | GF_KYRA1, 81 "fb722947d94897512b13b50cc84fd648", "DEMO1.WSA" }, 82 {0, 0, 0, 0, 0, 0} 83 }; 84 85 // Keep list of different supported games 86 static const struct KyraGameList { 87 const char *name; 88 const char *description; 89 uint32 features; 90 GameSettings toGameSettings() const { 91 GameSettings dummy = { name, description, features }; 92 return dummy; 93 } 94 } kyra_list[] = { 95 {"kyra1", "Legend of Kyrandia", GF_KYRA1}, 96 {0, 0, 0} 70 97 }; 71 98 72 99 GameList Engine_KYRA_gameList() { 73 100 GameList games; 74 const KyraGameSettings *g = kyra_settings; 101 const KyraGameList *g = kyra_list; 102 75 103 while (g->name) { 76 104 games.push_back(g->toGameSettings()); 77 105 g++; … … 80 108 } 81 109 82 110 DetectedGameList Engine_KYRA_detectGames(const FSList &fslist) { 83 const KyraGameSettings *game;84 111 DetectedGameList detectedGames; 112 const KyraGameSettings *g; 113 FSList::const_iterator file; 85 114 86 for (game = kyra_settings; game->name; ++game) { 87 if (game->detectName == NULL) 115 // Iterate over all files in the given directory 116 bool isFound = false; 117 for (file = fslist.begin(); file != fslist.end(); file++) { 118 if (file->isDirectory()) 88 119 continue; 89 120 90 for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { 91 if (!file->isDirectory()) { 92 const char *name = file->displayName().c_str(); 93 if ((!scumm_stricmp(game->detectName, name))) { 94 detectedGames.push_back(game->toGameSettings()); 95 break; 96 } 97 } 121 for (g = kyra_games; g->name; g++) { 122 if (scumm_stricmp(file->displayName().c_str(), g->checkFile) == 0) 123 isFound = true; 98 124 } 125 if (isFound) 126 break; 99 127 } 100 128 129 if (file == fslist.end()) 130 return detectedGames; 131 132 uint8 md5sum[16]; 133 char md5str[32 + 1]; 134 135 if (Common::md5_file(file->path().c_str(), md5sum, NULL, kMD5FileSizeLimit)) { 136 for (int i = 0; i < 16; i++) { 137 sprintf(md5str + i * 2, "%02x", (int)md5sum[i]); 138 } 139 for (g = kyra_games; g->name; g++) { 140 if (strcmp(g->md5sum, (char *)md5str) == 0) { 141 detectedGames.push_back(g->toGameSettings()); 142 } 143 } 144 if (detectedGames.isEmpty()) { 145 printf("Unknown MD5 (%s)! Please report the details (language, platform, etc.) of this game to the ScummVM team\n", md5str); 146 147 const KyraGameList *g1 = kyra_list; 148 while (g1->name) { 149 detectedGames.push_back(g1->toGameSettings()); 150 g1++; 151 } 152 } 153 } 101 154 return detectedGames; 102 155 } 103 156 … … 121 174 _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); 122 175 _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); 123 176 124 // gets the game 125 if (detector->_game.features & GF_KYRA1) { 126 if (detector->_game.features & GF_DEMO) { 127 _game = KYRA1DEMO; 128 } else if (detector->_game.features & GF_FLOPPY) { 129 _game = KYRA1; 130 } else { 131 _game = KYRA1CD; 132 } 133 } else if (detector->_game.features & GF_KYRA2) { 134 if (detector->_game.features & GF_FLOPPY) { 135 _game = KYRA2; 136 } else { 137 _game = KYRA2CD; 177 // Detect game features based on MD5. Again brutally ripped from Gobliins. 178 uint8 md5sum[16]; 179 char md5str[32 + 1]; 180 181 const KyraGameSettings *g; 182 bool found = false; 183 184 // TODO 185 // Fallback. Maybe we will be able to determine game type from game 186 // data contents 187 _features = GF_KYRA1; 188 189 for (g = kyra_games; g->name; g++) { 190 if (!Common::File::exists(g->checkFile)) 191 continue; 192 193 if (Common::md5_file(g->checkFile, md5sum, ConfMan.get("path").c_str(), kMD5FileSizeLimit)) { 194 for (int j = 0; j < 16; j++) { 195 sprintf(md5str + j*2, "%02x", (int)md5sum[j]); 196 } 197 } else 198 continue; 199 200 if (strcmp(g->md5sum, (char *)md5str) == 0) { 201 _features = g->features; 202 _game = g->id; 203 204 if (g->description) 205 g_system->setWindowCaption(g->description); 206 207 found = true; 208 break; 138 209 } 139 } else if (detector->_game.features & GF_KYRA3) {140 _game = KYRA3; 141 } else{142 error("unknown game");210 } 211 212 if (!found) { 213 printf("Unknown MD5 (%s)! Please report the details (language, platform, etc.) of this game to the ScummVM team\n", md5str); 143 214 } 144 215 } 145 216 … … 204 275 _quitFlag = false; 205 276 uint32 sz; 206 277 207 if (_ game == KYRA1) {278 if (_features & GF_FLOPPY) { 208 279 _screen->loadFont(Screen::FID_6_FNT, _res->fileData("6.FNT", &sz)); 209 280 } 210 281 _screen->loadFont(Screen::FID_8_FNT, _res->fileData("8FAT.FNT", &sz)); … … 212 283 213 284 _abortIntroFlag = false; 214 285 215 if (_ game == KYRA1DEMO) {286 if (_features & GF_DEMO) { 216 287 seq_demo(); 217 288 } else { 218 289 seq_intro(); … … 321 392 _screen->clearPage(10); 322 393 323 394 // Loading GUI bitmap 324 if (_ game == KYRA1CD) {395 if (_features & GF_ENGLISH && _features & GF_TALKIE) 325 396 loadBitmap("MAIN_ENG.CPS", 10, 10, 0); 326 } else { 397 else if(_features & GF_FRENCH ) 398 loadBitmap("MAIN_FRE.CPS", 10, 10, 0); 399 else if(_features & GF_GERMAN ) 400 loadBitmap("MAIN_GER.CPS", 10, 10, 0); 401 else 327 402 loadBitmap("MAIN15.CPS", 10, 10, 0); 328 }329 403 330 404 // Loading main room background 331 405 strncpy(buf, _rooms[roomID].filename, 8); … … 663 737 664 738 void KyraEngine::seq_intro() { 665 739 debug(9, "KyraEngine::seq_intro()"); 666 if (_ game == KYRA1CD) {740 if (_features & GF_TALKIE) { 667 741 _res->loadPakFile("INTRO.VRM"); 668 742 } 669 743 static const IntroProc introProcTable[] = { … … 686 760 waitTicks(30); 687 761 _seq->setCopyViewOffs(false); 688 762 _midi->stopMusic(); 689 if (_ game == KYRA1CD) {763 if (_features & GF_TALKIE) { 690 764 _res->unloadPakFile("INTRO.VRM"); 691 765 } 692 766 } … … 702 776 _system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200); 703 777 _screen->fadeFromBlack(); 704 778 705 if (_ game == KYRA1) {779 if (_features & GF_FLOPPY) { 706 780 if (_seq->playSequence(_seq_floppyData_WestwoodLogo, _skipIntroFlag)) { 707 781 _screen->fadeToBlack(); 708 782 _screen->clearPage(0); … … 714 788 _screen->clearPage(0); 715 789 return; 716 790 } 717 } else if (_ game == KYRA1CD) {791 } else if (_features & GF_TALKIE) { 718 792 if (_seq->playSequence(_seq_cdromData_WestwoodLogo, _skipIntroFlag)) { 719 793 _screen->fadeToBlack(); 720 794 _screen->clearPage(0); … … 750 824 waitTicks(1); 751 825 } while (y2 >= 64); 752 826 753 if (_ game == KYRA1) {827 if (_features & GF_FLOPPY) { 754 828 _seq->playSequence(_seq_floppyData_Forest, true); 755 } else if (_ game == KYRA1CD) {829 } else if (_features & GF_TALKIE) { 756 830 _seq->playSequence(_seq_cdromData_Forest, true); 757 831 } 758 832 } … … 768 842 debug(9, "KyraEngine::seq_introMalcomTree()"); 769 843 _screen->_curPage = 0; 770 844 _screen->clearPage(3); 771 if (_ game == KYRA1) {845 if (_features & GF_FLOPPY) { 772 846 _seq->playSequence(_seq_floppyData_MalcomTree, true); 773 } else if (_ game == KYRA1CD) {847 } else if (_features & GF_TALKIE) { 774 848 _seq->playSequence(_seq_cdromData_MalcomTree, true); 775 849 } 776 850 } … … 781 855 _screen->setAnimBlockPtr(5060); 782 856 _screen->_charWidth = -2; 783 857 _screen->clearPage(3); 784 if (_ game == KYRA1) {858 if (_features & GF_FLOPPY) { 785 859 _seq->playSequence(_seq_floppyData_KallakWriting, true); 786 } else if (_ game == KYRA1CD) {860 } else if (_features & GF_TALKIE) { 787 861 _seq->playSequence(_seq_cdromData_KallakWriting, true); 788 862 } 789 863 _seq->freeHandShapes(); … … 792 866 void KyraEngine::seq_introKallakMalcom() { 793 867 debug(9, "KyraEngine::seq_introKallakMalcom()"); 794 868 _screen->clearPage(3); 795 if (_ game == KYRA1) {869 if (_features & GF_FLOPPY) { 796 870 _seq->playSequence(_seq_floppyData_KallakMalcom, true); 797 } else if (_ game == KYRA1CD) {871 } else if (_features & GF_TALKIE) { 798 872 _seq->playSequence(_seq_cdromData_KallakMalcom, true); 799 873 } 800 874 } -
kyra/kyra.h
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvmcvs/kyra/kyra.h scummvm/kyra/kyra.h
old new 25 25 #include "base/engine.h" 26 26 #include "common/rect.h" 27 27 #include "sound/mixer.h" 28 #include "common/file.h" 28 29 29 30 class AudioStream; 30 31 … … 39 40 GF_KYRA2 = 1 << 3, 40 41 GF_KYRA3 = 1 << 4, 41 42 GF_AUDIOCD = 1 << 5, // FM-Towns versions seems to use audio CD 42 GF_DEMO = 1 << 6 43 GF_DEMO = 1 << 6, 44 GF_ENGLISH = 1 << 7, 45 GF_FRENCH = 1 << 8, 46 GF_GERMAN = 1 << 9 47 43 48 }; 44 49 45 50 enum { 46 KYRA1 = 0, 47 KYRA1CD = 1, 48 KYRA1DEMO = 2, 49 KYRA2 = 3, 50 KYRA2CD = 4, 51 KYRA3 = 5 51 GI_KYRA1 = 0 52 52 }; 53 53 54 54 struct Character { … … 157 157 158 158 void waitTicks(int ticks); 159 159 160 uint32 _features; 161 160 162 protected: 161 163 162 164 int go(); -
kyra/resource.cpp
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvmcvs/kyra/resource.cpp scummvm/kyra/resource.cpp
old new 30 30 _engine = engine; 31 31 32 32 // No PAK files in the demo version 33 if (_engine-> game() == KYRA1DEMO)33 if (_engine->_features & GF_DEMO) 34 34 return; 35 35 36 36 // prefetches all PAK Files … … 63 63 64 64 const char** usedFilelist = 0; 65 65 66 if (_engine-> game() == KYRA1)66 if (_engine->_features & GF_FLOPPY) 67 67 usedFilelist = kyra1Filelist; 68 else if (_engine-> game() == KYRA1CD)68 else if (_engine->_features & GF_TALKIE) 69 69 usedFilelist = kyra1CDFilelist; 70 70 else 71 71 error("no filelist found for this game"); … … 155 155 156 156 if (!(*size)) 157 157 continue; 158 158 debug("file: '%s'", file); 159 159 buffer = new uint8[*size]; 160 160 assert(buffer); 161 161 -
kyra/screen.cpp
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvmcvs/kyra/screen.cpp scummvm/kyra/screen.cpp
old new 549 549 DrawShapePlotPixelCallback plotPixel = _drawShapePlotPixelTable[ppc]; 550 550 551 551 const uint8 *src = shapeData; 552 if (_vm-> game() == KYRA1CD) {552 if (_vm->_features & GF_TALKIE) { 553 553 src += 2; 554 554 } 555 555 uint16 shapeFlags = READ_LE_UINT16(src); src += 2; -
kyra/seqplayer.cpp
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvmcvs/kyra/seqplayer.cpp scummvm/kyra/seqplayer.cpp
old new 60 60 uint16 numShapes = READ_LE_UINT16(data); 61 61 if (shape < numShapes) { 62 62 uint32 offs = 0; 63 if (_vm-> game() == KYRA1CD) {63 if (_vm->_features & GF_TALKIE) { 64 64 offs = READ_LE_UINT32(data + 2 + shape * 4); 65 65 } else { 66 66 offs = READ_LE_UINT16(data + 2 + shape * 2); … … 98 98 assert(wsaObj < ARRAYSIZE(_seqMovies)); 99 99 uint8 offscreenDecode = *_seqData++; 100 100 _seqWsaCurDecodePage = _seqMovies[wsaObj].page = (offscreenDecode == 0) ? 0 : 3; 101 if (_vm-> game() == KYRA1DEMO) {101 if (_vm->_features & GF_DEMO) { 102 102 _seqMovies[wsaObj].wsa = _vm->wsa_open(KyraEngine::_seq_demo_WSATable[wsaObj], offscreenDecode, 0); 103 103 } else { 104 104 _seqMovies[wsaObj].wsa = _vm->wsa_open(KyraEngine::_seq_WSATable[wsaObj], offscreenDecode, 0); … … 212 212 uint8 colNum = *_seqData++; 213 213 uint32 fileSize; 214 214 uint8 *srcData; 215 if (_vm-> game() == KYRA1DEMO) {215 if (_vm->_features & GF_DEMO) { 216 216 srcData = _res->fileData(KyraEngine::_seq_demo_COLTable[colNum], &fileSize); 217 217 } else { 218 218 srcData = _res->fileData(KyraEngine::_seq_COLTable[colNum], &fileSize); … … 306 306 void SeqPlayer::s1_copyRegionSpecial() { 307 307 static const uint8 colorMap[] = { 0, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0 }; 308 308 const char *copyStr = 0; 309 if (_vm-> game() == KYRA1 || _vm->game() == KYRA1DEMO) {309 if (_vm->_features & GF_FLOPPY || _vm->_features & GF_DEMO) { 310 310 copyStr = "Copyright (c) 1992 Westwood Studios"; 311 } else if (_vm-> game() == KYRA1CD) {311 } else if (_vm->_features & GF_TALKIE) { 312 312 copyStr = "Copyright (c) 1992,1993 Westwood Studios"; 313 313 } 314 314 … … 364 364 365 365 void SeqPlayer::s1_soundUnk2() { 366 366 uint8 msg = *_seqData++; 367 if (_vm-> game() == KYRA1 || _vm->game() == KYRA1DEMO) {367 if (_vm->_features & GF_FLOPPY || _vm->_features & GF_DEMO) { 368 368 switch (msg) { 369 369 case 0: 370 370 // nothing to do here... … … 385 385 warning("Unknown seq. message: %.02d", msg); 386 386 break; 387 387 } 388 } else if (_vm-> game() == KYRA1CD) {388 } else if (_vm->_features & GF_TALKIE) { 389 389 if (msg == 1) { 390 390 _midi->beginFadeOut(); 391 391 } else { … … 395 395 } 396 396 397 397 void SeqPlayer::s1_allocTempBuffer() { 398 if (_vm-> game() == KYRA1DEMO) {398 if (_vm->_features & GF_DEMO) { 399 399 _seqQuitFlag = true; 400 400 } else { 401 401 // allocate offscreen buffer, not needed … … 532 532 533 533 debug(9, "SeqPlayer::seq_playSequence(0x%X, %d)", seqData, skipSeq); 534 534 535 if (_vm-> game() == KYRA1 || _vm->game() == KYRA1DEMO) {535 if (_vm->_features & GF_FLOPPY || _vm->_features & GF_DEMO) { 536 536 commands = floppySeqProcs; 537 537 numCommands = ARRAYSIZE(floppySeqProcs); 538 } else if (_vm-> game() == KYRA1CD) {538 } else if (_vm->_features & GF_TALKIE) { 539 539 commands = cdromSeqProcs; 540 540 numCommands = ARRAYSIZE(cdromSeqProcs); 541 541 } else { -
kyra/wsamovie.cpp
diff --exclude=.cvsignore --exclude=.deps --exclude=CVS -Pur ./scummvmcvs/kyra/wsamovie.cpp scummvm/kyra/wsamovie.cpp
old new 41 41 wsa->deltaBufferSize = READ_LE_UINT16(wsaData); wsaData += 2; 42 42 wsa->offscreenBuffer = NULL; 43 43 wsa->flags = 0; 44 if (_ game == KYRA1CD) {44 if (_features & GF_TALKIE) { 45 45 flags = READ_LE_UINT16(wsaData); wsaData += 2; 46 46 } 47 47