/* ================== UI_Cinematics_GetCinList ================== */ static void UI_Cinematics_GetCinList (){ const char **fileList; char extension[16]; int numFiles; int i, count = 0; fileList = FS_ListFiles("video", NULL, true, &numFiles); if (numFiles > MAX_MENU_CINEMATICS) numFiles = MAX_MENU_CINEMATICS; for (i = 0; i < numFiles; i++){ // Only copy .cin and .RoQ files, ignore the rest Com_FileExtension(fileList[i], extension, sizeof(extension)); if (!Str_ICompare(extension, "cin") || !Str_ICompare(extension, "RoQ")){ Str_Copy(uiCinematics.cinematics[count], fileList[i], sizeof(uiCinematics.cinematics[count])); *strchr(uiCinematics.cinematics[count], '.') = 0; Str_SPrintf(uiCinematics.cinematicFiles[count], sizeof(uiCinematics.cinematicFiles[count]), "video/%s", fileList[i]); count++; } } FS_FreeFileList(fileList); for (i = 0; i < count; i++) uiCinematics.cinematicsPtr[i] = uiCinematics.cinematics[i]; for ( ; i < MAX_MENU_CINEMATICS; i++) uiCinematics.cinematicsPtr[i] = NULL; uiCinematics.cinList.itemNames = uiCinematics.cinematicsPtr; }
cLocalization::cLocalization() { int i; int iFileCount; char **ppszFiles; char szFilename[ MAX_QPATH ]; size_t iBasePos; ppszFiles = FS_ListFilteredFiles( "global", "txt", "localization*.txt", qfalse, &iFileCount ); strcpy( szFilename, "global/" ); memset( szFilename + 8, 0, sizeof( szFilename ) - 8 ); iBasePos = strlen( szFilename ); Com_Printf( "-- Localization: I see %d localization files\n", iFileCount ); qsort( ppszFiles, iFileCount, sizeof( char * ), compare_strings ); for( i = 0; i < iFileCount; i++ ) { strcpy( szFilename + iBasePos, ppszFiles[ i ] ); Com_Printf( "--- Localization: reading file %s\n", szFilename ); LoadFile( szFilename ); } memcpy( szFilename + iBasePos, "localization.txt", 17 ); Com_Printf( "--- Localization: reading file %s\n", szFilename ); LoadFile( szFilename ); FS_FreeFileList( ppszFiles ); }
void CM_LoadShaderFiles( void ) { if( !shaderText ) { char **shaderFiles1; int numShaders1; char *buffers[MAX_SHADER_FILES]; int numShaders; int i; int sum = 0; // scan for shader files shaderFiles1 = FS_ListFiles( "shaders", ".shader", &numShaders1 ); if ( !shaderFiles1 || !numShaders1 ) { Com_Printf( S_COLOR_YELLOW "WARNING: no shader files found\n" ); return; } numShaders = numShaders1; if ( numShaders > MAX_SHADER_FILES ) { numShaders = MAX_SHADER_FILES; } // load and parse shader files for ( i = 0; i < numShaders1; i++ ) { char filename[MAX_QPATH]; Com_sprintf( filename, sizeof( filename ), "shaders/%s", shaderFiles1[i] ); Com_DPrintf( "...loading '%s'\n", filename ); FS_ReadFile( filename, (void **)&buffers[i] ); if ( !buffers[i] ) { Com_Error( ERR_FATAL, "Couldn't load %s", filename ); } sum += COM_Compress( buffers[i] ); } // build single large buffer shaderText = (char *)Z_Malloc( sum + numShaders * 2, TAG_SHADERTEXT, qtrue); // free in reverse order, so the temp files are all dumped for ( i = numShaders - 1; i >= 0 ; i-- ) { strcat( shaderText, "\n" ); strcat( shaderText, buffers[i] ); FS_FreeFile( buffers[i] ); } // free up memory FS_FreeFileList( shaderFiles1 ); } }
std::vector<std::string> open_directory(const std::string& pathname) { int numFiles; char **files; std::vector<std::string> ret; files = FS_ListFiles(pathname.c_str(), NULL, &numFiles); for (int i = 0; i < numFiles; i++) { ret.push_back(std::string(files[i])); } FS_FreeFileList(files); return ret; }
int LoadStrFiles(char* language) { char buf[256]; sprintf_s(buf, sizeof(buf), "%s/localizedstrings/", language); int count; char** list = FS_ListFiles(buf, "str", 0, &count); for(int i = 0;i < count;i++) { sprintf_s(buf, sizeof(buf), "%s/localizedstrings/%s", language, list[i]); Com_Printf(0, "Parsing localized string file: %s\n", buf); char* Error = SE_Load(buf, 0); if(Error) Com_Printf(0, "Error parsing localized string file: %s\n", Error); } FS_FreeFileList(list); return count; }
/* ========== S_OGG_LoadFileList Load list of Ogg Vorbis files in music/ Based on code by QuDos ========== */ void S_OGG_LoadFileList (void) { char *p, *path = NULL; char **list; // List of .ogg files char findname[MAX_OSPATH]; char lastPath[MAX_OSPATH]; // Knightmare added int i, numfiles = 0; ogg_filelist = malloc(sizeof(char *) * MAX_OGGLIST); memset( ogg_filelist, 0, sizeof( char * ) * MAX_OGGLIST ); lastPath[0] = 0; // Knightmare added // Set search path path = FS_NextPath(path); while (path) { // Knightmare- catch repeated paths if ( strlen(lastPath) > 0 && !strcmp (path, lastPath) ) { path = FS_NextPath( path ); continue; } // Get file list Com_sprintf( findname, sizeof(findname), "%s/music/*.ogg", path ); list = FS_ListFiles(findname, &numfiles, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM); // Add valid Ogg Vorbis file to the list for (i=0; i<numfiles && ogg_numfiles<MAX_OGGLIST; i++) { if (!list || !list[i]) continue; p = list[i]; if (!strstr(p, ".ogg")) continue; // if (!S_OGG_Check(p)) // continue; if (!FS_ItemInList(p, ogg_numfiles, ogg_filelist)) // check if already in list { ogg_filelist[ogg_numfiles] = malloc(strlen(p)+1); sprintf(ogg_filelist[ogg_numfiles], "%s\0", p); ogg_numfiles++; } } if (numfiles) // Free the file list FS_FreeFileList(list, numfiles); strncpy (lastPath, path, sizeof(lastPath)); // Knightmare- copy to lastPath path = FS_NextPath( path ); } #ifndef OGG_DIRECT_FILE // check pak after if (list = FS_ListPak("music/", &numfiles)) { // Add valid Ogg Vorbis file to the list for (i=0; i<numfiles && ogg_numfiles<MAX_OGGLIST; i++) { if (!list || !list[i]) continue; p = list[i]; if (!strstr(p, ".ogg")) continue; // if (!S_OGG_Check(p)) // continue; if (!FS_ItemInList(p, ogg_numfiles, ogg_filelist)) // check if already in list { ogg_filelist[ogg_numfiles] = malloc(strlen(p)+1); sprintf(ogg_filelist[ogg_numfiles], "%s\0", p); ogg_numfiles++; } } } if (numfiles) FS_FreeFileList(list, numfiles); #endif // OGG_DIRECT_FILE }
void UI_Dump_f(void) { string sFinalOutput; vector <string> vStripEdFiles; #define OUTPUT sFinalOutput+= #define OUTPUTSTRIP vStripEdFiles[vStripEdFiles.size()-1] += OUTPUT("### UI_Dump(): Top\n"); for (ReferencesAndPackages_t::iterator it = ReferencesAndPackage.begin(); it!=ReferencesAndPackage.end(); ++it) { if ( (*it).second.size()>1) { OUTPUT(va("!!!DUP: Ref \"%s\" exists in:\n",(*it).first.c_str())); StringSet_t &Set = (*it).second; for (StringSet_t::iterator itS = Set.begin(); itS!=Set.end(); ++itS) { OUTPUT(va("%s\n",(*itS).c_str())); } } } OUTPUT("\nSP Package Reference list:\n"); for (StringSet_t::iterator itS = MenusUsed.begin(); itS!=MenusUsed.end(); ++itS) { OUTPUT(va("%s\n",(*itS).c_str())); } OUTPUT("\nBad Text list:\n"); for (References_t::iterator itBad=BadReferences.begin(); itBad!=BadReferences.end();++itBad) { Reference_t &BadReference = (*itBad); OUTPUT(va("File: %30s \"%s\"\n",BadReference.sMenu.c_str(), BadReference.sString.c_str())); } OUTPUT("\nAdding bad references to final correction list...\n"); for (itBad=BadReferences.begin(); itBad!=BadReferences.end();++itBad) { Reference_t &BadReference = (*itBad); EnterRef("", BadReference.sString.c_str(), BadReference.sMenu.c_str() ); } OUTPUT("\nFinal correction list:\n"); // qboolean bIsMulti = !!strstr((*CorrectionData.begin()).sMenuFile.c_str(),"jk2mp"); // actually do the find/replace... // for (CorrectionData_t::iterator itCorrectionData = CorrectionData.begin(); itCorrectionData != CorrectionData.end(); ++itCorrectionData) { CorrectionDataItem_t &CorrectionDataItem = (*itCorrectionData); if (CorrectionDataItem.sTextToFind.c_str()[0] && CorrectionDataItem.sTextToReplaceWith.c_str()[0]) { OUTPUT( va("Load File: \"%s\", find \"%s\", replace with \"%s\"\n", CorrectionDataItem.sMenuFile.c_str(), CorrectionDataItem.sTextToFind.c_str(), CorrectionDataItem.sTextToReplaceWith.c_str() ) ); // if (strstr(CorrectionDataItem.sTextToReplaceWith.c_str(),"START_A_NEW_GAME")) // { // int z=1; // } assert( CorrectionDataItem.sTextToReplaceWith.c_str()[0] ); string sReplace( CorrectionDataItem.sTextToReplaceWith.c_str() ); sReplace.insert(1,"_"); sReplace.insert(1,CorrectionDataItem.sStripEdFileRef.c_str()); DoFileFindReplace( CorrectionDataItem.sMenuFile.c_str(), CorrectionDataItem.sTextToFind.c_str(), sReplace.c_str()//CorrectionDataItem.sTextToReplaceWith.c_str() ); } } // scan in all SP files into one huge string, so I can pick out any foreign translations to add in when generating // new StripEd files... // char **ppsFiles; char *buffers[1000]; // max # SP files, well-OTT. int iNumFiles; int i; string sStripFiles; // scan for shader files ppsFiles = FS_ListFiles( "strip", ".sp", &iNumFiles ); if ( !ppsFiles || !iNumFiles ) { assert(0); } else { // load files... // for (i=0; i<iNumFiles; i++) { char sFilename[MAX_QPATH]; Com_sprintf( sFilename, sizeof( sFilename ), "strip/%s", ppsFiles[i] ); OutputDebugString( va("...loading '%s'\n", sFilename ) ); int iLen = FS_ReadFile( sFilename, (void **)&buffers[i] ); if ( iLen<1 ) { assert(0);//Com_Error( ERR_DROP, "Couldn't load %s", filename ); } } // free up memory... // FS_FreeFileList( ppsFiles ); // build single large buffer and free up buffers as we go... // // ( free in reverse order, so the temp files are all dumped ) for ( i=iNumFiles-1; i>=0; i-- ) { sStripFiles += buffers[i]; sStripFiles += "\r\n"; FS_FreeFile( buffers[i] ); } } int iIndex=0; for (itCorrectionData = CorrectionData.begin(); itCorrectionData != CorrectionData.end(); ++itCorrectionData) { CorrectionDataItem_t &CorrectionDataItem = (*itCorrectionData); if (CorrectionDataItem.sStripEdReference.c_str()[0] // skip over duplicate-resolving entries // && CorrectionDataItem.sStripEdText.c_str()[0] // ) { string strAnyForeignStringsFound; // will be entire line plus CR string strNotes; // will be just the bit within quotes LPCSTR psFoundExisting; int iInitialSearchPos = 0; while (iInitialSearchPos < sStripFiles.size() && (strAnyForeignStringsFound.empty() || strNotes.empty()) ) { if ( (psFoundExisting = strstr( sStripFiles.c_str()+iInitialSearchPos, va("\"%s\"",CorrectionDataItem.sStripEdText.c_str()))) != NULL ) { // see if we can find any NOTES entry above this... // LPCSTR p; if (strNotes.empty()) { p = psFoundExisting; while (p > sStripFiles.c_str() && *p!='{') { if (!strnicmp(p,"NOTES",5) && isspace(p[-1]) && isspace(p[5])) { p = strchr(p,'"'); if (!p++) break; while (*p != '"') strNotes += *p++; break; } p--; } } // now search for any foreign versions we already have translated... // if (strAnyForeignStringsFound.empty()) { p = psFoundExisting; LPCSTR psNextBrace = strchr(p,'}'); assert(psNextBrace); if (psNextBrace) { for (int i=2; i<10; i++) { LPCSTR psForeign = strstr(p,va("TEXT_LANGUAGE%d",i)); if (psForeign && psForeign < psNextBrace) { strAnyForeignStringsFound += " "; while (*psForeign != '\n' && *psForeign != '\0') { strAnyForeignStringsFound += *psForeign++; } strAnyForeignStringsFound += "\n"; } } } } iInitialSearchPos = psFoundExisting - sStripFiles.c_str(); iInitialSearchPos++; // one past, so we don't re-find ourselves } else { break; } } if (!strNotes.empty()) { strNotes = va(" NOTES \"%s\"\n",strNotes.c_str()); } // now do output... // if (!(iIndex%256)) { string s; vStripEdFiles.push_back(s); OUTPUTSTRIP( va( "VERSION 1\n" "CONFIG W:\\bin\\striped.cfg\n" "ID %d\n" "REFERENCE MENUS%d\n" "DESCRIPTION \"menu text\"\n" "COUNT 256\n", // count will need correcting for last one 250 + (iIndex/256), // 250 range seems to be unused iIndex/256 ) ); // OUTPUTSTRIP( va("REFERENCE %s\n", va("%sMENUS%d",bIsMulti?"MP":"SP",iIndex/256)) ); // OUTPUTSTRIP( va("REFERENCE %s\n", va( "MENUS%d",iIndex/256)) ); } OUTPUTSTRIP( va( "INDEX %d\n" "{\n" " REFERENCE %s\n" "%s" " TEXT_LANGUAGE1 \"%s\"\n" "%s" "}\n", iIndex%256, CorrectionDataItem.sStripEdReference.c_str(), (strNotes.empty()?"":strNotes.c_str()), CorrectionDataItem.sStripEdText.c_str(), strAnyForeignStringsFound.c_str() ) ); iIndex++; } } OUTPUT("### UI_Dump(): Bottom\n"); SendStringToNotepad(sFinalOutput.c_str(), "temp.txt"); // output the SP files... // for (i=0; i<vStripEdFiles.size(); i++) { // need to make local string, because ingame va() is crippled to 2 depths... // char sName[MAX_PATH]; sprintf(sName,"Source\\StarWars\\code\\base\\strip\\MENUS%d.sp",i); SendStringToNotepad(vStripEdFiles[i].c_str(), sName); } }
/* ========== S_OGG_LoadFileList Load list of Ogg Vorbis files in /music/ ========== */ static void S_OGG_LoadFileList (void) { char *p, *path = NULL; char **list; char findname[MAX_OSPATH]; char lastPath[MAX_OSPATH]; int i, numfiles = 0; extern char **FS_ListFiles( char *, int *, unsigned, unsigned ); extern qboolean FS_ItemInList (char *check, int num, char **list); if (!sound_started) return; ogg_filelist = malloc(sizeof(char *) * MAX_OGGLIST); memset(ogg_filelist, 0, sizeof( char * ) * MAX_OGGLIST ); lastPath[0] = 0; // set search path path = FS_NextPath(path); while (path) { // catch repeated paths if ( strlen(lastPath) > 0 && !strcmp (path, lastPath) ) { path = FS_NextPath( path ); continue; } // get file list Com_sprintf( findname, sizeof(findname), "%s/music/*.ogg", path ); list = FS_ListFiles(findname, &numfiles, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM); // add valid Ogg Vorbis files to the list for (i=0; i<numfiles && ogg_numfiles<MAX_OGGLIST; i++) { if (!list || !list[i]) continue; p = list[i]; if (!strstr(p, ".ogg")) continue; // check if already in list if (!FS_ItemInList(p, ogg_numfiles, ogg_filelist)) { ogg_filelist[ogg_numfiles] = malloc(strlen(p)+1); sprintf(ogg_filelist[ogg_numfiles], "%s\0", p); ogg_numfiles++; } } // Free the file list if (numfiles) FS_FreeFileList(list, numfiles); // copy to lastPath strncpy (lastPath, path, sizeof(lastPath)); path = FS_NextPath( path ); } // check pak after if (list = FS_ListPak("music/", &numfiles)) { // add valid Ogg Vorbis file to the list for (i=0; i<numfiles && ogg_numfiles<MAX_OGGLIST; i++) { if (!list || !list[i]) continue; p = list[i]; if (!strstr(p, ".ogg")) continue; // check if already in list if (!FS_ItemInList(p, ogg_numfiles, ogg_filelist)) { ogg_filelist[ogg_numfiles] = malloc(strlen(p)+1); sprintf(ogg_filelist[ogg_numfiles], "%s\0", p); ogg_numfiles++; } } } if (numfiles) FS_FreeFileList(list, numfiles); }
void R_CheckMP3s( const char *psDir ) { // Com_Printf(va("Scanning Dir: %s\n",psDir)); Com_Printf("."); // stops useful info scrolling off screen char **sysFiles, **dirFiles; int numSysFiles, i, numdirs; dirFiles = FS_ListFiles( psDir, "/", &numdirs); if (numdirs > 2) { for (i=2;i<numdirs;i++) { char sDirName[MAX_QPATH]; sprintf(sDirName, "%s\\%s", psDir, dirFiles[i]); R_CheckMP3s(sDirName); } } sysFiles = FS_ListFiles( psDir, ".mp3", &numSysFiles ); for(i=0; i<numSysFiles; i++) { char sFilename[MAX_QPATH]; sprintf(sFilename,"%s\\%s", psDir, sysFiles[i]); Com_Printf("%sFound file: %s",!i?"\n":"",sFilename); iFilesFound++; // read it in... // byte *pbData = NULL; int iSize = FS_ReadFile( sFilename, (void **)&pbData); if (pbData) { id3v1_1* pTAG; // do NOT check 'qbForceRescan' here as an opt, because we need to actually fill in 'pTAG' if there is one... // qboolean qbTagNeedsUpdating = (/* qbForceRescan || */ !MP3_ReadSpecialTagInfo(pbData, iSize, &pTAG))?qtrue:qfalse; if (pTAG == NULL || qbTagNeedsUpdating || qbForceRescan) { Com_Printf(" ( Updating )\n"); // I need to scan this file to get the volume... // // For EF1 I used a temp sfx_t struct, but I can't do that now with this new alloc scheme, // I have to ask for it legally, so I'll keep re-using one, and restoring it's name after use. // (slightly dodgy, but works ok if no-one else changes stuff) // //sfx_t SFX = {0}; extern sfx_t *S_FindName( const char *name ); // static sfx_t *pSFX = NULL; const char sReservedSFXEntrynameForMP3[] = "reserved_for_mp3"; // ( strlen() < MAX_QPATH ) if (pSFX == NULL) // once only { pSFX = S_FindName(sReservedSFXEntrynameForMP3); // always returns, else ERR_FATAL } if (MP3_IsValid(sFilename,pbData, iSize, qbForceStereo)) { wavinfo_t info; int iRawPCMDataSize = MP3_GetUnpackedSize(sFilename, pbData, iSize, qtrue, qbForceStereo); if (iRawPCMDataSize) // should always be true, unless file is f****d, in which case, stop this conversion process { float fMaxVol = 128; // any old default int iActualUnpackedSize = iRawPCMDataSize; // default, override later if not doing music if (!qbForceStereo) // no point for stereo files, which are for music and therefore no lip-sync { byte *pbUnpackBuffer = (byte *) Z_Malloc ( iRawPCMDataSize+10, TAG_TEMP_WORKSPACE ); // won't return if fails iActualUnpackedSize = MP3_UnpackRawPCM( sFilename, pbData, iSize, pbUnpackBuffer ); if (iActualUnpackedSize != iRawPCMDataSize) { Com_Error(ERR_DROP, "******* Whoah! MP3 %s unpacked to %d bytes, but size calc said %d!\n",sFilename,iActualUnpackedSize,iRawPCMDataSize); } // fake up a WAV structure so I can use the other post-load sound code such as volume calc for lip-synching // MP3_FakeUpWAVInfo( sFilename, pbData, iSize, iActualUnpackedSize, // these params are all references... info.format, info.rate, info.width, info.channels, info.samples, info.dataofs ); extern void S_LoadSound_Finalize(wavinfo_t *info, sfx_t *sfx, byte *data); S_LoadSound_Finalize(&info, pSFX, pbUnpackBuffer); // all this just for lipsynch. Oh well. fMaxVol = pSFX->fVolRange; // free sfx->data... // { // Hunk_FreeTempMemory( SFX.data ); // this will have been allocated inside S_LoadSound_Finalise() // // I want a big thankyou from the Mac guys for providing this define... :-) -ste // // #ifndef INT_MIN // #define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */ // #endif // pSFX->iLastTimeUsed = INT_MIN; // force this to be oldest sound file, therefore disposable... pSFX->bInMemory = qtrue; SND_FreeOldestSound(); // ... and do the disposal // now set our temp SFX struct back to default name so nothing else accidentally uses it... // strcpy(pSFX->sSoundName, sReservedSFXEntrynameForMP3); pSFX->bDefaultSound = qfalse; } // other stuff... // Z_Free(pbUnpackBuffer); } // well, time to update the file now... // fileHandle_t f = FS_FOpenFileWrite( sFilename ); if (f) { // write the file back out, but omitting the tag if there was one... // int iWritten = FS_Write(pbData, iSize-(pTAG?sizeof(*pTAG):0), f); if (iWritten) { // make up a new tag if we didn't find one in the original file... // id3v1_1 TAG; if (!pTAG) { pTAG = &TAG; memset(&TAG,0,sizeof(TAG)); strncpy(pTAG->id,"TAG",3); } strncpy(pTAG->title, Filename_WithoutPath(Filename_WithoutExt(sFilename)), sizeof(pTAG->title)); strncpy(pTAG->artist, "Raven Software", sizeof(pTAG->artist) ); strncpy(pTAG->year, "2001", sizeof(pTAG->year) ); strncpy(pTAG->comment, va("%s %g",sKEY_MAXVOL,fMaxVol), sizeof(pTAG->comment) ); strncpy(pTAG->album, va("%s %d",sKEY_UNCOMP,iActualUnpackedSize),sizeof(pTAG->album) ); if (FS_Write( pTAG, sizeof(*pTAG), f )) // NZ = success { iFilesUpdated++; } else { Com_Printf("*********** Failed write to file!\n"); iErrors++; } } else { Com_Printf("*********** Failed write to file!\n"); iErrors++; } FS_FCloseFile( f ); } else { Com_Printf("*********** Failed to re-open for write!\n"); iErrors++; } } else { Com_Error(ERR_DROP, "******* This MP3 should be deleted: %s\n",sFilename); } } else { Com_Printf("*********** File was not a valid MP3!\n"); iErrors++; } } else { Com_Printf(" ( OK )\n"); } FS_FreeFile( pbData ); } } FS_FreeFileList( sysFiles ); FS_FreeFileList( dirFiles ); }
static qboolean PlayerConfig_ScanDirectories (void) { char findname[1024]; char scratch[1024]; int ndirs = 0, npms = 0; char **dirnames; char *path = NULL; int i; //extern char **FS_ListFiles (char *, int *, unsigned, unsigned); s_numplayermodels = 0; // loop back to here if there were no valid player models found in the selected path do { // // get a list of directories // do { path = FS_NextPath(path); Com_sprintf( findname, sizeof(findname), "%s/players/*.*", path ); if ( (dirnames = FS_ListFiles(findname, &ndirs, SFF_SUBDIR, 0)) != 0 ) break; } while (path); if (!dirnames) return false; // // go through the subdirectories // npms = ndirs; if (npms > MAX_PLAYERMODELS) npms = MAX_PLAYERMODELS; if ( (s_numplayermodels + npms) > MAX_PLAYERMODELS ) npms = MAX_PLAYERMODELS - s_numplayermodels; for (i = 0; i < npms; i++) { int k, s; char *a, *b, *c; char **skinnames; char **imagenames; int nimagefiles; int nskins = 0; qboolean already_added = false; if (dirnames[i] == 0) continue; // check if dirnames[i] is already added to the s_pmi[i].directory list a = strrchr(dirnames[i], '/'); b = strrchr(dirnames[i], '\\'); c = (a > b) ? a : b; for (k=0; k < s_numplayermodels; k++) if (!strcmp(s_pmi[k].directory, c+1)) { already_added = true; break; } if (already_added) { // todo: add any skins for this model not already listed to skindisplaynames continue; } // verify the existence of tris.md2 // strncpy(scratch, dirnames[i]); // strncat(scratch, "/tris.md2"); Q_strncpyz(scratch, dirnames[i], sizeof(scratch)); Q_strncatz(scratch, "/tris.md2", sizeof(scratch)); if ( !Sys_FindFirst(scratch, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM) ) { free(dirnames[i]); dirnames[i] = 0; Sys_FindClose(); continue; } Sys_FindClose(); // verify the existence of at least one skin // strncpy(scratch, va("%s%s", dirnames[i], "/*.*")); // was "/*.pcx" Q_strncpyz(scratch, va("%s%s", dirnames[i], "/*.*"), sizeof(scratch)); // was "/*.pcx" imagenames = FS_ListFiles (scratch, &nimagefiles, 0, SFF_SUBDIR | SFF_HIDDEN | SFF_SYSTEM); if (!imagenames) { free(dirnames[i]); dirnames[i] = 0; continue; } // count valid skins, which consist of a skin with a matching "_i" icon for (k = 0; k < nimagefiles-1; k++) if ( IsValidSkin(imagenames, nimagefiles, k) ) nskins++; if (!nskins) continue; skinnames = malloc(sizeof(char *) * (nskins+1)); memset(skinnames, 0, sizeof(char *) * (nskins+1)); // copy the valid skins if (nimagefiles) for (s = 0, k = 0; k < nimagefiles-1; k++) { char *a, *b, *c; if ( IsValidSkin(imagenames, nimagefiles, k) ) { a = strrchr(imagenames[k], '/'); b = strrchr(imagenames[k], '\\'); c = (a > b) ? a : b; // strncpy(scratch, c+1); Q_strncpyz(scratch, c+1, sizeof(scratch)); if ( strrchr(scratch, '.') ) *strrchr(scratch, '.') = 0; skinnames[s] = strdup(scratch); s++; } } // at this point we have a valid player model s_pmi[s_numplayermodels].nskins = nskins; s_pmi[s_numplayermodels].skindisplaynames = skinnames; // make short name for the model a = strrchr(dirnames[i], '/'); b = strrchr(dirnames[i], '\\'); c = (a > b) ? a : b; strncpy(s_pmi[s_numplayermodels].displayname, c+1, MAX_DISPLAYNAME-1); // strncpy(s_pmi[s_numplayermodels].directory, c+1); Q_strncpyz(s_pmi[s_numplayermodels].directory, c+1, sizeof(s_pmi[s_numplayermodels].directory)); FS_FreeFileList (imagenames, nimagefiles); s_numplayermodels++; } if (dirnames) FS_FreeFileList (dirnames, ndirs); // if no valid player models found in path, // try next path, if there is one } while (path); // (s_numplayermodels == 0 && path); return true; //** DMP warning fix }