diff --git a/src/cmdlib.cpp b/src/cmdlib.cpp index f667610c0b..3c2e7e2807 100644 --- a/src/cmdlib.cpp +++ b/src/cmdlib.cpp @@ -184,6 +184,25 @@ bool FileExists (const char *filename) return stat(filename, &buff) == 0 && !(buff.st_mode & S_IFDIR); } +//========================================================================== +// +// DirExists +// +// Returns true if the given path exists and is a directory. +// +//========================================================================== + +bool DirExists(const char *filename) +{ + struct stat buff; + + // [RH] Empty filenames are never there + if (filename == NULL || *filename == 0) + return false; + + return stat(filename, &buff) == 0 && (buff.st_mode & S_IFDIR); +} + //========================================================================== // // DirEntryExists diff --git a/src/cmdlib.h b/src/cmdlib.h index 7af4e630b5..605a56995a 100644 --- a/src/cmdlib.h +++ b/src/cmdlib.h @@ -20,6 +20,7 @@ int Q_filelength (FILE *f); bool FileExists (const char *filename); +bool DirExists(const char *filename); bool DirEntryExists (const char *pathname); extern FString progdir; diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 2a8504dc16..1db1981bf7 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -48,80 +48,38 @@ #include "gameconfigfile.h" #include "resourcefiles/resourcefile.h" #include "version.h" +#include "doomerrors.h" +#include "v_text.h" CVAR (Bool, queryiwad, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); CVAR (String, defaultiwad, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG); -//========================================================================== -// -// Clear check list -// -//========================================================================== - -void FIWadManager::ClearChecks() -{ - mLumpsFound.Resize(mIWads.Size()); - for(unsigned i=0;i 1) + { + sc.ScriptMessage("Multiple IWAD records ignored"); + // Skip the rest. + break; + } + + FIWADInfo *iwad = result ? result : &mIWadInfos[mIWadInfos.Reserve(1)]; sc.MustGetStringName("{"); while (!sc.CheckString("}")) { @@ -138,6 +96,17 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize) sc.MustGetString(); iwad->Autoname = sc.String; } + else if (sc.Compare("IWadname")) + { + sc.MustGetStringName("="); + sc.MustGetString(); + iwad->IWadname = sc.String; + if (sc.CheckString(",")) + { + sc.MustGetNumber(); + iwad->prio = sc.Number; + } + } else if (sc.Compare("Config")) { sc.MustGetStringName("="); @@ -225,7 +194,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize) iwad->MapInfo = "mapinfo/mindefaults.txt"; } } - else if (sc.Compare("NAMES")) + else if (result == nullptr && sc.Compare("NAMES")) { sc.MustGetStringName("{"); mIWadNames.Push(FString()); @@ -247,6 +216,19 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize) #endif } } + else if (result == nullptr && sc.Compare("ORDER")) + { + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + mOrderNames.Push(sc.String); + } + } + else + { + sc.ScriptError("Unknown keyword '%s'", sc.String); + } } } @@ -256,7 +238,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize) // //========================================================================== -void FIWadManager::ParseIWadInfos(const char *fn) +FIWadManager::FIWadManager(const char *fn) { FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, NULL, true); if (resfile != NULL) @@ -275,7 +257,7 @@ void FIWadManager::ParseIWadInfos(const char *fn) } delete resfile; } - if (mIWadNames.Size() == 0 || mIWads.Size() == 0) + if (mIWadNames.Size() == 0 || mIWadInfos.Size() == 0) { I_FatalError("No IWAD definitions found"); } @@ -293,9 +275,25 @@ int FIWadManager::ScanIWAD (const char *iwad) { FResourceFile *iwadfile = FResourceFile::OpenResourceFile(iwad, NULL, true); + mLumpsFound.Resize(mIWadInfos.Size()); + + auto CheckLumpName = [=](const char *name) + { + for (unsigned i = 0; i< mIWadInfos.Size(); i++) + { + for (unsigned j = 0; j < mIWadInfos[i].Lumps.Size(); j++) + { + if (!mIWadInfos[i].Lumps[j].CompareNoCase(name)) + { + mLumpsFound[i] |= (1 << j); + } + } + } + }; + if (iwadfile != NULL) { - ClearChecks(); + memset(&mLumpsFound[0], 0, mLumpsFound.Size() * sizeof(mLumpsFound[0])); for(uint32_t ii = 0; ii < iwadfile->LumpCount(); ii++) { FResourceLump *lump = iwadfile->GetLump(ii); @@ -312,52 +310,170 @@ int FIWadManager::ScanIWAD (const char *iwad) } delete iwadfile; } - return GetIWadInfo(); + for (unsigned i = 0; i< mIWadInfos.Size(); i++) + { + if (mLumpsFound[i] == (1 << mIWadInfos[i].Lumps.Size()) - 1) + { + DPrintf(DMSG_NOTIFY, "Identified %s as %s\n", iwad, mIWadInfos[i].Name.GetChars()); + return i; + } + } + return -1; } //========================================================================== // -// CheckIWAD +// Look for IWAD definition lump // -// Tries to find an IWAD from a set of known IWAD names, and checks the -// contents of each one found to determine which game it belongs to. -// Returns the number of new wads found in this pass (does not count wads -// found from a previous call). -// //========================================================================== -int FIWadManager::CheckIWAD (const char *doomwaddir, WadStuff *wads) +int FIWadManager::CheckIWADInfo(const char *fn) { - const char *slash; - int numfound; - - numfound = 0; - - slash = (doomwaddir[0] && doomwaddir[strlen (doomwaddir)-1] != '/') ? "/" : ""; - - // Search for a pre-defined IWAD - for (unsigned i=0; i< mIWadNames.Size(); i++) + FResourceFile *resfile = FResourceFile::OpenResourceFile(fn, NULL, true); + if (resfile != NULL) { - if (mIWadNames[i].IsNotEmpty() && wads[i].Path.IsEmpty()) + uint32_t cnt = resfile->LumpCount(); + for (int i = cnt - 1; i >= 0; i--) { - FString iwad; - - iwad.Format ("%s%s%s", doomwaddir, slash, mIWadNames[i].GetChars()); - FixPathSeperator (iwad); - if (FileExists (iwad)) + FResourceLump *lmp = resfile->GetLump(i); + + if (lmp->Namespace == ns_global && !stricmp(lmp->Name, "IWADINFO")) { - wads[i].Type = ScanIWAD (iwad); - if (wads[i].Type != -1) + // Found one! + try { - wads[i].Path = iwad; - wads[i].Name = mIWads[wads[i].Type].Name; - numfound++; + FIWADInfo result; + ParseIWadInfo(resfile->Filename, (const char*)lmp->CacheLump(), lmp->LumpSize, &result); + delete resfile; + for (auto &wadinf : mIWadInfos) + { + if (wadinf.Name.Compare(result.Name)) + { + return -1; // do not show the same one twice. + } + } + return mIWadInfos.Push(result); } + catch (CRecoverableError &err) + { + delete resfile; + Printf(TEXTCOLOR_RED "%s: %s\nFile has been removed from the list of IWADs\n", fn, err.GetMessage()); + return -1; + } + break; + } + } + delete resfile; + Printf(TEXTCOLOR_RED "%s: Unable to find IWADINFO\nFile has been removed from the list of IWADs\n", fn); + return -1; + } + Printf(TEXTCOLOR_RED "%s: Unable to open as resource file.\nFile has been removed from the list of IWADs\n", fn); + return -1; +} + +//========================================================================== +// +// CollectSearchPaths +// +// collect all paths in a local array for easier management +// +//========================================================================== + +void FIWadManager::CollectSearchPaths() +{ + if (GameConfig->SetSection("IWADSearch.Directories")) + { + const char *key; + const char *value; + + while (GameConfig->NextInSection(key, value)) + { + if (stricmp(key, "Path") == 0) + { + FString nice = NicePath(value); + if (nice.Len() > 0) mSearchPaths.Push(nice); } } } + mSearchPaths.Append(I_GetGogPaths()); + mSearchPaths.Append(I_GetSteamPath()); - return numfound; + // Unify and remove trailing slashes + for (auto &str : mSearchPaths) + { + FixPathSeperator(str); + if (str[str.Len() - 1] == '/') str.Truncate(str.Len() - 1); + } +} + +//========================================================================== +// +// AddIWADCandidates +// +// scans the given directory and adds all potential IWAD candidates +// +//========================================================================== + +void FIWadManager::AddIWADCandidates(const char *dir) +{ + void *handle; + findstate_t findstate; + FStringf slasheddir("%s/", dir); + FString findmask = slasheddir + "*.*"; + if ((handle = I_FindFirst(findmask, &findstate)) != (void *)-1) + { + do + { + if (!(I_FindAttr(&findstate) & FA_DIREC)) + { + auto p = strrchr(findstate.Name, '.'); + if (p != nullptr) + { + // special IWAD extension. + if (!stricmp(p, ".iwad") || !stricmp(p, ".ipk3") || !stricmp(p, "ipk7")) + { + mFoundWads.Push(FFoundWadInfo{ slasheddir + findstate.Name, "", -1 }); + } + } + for (auto &name : mIWadNames) + { + if (!stricmp(name, findstate.Name)) + { + mFoundWads.Push(FFoundWadInfo{ slasheddir + name, "", -1 }); + } + } + } + } while (I_FindNext(handle, &findstate) == 0); + I_FindClose(handle); + } +} + +//========================================================================== +// +// ValidateIWADs +// +// validate all found candidates and eliminate the bogus ones. +// +//========================================================================== + +void FIWadManager::ValidateIWADs() +{ + TArray returns; + unsigned originalsize = mIWadInfos.Size(); + for (auto &p : mFoundWads) + { + int index; + auto x = strrchr(p.mFullPath, '.'); + if (x != nullptr && (!stricmp(x, ".iwad") || !stricmp(x, ".ipk3") || !stricmp(x, "ipk7"))) + { + index = CheckIWADInfo(p.mFullPath); + } + else + { + index = ScanIWAD(p.mFullPath); + } + p.mInfoIndex = index; + } } //========================================================================== @@ -385,129 +501,132 @@ static bool havepicked = false; int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, const char *zdoom_wad) { - TArray wads; - TArray foundwads; const char *iwadparm = Args->CheckValue ("-iwad"); - int pickwad; - size_t numwads; - size_t i; - bool iwadparmfound = false; FString custwad; - wads.Resize(mIWadNames.Size()); - foundwads.Resize(mIWads.Size()); - memset(&foundwads[0], 0, foundwads.Size() * sizeof(foundwads[0])); + CollectSearchPaths(); - if (iwadparm == NULL && iwad != NULL && *iwad != 0) + // Collect all IWADs in the search path + for (auto &dir : mSearchPaths) { - iwadparm = iwad; + AddIWADCandidates(dir); } + unsigned numFoundWads = mFoundWads.Size(); if (iwadparm) { + // Check if the given IWAD has an absolute path, in which case the search path will be ignored. custwad = iwadparm; - FixPathSeperator (custwad); - if (CheckIWAD (custwad, &wads[0])) - { // -iwad parameter was a directory - iwadparm = NULL; + FixPathSeperator(custwad); + bool isAbsolute = (custwad[0] == '/'); +#ifdef WINDOWS + isAbsolute |= (custwad.Len() >= 2 && custwad[1] == ':'); +#endif + if (isAbsolute) + { + if (FileExists(custwad)) mFoundWads.Push({ custwad, "", -1 }); } else { - DefaultExtension (custwad, ".wad"); - iwadparm = custwad; - mIWadNames[0] = custwad; - CheckIWAD ("", &wads[0]); - } - } - - if (iwadparm == NULL || wads[0].Path.IsEmpty() || mIWads[wads[0].Type].Required.IsNotEmpty()) - { - if (GameConfig->SetSection ("IWADSearch.Directories")) - { - const char *key; - const char *value; - - while (GameConfig->NextInSection (key, value)) + for (auto &dir : mSearchPaths) { - if (stricmp (key, "Path") == 0) + FStringf fullpath("%s/%s", dir, custwad.GetChars()); + if (FileExists(fullpath)) { - FString nice = NicePath(value); - FixPathSeperator(nice); - CheckIWAD(nice, &wads[0]); + mFoundWads.Push({ fullpath, "", -1 }); } } } - TArray gog_paths = I_GetGogPaths(); - for (i = 0; i < gog_paths.Size(); ++i) - { - CheckIWAD (gog_paths[i], &wads[0]); - } - TArray steam_path = I_GetSteamPath(); - for (i = 0; i < steam_path.Size(); ++i) - { - CheckIWAD (steam_path[i], &wads[0]); - } } + // -iwad not found or not specified. Revert back to standard behavior. + if (mFoundWads.Size() == numFoundWads) iwadparm = nullptr; - if (iwadparm != NULL && !wads[0].Path.IsEmpty()) - { - iwadparmfound = true; - } + // Now check if what got collected actually is an IWAD. + ValidateIWADs(); - for (i = numwads = 0; i < mIWadNames.Size(); i++) + // Check for required dependencies. + for (unsigned i = 0; i < mFoundWads.Size(); i++) { - if (!wads[i].Path.IsEmpty()) + auto infndx = mFoundWads[i].mInfoIndex; + if (infndx >= 0) { - if (i != numwads) + auto &wadinfo = mIWadInfos[infndx]; + if (wadinfo.Required.IsNotEmpty()) { - wads[numwads] = wads[i]; - } - foundwads[wads[numwads].Type] = numwads + 1; - numwads++; - } - } - - for (unsigned i=0; i= 0) { - found = true; - mIWads[i].preload = j; - } - break; - } - } - // The required WAD is not there so this one can't be used and must be deleted from the list - if (!found) - { - size_t kill = foundwads[i]; - for (size_t j = kill; j < numwads; ++j) - { - wads[j - 1] = wads[j]; - } - numwads--; - foundwads[i] = 0; - for (unsigned j = 0; j < foundwads.Size(); ++j) - { - if (foundwads[j] > kill) - { - foundwads[j]--; + if (!mIWadInfos[infndx].Required.Compare(mIWadInfos[inf2ndx].Name)) + { + mFoundWads[i].mRequiredPath = mFoundWads[j].mFullPath; + break; + } } } - + // The required dependency was not found. Skip this IWAD. + if (mFoundWads[i].mRequiredPath.IsEmpty()) mFoundWads[i].mInfoIndex = -1; } } } + TArray picks; + if (numFoundWads < mFoundWads.Size()) + { + // We have a -iwad parameter. Pick the first usable IWAD we found through that. + for (unsigned i = numFoundWads; i < mFoundWads.Size(); i++) + { + if (mFoundWads[i].mInfoIndex > 0) + { + picks.Push(mFoundWads[i]); + break; + } + } + } + else if (iwad != nullptr && *iwad != 0) + { + int pickedprio = -1; + // scan the list of found IWADs for a matching one for the current PWAD. + for (auto &found : mFoundWads) + { + if (mIWadInfos[found.mInfoIndex].IWadname.CompareNoCase(iwad) == 0 && mIWadInfos[found.mInfoIndex].prio > pickedprio) + { + picks.Clear(); + picks.Push(found); + pickedprio = mIWadInfos[found.mInfoIndex].prio; + } + } + } + if (picks.Size() == 0) + { + // Now sort what we found and discard all duplicates. + for (unsigned i = 0; i < mOrderNames.Size(); i++) + { + bool picked = false; + for (int j = 0; j < (int)mFoundWads.Size(); j++) + { + if (mIWadInfos[mFoundWads[j].mInfoIndex].Name.Compare(mOrderNames[i]) == 0) + { + if (!picked) + { + picked = true; + picks.Push(mFoundWads[j]); + } + mFoundWads.Delete(j--); + } + } + } + // What's left is IWADs with their own IWADINFO. Copy those in order of discovery. + for (auto &entry : mFoundWads) + { + if (entry.mInfoIndex >= 0) picks.Push(entry); + } + } - if (numwads == 0) + // If we still haven't found a suitable IWAD let's error out. + if (picks.Size() == 0) { I_FatalError ("Cannot find a game IWAD (doom.wad, doom2.wad, heretic.wad, etc.).\n" "Did you install " GAMENAME " properly? You can do either of the following:\n" @@ -526,38 +645,50 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, "iwads to the list beneath [IWADSearch.Directories]"); #endif } + int pick = 0; - pickwad = 0; - - if (!iwadparmfound && numwads > 1) + // We got more than one so present the IWAD selection box. + if (picks.Size() > 1) { - int defiwad = 0; - // Locate the user's prefered IWAD, if it was found. if (defaultiwad[0] != '\0') { - for (i = 0; i < numwads; ++i) + for (unsigned i = 0; i < picks.Size(); ++i) { - FString basename = ExtractFileBase(wads[i].Path); - if (stricmp(basename, defaultiwad) == 0) + FString basename = mIWadInfos[picks[i].mInfoIndex].Name; + FString defname = ExtractFileBase(defaultiwad); + if (stricmp(basename, defname) == 0) { - defiwad = (int)i; + // Delete all but the wanted one. + pick = i; break; } } } - if (!havepicked) // just use the first IWAD if the restart doesn't have a -iwad parameter. We cannot open the picker in fullscreen mode. + if (picks.Size() > 1) { - pickwad = I_PickIWad(&wads[0], (int)numwads, queryiwad, defiwad); - if (pickwad >= 0) + if (!havepicked) { - // The newly selected IWAD becomes the new default - FString basename = ExtractFileBase(wads[pickwad].Path); - defaultiwad = basename; + TArray wads; + for (auto & found : picks) + { + WadStuff stuff; + stuff.Name = mIWadInfos[found.mInfoIndex].Name; + stuff.Path = ExtractFileBase(found.mFullPath); + wads.Push(stuff); + } + pick = I_PickIWad(&wads[0], (int)wads.Size(), queryiwad, pick); + if (pick >= 0) + { + // The newly selected IWAD becomes the new default + defaultiwad = mIWadInfos[picks[pick].mInfoIndex].Name; + } + else + { + exit(0); + } + havepicked = true; } - if (pickwad < 0) - exit(0); - havepicked = true; } } @@ -565,15 +696,17 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, wadfiles.Clear(); D_AddFile (wadfiles, zdoom_wad); - if (mIWads[wads[pickwad].Type].preload >= 0) + if (picks[pick].mRequiredPath.IsNotEmpty()) { - D_AddFile (wadfiles, wads[foundwads[mIWads[wads[pickwad].Type].preload]-1].Path); + D_AddFile (wadfiles, picks[pick].mRequiredPath); } - D_AddFile (wadfiles, wads[pickwad].Path); + D_AddFile (wadfiles, picks[pick].mFullPath); - for (unsigned i=0; i < mIWads[wads[pickwad].Type].Load.Size(); i++) + auto info = mIWadInfos[picks[pick].mInfoIndex]; + // Load additional resources from the same directory as the IWAD itself. + for (unsigned i=0; i < info.Load.Size(); i++) { - long lastslash = wads[pickwad].Path.LastIndexOf ('/'); + long lastslash = picks[pick].mFullPath.LastIndexOf ('/'); FString path; if (lastslash == -1) @@ -582,13 +715,13 @@ int FIWadManager::IdentifyVersion (TArray &wadfiles, const char *iwad, } else { - path = FString (wads[pickwad].Path.GetChars(), lastslash + 1); + path = FString (picks[pick].mFullPath.GetChars(), lastslash + 1); } - path += mIWads[wads[pickwad].Type].Load[i]; + path += info.Load[i]; D_AddFile (wadfiles, path); } - return wads[pickwad].Type; + return picks[pick].mInfoIndex; } @@ -602,7 +735,7 @@ const FIWADInfo *FIWadManager::FindIWAD(TArray &wadfiles, const char *i { int iwadType = IdentifyVersion(wadfiles, iwad, basewad); //gameiwad = iwadType; - const FIWADInfo *iwad_info = &mIWads[iwadType]; + const FIWADInfo *iwad_info = &mIWadInfos[iwadType]; if (DoomStartupInfo.Name.IsEmpty()) DoomStartupInfo.Name = iwad_info->Name; if (DoomStartupInfo.BkColor == 0 && DoomStartupInfo.FgColor == 0) { diff --git a/src/d_main.cpp b/src/d_main.cpp index dd69b7d0d2..901884a174 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2342,8 +2342,7 @@ void D_DoomMain (void) } FString basewad = wad; - iwad_man = new FIWadManager; - iwad_man->ParseIWadInfos(basewad); + iwad_man = new FIWadManager(basewad); // Now that we have the IWADINFO, initialize the autoload ini sections. GameConfig->DoAutoloadSetup(iwad_man); @@ -2373,8 +2372,7 @@ void D_DoomMain (void) if (iwad_man == NULL) { - iwad_man = new FIWadManager; - iwad_man->ParseIWadInfos(basewad); + iwad_man = new FIWadManager(basewad); } const FIWADInfo *iwad_info = iwad_man->FindIWAD(allwads, iwad, basewad); gameinfo.gametype = iwad_info->gametype; diff --git a/src/d_main.h b/src/d_main.h index b7b9fabcdf..0cbdd9102c 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -70,29 +70,38 @@ extern uint32_t r_renderercaps; struct WadStuff { - WadStuff() : Type(0) {} - FString Path; FString Name; - int Type; }; struct FIWADInfo { FString Name; // Title banner text for this IWAD FString Autoname; // Name of autoload ini section for this IWAD + FString IWadname; // Default name this game would use - this is for IWAD detection in GAMEINFO. + int prio = 0; // selection priority for given IWAD name. FString Configname; // Name of config section for this IWAD FString Required; // Requires another IWAD - uint32_t FgColor; // Foreground color for title banner - uint32_t BkColor; // Background color for title banner - EGameType gametype; // which game are we playing? + uint32_t FgColor = 0; // Foreground color for title banner + uint32_t BkColor = 0xc0c0c0; // Background color for title banner + EGameType gametype = GAME_Doom; // which game are we playing? FString MapInfo; // Base mapinfo to load TArray Load; // Wads to be loaded with this one. TArray Lumps; // Lump names for identification - int flags; - int preload; + int flags = 0; +}; - FIWADInfo() { flags = 0; preload = -1; FgColor = 0; BkColor= 0xc0c0c0; gametype = GAME_Doom; } +struct FFoundWadInfo +{ + FString mFullPath; + FString mRequiredPath; + int mInfoIndex = -1; // must be an index because of reallocation + + FFoundWadInfo() {} + FFoundWadInfo(const FString &s1, const FString &s2, int index) + : mFullPath(s1), mRequiredPath(s2), mInfoIndex(index) + { + } }; struct FStartupInfo @@ -123,28 +132,31 @@ extern FStartupInfo DoomStartupInfo; class FIWadManager { - TArray mIWads; + TArray mIWadInfos; TArray mIWadNames; + TArray mSearchPaths; + TArray mOrderNames; + TArray mFoundWads; TArray mLumpsFound; - void ParseIWadInfo(const char *fn, const char *data, int datasize); - void ClearChecks(); - void CheckLumpName(const char *name); - int GetIWadInfo(); + void ParseIWadInfo(const char *fn, const char *data, int datasize, FIWADInfo *result = nullptr); int ScanIWAD (const char *iwad); - int CheckIWAD (const char *doomwaddir, WadStuff *wads); + int CheckIWADInfo(const char *iwad); int IdentifyVersion (TArray &wadfiles, const char *iwad, const char *zdoom_wad); + void CollectSearchPaths(); + void AddIWADCandidates(const char *dir); + void ValidateIWADs(); public: - void ParseIWadInfos(const char *fn); + FIWadManager(const char *fn); const FIWADInfo *FindIWAD(TArray &wadfiles, const char *iwad, const char *basewad); const FString *GetAutoname(unsigned int num) const { - if (num < mIWads.Size()) return &mIWads[num].Autoname; + if (num < mIWadInfos.Size()) return &mIWadInfos[num].Autoname; else return NULL; } int GetIWadFlags(unsigned int num) const { - if (num < mIWads.Size()) return mIWads[num].flags; + if (num < mIWadInfos.Size()) return mIWadInfos[num].flags; else return false; } diff --git a/src/tarray.h b/src/tarray.h index c8731f984b..92a456550a 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -242,6 +242,15 @@ public: ::new((void*)&Array[Count]) T(item); return Count++; } + void Append(const TArray &item) + { + unsigned start = Reserve(item.Size()); + for (unsigned i = 0; i < item.Size(); i++) + { + Array[start + i] = item[i]; + } + } + bool Pop () { if (Count > 0) diff --git a/wadsrc/static/iwadinfo.txt b/wadsrc/static/iwadinfo.txt index 37f9473172..c1056e6730 100644 --- a/wadsrc/static/iwadinfo.txt +++ b/wadsrc/static/iwadinfo.txt @@ -1,5 +1,17 @@ // Must be sorted in identification order (easiest to recognize first!) +IWad +{ + Name = "Rise Of The Wool Ball" + Autoname = "woolball.rotwb" + Game = "Doom" + Config = "WoolBall" + IWADName = "rotwb.wad" + Mapinfo = "mapinfo/doom2.txt" + MustContain = "E3M6", "B3DED", "WORLDMAP", "NUCLSKYM", "PLANETLE", "MEOWZEKI", "ZEKIINTR", "NOWAYBAC" + BannerColors = "32 54 43", "c6 dc d1" +} + IWad { Name = "Delaweare" @@ -7,6 +19,7 @@ IWad Game = "Doom" Config = "Delaweare" Mapinfo = "mapinfo/doom2.txt" + IWADName = "delaweare.wad" MustContain = "TITLEMAP", "ROVEA0", "GRLURD01", "SQOUI01" BannerColors = "00 00 00", "ff ff ff" } @@ -17,6 +30,7 @@ IWad Autoname = "square.square" Game = "Doom" Config = "Square" + IWADName = "square.pk3" Mapinfo = "mapinfo/mindefaults.txt" MustContain = "SQU-IWAD", "E1A1" BannerColors = "ff ff ff", "80 00 80" @@ -28,6 +42,7 @@ IWad Autoname = "square.squareware" Game = "Doom" Config = "Square" + IWADName = "square1.pk3" Mapinfo = "mapinfo/mindefaults.txt" MustContain = "SQU-SWE1", "E1A1" BannerColors = "ff ff ff", "80 00 80" @@ -39,6 +54,7 @@ IWad Autoname = "harmony" Game = "Doom" Config = "Harmony" + IWADName = "harm1.wad" Mapinfo = "mapinfo/harmony.txt" MustContain = "MAP01", "0HAWK01", "0CARA3", "0NOSE1" BannerColors = "6e b4 d6", "45 4f 7e" @@ -50,6 +66,7 @@ IWad Game = "Doom" Config = "Hacx" Autoname = "hacx.hacx2" + IWADName = "hacx2.wad" Mapinfo = "mapinfo/hacx.txt" MustContain = "MAP01", "HACX-E" BannerColors = "ff ff ff", "00 88 22" @@ -61,6 +78,7 @@ IWad Game = "Doom" Config = "Hacx" Autoname = "hacx.hacx1" + IWADName = "hacx.wad" Mapinfo = "mapinfo/hacx.txt" MustContain = "MAP01", "HACX-R" BannerColors = "00 00 a8", "a8 a8 a8" @@ -72,6 +90,7 @@ IWad Autoname = "urbanbrawl" Game = "Doom" Config = "UrbanBrawl" + IWADName = "action2.wad" Mapinfo = "mapinfo/urbanbrawl.txt" MustContain = "MAP01", "AD2LIB" BannerColors = "a8 a8 00", "a8 00 00" @@ -83,6 +102,7 @@ IWad Autoname = "chex.chex3" Game = "Chex" Config = "Chex" + IWADName = "chex3.wad" Mapinfo = "mapinfo/chex.txt" Compatibility = "NoTextcolor" MustContain = "E1M1", "CYCLA1", "FLMBA1", "MAPINFO" @@ -95,6 +115,7 @@ IWad Autoname = "chex.chex1" Game = "Chex" Config = "Chex" + IWADName = "chex.wad" Mapinfo = "mapinfo/chex.txt" MustContain = "E1M1", "E4M1", "W94_1", "POSSH0M0" BannerColors = "ff ff 00", "00 c0 00" @@ -106,6 +127,7 @@ IWad Autoname = "strife.veteran" Game = "Strife" Config = "Strife" + IWADName = "sve.wad" Mapinfo = "mapinfo/strife.txt" MustContain = "MAP35", "I_RELB", "FXAA_F" BannerColors = "f0 f0 f0", "6b 3c 18" @@ -119,6 +141,7 @@ IWad Autoname = "strife.strife" Game = "Strife" Config = "Strife" + IWADName = "strife1.wad" Mapinfo = "mapinfo/strife.txt" MustContain = "MAP01", "MAP33", "ENDSTRF" BannerColors = "d0 ad 99", "00 6b 65" @@ -155,6 +178,7 @@ IWad Game = "Hexen" Config = "Hexen" Autoname = "hexen.hexen" + IWADName = "hexen.wad" Mapinfo = "mapinfo/hexen.txt" Compatibility = "Poly1" MustContain = "TITLE", "MAP01", "MAP40", "WINNOWR" @@ -191,6 +215,7 @@ IWad Autoname = "blasphemer" Game = "Heretic" Config = "Heretic" + IWADName = "blasphemer.wad" Mapinfo = "mapinfo/heretic.txt" MustContain = "E1M1", "E2M1", "TITLE", "BLASPHEM" BannerColors = "73 00 00", "00 00 00" @@ -202,6 +227,7 @@ IWad Autoname = "heretic.shadow" Game = "Heretic" Config = "Heretic" + IWADName = "heretic.wad" Mapinfo = "mapinfo/heretic.txt" Compatibility = "Extended" MustContain = "E1M1", "E2M1", "TITLE", "MUS_E1M1", "EXTENDED" @@ -213,6 +239,7 @@ IWad Name = "Heretic" Game = "Heretic" Config = "Heretic" + IWADName = "heretic.wad" Autoname = "heretic.heretic" Mapinfo = "mapinfo/heretic.txt" MustContain = "E1M1", "E2M1", "TITLE", "MUS_E1M1" @@ -236,6 +263,7 @@ IWad Autoname = "doom.freedoom.freedm" Game = "Doom" Config = "Doom" + IWADName = "freedm.wad" Mapinfo = "mapinfo/doom2.txt" MustContain = "MAP01", "FREEDM" BannerColors = "32 54 43", "c6 dc d1" @@ -247,6 +275,7 @@ IWad Autoname = "doom.freedoom.phase2" Game = "Doom" Config = "Doom" + IWADName = "freedoom2.wad" Mapinfo = "mapinfo/doom2.txt" MustContain = "MAP01", "FREEDOOM" BannerColors = "32 54 43", "c6 dc d1" @@ -258,6 +287,7 @@ IWad Autoname = "doom.freedoom.phase1" Game = "Doom" Config = "Doom" + IWADName = "freedoom1.wad" Mapinfo = "mapinfo/doom1.txt" MustContain = "E1M1", "E2M1", "E3M1", "FREEDOOM" BannerColors = "32 54 43", "c6 dc d1" @@ -280,6 +310,7 @@ IWad Autoname = "doom.doom1.bfg" Game = "Doom" Config = "Doom" + IWADName = "doom.wad", 2 Mapinfo = "mapinfo/ultdoom.txt" Compatibility = "Shorttex" MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9", @@ -307,6 +338,7 @@ IWad Autoname = "doom.doom1.ultimate" Game = "Doom" Config = "Doom" + IWADName = "doom.wad" Mapinfo = "mapinfo/ultdoom.txt" Compatibility = "Shorttex" MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9", @@ -321,6 +353,7 @@ IWad Autoname = "doom.doom1.registered" Game = "Doom" Config = "Doom" + IWADName = "doom.wad", 1 Mapinfo = "mapinfo/doom1.txt" Compatibility = "Shorttex" MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9", @@ -329,17 +362,6 @@ IWad BannerColors = "54 54 54", "a8 a8 a8" } -IWad -{ - Name = "Rise Of The Wool Ball" - Autoname = "woolball.rotwb" - Game = "Doom" - Config = "WoolBall" - Mapinfo = "mapinfo/doom2.txt" - MustContain = "E3M6", "B3DED", "WORLDMAP", "NUCLSKYM", "PLANETLE", "MEOWZEKI", "ZEKIINTR", "NOWAYBAC" - BannerColors = "32 54 43", "c6 dc d1" -} - IWad { Name = "DOOM Shareware" @@ -357,6 +379,7 @@ IWad Autoname = "doom.doom2.tnt" Game = "Doom" Config = "Doom" + IWADName = "tnt.wad" Mapinfo = "mapinfo/tnt.txt" Compatibility = "Shorttex", "Stairs" MustContain = "MAP01", "REDTNT2" @@ -369,6 +392,7 @@ IWad Autoname = "doom.doom2.plutonia" Game = "Doom" Config = "Doom" + IWADName = "plutonia.wad" Mapinfo = "mapinfo/plutonia.txt" Compatibility = "Shorttex" MustContain = "MAP01", "CAMO1" @@ -381,6 +405,7 @@ IWad Autoname = "doom.doom2.bfg" Game = "Doom" Config = "Doom" + IWADName = "doom2.wad" Mapinfo = "mapinfo/doom2bfg.txt" Compatibility = "Shorttex" MustContain = "MAP01", "DMENUPIC", "M_ACPT", "M_CAN", "M_EXITO", "M_CHG" @@ -388,16 +413,6 @@ IWad Load = "nerve.wad" } -IWad -{ - Name = "WolfenDoom: Blade of Agony" - Game = "Doom" - BannerColors = "E30000", "E3E3E3" - Mapinfo = "mapinfo/doom2.txt" - MustContain = "BOALIB", "C1M1", "Episode3", "MSPUB0" - Config = "BoA" -} - // Doom 2 must be last to be checked becaude MAP01 is its only requirement IWad { @@ -405,6 +420,7 @@ IWad Autoname = "doom.doom2.commercial" Game = "Doom" Config = "Doom" + IWADName = "doom2.wad", 1 Mapinfo = "mapinfo/doom2.txt" Compatibility = "Shorttex" MustContain = "MAP01" @@ -412,7 +428,6 @@ IWad } - Names { "doom_complete.pk3" @@ -454,5 +469,41 @@ Names "square1.pk3" "delaweare.wad" "rotwb.wad" - "boa_c2.pk3" +} + +Order // Order in the IWAD selection box +{ + "DOOM: Complete: WadSmoosh" + "DOOM 2: Hell on Earth" + "Final Doom: Plutonia Experiment" + "Final Doom: TNT - Evilution" + "The Ultimate DOOM" + "DOOM Registered" + "DOOM Shareware" + "DOOM 2: BFG Edition" + "DOOM: BFG Edition" + "Freedoom: Phase 1" + "Freedoom: Phase 2" + "FreeDM" + "Heretic" + "Heretic: Shadow of the Serpent Riders" + "Heretic Shareware" + "Hexen: Beyond Heretic" + "Hexen: Deathkings of the Dark Citadel" + "Hexen: Demo Version" + "Strife: Quest for the Sigil" + "Strife: Veteran Edition" + "Strife: Teaser (Old Version)" + "Strife: Teaser (New Version)" + "Blasphemer" + "Chex(R) Quest" + "Chex(R) Quest 3" + "Action Doom 2: Urban Brawl" + "Harmony" + "Hacx: Twitch'n Kill" + "Hacx 2.0" + "The Adventures of Square" + "The Adventures of Square (Square-ware)" + "Delaweare" + "Rise Of The Wool Ball" }