/* ================ FS_OpenStream open and reading basic info from sound stream ================ */ stream_t *FS_OpenStream( const char *filename ) { const char *ext = FS_FileExtension( filename ); string path, loadname; qboolean anyformat = true; const streamfmt_t *format; stream_t *stream; Sound_Reset(); // clear old streaminfo Q_strncpy( loadname, filename, sizeof( loadname )); if( Q_stricmp( ext, "" )) { // we needs to compare file extension with list of supported formats // and be sure what is real extension, not a filename with dot for( format = sound.streamformat; format && format->formatstring; format++ ) { if( !Q_stricmp( format->ext, ext )) { FS_StripExtension( loadname ); anyformat = false; break; } } } // now try all the formats in the selected list for( format = sound.streamformat; format && format->formatstring; format++) { if( anyformat || !Q_stricmp( ext, format->ext )) { Q_sprintf( path, format->formatstring, loadname, "", format->ext ); if(( stream = format->openfunc( path )) != NULL ) { stream->format = format; return stream; // done } } } if( !sound.streamformat || sound.streamformat->ext == NULL ) MsgDev( D_NOTE, "FS_OpenStream: soundlib offline\n" ); else MsgDev( D_NOTE, "FS_OpenStream: couldn't open \"%s\"\n", loadname ); return NULL; }
/* ===================================== Cmd_GetSoundList Prints or complete sound filename ===================================== */ qboolean Cmd_GetSoundList( const char *s, char *completedname, int length ) { search_t *t; string matchbuf; int i, numsounds; const char *snddir = "sound/"; // constant t = FS_Search( va( "%s%s*.*", snddir, s ), true, false ); if( !t ) return false; Q_strncpy( matchbuf, t->filenames[0] + Q_strlen( snddir ), MAX_STRING ); FS_StripExtension( matchbuf ); if( completedname && length ) Q_strncpy( completedname, matchbuf, length ); if( t->numfilenames == 1 ) return true; for(i = 0, numsounds = 0; i < t->numfilenames; i++) { const char *ext = FS_FileExtension( t->filenames[i] ); if( !Q_stricmp( ext, "wav" ) || !Q_stricmp( ext, "mp3" )); else continue; Q_strncpy( matchbuf, t->filenames[i] + Q_strlen(snddir), MAX_STRING ); FS_StripExtension( matchbuf ); Msg( "%16s\n", matchbuf ); numsounds++; } Msg( "\n^3 %i sounds found.\n", numsounds ); Mem_Free( t ); // cut shortestMatch to the amount common with s if( completedname && length ) { for( i = 0; matchbuf[i]; i++ ) { if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] )) completedname[i] = 0; } } return true; }
/* ===================================== Cmd_GetMusicList Prints or complete background track filename ===================================== */ qboolean Cmd_GetMusicList( const char *s, char *completedname, int length ) { search_t *t; string matchbuf; int i, numtracks; t = FS_Search( va( "media/%s*.*", s ), true, false ); if( !t ) return false; FS_FileBase( t->filenames[0], matchbuf ); if( completedname && length ) Q_strncpy( completedname, matchbuf, length ); if( t->numfilenames == 1 ) return true; for(i = 0, numtracks = 0; i < t->numfilenames; i++) { const char *ext = FS_FileExtension( t->filenames[i] ); if( !Q_stricmp( ext, "wav" ) || !Q_stricmp( ext, "mp3" )); else continue; FS_FileBase( t->filenames[i], matchbuf ); Msg( "%16s\n", matchbuf ); numtracks++; } Msg( "\n^3 %i soundtracks found.\n", numtracks ); Mem_Free(t); // cut shortestMatch to the amount common with s if( completedname && length ) { for( i = 0; matchbuf[i]; i++ ) { if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] )) completedname[i] = 0; } } return true; }
/* ===================================== Cmd_GetItemsList Prints or complete item classname (weapons only) ===================================== */ qboolean Cmd_GetItemsList( const char *s, char *completedname, int length ) { search_t *t; string matchbuf; int i, numitems; if( !clgame.itemspath[0] ) return false; // not in game yet t = FS_Search( va( "%s/%s*.txt", clgame.itemspath, s ), true, false ); if( !t ) return false; FS_FileBase( t->filenames[0], matchbuf ); if( completedname && length ) Q_strncpy( completedname, matchbuf, length ); if( t->numfilenames == 1 ) return true; for(i = 0, numitems = 0; i < t->numfilenames; i++) { const char *ext = FS_FileExtension( t->filenames[i] ); if( Q_stricmp( ext, "txt" )) continue; FS_FileBase( t->filenames[i], matchbuf ); Msg( "%16s\n", matchbuf ); numitems++; } Msg( "\n^3 %i items found.\n", numitems ); Mem_Free( t ); // cut shortestMatch to the amount common with s if( completedname && length ) { for( i = 0; matchbuf[i]; i++ ) { if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] )) completedname[i] = 0; } } return true; }
/* ===================================== Cmd_GetSavesList Prints or complete savegame filename ===================================== */ qboolean Cmd_GetSavesList( const char *s, char *completedname, int length ) { search_t *t; string matchbuf; int i, numsaves; t = FS_Search( va( "save/%s*.sav", s ), true, true ); // lookup only in gamedir if( !t ) return false; FS_FileBase( t->filenames[0], matchbuf ); if( completedname && length ) Q_strncpy( completedname, matchbuf, length ); if( t->numfilenames == 1 ) return true; for( i = 0, numsaves = 0; i < t->numfilenames; i++ ) { const char *ext = FS_FileExtension( t->filenames[i] ); if( Q_stricmp( ext, "sav" )) continue; FS_FileBase( t->filenames[i], matchbuf ); Msg( "%16s\n", matchbuf ); numsaves++; } Msg( "\n^3 %i saves found.\n", numsaves ); Mem_Free( t ); // cut shortestMatch to the amount common with s if( completedname && length ) { for( i = 0; matchbuf[i]; i++ ) { if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] )) completedname[i] = 0; } } return true; }
/* ===================================== Cmd_GetConfigList Prints or complete .cfg filename ===================================== */ qboolean Cmd_GetConfigList( const char *s, char *completedname, int length ) { search_t *t; string matchbuf; int i, numconfigs; t = FS_Search( va( "%s*.cfg", s ), true, false ); if( !t ) return false; Q_strncpy( matchbuf, t->filenames[0], 256 ); if( completedname && length ) Q_strncpy( completedname, matchbuf, length ); if( t->numfilenames == 1 ) return true; for( i = 0, numconfigs = 0; i < t->numfilenames; i++ ) { const char *ext = FS_FileExtension( t->filenames[i] ); if( Q_stricmp( ext, "cfg" )) continue; Q_strncpy( matchbuf, t->filenames[i], 256 ); Msg( "%16s\n", matchbuf ); numconfigs++; } Msg( "\n^3 %i configs found.\n", numconfigs ); Mem_Free( t ); // cut shortestMatch to the amount common with s if( completedname && length ) { for( i = 0; matchbuf[i]; i++ ) { if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] )) completedname[i] = 0; } } return true; }
void HTTPSV_GetMethod(cluster_t *cluster, oproxy_t *pend) { #define URLCOMPARE(url, str, skip) (!strncmp(url, str, (skip = sizeof(str) - 1))) char *s; char *getpath; char geturl[1024]; int skiplen = 0; HTTPSV_GetURLFromRequest(geturl, (char *)pend->inbuffer, sizeof(geturl)); getpath = geturl; // RFC 2616 requires us to be able to parse an absolute URI also. if (URLCOMPARE(getpath, "http://", skiplen)) { getpath += skiplen; while (*getpath && (*getpath != '\t') && (*getpath != '\r') && (*getpath != '\n') && (*getpath != ' ') && (*getpath != '/')) { getpath++; } } if (URLCOMPARE(getpath, "/nowplaying", skiplen)) { HTTPSV_GenerateNowPlaying(cluster, pend); } else if (URLCOMPARE(getpath, "/watch.qtv?sid=", skiplen)) { HTTPSV_GenerateQTVStub(cluster, pend, "", getpath + skiplen); } else if (URLCOMPARE(getpath, "/watch.qtv?demo=", skiplen)) { HTTPSV_GenerateQTVStub(cluster, pend, "file:", getpath + skiplen); } else if (URLCOMPARE(getpath, "/join.qtv?sid=", skiplen)) { HTTPSV_GenerateQTVJoinStub(cluster, pend, getpath + skiplen); } else if (URLCOMPARE(getpath, "/admin", skiplen)) { HTTPSV_GenerateAdmin(cluster, pend, 0, NULL); } else if (URLCOMPARE(getpath, "/demos", skiplen)) { HTTPSV_GenerateDemoListing(cluster, pend); } else if (!strcmp(getpath, "/style.css")) { HTTPSV_GenerateCSSFile(cluster, pend); } else if (!strcmp(getpath, "/script.js")) { HTTPSV_GenerateJSFile(cluster, pend); } else if (URLCOMPARE(getpath, "/levelshots/", skiplen)) { HTTPSV_GenerateLevelshot(cluster, pend, getpath + skiplen); } else if (URLCOMPARE(getpath, "/dl/demos/", skiplen)) { HTTPSV_GenerateDemoDownload(cluster, pend, getpath + skiplen); } else if (URLCOMPARE(getpath, "/rss", skiplen)) { HTTPSV_GenerateRSS(cluster, pend, ""); } else if (URLCOMPARE(getpath, "/status", skiplen)) { HTTPSV_GenerateQTVStatus(cluster, pend, getpath + skiplen); } else if (!strcmp(FS_FileExtension(getpath), ".png")) { s = strchrrev(getpath, '/') + 1; HTTPSV_GenerateImage(cluster, pend, s); } else if (!strcmp(getpath, "/about")) { // Redirect them to our funky website. s = "HTTP/1.0 302 Found" CRLF "Location: https://github.com/deurk/qtv" CRLF CRLF; Net_ProxySend(cluster, pend, s, strlen(s)); } else if (!strcmp(getpath, "/")) { s = "HTTP/1.0 302 Found" CRLF "Location: /nowplaying/" CRLF CRLF; Net_ProxySend(cluster, pend, s, strlen(s)); } else { HTTPSV_SendHTTPHeader(cluster, pend, "404", "text/html", true); HTTPSV_SendHTMLHeader(cluster, pend, "Address not recognised"); s = " <h1>Address not recognised</h1>\n"; Net_ProxySend(cluster, pend, s, strlen(s)); HTTPSV_SendHTMLFooter(cluster, pend); } }
qboolean Cmd_CheckMapsList_R( qboolean fRefresh, qboolean onlyingamedir ) { byte buf[MAX_SYSPATH]; char *buffer; string result; int i, size; search_t *t; file_t *f; if( FS_FileSize( "maps.lst", onlyingamedir ) > 0 && !fRefresh ) { MsgDev( D_NOTE, "maps.lst is exist: %s\n", onlyingamedir ? "basedir" : "gamedir" ); return true; // exist } t = FS_Search( "maps/*.bsp", false, onlyingamedir ); if( !t ) { if( onlyingamedir ) { // mod doesn't contain any maps (probably this is a bot) return Cmd_CheckMapsList_R( fRefresh, false ); } return false; } buffer = Mem_Alloc( host.mempool, t->numfilenames * 2 * sizeof( result )); for( i = 0; i < t->numfilenames; i++ ) { char *ents = NULL, *pfile; int ver = -1, lumpofs = 0, lumplen = 0; string mapname, message, entfilename; const char *ext = FS_FileExtension( t->filenames[i] ); if( Q_stricmp( ext, "bsp" )) continue; f = FS_Open( t->filenames[i], "rb", onlyingamedir ); FS_FileBase( t->filenames[i], mapname ); if( f ) { int num_spawnpoints = 0; dheader_t *header; Q_memset( buf, 0, MAX_SYSPATH ); FS_Read( f, buf, MAX_SYSPATH ); ver = *(uint *)buf; switch( ver ) { case Q1BSP_VERSION: case HLBSP_VERSION: case XTBSP_VERSION: header = (dheader_t *)buf; if( header->lumps[LUMP_ENTITIES].fileofs <= 1024 ) { lumpofs = header->lumps[LUMP_PLANES].fileofs; lumplen = header->lumps[LUMP_PLANES].filelen; } else { lumpofs = header->lumps[LUMP_ENTITIES].fileofs; lumplen = header->lumps[LUMP_ENTITIES].filelen; } break; } Q_strncpy( entfilename, t->filenames[i], sizeof( entfilename )); FS_StripExtension( entfilename ); FS_DefaultExtension( entfilename, ".ent" ); ents = FS_LoadFile( entfilename, NULL, true ); if( !ents && lumplen >= 10 ) { FS_Seek( f, lumpofs, SEEK_SET ); ents = (char *)Mem_Alloc( host.mempool, lumplen + 1 ); FS_Read( f, ents, lumplen ); } if( ents ) { // if there are entities to parse, a missing message key just // means there is no title, so clear the message string now char token[2048]; qboolean worldspawn = true; Q_strncpy( message, "No Title", MAX_STRING ); pfile = ents; while(( pfile = COM_ParseFile( pfile, token )) != NULL ) { if( token[0] == '}' && worldspawn ) worldspawn = false; else if( !Q_strcmp( token, "message" ) && worldspawn ) { // get the message contents pfile = COM_ParseFile( pfile, message ); } else if( !Q_strcmp( token, "classname" )) { pfile = COM_ParseFile( pfile, token ); if( !Q_strcmp( token, GI->mp_entity )) num_spawnpoints++; } if( num_spawnpoints ) break; // valid map } Mem_Free( ents ); } if( f ) FS_Close( f ); if( num_spawnpoints ) { // format: mapname "maptitle"\n Q_sprintf( result, "%s \"%s\"\n", mapname, message ); Q_strcat( buffer, result ); // add new string } } } if( t ) Mem_Free( t ); // free search result size = Q_strlen( buffer ); if( !size ) { if( buffer ) Mem_Free( buffer ); if( onlyingamedir ) return Cmd_CheckMapsList_R( fRefresh, false ); return false; } // write generated maps.lst if( FS_WriteFile( "maps.lst", buffer, Q_strlen( buffer ))) { if( buffer ) Mem_Free( buffer ); return true; } return false; }
/* ===================================== Cmd_GetMapList Prints or complete map filename ===================================== */ qboolean Cmd_GetMapList( const char *s, char *completedname, int length ) { search_t *t; file_t *f; string message; string matchbuf; byte buf[MAX_SYSPATH]; // 1 kb int i, nummaps; t = FS_Search( va( "maps/%s*.bsp", s ), true, con_gamemaps->integer ); if( !t ) return false; FS_FileBase( t->filenames[0], matchbuf ); Q_strncpy( completedname, matchbuf, length ); if( t->numfilenames == 1 ) return true; for( i = 0, nummaps = 0; i < t->numfilenames; i++ ) { char entfilename[CS_SIZE]; int ver = -1, mapver = -1, lumpofs = 0, lumplen = 0; const char *ext = FS_FileExtension( t->filenames[i] ); char *ents = NULL, *pfile; qboolean paranoia = false; qboolean gearbox = false; if( Q_stricmp( ext, "bsp" )) continue; Q_strncpy( message, "^1error^7", sizeof( message )); f = FS_Open( t->filenames[i], "rb", con_gamemaps->integer ); if( f ) { dheader_t *header; dextrahdr_t *hdrext; Q_memset( buf, 0, sizeof( buf )); FS_Read( f, buf, sizeof( buf )); header = (dheader_t *)buf; ver = header->version; switch( ver ) { case Q1BSP_VERSION: case HLBSP_VERSION: case XTBSP_VERSION: if( header->lumps[LUMP_ENTITIES].fileofs <= 1024 && !(header->lumps[LUMP_ENTITIES].filelen % sizeof(dplane_t))) { lumpofs = header->lumps[LUMP_PLANES].fileofs; lumplen = header->lumps[LUMP_PLANES].filelen; gearbox = true; } else { lumpofs = header->lumps[LUMP_ENTITIES].fileofs; lumplen = header->lumps[LUMP_ENTITIES].filelen; gearbox = false; } break; } if( ver == XTBSP_VERSION ) hdrext = (dextrahdr_t *)((byte *)buf + sizeof( dheader31_t )); else hdrext = (dextrahdr_t *)((byte *)buf + sizeof( dheader_t )); if( hdrext->id == IDEXTRAHEADER && hdrext->version == EXTRA_VERSION ) paranoia = true; Q_strncpy( entfilename, t->filenames[i], sizeof( entfilename )); FS_StripExtension( entfilename ); FS_DefaultExtension( entfilename, ".ent" ); ents = FS_LoadFile( entfilename, NULL, true ); if( !ents && lumplen >= 10 ) { FS_Seek( f, lumpofs, SEEK_SET ); ents = (char *)Mem_Alloc( host.mempool, lumplen + 1 ); FS_Read( f, ents, lumplen ); } if( ents ) { // if there are entities to parse, a missing message key just // means there is no title, so clear the message string now char token[2048]; message[0] = 0; pfile = ents; while(( pfile = COM_ParseFile( pfile, token )) != NULL ) { if( !Q_strcmp( token, "{" )) continue; else if(!Q_strcmp( token, "}" )) break; else if(!Q_strcmp( token, "message" )) { // get the message contents pfile = COM_ParseFile( pfile, message ); } else if(!Q_strcmp( token, "mapversion" )) { // get the message contents pfile = COM_ParseFile( pfile, token ); mapver = Q_atoi( token ); } } Mem_Free( ents ); } } if( f ) FS_Close(f); FS_FileBase( t->filenames[i], matchbuf ); switch( ver ) { case Q1BSP_VERSION: if( mapver == 220 ) Q_strncpy( buf, "Half-Life Alpha", sizeof( buf )); else Q_strncpy( buf, "Quake", sizeof( buf )); break; case HLBSP_VERSION: if( gearbox ) Q_strncpy( buf, "Blue-Shift", sizeof( buf )); else if( paranoia ) Q_strncpy( buf, "Paranoia 2", sizeof( buf )); else Q_strncpy( buf, "Half-Life", sizeof( buf )); break; case XTBSP_VERSION: if( paranoia ) Q_strncpy( buf, "Paranoia 2", sizeof( buf )); else Q_strncpy( buf, "Xash3D", sizeof( buf )); break; default: Q_strncpy( buf, "??", sizeof( buf )); break; } Msg( "%16s (%s) ^3%s^7\n", matchbuf, buf, message ); nummaps++; } Msg( "\n^3 %i maps found.\n", nummaps ); Mem_Free( t ); // cut shortestMatch to the amount common with s for( i = 0; matchbuf[i]; i++ ) { if( Q_tolower( completedname[i] ) != Q_tolower( matchbuf[i] )) completedname[i] = 0; } return true; }
/* ================ FS_LoadSound loading and unpack to wav any known sound ================ */ wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size ) { const char *ext = FS_FileExtension( filename ); string path, loadname; qboolean anyformat = true; int filesize = 0; const loadwavfmt_t *format; byte *f; Sound_Reset(); // clear old sounddata Q_strncpy( loadname, filename, sizeof( loadname )); if( Q_stricmp( ext, "" )) { // we needs to compare file extension with list of supported formats // and be sure what is real extension, not a filename with dot for( format = sound.loadformats; format && format->formatstring; format++ ) { if( !Q_stricmp( format->ext, ext )) { FS_StripExtension( loadname ); anyformat = false; break; } } } // HACKHACK: skip any checks, load file from buffer if( filename[0] == '#' && buffer && size ) goto load_internal; // now try all the formats in the selected list for( format = sound.loadformats; format && format->formatstring; format++) { if( anyformat || !Q_stricmp( ext, format->ext )) { Q_sprintf( path, format->formatstring, loadname, "", format->ext ); f = FS_LoadFile( path, &filesize, false ); if( f && filesize > 0 ) { if( format->loadfunc( path, f, filesize )) { Mem_Free(f); // release buffer return SoundPack(); // loaded } else Mem_Free(f); // release buffer } } } load_internal: for( format = sound.loadformats; format && format->formatstring; format++ ) { if( anyformat || !Q_stricmp( ext, format->ext )) { if( buffer && size > 0 ) { if( format->loadfunc( loadname, buffer, size )) return SoundPack(); // loaded } } } if( !sound.loadformats || sound.loadformats->ext == NULL ) MsgDev( D_NOTE, "FS_LoadSound: soundlib offline\n" ); else if( filename[0] != '#' ) MsgDev( D_WARN, "FS_LoadSound: couldn't load \"%s\"\n", loadname ); return NULL; }
/* ================ Image_Save writes image as any known format ================ */ qboolean FS_SaveImage( const char *filename, rgbdata_t *pix ) { const char *ext = FS_FileExtension( filename ); qboolean anyformat = !Q_stricmp( ext, "" ) ? true : false; string path, savename; const savepixformat_t *format; if( !pix || !pix->buffer || anyformat ) { // clear any force flags image.force_flags = 0; return false; } Q_strncpy( savename, filename, sizeof( savename )); FS_StripExtension( savename ); // remove extension if needed if( pix->flags & (IMAGE_CUBEMAP|IMAGE_SKYBOX)) { size_t realSize = pix->size; // keep real pic size byte *picBuffer; // to avoid corrupt memory on free data const suffix_t *box; int i; if( pix->flags & IMAGE_SKYBOX ) box = skybox_qv1; else if( pix->flags & IMAGE_CUBEMAP ) box = cubemap_v2; else { // clear any force flags image.force_flags = 0; return false; // do not happens } pix->size /= 6; // now set as side size picBuffer = pix->buffer; // save all sides seperately for( format = image.saveformats; format && format->formatstring; format++ ) { if( !Q_stricmp( ext, format->ext )) { for( i = 0; i < 6; i++ ) { Q_sprintf( path, format->formatstring, savename, box[i].suf, format->ext ); if( !format->savefunc( path, pix )) break; // there were errors pix->buffer += pix->size; // move pointer } // restore pointers pix->size = realSize; pix->buffer = picBuffer; // clear any force flags image.force_flags = 0; return ( i == 6 ); } } } else { for( format = image.saveformats; format && format->formatstring; format++ ) { if( !Q_stricmp( ext, format->ext )) { Q_sprintf( path, format->formatstring, savename, "", format->ext ); if( format->savefunc( path, pix )) { // clear any force flags image.force_flags = 0; return true; // saved } } } } // clear any force flags image.force_flags = 0; return false; }
/* ================ FS_LoadImage loading and unpack to rgba any known image ================ */ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) { const char *ext = FS_FileExtension( filename ); string path, loadname, sidename; qboolean anyformat = true; int i, filesize = 0; const loadpixformat_t *format; const cubepack_t *cmap; byte *f; Image_Reset(); // clear old image Q_strncpy( loadname, filename, sizeof( loadname )); if( Q_stricmp( ext, "" )) { // we needs to compare file extension with list of supported formats // and be sure what is real extension, not a filename with dot for( format = image.loadformats; format && format->formatstring; format++ ) { if( !Q_stricmp( format->ext, ext )) { FS_StripExtension( loadname ); anyformat = false; break; } } } // HACKHACK: skip any checks, load file from buffer if( filename[0] == '#' && buffer && size ) goto load_internal; // now try all the formats in the selected list for( format = image.loadformats; format && format->formatstring; format++) { if( anyformat || !Q_stricmp( ext, format->ext )) { Q_sprintf( path, format->formatstring, loadname, "", format->ext ); image.hint = format->hint; f = FS_LoadFile( path, &filesize, false ); if( f && filesize > 0 ) { if( format->loadfunc( path, f, filesize )) { Mem_Free( f ); // release buffer return ImagePack(); // loaded } else Mem_Free(f); // release buffer } } } // check all cubemap sides with package suffix for( cmap = load_cubemap; cmap && cmap->type; cmap++ ) { for( i = 0; i < 6; i++ ) { // for support mixed cubemaps e.g. sky_ft.bmp, sky_rt.tga // NOTE: all loaders must keep sides in one format for all for( format = image.loadformats; format && format->formatstring; format++ ) { if( anyformat || !Q_stricmp( ext, format->ext )) { Q_sprintf( path, format->formatstring, loadname, cmap->type[i].suf, format->ext ); image.hint = cmap->type[i].hint; // side hint f = FS_LoadFile( path, &filesize, false ); if( f && filesize > 0 ) { // this name will be used only for tell user about problems if( format->loadfunc( path, f, filesize )) { Q_snprintf( sidename, sizeof( sidename ), "%s%s.%s", loadname, cmap->type[i].suf, format->ext ); if( FS_AddSideToPack( sidename, cmap->type[i].flags )) // process flags to flip some sides { Mem_Free( f ); break; // loaded } } Mem_Free( f ); } } } if( image.num_sides != i + 1 ) // check side { // first side not found, probably it's not cubemap // it contain info about image_type and dimensions, don't generate black cubemaps if( !image.cubemap ) break; MsgDev( D_ERROR, "FS_LoadImage: couldn't load (%s%s), create black image\n", loadname, cmap->type[i].suf ); // Mem_Alloc already filled memblock with 0x00, no need to do it again image.cubemap = Mem_Realloc( host.imagepool, image.cubemap, image.ptr + image.size ); image.ptr += image.size; // move to next image.num_sides++; // merge counter } } // make sure what all sides is loaded if( image.num_sides != 6 ) { // unexpected errors ? if( image.cubemap ) Mem_Free( image.cubemap ); Image_Reset(); } else break; } if( image.cubemap ) return ImagePack(); // all done load_internal: for( format = image.loadformats; format && format->formatstring; format++ ) { if( anyformat || !Q_stricmp( ext, format->ext )) { image.hint = format->hint; if( buffer && size > 0 ) { if( format->loadfunc( loadname, buffer, size )) return ImagePack(); // loaded } } } if( !image.loadformats || image.loadformats->ext == NULL ) MsgDev( D_NOTE, "FS_LoadImage: imagelib offline\n" ); else if( filename[0] != '#' ) MsgDev( D_WARN, "FS_LoadImage: couldn't load \"%s\"\n", loadname ); // clear any force flags image.force_flags = 0; return NULL; }