2009-03-22 11:42:46 +00:00
/*
* * d_iwad . cpp
* * IWAD detection code
* *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* * Copyright 1998 - 2009 Randy Heit
* * Copyright 2009 CHristoph Oelckers
* * All rights reserved .
* *
* * Redistribution and use in source and binary forms , with or without
* * modification , are permitted provided that the following conditions
* * are met :
* *
* * 1. Redistributions of source code must retain the above copyright
* * notice , this list of conditions and the following disclaimer .
* * 2. Redistributions in binary form must reproduce the above copyright
* * notice , this list of conditions and the following disclaimer in the
* * documentation and / or other materials provided with the distribution .
* * 3. The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission .
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* * INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* * NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* * DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* *
*/
# include "d_main.h"
# include "gi.h"
# include "cmdlib.h"
# include "doomstat.h"
# include "i_system.h"
# include "w_wad.h"
# include "w_zip.h"
# include "v_palette.h"
# include "m_argv.h"
2009-03-23 07:37:57 +00:00
# include "m_misc.h"
2009-03-22 11:42:46 +00:00
# include "c_cvars.h"
# include "gameconfigfile.h"
2009-05-30 09:53:38 +00:00
# include "resourcefiles/resourcefile.h"
2009-03-22 11:42:46 +00:00
CVAR ( Bool , queryiwad , true , CVAR_ARCHIVE | CVAR_GLOBALCONFIG ) ;
CVAR ( String , defaultiwad , " " , CVAR_ARCHIVE | CVAR_GLOBALCONFIG ) ;
2009-06-04 22:05:12 +00:00
EIWADType gameiwad ;
2009-03-22 11:42:46 +00:00
// If autoname is NULL, that's either because that game doesn't allow
// loading of external wads or because it's already caught by the
// general game-specific wads section.
const IWADInfo IWADInfos [ NUM_IWAD_TYPES ] =
{
// banner text, autoname, fg color, bg color
2010-05-12 06:54:59 +00:00
{ " Final Doom: TNT - Evilution " , " TNT " , MAKERGB ( 168 , 0 , 0 ) , MAKERGB ( 168 , 168 , 168 ) , GAME_Doom , " mapinfo/tnt.txt " , GI_MAPxx | GI_COMPATSHORTTEX | GI_COMPATSTAIRS } ,
2009-12-11 09:21:08 +00:00
{ " Final Doom: Plutonia Experiment " , " Plutonia " , MAKERGB ( 168 , 0 , 0 ) , MAKERGB ( 168 , 168 , 168 ) , GAME_Doom , " mapinfo/plutonia.txt " , GI_MAPxx | GI_COMPATSHORTTEX } ,
2010-08-15 10:02:10 +00:00
{ " Hexen: Beyond Heretic " , NULL , MAKERGB ( 240 , 240 , 240 ) , MAKERGB ( 107 , 44 , 24 ) , GAME_Hexen , " mapinfo/hexen.txt " , GI_MAPxx | GI_COMPATPOLY1 } ,
2010-10-06 10:44:03 +00:00
{ " Hexen: Deathkings of the Dark Citadel " , " HexenDK " , MAKERGB ( 240 , 240 , 240 ) , MAKERGB ( 139 , 68 , 9 ) , GAME_Hexen , " mapinfo/hexdd.txt " , GI_MAPxx | GI_COMPATPOLY1 | GI_COMPATPOLY2 } ,
2009-03-22 11:42:46 +00:00
{ " Hexen: Demo Version " , " HexenDemo " , MAKERGB ( 240 , 240 , 240 ) , MAKERGB ( 107 , 44 , 24 ) , GAME_Hexen , " mapinfo/hexen.txt " , GI_MAPxx | GI_SHAREWARE } ,
2009-12-11 09:21:08 +00:00
{ " DOOM 2: Hell on Earth " , " Doom2 " , MAKERGB ( 168 , 0 , 0 ) , MAKERGB ( 168 , 168 , 168 ) , GAME_Doom , " mapinfo/doom2.txt " , GI_MAPxx | GI_COMPATSHORTTEX } ,
2009-03-22 11:42:46 +00:00
{ " Heretic Shareware " , NULL , MAKERGB ( 252 , 252 , 0 ) , MAKERGB ( 168 , 0 , 0 ) , GAME_Heretic , " mapinfo/hereticsw.txt " , GI_SHAREWARE } ,
2010-10-12 22:52:35 +00:00
{ " Heretic: Shadow of the Serpent Riders " , " Heretic1 " , MAKERGB ( 252 , 252 , 0 ) , MAKERGB ( 168 , 0 , 0 ) , GAME_Heretic , " mapinfo/heretic.txt " , GI_MENUHACK_EXTENDED } ,
{ " Heretic " , " Heretic1 " , MAKERGB ( 252 , 252 , 0 ) , MAKERGB ( 168 , 0 , 0 ) , GAME_Heretic , " mapinfo/heretic.txt " } ,
2009-12-11 09:21:08 +00:00
{ " DOOM Shareware " , NULL , MAKERGB ( 168 , 0 , 0 ) , MAKERGB ( 168 , 168 , 168 ) , GAME_Doom , " mapinfo/doom1.txt " , GI_SHAREWARE | GI_COMPATSHORTTEX } ,
{ " The Ultimate DOOM " , " Doom1 " , MAKERGB ( 84 , 84 , 84 ) , MAKERGB ( 168 , 168 , 168 ) , GAME_Doom , " mapinfo/ultdoom.txt " , GI_COMPATSHORTTEX } ,
{ " DOOM Registered " , " Doom1 " , MAKERGB ( 84 , 84 , 84 ) , MAKERGB ( 168 , 168 , 168 ) , GAME_Doom , " mapinfo/doom1.txt " , GI_COMPATSHORTTEX } ,
2009-03-22 11:42:46 +00:00
{ " Strife: Quest for the Sigil " , NULL , MAKERGB ( 224 , 173 , 153 ) , MAKERGB ( 0 , 107 , 101 ) , GAME_Strife , " mapinfo/strife.txt " , GI_MAPxx } ,
{ " Strife: Teaser (Old Version) " , NULL , MAKERGB ( 224 , 173 , 153 ) , MAKERGB ( 0 , 107 , 101 ) , GAME_Strife , " mapinfo/strife.txt " , GI_MAPxx | GI_SHAREWARE } ,
{ " Strife: Teaser (New Version) " , NULL , MAKERGB ( 224 , 173 , 153 ) , MAKERGB ( 0 , 107 , 101 ) , GAME_Strife , " mapinfo/strife.txt " , GI_MAPxx | GI_SHAREWARE | GI_TEASER2 } ,
{ " Freedoom " , " Freedoom " , MAKERGB ( 50 , 84 , 67 ) , MAKERGB ( 198 , 220 , 209 ) , GAME_Doom , " mapinfo/doom2.txt " , GI_MAPxx } ,
2009-05-30 08:56:40 +00:00
{ " Ultimate Freedoom " , " Freedoom1 " , MAKERGB ( 50 , 84 , 67 ) , MAKERGB ( 198 , 220 , 209 ) , GAME_Doom , " mapinfo/doom1.txt " } ,
{ " Freedoom \" Demo \" " , NULL , MAKERGB ( 50 , 84 , 67 ) , MAKERGB ( 198 , 220 , 209 ) , GAME_Doom , " mapinfo/doom1.txt " } ,
2009-03-22 11:42:46 +00:00
{ " FreeDM " , " FreeDM " , MAKERGB ( 50 , 84 , 67 ) , MAKERGB ( 198 , 220 , 209 ) , GAME_Doom , " mapinfo/doom2.txt " , GI_MAPxx } ,
2009-10-29 05:51:20 +00:00
{ " Blasphemer " , " Blasphemer " , MAKERGB ( 115 , 0 , 0 ) , MAKERGB ( 0 , 0 , 0 ) , GAME_Heretic , " mapinfo/heretic.txt " } ,
2009-03-22 11:42:46 +00:00
{ " Chex(R) Quest " , " Chex1 " , MAKERGB ( 255 , 255 , 0 ) , MAKERGB ( 0 , 192 , 0 ) , GAME_Chex , " mapinfo/chex.txt " } ,
2010-09-14 17:28:18 +00:00
{ " Chex(R) Quest 3 " , " Chex3 " , MAKERGB ( 255 , 255 , 0 ) , MAKERGB ( 0 , 192 , 0 ) , GAME_Chex , " mapinfo/chex3.txt " , GI_NOTEXTCOLOR } ,
2010-09-26 06:53:40 +00:00
{ " Action Doom 2: Urban Brawl " , " UrbanBrawl " , MAKERGB ( 168 , 168 , 0 ) , MAKERGB ( 168 , 0 , 0 ) , GAME_Doom , " mapinfo/urbanbrawl.txt " , GI_MAPxx } ,
2010-01-05 13:45:07 +00:00
{ " Harmony " , " Harmony " , MAKERGB ( 110 , 180 , 230 ) , MAKERGB ( 69 , 79 , 126 ) , GAME_Doom , " mapinfo/doom2.txt " , GI_MAPxx } ,
2010-10-09 00:10:54 +00:00
{ " Hacx: Twitch n' Kill " , " Hacx " , MAKERGB ( 168 , 0 , 0 ) , MAKERGB ( 168 , 168 , 168 ) , GAME_Doom , " mapinfo/doom2.txt " , GI_MAPxx } ,
2009-03-22 11:42:46 +00:00
//{ "ZDoom Engine", NULL, MAKERGB(168,0,0), MAKERGB(168,168,168) },
} ;
static const char * IWADNames [ ] =
{
NULL ,
" doom2f.wad " ,
" doom2.wad " ,
" plutonia.wad " ,
" tnt.wad " ,
" doomu.wad " , // Hack from original Linux version. Not necessary, but I threw it in anyway.
" doom.wad " ,
" doom1.wad " ,
" heretic.wad " ,
" heretic1.wad " ,
" hexen.wad " ,
" hexdd.wad " ,
" hexendemo.wad " ,
" hexdemo.wad " ,
" strife1.wad " ,
" strife0.wad " ,
" freedoom.wad " , // Freedoom.wad is distributed as Doom2.wad, but this allows to have both in the same directory.
" freedoom1.wad " ,
2009-05-30 08:56:40 +00:00
" freedoomu.wad " ,
2009-03-22 11:42:46 +00:00
" freedm.wad " ,
2009-10-29 05:51:20 +00:00
" blasphem.wad " ,
" blasphemer.wad " ,
2009-03-22 11:42:46 +00:00
" chex.wad " ,
" chex3.wad " ,
2009-10-29 05:51:20 +00:00
" action2.wad " ,
2009-12-11 09:21:08 +00:00
" harm1.wad " ,
2010-10-09 00:10:54 +00:00
" hacx.wad " ,
2009-03-22 11:42:46 +00:00
# ifdef unix
" DOOM2.WAD " , // Also look for all-uppercase names
" PLUTONIA.WAD " ,
" TNT.WAD " ,
" DOOM.WAD " ,
" DOOM1.WAD " ,
" HERETIC.WAD " ,
" HERETIC1.WAD " ,
" HEXEN.WAD " ,
" HEXDD.WAD " ,
" HEXENDEMO.WAD " ,
" HEXDEMO.WAD " ,
" STRIFE1.WAD " ,
" STRIFE0.WAD " ,
" FREEDOOM.WAD " ,
" FREEDOOM1.WAD " ,
2009-05-30 08:56:40 +00:00
" FREEDOOMU.WAD " ,
2009-03-22 11:42:46 +00:00
" FREEDM.WAD " ,
2009-10-29 05:51:20 +00:00
" BLASPHEM.WAD " ,
" BLASPHEMER.WAD " ,
2009-03-22 11:42:46 +00:00
" CHEX.WAD " ,
" CHEX3.WAD " ,
2009-10-29 05:51:20 +00:00
" ACTION2.WAD " ,
2009-12-11 09:21:08 +00:00
" HARM1.WAD " ,
2010-10-09 00:10:54 +00:00
" HACX.WAD " ,
2009-03-22 11:42:46 +00:00
# endif
NULL
} ;
//==========================================================================
//
// ScanIWAD
//
// Scan the contents of an IWAD to determine which one it is
//==========================================================================
static EIWADType ScanIWAD ( const char * iwad )
{
static const char checklumps [ ] [ 8 ] =
{
2009-10-29 05:51:20 +00:00
" AD2LIB " ,
2009-03-22 11:42:46 +00:00
" E1M1 " ,
" E4M2 " ,
" MAP01 " ,
" MAP40 " ,
" MAP60 " ,
" TITLE " ,
" REDTNT2 " ,
" CAMO1 " ,
{ ' E ' , ' X ' , ' T ' , ' E ' , ' N ' , ' D ' , ' E ' , ' D ' } ,
" ENDSTRF " ,
" MAP33 " ,
" INVCURS " ,
{ ' F ' , ' R ' , ' E ' , ' E ' , ' D ' , ' O ' , ' O ' , ' M ' } ,
2009-10-29 05:51:20 +00:00
{ ' B ' , ' L ' , ' A ' , ' S ' , ' P ' , ' H ' , ' E ' , ' M ' } ,
2009-03-22 11:42:46 +00:00
" W94_1 " ,
{ ' P ' , ' O ' , ' S ' , ' S ' , ' H ' , ' 0 ' , ' M ' , ' 0 ' } ,
" CYCLA1 " ,
" FLMBA1 " ,
" MAPINFO " ,
2009-12-11 09:21:08 +00:00
" 0HAWK01 " ,
" 0CARA3 " ,
" 0NOSE1 " ,
2010-10-09 00:10:54 +00:00
" HACX-R " ,
2009-03-22 11:42:46 +00:00
{ ' G ' , ' A ' , ' M ' , ' E ' , ' I ' , ' N ' , ' F ' , ' O ' } ,
" E2M1 " , " E2M2 " , " E2M3 " , " E2M4 " , " E2M5 " , " E2M6 " , " E2M7 " , " E2M8 " , " E2M9 " ,
" E3M1 " , " E3M2 " , " E3M3 " , " E3M4 " , " E3M5 " , " E3M6 " , " E3M7 " , " E3M8 " , " E3M9 " ,
" DPHOOF " , " BFGGA0 " , " HEADA1 " , " CYBRA1 " ,
{ ' S ' , ' P ' , ' I ' , ' D ' , ' A ' , ' 1 ' , ' D ' , ' 1 ' } ,
} ;
2009-11-10 02:29:18 +00:00
# define NUM_CHECKLUMPS (countof(checklumps))
2009-03-22 11:42:46 +00:00
enum
{
2009-10-29 05:51:20 +00:00
Check_ad2lib ,
2009-03-22 11:42:46 +00:00
Check_e1m1 ,
Check_e4m1 ,
Check_map01 ,
Check_map40 ,
Check_map60 ,
Check_title ,
Check_redtnt2 ,
Check_cam01 ,
Check_Extended ,
Check_endstrf ,
Check_map33 ,
Check_invcurs ,
Check_FreeDoom ,
2009-10-29 05:51:20 +00:00
Check_Blasphem ,
2009-03-22 11:42:46 +00:00
Check_W94_1 ,
Check_POSSH0M0 ,
Check_Cycla1 ,
Check_Flmba1 ,
Check_Mapinfo ,
2009-12-11 09:21:08 +00:00
Check_Hawk ,
Check_Car ,
Check_Nose ,
2010-10-09 00:10:54 +00:00
Check_Hacx ,
2009-03-22 11:42:46 +00:00
Check_Gameinfo ,
Check_e2m1
} ;
2009-11-10 02:29:18 +00:00
bool lumpsfound [ NUM_CHECKLUMPS ] ;
2009-06-03 03:05:02 +00:00
size_t i ;
2009-03-22 11:42:46 +00:00
memset ( lumpsfound , 0 , sizeof ( lumpsfound ) ) ;
2009-05-30 09:53:38 +00:00
FResourceFile * iwadfile = FResourceFile : : OpenResourceFile ( iwad , NULL , true ) ;
if ( iwadfile ! = NULL )
2009-03-22 11:42:46 +00:00
{
2009-05-30 17:14:17 +00:00
for ( DWORD ii = 0 ; ii < iwadfile - > LumpCount ( ) ; ii + + )
2009-03-22 11:42:46 +00:00
{
2009-05-30 17:14:17 +00:00
FResourceLump * lump = iwadfile - > GetLump ( ii ) ;
2009-11-10 02:29:18 +00:00
size_t j ;
2009-03-22 11:42:46 +00:00
2009-11-10 02:29:18 +00:00
for ( j = 0 ; j < NUM_CHECKLUMPS ; j + + )
{
if ( ! lumpsfound [ j ] )
{
if ( strnicmp ( lump - > Name , checklumps [ j ] , 8 ) = = 0 )
{
lumpsfound [ j ] = true ;
break ;
}
// Check for maps inside zips, too.
else if ( lump - > FullName ! = NULL )
{
if ( checklumps [ j ] [ 0 ] = = ' E ' & & checklumps [ j ] [ 2 ] = = ' M ' & & checklumps [ j ] [ 4 ] = = ' \0 ' )
{
if ( strnicmp ( lump - > FullName , " maps/ " , 5 ) = = 0 & &
strnicmp ( lump - > FullName + 5 , checklumps [ j ] , 4 ) = = 0 & &
stricmp ( lump - > FullName + 9 , " .wad " ) = = 0 )
{
lumpsfound [ j ] = true ;
break ;
}
}
else if ( checklumps [ j ] [ 0 ] = = ' M ' & & checklumps [ j ] [ 1 ] = = ' A ' & & checklumps [ j ] [ 2 ] = = ' P ' & &
checklumps [ j ] [ 5 ] = = ' \0 ' )
{
if ( strnicmp ( lump - > FullName , " maps/ " , 5 ) = = 0 & &
strnicmp ( lump - > FullName + 5 , checklumps [ j ] , 5 ) = = 0 & &
stricmp ( lump - > FullName + 10 , " .wad " ) = = 0 )
{
lumpsfound [ j ] = true ;
break ;
}
}
}
}
}
2009-03-22 11:42:46 +00:00
}
2009-05-30 09:53:38 +00:00
delete iwadfile ;
2009-03-22 11:42:46 +00:00
}
// Always check for custom iwads first.
#if 0
if ( lumpsfound [ Check_Gameinfo ] )
{
return IWAD_Custom ;
}
# endif
if ( lumpsfound [ Check_title ] & & lumpsfound [ Check_map60 ] )
{
return IWAD_HexenDK ;
}
else if ( lumpsfound [ Check_map33 ] & & lumpsfound [ Check_endstrf ] )
{
if ( lumpsfound [ Check_map01 ] )
{
return IWAD_Strife ;
}
else if ( lumpsfound [ Check_invcurs ] )
{
2010-01-22 05:17:57 +00:00
return IWAD_StrifeTeaser2 ; // Strife0.wad from 14 Mar 1996
2009-03-22 11:42:46 +00:00
}
else
{
2010-01-22 05:17:57 +00:00
return IWAD_StrifeTeaser ; // Strife0.wad from 22 Feb 1996
2009-03-22 11:42:46 +00:00
}
}
else if ( lumpsfound [ Check_map01 ] )
{
2009-10-29 05:51:20 +00:00
if ( lumpsfound [ Check_ad2lib ] )
{
return IWAD_ActionDoom2 ;
}
2009-12-11 09:21:08 +00:00
else if ( lumpsfound [ Check_Hawk ] & & lumpsfound [ Check_Car ] & & lumpsfound [ Check_Nose ] )
{
return IWAD_Harmony ;
}
2010-10-09 00:10:54 +00:00
else if ( lumpsfound [ Check_Hacx ] )
{
return IWAD_Hacx ;
}
2009-10-29 05:51:20 +00:00
else if ( lumpsfound [ Check_FreeDoom ] )
2009-03-22 11:42:46 +00:00
{
// Is there a 100% reliable way to tell FreeDoom and FreeDM
// apart based solely on the lump names?
if ( strstr ( iwad , " freedm.wad " ) | | strstr ( iwad , " FREEDM.WAD " ) )
{
return IWAD_FreeDM ;
}
else
{
return IWAD_FreeDoom ;
}
}
else if ( lumpsfound [ Check_redtnt2 ] )
{
return IWAD_Doom2TNT ;
}
else if ( lumpsfound [ Check_cam01 ] )
{
return IWAD_Doom2Plutonia ;
}
else
{
if ( lumpsfound [ Check_title ] )
{
if ( lumpsfound [ Check_map40 ] )
{
return IWAD_Hexen ;
}
else
{
return IWAD_HexenDemo ;
}
}
else
{
return IWAD_Doom2 ;
}
}
}
else if ( lumpsfound [ Check_e1m1 ] )
{
if ( lumpsfound [ Check_title ] )
{
if ( ! lumpsfound [ Check_e2m1 ] )
{
return IWAD_HereticShareware ;
}
else
{
2009-10-29 05:51:20 +00:00
if ( lumpsfound [ Check_Blasphem ] )
{
return IWAD_Blasphemer ;
}
else if ( lumpsfound [ Check_Extended ] )
2009-03-22 11:42:46 +00:00
{
return IWAD_HereticExtended ;
}
else
{
return IWAD_Heretic ;
}
}
}
else if ( lumpsfound [ Check_Cycla1 ] & & lumpsfound [ Check_Flmba1 ] )
{
if ( ! lumpsfound [ Check_Mapinfo ] )
{
// The original release won't work without its hacked custom EXE.
//I_FatalError("Found an incompatible version of Chex Quest 3");
return NUM_IWAD_TYPES ; // Can't use it.
}
return IWAD_ChexQuest3 ;
}
else
{
if ( lumpsfound [ Check_FreeDoom ] )
{
2009-05-30 08:56:40 +00:00
if ( ! lumpsfound [ Check_e2m1 ] )
{
return IWAD_FreeDoom1 ;
}
else
{
return IWAD_FreeDoomU ;
}
2009-03-22 11:42:46 +00:00
}
for ( i = Check_e2m1 ; i < NUM_CHECKLUMPS ; i + + )
{
if ( ! lumpsfound [ i ] )
{
return IWAD_DoomShareware ;
}
}
if ( i = = NUM_CHECKLUMPS )
{
if ( lumpsfound [ Check_e4m1 ] )
{
if ( lumpsfound [ Check_W94_1 ] & & lumpsfound [ Check_POSSH0M0 ] )
{
return IWAD_ChexQuest ;
}
else
{
return IWAD_UltimateDoom ;
}
}
else
{
return IWAD_DoomRegistered ;
}
}
}
}
return NUM_IWAD_TYPES ; // Don't know
}
//==========================================================================
//
// CheckIWAD
//
// 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).
//
//==========================================================================
static int CheckIWAD ( const char * doomwaddir , WadStuff * wads )
{
const char * slash ;
int i ;
int numfound ;
numfound = 0 ;
slash = ( doomwaddir [ 0 ] & & doomwaddir [ strlen ( doomwaddir ) - 1 ] ! = ' / ' ) ? " / " : " " ;
// Search for a pre-defined IWAD
for ( i = IWADNames [ 0 ] ? 0 : 1 ; IWADNames [ i ] ; i + + )
{
if ( wads [ i ] . Path . IsEmpty ( ) )
{
FString iwad ;
iwad . Format ( " %s%s%s " , doomwaddir , slash , IWADNames [ i ] ) ;
2010-01-01 15:31:00 +00:00
FixPathSeperator ( iwad ) ;
2009-03-22 11:42:46 +00:00
if ( FileExists ( iwad ) )
{
wads [ i ] . Type = ScanIWAD ( iwad ) ;
if ( wads [ i ] . Type ! = NUM_IWAD_TYPES )
{
wads [ i ] . Path = iwad ;
numfound + + ;
}
}
}
}
return numfound ;
}
//==========================================================================
//
// IdentifyVersion
//
// Tries to find an IWAD in one of four directories under DOS or Win32:
// 1. Current directory
// 2. Executable directory
// 3. $DOOMWADDIR
// 4. $HOME
//
// Under UNIX OSes, the search path is:
// 1. Current directory
// 2. $DOOMWADDIR
// 3. $HOME/.zdoom
// 4. The share directory defined at compile time (/usr/local/share/zdoom)
//
// The search path can be altered by editing the IWADSearch.Directories
// section of the config file.
//
//==========================================================================
2010-01-01 15:31:00 +00:00
static EIWADType IdentifyVersion ( TArray < FString > & wadfiles , const char * iwad , const char * zdoom_wad )
2009-03-22 11:42:46 +00:00
{
WadStuff wads [ countof ( IWADNames ) ] ;
size_t foundwads [ NUM_IWAD_TYPES ] = { 0 } ;
const char * iwadparm = Args - > CheckValue ( " -iwad " ) ;
size_t numwads ;
int pickwad ;
size_t i ;
bool iwadparmfound = false ;
FString custwad ;
2010-01-01 15:31:00 +00:00
if ( iwadparm = = NULL & & iwad ! = NULL & & * iwad ! = 0 )
{
iwadparm = iwad ;
}
2009-03-22 11:42:46 +00:00
if ( iwadparm )
{
custwad = iwadparm ;
2010-01-01 15:31:00 +00:00
FixPathSeperator ( custwad ) ;
2009-03-22 11:42:46 +00:00
if ( CheckIWAD ( custwad , wads ) )
{ // -iwad parameter was a directory
iwadparm = NULL ;
}
else
{
DefaultExtension ( custwad , " .wad " ) ;
iwadparm = custwad ;
IWADNames [ 0 ] = iwadparm ;
CheckIWAD ( " " , wads ) ;
}
}
if ( iwadparm = = NULL | | wads [ 0 ] . Path . IsEmpty ( ) )
{
if ( GameConfig - > SetSection ( " IWADSearch.Directories " ) )
{
const char * key ;
const char * value ;
while ( GameConfig - > NextInSection ( key , value ) )
{
if ( stricmp ( key , " Path " ) = = 0 )
{
2009-09-09 17:12:47 +00:00
FString nice = NicePath ( value ) ;
2010-01-01 15:31:00 +00:00
FixPathSeperator ( nice ) ;
2009-09-09 17:12:47 +00:00
CheckIWAD ( nice , wads ) ;
2009-03-22 11:42:46 +00:00
}
}
}
# ifdef _WIN32
FString steam_path = I_GetSteamPath ( ) ;
if ( steam_path . IsNotEmpty ( ) )
{
static const char * const steam_dirs [ ] =
{
" doom 2/base " ,
" final doom/base " ,
" heretic shadow of the serpent riders/base " ,
" hexen/base " ,
" hexen deathkings of the dark citadel/base " ,
" ultimate doom/base "
} ;
steam_path + = " /SteamApps/common/ " ;
for ( i = 0 ; i < countof ( steam_dirs ) ; + + i )
{
CheckIWAD ( steam_path + steam_dirs [ i ] , wads ) ;
}
}
# endif
}
if ( iwadparm ! = NULL & & ! wads [ 0 ] . Path . IsEmpty ( ) )
{
iwadparmfound = true ;
}
for ( i = numwads = 0 ; i < countof ( IWADNames ) ; i + + )
{
if ( ! wads [ i ] . Path . IsEmpty ( ) )
{
if ( i ! = numwads )
{
wads [ numwads ] = wads [ i ] ;
}
foundwads [ wads [ numwads ] . Type ] = numwads + 1 ;
numwads + + ;
}
}
if ( foundwads [ IWAD_HexenDK ] & & ! foundwads [ IWAD_Hexen ] )
{ // Cannot play Hexen DK without Hexen
size_t kill = foundwads [ IWAD_HexenDK ] ;
for ( i = kill ; i < numwads ; + + i )
{
wads [ i - 1 ] = wads [ i ] ;
}
numwads - - ;
foundwads [ IWAD_HexenDK ] = 0 ;
for ( i = 0 ; i < NUM_IWAD_TYPES ; + + i )
{
if ( foundwads [ i ] > kill )
{
foundwads [ i ] - - ;
}
}
}
if ( numwads = = 0 )
{
I_FatalError ( " Cannot find a game IWAD (doom.wad, doom2.wad, heretic.wad, etc.). \n "
" Did you install ZDoom properly? You can do either of the following: \n "
" \n "
" 1. Place one or more of these wads in the same directory as ZDoom. \n "
" 2. Edit your zdoom-username.ini and add the directories of your iwads \n "
" to the list beneath [IWADSearch.Directories] " ) ;
}
pickwad = 0 ;
if ( ! iwadparmfound & & numwads > 1 )
{
int defiwad = 0 ;
// Locate the user's prefered IWAD, if it was found.
if ( defaultiwad [ 0 ] ! = ' \0 ' )
{
for ( i = 0 ; i < numwads ; + + i )
{
FString basename = ExtractFileBase ( wads [ i ] . Path ) ;
if ( stricmp ( basename , defaultiwad ) = = 0 )
{
defiwad = ( int ) i ;
break ;
}
}
}
pickwad = I_PickIWad ( wads , ( int ) numwads , queryiwad , defiwad ) ;
if ( pickwad > = 0 )
{
// The newly selected IWAD becomes the new default
FString basename = ExtractFileBase ( wads [ pickwad ] . Path ) ;
defaultiwad = basename ;
}
}
if ( pickwad < 0 )
exit ( 0 ) ;
// zdoom.pk3 must always be the first file loaded and the IWAD second.
2010-01-01 12:40:47 +00:00
D_AddFile ( wadfiles , zdoom_wad ) ;
2009-03-22 11:42:46 +00:00
if ( wads [ pickwad ] . Type = = IWAD_HexenDK )
{ // load hexen.wad before loading hexdd.wad
2010-01-01 12:40:47 +00:00
D_AddFile ( wadfiles , wads [ foundwads [ IWAD_Hexen ] - 1 ] . Path ) ;
2009-03-22 11:42:46 +00:00
}
2010-01-01 12:40:47 +00:00
D_AddFile ( wadfiles , wads [ pickwad ] . Path ) ;
2009-03-22 11:42:46 +00:00
if ( wads [ pickwad ] . Type = = IWAD_Strife )
{ // Try to load voices.wad along with strife1.wad
long lastslash = wads [ pickwad ] . Path . LastIndexOf ( ' / ' ) ;
FString path ;
if ( lastslash = = - 1 )
{
path = " " ; // wads[pickwad].Path;
}
else
{
path = FString ( wads [ pickwad ] . Path . GetChars ( ) , lastslash + 1 ) ;
}
path + = " voices.wad " ;
2010-01-01 12:40:47 +00:00
D_AddFile ( wadfiles , path ) ;
2009-03-22 11:42:46 +00:00
}
return wads [ pickwad ] . Type ;
}
2010-01-01 15:31:00 +00:00
const IWADInfo * D_FindIWAD ( TArray < FString > & wadfiles , const char * iwad , const char * basewad )
2009-03-22 11:42:46 +00:00
{
2010-01-01 15:31:00 +00:00
EIWADType iwadType = IdentifyVersion ( wadfiles , iwad , basewad ) ;
2009-06-04 22:05:12 +00:00
gameiwad = iwadType ;
2009-03-22 11:42:46 +00:00
const IWADInfo * iwad_info = & IWADInfos [ iwadType ] ;
2010-09-24 14:27:52 +00:00
if ( DoomStartupInfo . Name . IsEmpty ( ) ) DoomStartupInfo . Name = iwad_info - > Name ;
if ( DoomStartupInfo . BkColor = = 0 & & DoomStartupInfo . FgColor = = 0 )
{
DoomStartupInfo . BkColor = iwad_info - > BkColor ;
DoomStartupInfo . FgColor = iwad_info - > FgColor ;
}
2009-03-22 11:42:46 +00:00
I_SetIWADInfo ( iwad_info ) ;
return iwad_info ;
}