static bool VerifyFile( const std::string &filename, std::string &base_filename, std::string &full_filename, const std::string &hash = "") { std::string ext; M_ExtractFileExtension(filename, ext); base_filename = D_CleanseFileName(filename); if (base_filename.empty()) return false; // is there an exact match for the filename and hash? full_filename = BaseFileSearch(base_filename, "." + ext, hash); if (!full_filename.empty()) return true; // is there a file with matching name even if the hash is incorrect? full_filename = BaseFileSearch(base_filename, "." + ext); if (full_filename.empty()) return false; // if it's an IWAD, check if we have a valid alternative hash std::string found_hash = W_MD5(full_filename); if (W_IsIWAD(base_filename, found_hash)) return true; return false; }
void W_InitMultipleFiles(char **filenames) { char **ptr; byte loaded[64]; // Enough? iwadLoaded = false; // Open all the files, load headers, and count lumps numlumps = 0; lumpinfo = malloc(1); // Will be realloced as lumps are added // This'll force the loader NOT the flag new records Runtime. (?) loadingForStartup = true; memset(loaded, 0, sizeof(loaded)); // IWAD(s) must be loaded first. Let's see if one has been specified // with -iwad or -file options. for(ptr = filenames; *ptr; ptr++) { if(W_IsIWAD(*ptr)) { loaded[ptr - filenames] = true; W_AddFile(*ptr, false); } } // Make sure an IWAD gets loaded; if not, display a warning. W_CheckIWAD(); // Load the rest of the WADs. for(ptr = filenames; *ptr; ptr++) if(!loaded[ptr - filenames]) W_AddFile(*ptr, false); if(!numlumps) { Con_Error("W_InitMultipleFiles: no files found"); } }
// // G_LoadWad // // Determines if the vectors of wad & patch filenames differs from the currently // loaded ones and calls D_DoomWadReboot if so. // bool G_LoadWad( const std::vector<std::string> &newwadfiles, const std::vector<std::string> &newpatchfiles, const std::vector<std::string> &newwadhashes, const std::vector<std::string> &newpatchhashes, const std::string &mapname) { bool AddedIWAD = false; bool Reboot = false; size_t i, j; // Did we pass an IWAD? if (!newwadfiles.empty() && W_IsIWAD(newwadfiles[0])) AddedIWAD = true; // Check our environment, if the same WADs are used, ignore this command. // Did we switch IWAD files? if (AddedIWAD && !wadfiles.empty()) { if (StdStringCompare(M_ExtractFileName(newwadfiles[0]), M_ExtractFileName(wadfiles[1]), true) != 0) Reboot = true; } // Do the sizes of the WAD lists not match up? if (!Reboot) { if (wadfiles.size() - 2 != newwadfiles.size() - (AddedIWAD ? 1 : 0)) Reboot = true; } // Do our WAD lists match up exactly? if (!Reboot) { for (i = 2, j = (AddedIWAD ? 1 : 0); i < wadfiles.size() && j < newwadfiles.size(); i++, j++) { if (StdStringCompare(M_ExtractFileName(newwadfiles[j]), M_ExtractFileName(wadfiles[i]), true) != 0) { Reboot = true; break; } } } // Do the sizes of the patch lists not match up? if (!Reboot) { if (patchfiles.size() != newpatchfiles.size()) Reboot = true; } // Do our patchfile lists match up exactly? if (!Reboot) { for (i = 0, j = 0; i < patchfiles.size() && j < newpatchfiles.size(); i++, j++) { if (StdStringCompare(M_ExtractFileName(newpatchfiles[j]), M_ExtractFileName(patchfiles[i]), true) != 0) { Reboot = true; break; } } } if (Reboot) { D_DoomWadReboot(newwadfiles, newpatchfiles, newwadhashes, newpatchhashes); if (!missingfiles.empty()) return false; } unnatural_level_progression = true; if (mapname.length()) G_DeferedInitNew((char *)mapname.c_str()); else G_DeferedInitNew(startmap); return true; }
// // D_DoomWadReboot // [denis] change wads at runtime // Returns false if there are missing files and fills the missingfiles // vector // // [SL] passing an IWAD as newwadfiles[0] is now optional // TODO: hash checking for patchfiles // bool D_DoomWadReboot( const std::vector<std::string> &newwadfiles, const std::vector<std::string> &newpatchfiles, const std::vector<std::string> &newwadhashes, const std::vector<std::string> &newpatchhashes ) { size_t i; bool hashcheck = (newwadfiles.size() == newwadhashes.size()); missingfiles.clear(); missinghashes.clear(); // already loaded these? if (lastWadRebootSuccess && !wadhashes.empty() && newwadhashes == std::vector<std::string>(wadhashes.begin()+1, wadhashes.end())) { // fast track if files have not been changed // denis - todo - actually check the file timestamps Printf (PRINT_HIGH, "Currently loaded WADs match server checksum\n\n"); return true; } lastWadRebootSuccess = false; if (gamestate == GS_LEVEL) G_ExitLevel(0, 0); S_Stop(); DThinker::DestroyAllThinkers(); // Close all open WAD files W_Close(); // [ML] 9/11/10: Reset custom wad level information from MAPINFO et al. for (i = 0; i < wadlevelinfos.size(); i++) { if (wadlevelinfos[i].snapshot) { delete wadlevelinfos[i].snapshot; wadlevelinfos[i].snapshot = NULL; } } wadlevelinfos.clear(); wadclusterinfos.clear(); // Restart the memory manager Z_Init(); SetLanguageIDs (); gamestate_t oldgamestate = gamestate; gamestate = GS_STARTUP; // prevent console from trying to use nonexistant font // [SL] 2012-12-06 - If we weren't provided with a new IWAD filename in // newwadfiles, use the previous IWAD. std::string iwad_filename, iwad_hash; if ((newwadfiles.empty() || !W_IsIWAD(newwadfiles[0])) && (wadfiles.size() >= 2)) { iwad_filename = wadfiles[1]; iwad_hash = wadhashes[1]; } else if (!newwadfiles.empty()) { iwad_filename = newwadfiles[0]; iwad_hash = hashcheck ? newwadhashes[0] : ""; } wadfiles.clear(); D_AddDefWads(iwad_filename); // add odamex.wad & IWAD // check if the wad files exist and if they match the MD5SUM std::string base_filename, full_filename; if (!VerifyFile(iwad_filename, base_filename, full_filename, iwad_hash)) { Printf(PRINT_HIGH, "could not find WAD: %s\n", base_filename.c_str()); missingfiles.push_back(base_filename); if (hashcheck) missinghashes.push_back(iwad_hash); } for (i = 0; i < newwadfiles.size(); i++) { std::string hash = hashcheck ? newwadhashes[i] : ""; // already added the IWAD with D_AddDefWads if (W_IsIWAD(newwadfiles[i])) continue; if (VerifyFile(newwadfiles[i], base_filename, full_filename, hash)) wadfiles.push_back(full_filename); else { Printf(PRINT_HIGH, "could not find WAD: %s\n", base_filename.c_str()); missingfiles.push_back(base_filename); if (hashcheck) missinghashes.push_back(newwadhashes[i]); } } modifiedgame = (wadfiles.size() > 2) || !patchfiles.empty(); // more than odamex.wad and IWAD? if (modifiedgame && (gameinfo.flags & GI_SHAREWARE)) I_Error("\nYou cannot load additional WADs with the shareware version. Register!"); wadhashes = W_InitMultipleFiles (wadfiles); // get skill / episode / map from parms strcpy(startmap, (gameinfo.flags & GI_MAPxx) ? "MAP01" : "E1M1"); UndoDehPatch(); patchfiles.clear(); // [RH] Initialize localizable strings. GStrings.ResetStrings (); GStrings.Compact (); D_DoDefDehackedPatch(newpatchfiles); D_NewWadInit(); // preserve state lastWadRebootSuccess = missingfiles.empty(); gamestate = oldgamestate; // GS_STARTUP would prevent netcode connecting properly return missingfiles.empty(); }