diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5326ee3aa0..bf9dcdb6ee 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,11 @@ January 1, 2010 (Changes by Graf Zahl) +- added initial support for a GAMEINFO lump in PWADs. When the game is started + all files loaded with '-file' are scanned for this lump. This lump is read + before any WAD initialization takes place, in particular the IWAD is not yet + loaded at this time. This allows PWADs the option to specify an IWAD they + want to run with and optionally autoload external resource WADs. +- Fixed a few places where FixPathSeperator was called with a locked FString buffer. + It's better to use the FString version of this function instead. - replaced wadlist_t with an array of FStrings and added a list parameter to everything that eventually calls D_AddFile. Also create the list of files loaded on the command line separately to allow further checks on them. diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 421a35e4ac..075f5f700c 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -446,8 +446,7 @@ static int CheckIWAD (const char *doomwaddir, WadStuff *wads) FString iwad; iwad.Format ("%s%s%s", doomwaddir, slash, IWADNames[i]); - FixPathSeperator (iwad.LockBuffer()); - iwad.UnlockBuffer(); + FixPathSeperator (iwad); if (FileExists (iwad)) { wads[i].Type = ScanIWAD (iwad); @@ -484,7 +483,7 @@ static int CheckIWAD (const char *doomwaddir, WadStuff *wads) // //========================================================================== -static EIWADType IdentifyVersion (TArray &wadfiles, const char *zdoom_wad) +static EIWADType IdentifyVersion (TArray &wadfiles, const char *iwad, const char *zdoom_wad) { WadStuff wads[countof(IWADNames)]; size_t foundwads[NUM_IWAD_TYPES] = { 0 }; @@ -495,10 +494,15 @@ static EIWADType IdentifyVersion (TArray &wadfiles, const char *zdoom_w bool iwadparmfound = false; FString custwad; + if (iwadparm == NULL && iwad != NULL && *iwad != 0) + { + iwadparm = iwad; + } + if (iwadparm) { custwad = iwadparm; - FixPathSeperator (custwad.LockBuffer()); + FixPathSeperator (custwad); if (CheckIWAD (custwad, wads)) { // -iwad parameter was a directory iwadparm = NULL; @@ -524,8 +528,7 @@ static EIWADType IdentifyVersion (TArray &wadfiles, const char *zdoom_w if (stricmp (key, "Path") == 0) { FString nice = NicePath(value); - FixPathSeperator(nice.LockBuffer()); - nice.UnlockBuffer(); + FixPathSeperator(nice); CheckIWAD(nice, wads); } } @@ -660,9 +663,9 @@ static EIWADType IdentifyVersion (TArray &wadfiles, const char *zdoom_w } -const IWADInfo *D_FindIWAD(TArray &wadfiles, const char *basewad) +const IWADInfo *D_FindIWAD(TArray &wadfiles, const char *iwad, const char *basewad) { - EIWADType iwadType = IdentifyVersion(wadfiles, basewad); + EIWADType iwadType = IdentifyVersion(wadfiles, iwad, basewad); gameiwad = iwadType; const IWADInfo *iwad_info = &IWADInfos[iwadType]; I_SetIWADInfo(iwad_info); diff --git a/src/d_main.cpp b/src/d_main.cpp index d59eee1e52..732cd6acd3 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include "doomerrors.h" @@ -102,6 +103,8 @@ #include "m_cheat.h" #include "compatibility.h" #include "m_joy.h" +#include "sc_man.h" +#include "resourcefiles/resourcefile.h" EXTERN_CVAR(Bool, hud_althud) void DrawHUD(); @@ -118,7 +121,7 @@ extern void R_ExecuteSetViewSize (); extern void G_NewInit (); extern void SetupPlayerClasses (); extern bool CheckCheatmode (); -const IWADInfo *D_FindIWAD(TArray &wadfiles, const char *basewad); +const IWADInfo *D_FindIWAD(TArray &wadfiles, const char *iwad, const char *basewad); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -1241,11 +1244,11 @@ CCMD (endgame) // //========================================================================== -void D_AddFile (TArray &wadfiles, const char *file, bool check) +bool D_AddFile (TArray &wadfiles, const char *file, bool check, int position) { if (file == NULL) { - return; + return false; } if (check && !DirEntryExists (file)) @@ -1254,14 +1257,16 @@ void D_AddFile (TArray &wadfiles, const char *file, bool check) if (f == NULL) { Printf ("Can't find '%s'\n", file); - return; + return false; } file = f; } FString f = file; FixPathSeperator(f); - wadfiles.Push(f); + if (position == -1) wadfiles.Push(f); + else wadfiles.Insert(position, f); + return true; } //========================================================================== @@ -1628,6 +1633,114 @@ static void CopyFiles(TArray &to, TArray &from) } } +static FString ParseGameInfo(TArray &pwads, const char *fn, const char *data, int size) +{ + FScanner sc; + FString iwad; + int pos = 0; + + const char *lastSlash = strrchr (fn, '/'); + + sc.OpenMem("GAMEINFO", data, size); + while(sc.GetToken()) + { + sc.TokenMustBe(TK_Identifier); + FString nextKey = sc.String; + sc.MustGetToken('='); + if (!nextKey.CompareNoCase("IWAD")) + { + sc.MustGetString(); + iwad = sc.String; + } + else if (!nextKey.CompareNoCase("LOAD")) + { + do + { + sc.MustGetToken(TK_StringConst); + + // Try looking for the wad in the same directory as the .wad + // before looking for it in the current directory. + + if (lastSlash != NULL) + { + FString checkpath(fn, (lastSlash - fn) + 1); + checkpath += sc.String; + + if (!FileExists (checkpath)) + { + pos += D_AddFile(pwads, sc.String, true, pos); + } + else + { + pos += D_AddFile(pwads, checkpath, true, pos); + } + } + } + while (sc.CheckToken(',')); + } + } + return iwad; +} + +static FString CheckGameInfo(TArray & pwads) +{ + DWORD t = I_FPSTime(); + // scan the list of WADs backwards to find the last one that contains a GAMEINFO lump + for(int i=pwads.Size()-1; i>=0; i--) + { + bool isdir = false; + FileReader *wadinfo; + FResourceFile *resfile; + const char *filename = pwads[i]; + + // Does this exist? If so, is it a directory? + struct stat info; + if (stat(pwads[i], &info) != 0) + { + Printf(TEXTCOLOR_RED "Could not stat %s\n", filename); + continue; + } + isdir = (info.st_mode & S_IFDIR) != 0; + + if (!isdir) + { + try + { + wadinfo = new FileReader(filename); + } + catch (CRecoverableError &) + { + // Didn't find file + continue; + } + resfile = FResourceFile::OpenResourceFile(filename, wadinfo, true); + } + else + resfile = FResourceFile::OpenDirectory(filename, true); + + if (resfile != NULL) + { + DWORD cnt = resfile->LumpCount(); + for(int i=cnt-1; i>=0; i--) + { + FResourceLump *lmp = resfile->GetLump(i); + + if (lmp->Namespace == ns_global && !stricmp(lmp->Name, "GAMEINFO")) + { + // Found one! + FString iwad = ParseGameInfo(pwads, resfile->Filename, (const char*)lmp->CacheLump(), lmp->LumpSize); + delete resfile; + return iwad; + } + } + delete resfile; + } + } + t = I_FPSTime() - t; + Printf("Gameinfo scan took %d ms\n", t); + return ""; +} + //========================================================================== // // D_DoomMain @@ -1681,11 +1794,15 @@ void D_DoomMain (void) { I_FatalError ("Cannot find " BASEWAD); } + FString basewad = wad; // Load zdoom.pk3 alone so that we can get access to the internal gameinfos before // the IWAD is known. - const IWADInfo *iwad_info = D_FindIWAD(allwads, wad); + GetCmdLineFiles(pwads); + FString iwad = CheckGameInfo(pwads); + + const IWADInfo *iwad_info = D_FindIWAD(allwads, iwad, basewad); gameinfo.gametype = iwad_info->gametype; gameinfo.flags = iwad_info->flags; @@ -1748,8 +1865,6 @@ void D_DoomMain (void) C_ExecCmdLineParams (); // [RH] do all +set commands on the command line - GetCmdLineFiles(pwads); - CopyFiles(allwads, pwads); Printf ("W_Init: Init WADfiles.\n"); diff --git a/src/d_main.h b/src/d_main.h index 3e22acb717..517653bec3 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -49,7 +49,7 @@ void D_PageTicker (void); void D_PageDrawer (void); void D_AdvanceDemo (void); void D_StartTitle (void); -void D_AddFile (TArray &wadfiles, const char *file, bool check = true); +bool D_AddFile (TArray &wadfiles, const char *file, bool check = true, int position = -1); // [RH] Set this to something to draw an icon during the next screen refresh. diff --git a/src/resourcefiles/resourcefile.cpp b/src/resourcefiles/resourcefile.cpp index 9831ec70cb..c5bde5712b 100644 --- a/src/resourcefiles/resourcefile.cpp +++ b/src/resourcefiles/resourcefile.cpp @@ -283,9 +283,9 @@ FResourceFile *FResourceFile::OpenResourceFile(const char *filename, FileReader return NULL; } -FResourceFile *FResourceFile::OpenDirectory(const char *filename) +FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet) { - return CheckDir(filename, NULL, false); + return CheckDir(filename, NULL, quiet); } //========================================================================== diff --git a/src/resourcefiles/resourcefile.h b/src/resourcefiles/resourcefile.h index 39c9594f81..ac8499944b 100644 --- a/src/resourcefiles/resourcefile.h +++ b/src/resourcefiles/resourcefile.h @@ -67,7 +67,7 @@ private: public: static FResourceFile *OpenResourceFile(const char *filename, FileReader *file, bool quiet = false); - static FResourceFile *OpenDirectory(const char *filename); + static FResourceFile *OpenDirectory(const char *filename, bool quiet = false); virtual ~FResourceFile(); FileReader *GetReader() const { return Reader; } DWORD LumpCount() const { return NumLumps; }