~ubuntu-branches/ubuntu/precise/openarena/precise

« back to all changes in this revision

Viewing changes to code/qcommon/files.c

  • Committer: Bazaar Package Importer
  • Author(s): Ansgar Burchardt
  • Date: 2008-09-05 21:14:51 UTC
  • mfrom: (1.2.1 upstream) (2.1.5 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080905211451-243bmbl6l6gdav7l
* Remove non-free code/tools/lcc (Closes: #496346)
  + Remove hunk from patch 10_fix_build_and_binary_on_alpha
  + debian/rules: Add BUILD_GAME_QVM=0 to $(MAKE) call
    (thanks to Peter De Wachter)
* Remove code/libs containing binary libraries for Mac OS X and Win32
* debian/copyright: Explain which parts of upstream's sources were removed
* debian/rules: replace ${source:Upstream-Version} by 0.7.7
  because the variable also contains the `+dfsg1' part
* Add -fsigned-char to compiler options (Closes: #487970)
  (thanks to Peter De Wachter)
* Add myself to Uploaders
* debian/control: Remove article from beginning of short description,
  don't start short description with a capital letter
* debian/openarena.6: Escape minus signs
  + fixes lintian warnings: hyphen-used-as-minus-sign

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
be modified at all after startup.  Any files that are created (demos, screenshots,
52
52
etc) will be created reletive to the base path, so base path should usually be writable.
53
53
 
54
 
The "cd path" is the path to an alternate hierarchy that will be searched if a file
55
 
is not located in the base path.  A user can do a partial install that copies some
56
 
data to a base path created on their hard drive and leave the rest on the cd.  Files
57
 
are never writen to the cd path.  It defaults to a value set by the installer, like
58
 
"e:\quake3", but it can be overridden with "+set fs_cdpath g:\quake3".
59
 
 
60
 
If a user runs the game directly from a CD, the base path would be on the CD.  This
61
 
should still function correctly, but all file writes will fail (harmlessly).
62
 
 
63
54
The "home path" is the path used for all write access. On win32 systems we have "base path"
64
55
== "home path", but on *nix systems the base installation is usually readonly, and
65
56
"home path" points to ~/.q3a or similar
93
84
should be exactly the same executables as release versions, but with different data that
94
85
automatically restricts where game media can come from to prevent add-ons from working.
95
86
 
96
 
After the paths are initialized, quake will look for the product.txt file.  If not
97
 
found and verified, the game will run in restricted mode.  In restricted mode, only 
98
 
files contained in demoq3/pak0.pk3 will be available for loading, and only if the zip header is
99
 
verified to not have been modified.  A single exception is made for q3config.cfg.  Files
100
 
can still be written out in restricted mode, so screenshots and demos are allowed.
101
 
Restricted mode can be tested by setting "+set fs_restrict 1" on the command line, even
102
 
if there is a valid product.txt under the basepath or cdpath.
103
 
 
104
 
If not running in restricted mode, and a file is not found in any local filesystem,
105
 
an attempt will be made to download it and save it under the base path.
106
 
 
107
 
If the "fs_copyfiles" cvar is set to 1, then every time a file is sourced from the cd
108
 
path, it will be copied over to the base path.  This is a development aid to help build
109
 
test releases and to copy working sets over slow network links.
110
 
 
111
87
File search order: when FS_FOpenFileRead gets called it will go through the fs_searchpaths
112
88
structure and stop on the first successful hit. fs_searchpaths is built with successive
113
89
calls to FS_AddGameDirectory
196
172
 
197
173
*/
198
174
 
199
 
#define DEMOGAME                        "demota"
200
 
 
201
175
// every time a new demo pk3 file is built, this checksum must be updated.
202
176
// the easiest way to get it is to just run the game and see what it spits out
203
177
#define DEMO_PAK0_CHECKSUM      2985612116u
204
 
#define PAK0_CHECKSUM                           1566731103u
 
178
static const unsigned pak_checksums[] = {
 
179
        1566731103u,
 
180
        298122907u,
 
181
        412165236u,
 
182
        2991495316u,
 
183
        1197932710u,
 
184
        4087071573u,
 
185
        3709064859u,
 
186
        908855077u,
 
187
        977125798u
 
188
};
205
189
 
206
190
// if this is defined, the executable positively won't work with any paks other
207
191
// than the demo pak, even if productid is present.  This is only used for our
250
234
static  char            fs_gamedir[MAX_OSPATH]; // this will be a single file name with no separators
251
235
static  cvar_t          *fs_debug;
252
236
static  cvar_t          *fs_homepath;
 
237
 
 
238
#ifdef MACOS_X
 
239
// Also search the .app bundle for .pk3 files
 
240
static  cvar_t          *fs_apppath;
 
241
#endif
 
242
 
253
243
static  cvar_t          *fs_basepath;
254
244
static  cvar_t          *fs_basegame;
255
 
static  cvar_t          *fs_cdpath;
256
 
static  cvar_t          *fs_copyfiles;
257
245
static  cvar_t          *fs_gamedirvar;
258
 
static  cvar_t          *fs_restrict;
259
246
static  searchpath_t    *fs_searchpaths;
260
247
static  int                     fs_readCount;                   // total bytes read
261
248
static  int                     fs_loadCount;                   // total files read
354
341
{
355
342
        return fs_loadStack;
356
343
}
357
 
                      
 
344
 
358
345
/*
359
346
================
360
347
return a hash value for the filename
668
655
/*
669
656
===========
670
657
FS_SV_FOpenFileRead
671
 
search for a file somewhere below the home path, base path or cd path
672
 
we search in that order, matching FS_SV_FOpenFileRead order
 
658
 
 
659
Search for a file somewhere below the home path then base path
 
660
in that order
673
661
===========
674
662
*/
675
663
int FS_SV_FOpenFileRead( const char *filename, fileHandle_t *fp ) {
688
676
        // don't let sound stutter
689
677
        S_ClearSoundBuffer();
690
678
 
691
 
  // search homepath
 
679
        // search homepath
692
680
        ospath = FS_BuildOSPath( fs_homepath->string, filename, "" );
693
681
        // remove trailing slash
694
682
        ospath[strlen(ospath)-1] = '\0';
699
687
 
700
688
        fsh[f].handleFiles.file.o = fopen( ospath, "rb" );
701
689
        fsh[f].handleSync = qfalse;
702
 
  if (!fsh[f].handleFiles.file.o)
703
 
  {
704
 
    // NOTE TTimo on non *nix systems, fs_homepath == fs_basepath, might want to avoid
705
 
    if (Q_stricmp(fs_homepath->string,fs_basepath->string))
706
 
    {
707
 
      // search basepath
708
 
      ospath = FS_BuildOSPath( fs_basepath->string, filename, "" );
709
 
      ospath[strlen(ospath)-1] = '\0';
710
 
 
711
 
      if ( fs_debug->integer )
712
 
      {
713
 
        Com_Printf( "FS_SV_FOpenFileRead (fs_basepath): %s\n", ospath );
714
 
      }
715
 
 
716
 
      fsh[f].handleFiles.file.o = fopen( ospath, "rb" );
717
 
      fsh[f].handleSync = qfalse;
718
 
 
719
 
      if ( !fsh[f].handleFiles.file.o )
720
 
      {
721
 
        f = 0;
722
 
      }
723
 
    }
724
 
  }
725
 
 
726
 
        if (!fsh[f].handleFiles.file.o) {
727
 
    // search cd path
728
 
    ospath = FS_BuildOSPath( fs_cdpath->string, filename, "" );
729
 
    ospath[strlen(ospath)-1] = '\0';
730
 
 
731
 
    if (fs_debug->integer)
732
 
    {
733
 
      Com_Printf( "FS_SV_FOpenFileRead (fs_cdpath) : %s\n", ospath );
734
 
    }
735
 
 
736
 
          fsh[f].handleFiles.file.o = fopen( ospath, "rb" );
737
 
          fsh[f].handleSync = qfalse;
738
 
 
739
 
          if( !fsh[f].handleFiles.file.o ) {
740
 
            f = 0;
741
 
          }
742
 
  }
743
 
  
 
690
        if (!fsh[f].handleFiles.file.o)
 
691
        {
 
692
                // If fs_homepath == fs_basepath, don't bother
 
693
                if (Q_stricmp(fs_homepath->string,fs_basepath->string))
 
694
                {
 
695
                        // search basepath
 
696
                        ospath = FS_BuildOSPath( fs_basepath->string, filename, "" );
 
697
                        ospath[strlen(ospath)-1] = '\0';
 
698
 
 
699
                        if ( fs_debug->integer )
 
700
                        {
 
701
                                Com_Printf( "FS_SV_FOpenFileRead (fs_basepath): %s\n", ospath );
 
702
                        }
 
703
 
 
704
                        fsh[f].handleFiles.file.o = fopen( ospath, "rb" );
 
705
                        fsh[f].handleSync = qfalse;
 
706
                }
 
707
 
 
708
                if ( !fsh[f].handleFiles.file.o )
 
709
                {
 
710
                        f = 0;
 
711
                }
 
712
        }
 
713
 
744
714
        *fp = f;
745
715
        if (f) {
746
716
                return FS_filelength(f);
828
798
                Com_Error( ERR_FATAL, "Filesystem call made without initialization\n" );
829
799
        }
830
800
 
831
 
        if (fsh[f].streamed) {
832
 
                Sys_EndStreamedFile(f);
833
 
        }
834
801
        if (fsh[f].zipFile == qtrue) {
835
802
                unzCloseCurrentFile( fsh[f].handleFiles.file.z );
836
803
                if ( fsh[f].handleFiles.unique ) {
966
933
 
967
934
/*
968
935
===========
969
 
FS_ShiftedStrStr
970
 
===========
971
 
*/
972
 
char *FS_ShiftedStrStr(const char *string, const char *substring, int shift) {
973
 
        char buf[MAX_STRING_TOKENS];
974
 
        int i;
975
 
 
976
 
        for (i = 0; substring[i]; i++) {
977
 
                buf[i] = substring[i] + shift;
978
 
        }
979
 
        buf[i] = '\0';
980
 
        return strstr(string, buf);
981
 
}
982
 
 
983
 
/*
984
 
===========
985
936
FS_FOpenFileRead
986
937
 
987
938
Finds the file in the search path.
1115
1066
                                                }
1116
1067
                                        }
1117
1068
 
1118
 
                                        // qagame.qvm   - 13
1119
 
                                        // dTZT`X!di`
1120
 
                                        if (!(pak->referenced & FS_QAGAME_REF) && FS_ShiftedStrStr(filename, "dTZT`X!di`", 13)) {
 
1069
                                        if (!(pak->referenced & FS_QAGAME_REF) && strstr(filename, "qagame.qvm")) {
1121
1070
                                                pak->referenced |= FS_QAGAME_REF;
1122
1071
                                        }
1123
 
                                        // cgame.qvm    - 7
1124
 
                                        // \`Zf^'jof
1125
 
                                        if (!(pak->referenced & FS_CGAME_REF) && FS_ShiftedStrStr(filename , "\\`Zf^'jof", 7)) {
 
1072
                                        if (!(pak->referenced & FS_CGAME_REF) && strstr(filename, "cgame.qvm")) {
1126
1073
                                                pak->referenced |= FS_CGAME_REF;
1127
1074
                                        }
1128
 
                                        // ui.qvm               - 5
1129
 
                                        // pd)lqh
1130
 
                                        if (!(pak->referenced & FS_UI_REF) && FS_ShiftedStrStr(filename , "pd)lqh", 5)) {
 
1075
                                        if (!(pak->referenced & FS_UI_REF) && strstr(filename, "ui.qvm")) {
1131
1076
                                                pak->referenced |= FS_UI_REF;
1132
1077
                                        }
1133
1078
 
1147
1092
                                        temp = zfi->file;
1148
1093
                                        // set the file position in the zip file (also sets the current file info)
1149
1094
                                        unzSetCurrentFileInfoPosition(pak->handle, pakFile->pos);
1150
 
                                        // copy the file info into the unzip structure
1151
 
                                        Com_Memcpy( zfi, pak->handle, sizeof(unz_s) );
 
1095
                                        if ( zfi != pak->handle ) {
 
1096
                                                // copy the file info into the unzip structure
 
1097
                                                Com_Memcpy( zfi, pak->handle, sizeof(unz_s) );
 
1098
                                        }
1152
1099
                                        // we copy this back into the structure
1153
1100
                                        zfi->file = temp;
1154
1101
                                        // open the file in the zip
1169
1116
                        // if we are running restricted, the only files we
1170
1117
                        // will allow to come from the directory are .cfg files
1171
1118
                        l = strlen( filename );
1172
 
      // FIXME TTimo I'm not sure about the fs_numServerPaks test
1173
 
      // if you are using FS_ReadFile to find out if a file exists,
1174
 
      //   this test can make the search fail although the file is in the directory
1175
 
      // I had the problem on https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8
1176
 
      // turned out I used FS_FileExists instead
1177
 
                        if ( fs_restrict->integer || fs_numServerPaks ) {
 
1119
                        // FIXME TTimo I'm not sure about the fs_numServerPaks test
 
1120
                        // if you are using FS_ReadFile to find out if a file exists,
 
1121
                        //   this test can make the search fail although the file is in the directory
 
1122
                        // I had the problem on https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8
 
1123
                        // turned out I used FS_FileExists instead
 
1124
                        if ( fs_numServerPaks ) {
1178
1125
 
1179
1126
                                if ( Q_stricmp( filename + l - 4, ".cfg" )              // for config files
1180
1127
                                        && Q_stricmp( filename + l - 5, ".menu" )       // menu files
1200
1147
                                && Q_stricmp( filename + l - 4, ".dat" ) ) {    // for journal files
1201
1148
                                fs_fakeChkSum = random();
1202
1149
                        }
1203
 
      
 
1150
 
1204
1151
                        Q_strncpyz( fsh[*file].name, filename, sizeof( fsh[*file].name ) );
1205
1152
                        fsh[*file].zipFile = qfalse;
1206
1153
                        if ( fs_debug->integer ) {
1208
1155
                                        dir->path, dir->gamedir );
1209
1156
                        }
1210
1157
 
1211
 
                        // if we are getting it from the cdpath, optionally copy it
1212
 
                        //  to the basepath
1213
 
                        if ( fs_copyfiles->integer && !Q_stricmp( dir->path, fs_cdpath->string ) ) {
1214
 
                                char    *copypath;
1215
 
 
1216
 
                                copypath = FS_BuildOSPath( fs_basepath->string, dir->gamedir, filename );
1217
 
                                FS_CopyFile( netpath, copypath );
1218
 
                        }
1219
 
 
1220
1158
                        return FS_filelength (*file);
1221
1159
                }               
1222
1160
        }
1223
1161
        
1224
 
        Com_DPrintf ("Can't find %s\n", filename);
1225
1162
#ifdef FS_MISSING
1226
1163
        if (missingFiles) {
1227
1164
                fprintf(missingFiles, "%s\n", filename);
1250
1187
        if (fsh[f].streamed) {
1251
1188
                int r;
1252
1189
                fsh[f].streamed = qfalse;
1253
 
                r = Sys_StreamedRead( buffer, len, 1, f);
 
1190
                r = FS_Read( buffer, len, f );
1254
1191
                fsh[f].streamed = qtrue;
1255
1192
                return r;
1256
1193
        } else {
1386
1323
 
1387
1324
        if (fsh[f].streamed) {
1388
1325
                fsh[f].streamed = qfalse;
1389
 
                Sys_StreamSeek( f, offset, origin );
 
1326
                FS_Seek( f, offset, origin );
1390
1327
                fsh[f].streamed = qtrue;
1391
1328
        }
1392
1329
 
1961
1898
                        char    *name;
1962
1899
 
1963
1900
                        // don't scan directories for files if we are pure or restricted
1964
 
                        if ( fs_restrict->integer || fs_numServerPaks ) {
 
1901
                        if ( fs_numServerPaks ) {
1965
1902
                        continue;
1966
1903
                    } else {
1967
1904
                                netpath = FS_BuildOSPath( search->dir->path, search->dir->gamedir, path );
2075
2012
 */
2076
2013
static unsigned int Sys_CountFileList(char **list)
2077
2014
{
2078
 
  int i = 0;
 
2015
        int i = 0;
2079
2016
 
2080
 
  if (list)
2081
 
  {
2082
 
    while (*list)
2083
 
    {
2084
 
      list++;
2085
 
      i++;
2086
 
    }
2087
 
  }
2088
 
  return i;
 
2017
        if (list)
 
2018
        {
 
2019
                while (*list)
 
2020
                {
 
2021
                        list++;
 
2022
                        i++;
 
2023
                }
 
2024
        }
 
2025
        return i;
2089
2026
}
2090
2027
 
2091
 
static char** Sys_ConcatenateFileLists( char **list0, char **list1, char **list2 )
 
2028
static char** Sys_ConcatenateFileLists( char **list0, char **list1 )
2092
2029
{
2093
 
  int totalLength = 0;
2094
 
  char** cat = NULL, **dst, **src;
2095
 
 
2096
 
  totalLength += Sys_CountFileList(list0);
2097
 
  totalLength += Sys_CountFileList(list1);
2098
 
  totalLength += Sys_CountFileList(list2);
2099
 
 
2100
 
  /* Create new list. */
2101
 
  dst = cat = Z_Malloc( ( totalLength + 1 ) * sizeof( char* ) );
2102
 
 
2103
 
  /* Copy over lists. */
2104
 
  if (list0)
2105
 
  {
2106
 
    for (src = list0; *src; src++, dst++)
2107
 
      *dst = *src;
2108
 
  }
2109
 
  if (list1)
2110
 
  {
2111
 
    for (src = list1; *src; src++, dst++)
2112
 
      *dst = *src;
2113
 
  }
2114
 
  if (list2)
2115
 
  {
2116
 
    for (src = list2; *src; src++, dst++)
2117
 
      *dst = *src;
2118
 
  }
2119
 
 
2120
 
  // Terminate the list
2121
 
  *dst = NULL;
2122
 
 
2123
 
  // Free our old lists.
2124
 
  // NOTE: not freeing their content, it's been merged in dst and still being used
2125
 
  if (list0) Z_Free( list0 );
2126
 
  if (list1) Z_Free( list1 );
2127
 
  if (list2) Z_Free( list2 );
2128
 
 
2129
 
  return cat;
 
2030
        int totalLength = 0;
 
2031
        char** cat = NULL, **dst, **src;
 
2032
 
 
2033
        totalLength += Sys_CountFileList(list0);
 
2034
        totalLength += Sys_CountFileList(list1);
 
2035
 
 
2036
        /* Create new list. */
 
2037
        dst = cat = Z_Malloc( ( totalLength + 1 ) * sizeof( char* ) );
 
2038
 
 
2039
        /* Copy over lists. */
 
2040
        if (list0)
 
2041
        {
 
2042
                for (src = list0; *src; src++, dst++)
 
2043
                        *dst = *src;
 
2044
        }
 
2045
        if (list1)
 
2046
        {
 
2047
                for (src = list1; *src; src++, dst++)
 
2048
                        *dst = *src;
 
2049
        }
 
2050
 
 
2051
        // Terminate the list
 
2052
        *dst = NULL;
 
2053
 
 
2054
        // Free our old lists.
 
2055
        // NOTE: not freeing their content, it's been merged in dst and still being used
 
2056
        if (list0) Z_Free( list0 );
 
2057
        if (list1) Z_Free( list1 );
 
2058
 
 
2059
        return cat;
2130
2060
}
2131
2061
 
2132
2062
/*
2139
2069
================
2140
2070
*/
2141
2071
int     FS_GetModList( char *listbuf, int bufsize ) {
2142
 
  int           nMods, i, j, nTotal, nLen, nPaks, nPotential, nDescLen;
2143
 
  char **pFiles = NULL;
2144
 
  char **pPaks = NULL;
2145
 
  char *name, *path;
2146
 
  char descPath[MAX_OSPATH];
2147
 
  fileHandle_t descHandle;
2148
 
 
2149
 
  int dummy;
2150
 
  char **pFiles0 = NULL;
2151
 
  char **pFiles1 = NULL;
2152
 
  char **pFiles2 = NULL;
2153
 
  qboolean bDrop = qfalse;
2154
 
 
2155
 
  *listbuf = 0;
2156
 
  nMods = nPotential = nTotal = 0;
2157
 
 
2158
 
  pFiles0 = Sys_ListFiles( fs_homepath->string, NULL, NULL, &dummy, qtrue );
2159
 
  pFiles1 = Sys_ListFiles( fs_basepath->string, NULL, NULL, &dummy, qtrue );
2160
 
  pFiles2 = Sys_ListFiles( fs_cdpath->string, NULL, NULL, &dummy, qtrue );
2161
 
  // we searched for mods in the three paths
2162
 
  // it is likely that we have duplicate names now, which we will cleanup below
2163
 
  pFiles = Sys_ConcatenateFileLists( pFiles0, pFiles1, pFiles2 );
2164
 
  nPotential = Sys_CountFileList(pFiles);
2165
 
 
2166
 
  for ( i = 0 ; i < nPotential ; i++ ) {
2167
 
    name = pFiles[i];
2168
 
    // NOTE: cleaner would involve more changes
2169
 
    // ignore duplicate mod directories
2170
 
    if (i!=0) {
2171
 
      bDrop = qfalse;
2172
 
      for(j=0; j<i; j++)
2173
 
      {
2174
 
        if (Q_stricmp(pFiles[j],name)==0) {
2175
 
          // this one can be dropped
2176
 
          bDrop = qtrue;
2177
 
          break;
2178
 
        }
2179
 
      }
2180
 
    }
2181
 
    if (bDrop) {
2182
 
      continue;
2183
 
    }
2184
 
    // we drop "baseq3" "." and ".."
2185
 
    if (Q_stricmp(name, BASEGAME) && Q_stricmpn(name, ".", 1)) {
2186
 
      // now we need to find some .pk3 files to validate the mod
2187
 
      // NOTE TTimo: (actually I'm not sure why .. what if it's a mod under developement with no .pk3?)
2188
 
      // we didn't keep the information when we merged the directory names, as to what OS Path it was found under
2189
 
      //   so it could be in base path, cd path or home path
2190
 
      //   we will try each three of them here (yes, it's a bit messy)
2191
 
      path = FS_BuildOSPath( fs_basepath->string, name, "" );
2192
 
      nPaks = 0;
2193
 
      pPaks = Sys_ListFiles(path, ".pk3", NULL, &nPaks, qfalse); 
2194
 
      Sys_FreeFileList( pPaks ); // we only use Sys_ListFiles to check wether .pk3 files are present
2195
 
 
2196
 
      /* Try on cd path */
2197
 
      if( nPaks <= 0 ) {
2198
 
        path = FS_BuildOSPath( fs_cdpath->string, name, "" );
2199
 
        nPaks = 0;
2200
 
        pPaks = Sys_ListFiles( path, ".pk3", NULL, &nPaks, qfalse );
2201
 
        Sys_FreeFileList( pPaks );
2202
 
      }
2203
 
 
2204
 
      /* try on home path */
2205
 
      if ( nPaks <= 0 )
2206
 
      {
2207
 
        path = FS_BuildOSPath( fs_homepath->string, name, "" );
2208
 
        nPaks = 0;
2209
 
        pPaks = Sys_ListFiles( path, ".pk3", NULL, &nPaks, qfalse );
2210
 
        Sys_FreeFileList( pPaks );
2211
 
      }
2212
 
 
2213
 
      if (nPaks > 0) {
2214
 
        nLen = strlen(name) + 1;
2215
 
        // nLen is the length of the mod path
2216
 
        // we need to see if there is a description available
2217
 
        descPath[0] = '\0';
2218
 
        strcpy(descPath, name);
2219
 
        strcat(descPath, "/description.txt");
2220
 
        nDescLen = FS_SV_FOpenFileRead( descPath, &descHandle );
2221
 
        if ( nDescLen > 0 && descHandle) {
2222
 
          FILE *file;
2223
 
          file = FS_FileForHandle(descHandle);
2224
 
          Com_Memset( descPath, 0, sizeof( descPath ) );
2225
 
          nDescLen = fread(descPath, 1, 48, file);
2226
 
          if (nDescLen >= 0) {
2227
 
            descPath[nDescLen] = '\0';
2228
 
          }
2229
 
          FS_FCloseFile(descHandle);
2230
 
        } else {
2231
 
          strcpy(descPath, name);
2232
 
        }
2233
 
        nDescLen = strlen(descPath) + 1;
2234
 
 
2235
 
        if (nTotal + nLen + 1 + nDescLen + 1 < bufsize) {
2236
 
          strcpy(listbuf, name);
2237
 
          listbuf += nLen;
2238
 
          strcpy(listbuf, descPath);
2239
 
          listbuf += nDescLen;
2240
 
          nTotal += nLen + nDescLen;
2241
 
          nMods++;
2242
 
        }
2243
 
        else {
2244
 
          break;
2245
 
        }
2246
 
      }
2247
 
    }
2248
 
  }
2249
 
  Sys_FreeFileList( pFiles );
2250
 
 
2251
 
  return nMods;
 
2072
        int             nMods, i, j, nTotal, nLen, nPaks, nPotential, nDescLen;
 
2073
        char **pFiles = NULL;
 
2074
        char **pPaks = NULL;
 
2075
        char *name, *path;
 
2076
        char descPath[MAX_OSPATH];
 
2077
        fileHandle_t descHandle;
 
2078
 
 
2079
        int dummy;
 
2080
        char **pFiles0 = NULL;
 
2081
        char **pFiles1 = NULL;
 
2082
        qboolean bDrop = qfalse;
 
2083
 
 
2084
        *listbuf = 0;
 
2085
        nMods = nPotential = nTotal = 0;
 
2086
 
 
2087
        pFiles0 = Sys_ListFiles( fs_homepath->string, NULL, NULL, &dummy, qtrue );
 
2088
        pFiles1 = Sys_ListFiles( fs_basepath->string, NULL, NULL, &dummy, qtrue );
 
2089
        // we searched for mods in the three paths
 
2090
        // it is likely that we have duplicate names now, which we will cleanup below
 
2091
        pFiles = Sys_ConcatenateFileLists( pFiles0, pFiles1 );
 
2092
        nPotential = Sys_CountFileList(pFiles);
 
2093
 
 
2094
        for ( i = 0 ; i < nPotential ; i++ ) {
 
2095
                name = pFiles[i];
 
2096
                // NOTE: cleaner would involve more changes
 
2097
                // ignore duplicate mod directories
 
2098
                if (i!=0) {
 
2099
                        bDrop = qfalse;
 
2100
                        for(j=0; j<i; j++)
 
2101
                        {
 
2102
                                if (Q_stricmp(pFiles[j],name)==0) {
 
2103
                                        // this one can be dropped
 
2104
                                        bDrop = qtrue;
 
2105
                                        break;
 
2106
                                }
 
2107
                        }
 
2108
                }
 
2109
                if (bDrop) {
 
2110
                        continue;
 
2111
                }
 
2112
                // we drop "baseq3" "." and ".."
 
2113
                if (Q_stricmp(name, BASEGAME) && Q_stricmpn(name, ".", 1)) {
 
2114
                        // now we need to find some .pk3 files to validate the mod
 
2115
                        // NOTE TTimo: (actually I'm not sure why .. what if it's a mod under developement with no .pk3?)
 
2116
                        // we didn't keep the information when we merged the directory names, as to what OS Path it was found under
 
2117
                        //   so it could be in base path, cd path or home path
 
2118
                        //   we will try each three of them here (yes, it's a bit messy)
 
2119
                        path = FS_BuildOSPath( fs_basepath->string, name, "" );
 
2120
                        nPaks = 0;
 
2121
                        pPaks = Sys_ListFiles(path, ".pk3", NULL, &nPaks, qfalse); 
 
2122
                        Sys_FreeFileList( pPaks ); // we only use Sys_ListFiles to check wether .pk3 files are present
 
2123
 
 
2124
                        /* try on home path */
 
2125
                        if ( nPaks <= 0 )
 
2126
                        {
 
2127
                                path = FS_BuildOSPath( fs_homepath->string, name, "" );
 
2128
                                nPaks = 0;
 
2129
                                pPaks = Sys_ListFiles( path, ".pk3", NULL, &nPaks, qfalse );
 
2130
                                Sys_FreeFileList( pPaks );
 
2131
                        }
 
2132
 
 
2133
                        if (nPaks > 0) {
 
2134
                                nLen = strlen(name) + 1;
 
2135
                                // nLen is the length of the mod path
 
2136
                                // we need to see if there is a description available
 
2137
                                descPath[0] = '\0';
 
2138
                                strcpy(descPath, name);
 
2139
                                strcat(descPath, "/description.txt");
 
2140
                                nDescLen = FS_SV_FOpenFileRead( descPath, &descHandle );
 
2141
                                if ( nDescLen > 0 && descHandle) {
 
2142
                                        FILE *file;
 
2143
                                        file = FS_FileForHandle(descHandle);
 
2144
                                        Com_Memset( descPath, 0, sizeof( descPath ) );
 
2145
                                        nDescLen = fread(descPath, 1, 48, file);
 
2146
                                        if (nDescLen >= 0) {
 
2147
                                                descPath[nDescLen] = '\0';
 
2148
                                        }
 
2149
                                        FS_FCloseFile(descHandle);
 
2150
                                } else {
 
2151
                                        strcpy(descPath, name);
 
2152
                                }
 
2153
                                nDescLen = strlen(descPath) + 1;
 
2154
 
 
2155
                                if (nTotal + nLen + 1 + nDescLen + 1 < bufsize) {
 
2156
                                        strcpy(listbuf, name);
 
2157
                                        listbuf += nLen;
 
2158
                                        strcpy(listbuf, descPath);
 
2159
                                        listbuf += nDescLen;
 
2160
                                        nTotal += nLen + nDescLen;
 
2161
                                        nMods++;
 
2162
                                }
 
2163
                                else {
 
2164
                                        break;
 
2165
                                }
 
2166
                        }
 
2167
                }
 
2168
        }
 
2169
        Sys_FreeFileList( pFiles );
 
2170
 
 
2171
        return nMods;
2252
2172
}
2253
2173
 
2254
2174
 
2315
2235
*/
2316
2236
int FS_PathCmp( const char *s1, const char *s2 ) {
2317
2237
        int             c1, c2;
2318
 
        
 
2238
 
2319
2239
        do {
2320
2240
                c1 = *s1++;
2321
2241
                c2 = *s2++;
2444
2364
/*
2445
2365
============
2446
2366
FS_TouchFile_f
2447
 
 
2448
 
The only purpose of this function is to allow game script files to copy
2449
 
arbitrary files furing an "fs_copyfiles 1" run.
2450
2367
============
2451
2368
*/
2452
2369
void FS_TouchFile_f( void ) {
2483
2400
then loads the zip headers
2484
2401
================
2485
2402
*/
2486
 
#define MAX_PAKFILES    1024
2487
 
static void FS_AddGameDirectory( const char *path, const char *dir ) {
 
2403
void FS_AddGameDirectory( const char *path, const char *dir ) {
2488
2404
        searchpath_t    *sp;
2489
2405
        int                             i;
2490
2406
        searchpath_t    *search;
2492
2408
        char                    *pakfile;
2493
2409
        int                             numfiles;
2494
2410
        char                    **pakfiles;
2495
 
        char                    *sorted[MAX_PAKFILES];
2496
2411
 
2497
 
        // this fixes the case where fs_basepath is the same as fs_cdpath
2498
 
        // which happens on full installs
 
2412
        // Unique
2499
2413
        for ( sp = fs_searchpaths ; sp ; sp = sp->next ) {
2500
2414
                if ( sp->dir && !Q_stricmp(sp->dir->path, path) && !Q_stricmp(sp->dir->gamedir, dir)) {
2501
2415
                        return;                 // we've already got this one
2521
2435
 
2522
2436
        pakfiles = Sys_ListFiles( pakfile, ".pk3", NULL, &numfiles, qfalse );
2523
2437
 
2524
 
        // sort them so that later alphabetic matches override
2525
 
        // earlier ones.  This makes pak1.pk3 override pak0.pk3
2526
 
        if ( numfiles > MAX_PAKFILES ) {
2527
 
                numfiles = MAX_PAKFILES;
2528
 
        }
2529
 
        for ( i = 0 ; i < numfiles ; i++ ) {
2530
 
                sorted[i] = pakfiles[i];
2531
 
        }
2532
 
 
2533
 
        qsort( sorted, numfiles, sizeof(char*), paksort );
2534
 
 
2535
 
        for ( i = 0 ; i < numfiles ; i++ ) {
2536
 
                pakfile = FS_BuildOSPath( path, dir, sorted[i] );
2537
 
                if ( ( pak = FS_LoadZipFile( pakfile, sorted[i] ) ) == 0 )
 
2438
        qsort( pakfiles, numfiles, sizeof(char*), paksort );
 
2439
 
 
2440
        for ( i = 0 ; i < numfiles ; i++ ) {
 
2441
                pakfile = FS_BuildOSPath( path, dir, pakfiles[i] );
 
2442
                if ( ( pak = FS_LoadZipFile( pakfile, pakfiles[i] ) ) == 0 )
2538
2443
                        continue;
2539
2444
                // store the game name for downloading
2540
2445
                strcpy(pak->pakGamename, dir);
2635
2540
 
2636
2541
                // Make sure the server cannot make us write to non-quake3 directories.
2637
2542
                if(FS_CheckDirTraversal(fs_serverReferencedPakNames[i]))
2638
 
                {
 
2543
                {
2639
2544
                        Com_Printf("WARNING: Invalid download name %s\n", fs_serverReferencedPakNames[i]);
2640
 
                        continue;
2641
 
                }
 
2545
                        continue;
 
2546
                }
2642
2547
 
2643
2548
                for ( sp = fs_searchpaths ; sp ; sp = sp->next ) {
2644
2549
                        if ( sp->pack && sp->pack->checksum == fs_serverReferencedPaks[i] ) {
2650
2555
                if ( !havepak && fs_serverReferencedPakNames[i] && *fs_serverReferencedPakNames[i] ) { 
2651
2556
                        // Don't got it
2652
2557
 
2653
 
      if (dlstring)
2654
 
      {
2655
 
        // We need this to make sure we won't hit the end of the buffer or the server could
2656
 
        // overwrite non-pk3 files on clients by writing so much crap into neededpaks that
2657
 
        // Q_strcat cuts off the .pk3 extension.
2658
 
        
2659
 
        origpos += strlen(origpos);
2660
 
        
2661
 
        // Remote name
2662
 
        Q_strcat( neededpaks, len, "@");
2663
 
        Q_strcat( neededpaks, len, fs_serverReferencedPakNames[i] );
2664
 
        Q_strcat( neededpaks, len, ".pk3" );
2665
 
 
2666
 
        // Local name
2667
 
        Q_strcat( neededpaks, len, "@");
2668
 
        // Do we have one with the same name?
2669
 
        if ( FS_SV_FileExists( va( "%s.pk3", fs_serverReferencedPakNames[i] ) ) )
2670
 
        {
2671
 
          char st[MAX_ZPATH];
2672
 
          // We already have one called this, we need to download it to another name
2673
 
          // Make something up with the checksum in it
2674
 
          Com_sprintf( st, sizeof( st ), "%s.%08x.pk3", fs_serverReferencedPakNames[i], fs_serverReferencedPaks[i] );
2675
 
          Q_strcat( neededpaks, len, st );
2676
 
        } else
2677
 
        {
2678
 
          Q_strcat( neededpaks, len, fs_serverReferencedPakNames[i] );
2679
 
          Q_strcat( neededpaks, len, ".pk3" );
2680
 
        }
2681
 
        
2682
 
        // Find out whether it might have overflowed the buffer and don't add this file to the
2683
 
        // list if that is the case.
2684
 
        if(strlen(origpos) + (origpos - neededpaks) >= len - 1)
2685
 
        {
2686
 
                *origpos = '\0';
2687
 
                break;
2688
 
        }
2689
 
      }
2690
 
      else
2691
 
      {
2692
 
        Q_strcat( neededpaks, len, fs_serverReferencedPakNames[i] );
2693
 
                          Q_strcat( neededpaks, len, ".pk3" );
2694
 
        // Do we have one with the same name?
2695
 
        if ( FS_SV_FileExists( va( "%s.pk3", fs_serverReferencedPakNames[i] ) ) )
2696
 
        {
2697
 
          Q_strcat( neededpaks, len, " (local file exists with wrong checksum)");
2698
 
        }
2699
 
        Q_strcat( neededpaks, len, "\n");
2700
 
      }
 
2558
                        if (dlstring)
 
2559
                        {
 
2560
                                // We need this to make sure we won't hit the end of the buffer or the server could
 
2561
                                // overwrite non-pk3 files on clients by writing so much crap into neededpaks that
 
2562
                                // Q_strcat cuts off the .pk3 extension.
 
2563
 
 
2564
                                origpos += strlen(origpos);
 
2565
 
 
2566
                                // Remote name
 
2567
                                Q_strcat( neededpaks, len, "@");
 
2568
                                Q_strcat( neededpaks, len, fs_serverReferencedPakNames[i] );
 
2569
                                Q_strcat( neededpaks, len, ".pk3" );
 
2570
 
 
2571
                                // Local name
 
2572
                                Q_strcat( neededpaks, len, "@");
 
2573
                                // Do we have one with the same name?
 
2574
                                if ( FS_SV_FileExists( va( "%s.pk3", fs_serverReferencedPakNames[i] ) ) )
 
2575
                                {
 
2576
                                        char st[MAX_ZPATH];
 
2577
                                        // We already have one called this, we need to download it to another name
 
2578
                                        // Make something up with the checksum in it
 
2579
                                        Com_sprintf( st, sizeof( st ), "%s.%08x.pk3", fs_serverReferencedPakNames[i], fs_serverReferencedPaks[i] );
 
2580
                                        Q_strcat( neededpaks, len, st );
 
2581
                                }
 
2582
                                else
 
2583
                                {
 
2584
                                        Q_strcat( neededpaks, len, fs_serverReferencedPakNames[i] );
 
2585
                                        Q_strcat( neededpaks, len, ".pk3" );
 
2586
                                }
 
2587
 
 
2588
                                // Find out whether it might have overflowed the buffer and don't add this file to the
 
2589
                                // list if that is the case.
 
2590
                                if(strlen(origpos) + (origpos - neededpaks) >= len - 1)
 
2591
                                {
 
2592
                                        *origpos = '\0';
 
2593
                                        break;
 
2594
                                }
 
2595
                        }
 
2596
                        else
 
2597
                        {
 
2598
                                Q_strcat( neededpaks, len, fs_serverReferencedPakNames[i] );
 
2599
                                Q_strcat( neededpaks, len, ".pk3" );
 
2600
                                // Do we have one with the same name?
 
2601
                                if ( FS_SV_FileExists( va( "%s.pk3", fs_serverReferencedPakNames[i] ) ) )
 
2602
                                {
 
2603
                                        Q_strcat( neededpaks, len, " (local file exists with wrong checksum)");
 
2604
                                }
 
2605
                                Q_strcat( neededpaks, len, "\n");
 
2606
                        }
2701
2607
                }
2702
2608
        }
2703
2609
 
2757
2663
 
2758
2664
void Com_AppendCDKey( const char *filename );
2759
2665
void Com_ReadCDKey( const char *filename );
2760
 
 
 
2666
 
2761
2667
/*
2762
2668
================
2763
2669
FS_ReorderPurePaks
2771
2677
        int i;
2772
2678
        searchpath_t **p_insert_index, // for linked list reordering
2773
2679
                **p_previous; // when doing the scan
2774
 
        
 
2680
 
2775
2681
        // only relevant when connected to pure server
2776
2682
        if ( !fs_numServerPaks )
2777
2683
                return;
2778
 
        
 
2684
 
2779
2685
        fs_reordered = qfalse;
2780
 
        
2781
 
        p_insert_index = &fs_searchpaths; // we insert in order at the beginning of the list 
 
2686
 
 
2687
        p_insert_index = &fs_searchpaths; // we insert in order at the beginning of the list
2782
2688
        for ( i = 0 ; i < fs_numServerPaks ; i++ ) {
2783
2689
                p_previous = p_insert_index; // track the pointer-to-current-item
2784
2690
                for (s = *p_insert_index; s; s = s->next) {
2793
2699
                                p_insert_index = &s->next;
2794
2700
                                break; // iterate to next server pack
2795
2701
                        }
2796
 
                        p_previous = &s->next; 
 
2702
                        p_previous = &s->next;
2797
2703
                }
2798
2704
        }
2799
2705
}
2803
2709
FS_Startup
2804
2710
================
2805
2711
*/
2806
 
static void FS_Startup( const char *gameName ) {
2807
 
        const char *homePath;
 
2712
static void FS_Startup( const char *gameName )
 
2713
{
 
2714
        const char *homePath;
2808
2715
        cvar_t  *fs;
2809
2716
 
2810
2717
        Com_Printf( "----- FS_Startup -----\n" );
2811
2718
 
2812
2719
        fs_debug = Cvar_Get( "fs_debug", "0", 0 );
2813
 
        fs_copyfiles = Cvar_Get( "fs_copyfiles", "0", CVAR_INIT );
2814
 
        fs_cdpath = Cvar_Get ("fs_cdpath", Sys_DefaultCDPath(), CVAR_INIT );
2815
2720
        fs_basepath = Cvar_Get ("fs_basepath", Sys_DefaultInstallPath(), CVAR_INIT );
2816
2721
        fs_basegame = Cvar_Get ("fs_basegame", "", CVAR_INIT );
2817
 
  homePath = Sys_DefaultHomePath();
2818
 
  if (!homePath || !homePath[0]) {
 
2722
        homePath = Sys_DefaultHomePath();
 
2723
        if (!homePath || !homePath[0]) {
2819
2724
                homePath = fs_basepath->string;
2820
2725
        }
2821
2726
        fs_homepath = Cvar_Get ("fs_homepath", homePath, CVAR_INIT );
2822
2727
        fs_gamedirvar = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
2823
 
        fs_restrict = Cvar_Get ("fs_restrict", "", CVAR_INIT );
2824
2728
 
2825
2729
        // add search path elements in reverse priority order
2826
 
        if (fs_cdpath->string[0]) {
2827
 
                FS_AddGameDirectory( fs_cdpath->string, gameName );
2828
 
        }
2829
2730
        if (fs_basepath->string[0]) {
2830
2731
                FS_AddGameDirectory( fs_basepath->string, gameName );
2831
2732
        }
2832
 
  // fs_homepath is somewhat particular to *nix systems, only add if relevant
2833
 
  // NOTE: same filtering below for mods and basegame
2834
 
        if (fs_basepath->string[0] && Q_stricmp(fs_homepath->string,fs_basepath->string)) {
 
2733
        // fs_homepath is somewhat particular to *nix systems, only add if relevant
 
2734
        
 
2735
        #ifdef MACOS_X
 
2736
        fs_apppath = Cvar_Get ("fs_apppath", Sys_DefaultAppPath(), CVAR_INIT );
 
2737
        // Make MacOSX also include the base path included with the .app bundle
 
2738
        if (fs_apppath->string[0])
 
2739
                FS_AddGameDirectory(fs_apppath->string, gameName);
 
2740
        #endif
 
2741
        
 
2742
        // NOTE: same filtering below for mods and basegame
 
2743
        if (fs_homepath->string[0] && Q_stricmp(fs_homepath->string,fs_basepath->string)) {
2835
2744
                FS_AddGameDirectory ( fs_homepath->string, gameName );
2836
2745
        }
2837
 
        
 
2746
 
2838
2747
        // check for additional base game so mods can be based upon other mods
2839
2748
        if ( fs_basegame->string[0] && !Q_stricmp( gameName, BASEGAME ) && Q_stricmp( fs_basegame->string, gameName ) ) {
2840
 
                if (fs_cdpath->string[0]) {
2841
 
                        FS_AddGameDirectory(fs_cdpath->string, fs_basegame->string);
2842
 
                }
2843
2749
                if (fs_basepath->string[0]) {
2844
2750
                        FS_AddGameDirectory(fs_basepath->string, fs_basegame->string);
2845
2751
                }
2850
2756
 
2851
2757
        // check for additional game folder for mods
2852
2758
        if ( fs_gamedirvar->string[0] && !Q_stricmp( gameName, BASEGAME ) && Q_stricmp( fs_gamedirvar->string, gameName ) ) {
2853
 
                if (fs_cdpath->string[0]) {
2854
 
                        FS_AddGameDirectory(fs_cdpath->string, fs_gamedirvar->string);
2855
 
                }
2856
2759
                if (fs_basepath->string[0]) {
2857
2760
                        FS_AddGameDirectory(fs_basepath->string, fs_gamedirvar->string);
2858
2761
                }
2876
2779
        // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=506
2877
2780
        // reorder the pure pk3 files according to server order
2878
2781
        FS_ReorderPurePaks();
2879
 
        
 
2782
 
2880
2783
        // print the current search paths
2881
2784
        FS_Path_f();
2882
2785
 
2903
2806
*/
2904
2807
static void FS_CheckPak0( void )
2905
2808
{
2906
 
/*
2907
 
        searchpath_t    *path;
2908
 
        qboolean                        foundPak0 = qfalse;
2909
 
 
2910
 
        for( path = fs_searchpaths; path; path = path->next ) {
2911
 
                if( path->pack &&
2912
 
                                !Q_stricmpn( path->pack->pakBasename, "pak0", MAX_OSPATH ) &&
2913
 
                                (!Q_stricmpn( path->pack->pakGamename, BASEGAME, MAX_OSPATH ) ||
2914
 
                                !Q_stricmpn( path->pack->pakGamename, "demoq3", MAX_OSPATH ))) {
2915
 
                        foundPak0 = qtrue;
2916
 
 
2917
 
                        if( path->pack->checksum == DEMO_PAK0_CHECKSUM ) {
 
2809
        /*searchpath_t  *path;
 
2810
        qboolean founddemo = qfalse;
 
2811
        unsigned foundPak = 0;
 
2812
 
 
2813
        for( path = fs_searchpaths; path; path = path->next )
 
2814
        {
 
2815
                const char* pakBasename = path->pack->pakBasename;
 
2816
 
 
2817
                if(!path->pack)
 
2818
                        continue;
 
2819
 
 
2820
                if(!Q_stricmpn( path->pack->pakGamename, "demoq3", MAX_OSPATH )
 
2821
                   && !Q_stricmpn( pakBasename, "pak0", MAX_OSPATH ))
 
2822
                {
 
2823
                        founddemo = qtrue;
 
2824
 
 
2825
                        if( path->pack->checksum == DEMO_PAK0_CHECKSUM )
 
2826
                        {
2918
2827
                                Com_Printf( "\n\n"
2919
2828
                                                "**************************************************\n"
2920
2829
                                                "WARNING: It looks like you're using pak0.pk3\n"
2921
2830
                                                "from the demo. This may work fine, but it is not\n"
2922
2831
                                                "guaranteed or supported.\n"
2923
2832
                                                "**************************************************\n\n\n" );
2924
 
                        } else if( path->pack->checksum != PAK0_CHECKSUM ) {
2925
 
                                Com_Printf( "\n\n"
 
2833
                        }
 
2834
                }
 
2835
 
 
2836
                else if(!Q_stricmpn( path->pack->pakGamename, BASEGAME, MAX_OSPATH )
 
2837
                        && strlen(pakBasename) == 4 && !Q_stricmpn( pakBasename, "pak", 3 )
 
2838
                        && pakBasename[3] >= '0' && pakBasename[3] <= '8')
 
2839
                {
 
2840
                        if( path->pack->checksum != pak_checksums[pakBasename[3]-'0'] )
 
2841
                        {
 
2842
                                if(pakBasename[0] == '0')
 
2843
                                {
 
2844
                                        Com_Printf("\n\n"
2926
2845
                                                "**************************************************\n"
2927
2846
                                                "WARNING: pak0.pk3 is present but its checksum (%u)\n"
2928
2847
                                                "is not correct. Please re-copy pak0.pk3 from your\n"
2929
2848
                                                "legitimate Q3 CDROM.\n"
2930
2849
                                                "**************************************************\n\n\n",
2931
2850
                                                path->pack->checksum );
 
2851
                                }
 
2852
                                else
 
2853
                                {
 
2854
                                        Com_Printf("\n\n"
 
2855
                                                "**************************************************\n"
 
2856
                                                "WARNING: pak%d.pk3 is present but its checksum (%u)\n"
 
2857
                                                "is not correct. Please re-install the point release\n"
 
2858
                                                "**************************************************\n\n\n",
 
2859
                                                pakBasename[3]-'0', path->pack->checksum );
 
2860
                                }
2932
2861
                        }
2933
 
                }
2934
 
        }
2935
 
 
2936
 
        if( !foundPak0 ) {
2937
 
                Com_Error( ERR_FATAL, "Couldn't find pak0.pk3. Check that your Q3\n"
2938
 
                                "executable is in the correct place and that every file\n"
2939
 
                                "in the %s directory is present and readable.", BASEGAME);
2940
 
        }
2941
 
*/
 
2862
 
 
2863
                        foundPak |= 1<<(pakBasename[3]-'0');
 
2864
                }
 
2865
        }
 
2866
 
 
2867
        if(!founddemo && (foundPak & 0x1ff) != 0x1ff )
 
2868
        {
 
2869
                if((foundPak&1) != 1 )
 
2870
                {
 
2871
                        Com_Printf("\n\n"
 
2872
                        "pak0.pk3 is missing. Please copy it\n"
 
2873
                        "from your legitimate Q3 CDROM.\n");
 
2874
                }
 
2875
 
 
2876
                if((foundPak&0x1fe) != 0x1fe )
 
2877
                {
 
2878
                        Com_Printf("\n\n"
 
2879
                        "Point Release files are missing. Please\n"
 
2880
                        "re-install the 1.32 point release.\n");
 
2881
                }
 
2882
 
 
2883
                Com_Printf("\n\n"
 
2884
                        "Also check that your Q3 executable is in\n"
 
2885
                        "the correct place and that every file\n"
 
2886
                        "in the %s directory is present and readable.\n", BASEGAME);
 
2887
 
 
2888
                if(!fs_gamedirvar->string[0]
 
2889
                || !Q_stricmp( fs_gamedirvar->string, BASEGAME )
 
2890
                || !Q_stricmp( fs_gamedirvar->string, "missionpack" ))
 
2891
                        Com_Error(ERR_FATAL, "You need to install Quake III Arena in order to play");
 
2892
        }*/
2942
2893
}
2943
2894
 
2944
2895
/*
3304
3255
        // we have to specially handle this, because normal command
3305
3256
        // line variable sets don't happen until after the filesystem
3306
3257
        // has already been initialized
3307
 
        Com_StartupVariable( "fs_cdpath" );
3308
3258
        Com_StartupVariable( "fs_basepath" );
3309
3259
        Com_StartupVariable( "fs_homepath" );
3310
3260
        Com_StartupVariable( "fs_game" );
3311
 
        Com_StartupVariable( "fs_copyfiles" );
3312
 
        Com_StartupVariable( "fs_restrict" );
3313
3261
 
3314
3262
        // try to start up normally
3315
3263
        FS_Startup( BASEGAME );
3316
3264
 
3317
 
        FS_CheckPak0( );
 
3265
        //FS_CheckPak0( );
3318
3266
 
3319
3267
        // if we can't find default.cfg, assume that the paths are
3320
3268
        // busted and error out now, rather than getting an unreadable
3321
3269
        // graphics screen when the font fails to load
3322
3270
        if ( FS_ReadFile( "default.cfg", NULL ) <= 0 ) {
3323
3271
                Com_Error( ERR_FATAL, "Couldn't load default.cfg" );
3324
 
                // bk001208 - SafeMode see below, FIXME?
3325
3272
        }
3326
3273
 
3327
3274
        Q_strncpyz(lastValidBase, fs_basepath->string, sizeof(lastValidBase));
3328
3275
        Q_strncpyz(lastValidGame, fs_gamedirvar->string, sizeof(lastValidGame));
3329
 
 
3330
 
  // bk001208 - SafeMode see below, FIXME?
3331
3276
}
3332
3277
 
3333
3278
 
3350
3295
        // try to start up normally
3351
3296
        FS_Startup( BASEGAME );
3352
3297
 
3353
 
        // FS_CheckPak0( );
 
3298
        FS_CheckPak0( );
3354
3299
 
3355
3300
        // if we can't find default.cfg, assume that the paths are
3356
3301
        // busted and error out now, rather than getting an unreadable
3364
3309
                        Cvar_Set("fs_gamedirvar", lastValidGame);
3365
3310
                        lastValidBase[0] = '\0';
3366
3311
                        lastValidGame[0] = '\0';
3367
 
                        Cvar_Set( "fs_restrict", "0" );
3368
3312
                        FS_Restart(checksumFeed);
3369
 
                        Com_Error( ERR_DROP, "Invalid game folder\n" );
 
3313
                        Com_Error( ERR_DROP, "PK3 mismatch, you might need to upgrade.   See www.openarena.ws for more information\n" );
3370
3314
                        return;
3371
3315
                }
3372
3316
                Com_Error( ERR_FATAL, "Couldn't load default.cfg" );
3373
3317
        }
3374
3318
 
3375
 
        // bk010116 - new check before safeMode
3376
3319
        if ( Q_stricmp(fs_gamedirvar->string, lastValidGame) ) {
3377
3320
                // skip the q3config.cfg if "safe" is on the command line
3378
3321
                if ( !Com_SafeMode() ) {
3379
 
                        Cbuf_AddText ("exec q3config.cfg\n");
 
3322
                        Cbuf_AddText ("exec " Q3CONFIG_CFG "\n");
3380
3323
                }
3381
3324
        }
3382
3325
 
3452
3395
                fsh[*f].streamed = qfalse;
3453
3396
 
3454
3397
                if (mode == FS_READ) {
3455
 
                        Sys_BeginStreamedFile( *f, 0x4000 );
3456
3398
                        fsh[*f].streamed = qtrue;
3457
3399
                }
3458
3400
        }