/* ================ 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; }
/* =============== Cmd_Exec_f =============== */ void Cmd_Exec_f (void) { const char *path; char *f, *p; int len; char f2[COMMAND_BUFFER_SIZE+2]; if (Cmd_Argc () != 2) { Com_Printf ("exec <filename> : execute a config file\n", LOG_GENERAL); return; } path = Cmd_Argv(1); //r1: normalize while ((p = strchr (path, '\\')) != NULL) p[0] = '/'; //r1: deny traversing outside the q2 directory p = strstr (path, "../"); if (p) { p += 3; if (strstr (p, "../")) { Com_Printf ("WARNING: Illegal config path '%s'\n", LOG_GENERAL, path); return; } } //r1: sanity check length first so people don't exec pak0.pak and eat 300MB ram len = FS_LoadFile (path, NULL); if (len > COMMAND_BUFFER_SIZE - 2) { Com_Printf ("WARNING: %s exceeds maximum config file length\n", LOG_GENERAL, Cmd_Argv(1)); len = COMMAND_BUFFER_SIZE - 2; } len = FS_LoadFile (path, (void **)&f); if (!f || len <= 0) { //ugly hack to avoid printing missing config errors before startup finishes if (q2_initialized) Com_Printf ("couldn't exec %s\n", LOG_GENERAL, path); return; } #ifndef DEDICATED_ONLY if (Com_ServerState()) #endif Com_Printf ("execing %s\n", LOG_GENERAL, path); #ifndef DEDICATED_ONLY else Com_DPrintf ("execing %s\n",path); #endif // the file doesn't have a trailing 0, so we need to copy it off //f2 = Z_TagMalloc(len+2, TAGMALLOC_CMDBUFF); //f2 = alloca (len+2); memcpy (f2, f, len); //r1: fix for "no trailing newline = 'u or s'" bug. f2[len] = '\n'; f2[len+1] = 0; if ((p = strchr(f2, '\r')) != NULL && *(p+1) != '\n') Com_Printf ("WARNING: Raw \\r found in config file %s\n", LOG_GENERAL|LOG_WARNING, path); Cbuf_InsertText (f2); //Z_Free (f2); FS_FreeFile (f); }
/* ==================== Curl_FindPackURL finds the URL where to find a given package. For this, it reads a file "curl_urls.txt" of the following format: data*.pk3 - revdm*.pk3 http://revdm/downloads/are/here/ * http://any/other/stuff/is/here/ The URLs should end in /. If not, downloads will still work, but the cached files can't be just put into the data directory with the same download configuration (you might want to do this if you want to tag downloaded files from your server, but you should not). "-" means "don't download". If no single pattern matched, the cvar sv_curl_defaulturl is used as download location instead. Note: pak1.pak and data*.pk3 are excluded from autodownload at another point in this file for obvious reasons. ==================== */ static const char *Curl_FindPackURL(const char *filename) { static char foundurl[1024]; fs_offset_t filesize; char *buf = (char *) FS_LoadFile("curl_urls.txt", tempmempool, true, &filesize); if(buf && filesize) { // read lines of format "pattern url" char *p = buf; char *pattern = NULL, *patternend = NULL, *url = NULL, *urlend = NULL; qboolean eof = false; pattern = p; while(!eof) { switch(*p) { case 0: eof = true; // fallthrough case '\n': case '\r': if(pattern && url && patternend) { if(!urlend) urlend = p; *patternend = 0; *urlend = 0; if(matchpattern(filename, pattern, true)) { strlcpy(foundurl, url, sizeof(foundurl)); Z_Free(buf); return foundurl; } } pattern = NULL; patternend = NULL; url = NULL; urlend = NULL; break; case ' ': case '\t': if(pattern && !patternend) patternend = p; else if(url && !urlend) urlend = p; break; default: if(!pattern) pattern = p; else if(pattern && patternend && !url) url = p; break; } ++p; } } if(buf) Z_Free(buf); return sv_curl_defaulturl.string; }
/* * Play Ogg Vorbis file (with absolute or relative index). */ qboolean OGG_Open(ogg_seek_t type, int offset) { int size; /* File size. */ int pos = -1; /* Absolute position. */ int res; /* Error indicator. */ switch (type) { case ABS: /* Absolute index. */ if ((offset < 0) || (offset >= ogg_numfiles)) { Com_Printf("OGG_Open: %d out of range.\n", offset + 1); return false; } else { pos = offset; } break; case REL: /* Simulate a loopback. */ if ((ogg_curfile == -1) && (offset < 0)) { offset++; } while (ogg_curfile + offset < 0) { offset += ogg_numfiles; } while (ogg_curfile + offset >= ogg_numfiles) { offset -= ogg_numfiles; } pos = ogg_curfile + offset; break; } /* Check running music. */ if (ogg_status == PLAY) { if (ogg_curfile == pos) { return true; } else { OGG_Stop(); } } /* Find file. */ if ((size = FS_LoadFile(ogg_filelist[pos], (void **)&ogg_buffer)) == -1) { Com_Printf("OGG_Open: could not open %d (%s): %s.\n", pos, ogg_filelist[pos], strerror(errno)); return false; } /* Open ogg vorbis file. */ if ((res = ov_open(NULL, &ovFile, (char *)ogg_buffer, size)) < 0) { Com_Printf("OGG_Open: '%s' is not a valid Ogg Vorbis file (error %i).\n", ogg_filelist[pos], res); FS_FreeFile(ogg_buffer); ogg_buffer = NULL; return false; } ogg_info = ov_info(&ovFile, 0); if (!ogg_info) { Com_Printf("OGG_Open: Unable to get stream information for %s.\n", ogg_filelist[pos]); ov_clear(&ovFile); FS_FreeFile(ogg_buffer); ogg_buffer = NULL; return false; } /* Play file. */ ovSection = 0; ogg_curfile = pos; ogg_status = PLAY; return true; }
static void ParseMasterArgs(netadr_t *broadcast) { void *data; int len; void (*parse)(void *, size_t, size_t); size_t chunk; char *s, *p; int i, argc; Cmd_TokenizeString(m_servers.args, false); argc = Cmd_Argc(); if (!argc) { // default action to take when no URLs are given ParseAddressBook(); broadcast->type = NA_BROADCAST; broadcast->port = BigShort(PORT_SERVER); return; } for (i = 0; i < argc; i++) { s = Cmd_Argv(i); if (!*s) continue; // parse binary format specifier parse = ParsePlain; chunk = 0; if (*s == '+' || *s == '-') { parse = ParseBinary; chunk = strtoul(s, &p, 10); if (s == p) { chunk = 6; s = p + 1; } else { if (chunk < 6) goto ignore; s = p; } } if (!strncmp(s, "file://", 7)) { len = FS_LoadFile(s + 7, &data); if (len < 0) continue; (*parse)(data, len, chunk); FS_FreeFile(data); continue; } if (!strncmp(s, "http://", 7)) { #if USE_CURL len = HTTP_FetchFile(s + 7, &data); if (len < 0) continue; (*parse)(data, len, chunk); Z_Free(data); #else Com_Printf("Can't fetch '%s', no HTTP support compiled in.\n", s); #endif continue; } if (!strncmp(s, "favorites://", 12)) { ParseAddressBook(); continue; } if (!strncmp(s, "broadcast://", 12)) { broadcast->type = NA_BROADCAST; broadcast->port = BigShort(PORT_SERVER); continue; } if (!strncmp(s, "quake2://", 9)) { AddServer(NULL, s + 9); continue; } ignore: Com_Printf("Ignoring invalid master URL: %s\n", s); } }
/* ===================================== 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; }
/* ============== SCR_LoadPCX ============== */ void SCR_LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height) { byte *raw; pcx_t *pcx; int x, y; int len; int dataByte, runLength; byte *out, *pix; *pic = NULL; // // load the file // len = FS_LoadFile (filename, (void **)&raw); if (!raw) return; // Com_Printf ("Bad pcx file %s.\n", filename); // // parse the PCX file // pcx = (pcx_t *)raw; raw = &pcx->data; if (pcx->manufacturer != 0x0a || pcx->version != 5 || pcx->encoding != 1 || pcx->bits_per_pixel != 8 || pcx->xmax >= 640 || pcx->ymax >= 480) { Com_Printf ("Bad pcx file %s.\n", filename); return; } out = Z_Malloc ( (pcx->ymax+1) * (pcx->xmax+1) ); *pic = out; pix = out; if (palette) { *palette = Z_Malloc(768); memcpy (*palette, (byte *)pcx + len - 768, 768); } if (width) *width = pcx->xmax+1; if (height) *height = pcx->ymax+1; for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1) { for (x=0 ; x<=pcx->xmax ; ) { dataByte = *raw++; if ((dataByte & 0xC0) == 0xC0) { runLength = dataByte & 0x3F; dataByte = *raw++; } else runLength = 1; while(runLength-- > 0) pix[x++] = dataByte; } } if ( raw - (byte *)pcx > len) { Com_Printf ("PCX file %s was malformed.", filename); Z_Free (*pic); *pic = NULL; } FS_FreeFile (pcx); }
static void Palette_Load(void) { int i; unsigned char *out; float gamma, scale, base; fs_offset_t filesize; unsigned char *palfile; unsigned char texturegammaramp[256]; union { unsigned char b[4]; unsigned int i; } bgra; gamma = 1; scale = 1; base = 0; // COMMANDLINEOPTION: Client: -texgamma <number> sets the quake palette gamma, allowing you to make quake textures brighter/darker, not recommended i = COM_CheckParm("-texgamma"); if (i) gamma = atof(com_argv[i + 1]); // COMMANDLINEOPTION: Client: -texcontrast <number> sets the quake palette contrast, allowing you to make quake textures brighter/darker, not recommended i = COM_CheckParm("-texcontrast"); if (i) scale = atof(com_argv[i + 1]); // COMMANDLINEOPTION: Client: -texbrightness <number> sets the quake palette brightness (brightness of black), allowing you to make quake textures brighter/darker, not recommended i = COM_CheckParm("-texbrightness"); if (i) base = atof(com_argv[i + 1]); gamma = bound(0.01, gamma, 10.0); scale = bound(0.01, scale, 10.0); base = bound(0, base, 0.95); BuildGammaTable8(1.0f, gamma, scale, base, 1, texturegammaramp, 256); palfile = (unsigned char *)FS_LoadFile ("gfx/palette.lmp", tempmempool, false, &filesize); if (palfile && filesize >= 768) memcpy(palette_rgb, palfile, 768); else { Con_DPrint("Couldn't load gfx/palette.lmp, falling back on internal palette\n"); memcpy(palette_rgb, host_quakepal, 768); } if (palfile) Mem_Free(palfile); out = (unsigned char *) palette_bgra_complete; // palette is accessed as 32bit for speed reasons, but is created as 8bit bytes for (i = 0;i < 256;i++) { out[i*4+2] = texturegammaramp[palette_rgb[i][0]]; out[i*4+1] = texturegammaramp[palette_rgb[i][1]]; out[i*4+0] = texturegammaramp[palette_rgb[i][2]]; out[i*4+3] = 255; } if(*r_colormap_palette.string) palfile = (unsigned char *)FS_LoadFile (r_colormap_palette.string, tempmempool, false, &filesize); else palfile = NULL; if (palfile && filesize >= 48*2) { memcpy(palette_rgb_shirtcolormap[0], palfile, 48); memcpy(palette_rgb_shirtscoreboard[0], palfile + 48, 48); } else { for(i = 0;i < 16;i++) { VectorCopy(palette_rgb[(i << 4) | ((i >= 8 && i <= 13) ? 0x04 : 0x0C)], palette_rgb_shirtcolormap[i]); VectorCopy(palette_rgb[(i << 4) | 0x08], palette_rgb_shirtscoreboard[i]); } } if (palfile && filesize >= 48*4) { memcpy(palette_rgb_pantscolormap[0], palfile + 48*2, 48); memcpy(palette_rgb_pantsscoreboard[0], palfile + 48*3, 48); } else { memcpy(palette_rgb_pantscolormap, palette_rgb_shirtcolormap, sizeof(palette_rgb_pantscolormap)); memcpy(palette_rgb_pantsscoreboard, palette_rgb_shirtscoreboard, sizeof(palette_rgb_pantsscoreboard)); } if(palfile) Mem_Free(palfile); memset(palette_bgra_embeddedpic, 0, sizeof(palette_bgra_embeddedpic)); for (i = '1';i <= '7';i++) { Vector4Set(bgra.b, 255, 255, 255, (i - '0') * 255 / 7); palette_bgra_embeddedpic[i] = bgra.i; } Palette_SetupSpecialPalettes(); Palette_LoadQ2Colormap(); }
static void Palette_SetupSpecialPalettes(void) { int i; int fullbright_start, fullbright_end; int pants_start, pants_end; int shirt_start, shirt_end; int reversed_start, reversed_end; int transparentcolor; unsigned char *colormap; fs_offset_t filesize; union { int i; unsigned char b[4]; } u; colormap = FS_LoadFile("gfx/colormap.lmp", tempmempool, true, &filesize); if (colormap && filesize >= 16385) fullbright_start = 256 - colormap[16384]; else fullbright_start = 256; if (colormap) Mem_Free(colormap); fullbright_end = 256; pants_start = 96; pants_end = 112; shirt_start = 16; shirt_end = 32; reversed_start = 128; reversed_end = 224; transparentcolor = 255; for (i = 0;i < 256;i++) palette_featureflags[i] = PALETTEFEATURE_STANDARD; for (i = reversed_start;i < reversed_end;i++) palette_featureflags[i] = PALETTEFEATURE_REVERSED; for (i = pants_start;i < pants_end;i++) palette_featureflags[i] = PALETTEFEATURE_PANTS; for (i = shirt_start;i < shirt_end;i++) palette_featureflags[i] = PALETTEFEATURE_SHIRT; for (i = fullbright_start;i < fullbright_end;i++) palette_featureflags[i] = PALETTEFEATURE_GLOW; palette_featureflags[0] = PALETTEFEATURE_ZERO; palette_featureflags[transparentcolor] = PALETTEFEATURE_TRANSPARENT; for (i = 0;i < 256;i++) palette_bgra_transparent[i] = palette_bgra_complete[i]; palette_bgra_transparent[transparentcolor] = 0; for (i = 0;i < fullbright_start;i++) palette_bgra_nofullbrights[i] = palette_bgra_complete[i]; for (i = fullbright_start;i < fullbright_end;i++) palette_bgra_nofullbrights[i] = palette_bgra_complete[0]; for (i = 0;i < 256;i++) palette_bgra_onlyfullbrights[i] = 0; for (i = fullbright_start;i < fullbright_end;i++) palette_bgra_onlyfullbrights[i] = palette_bgra_complete[i]; for (i = 0;i < 256;i++) palette_bgra_nocolormapnofullbrights[i] = palette_bgra_complete[i]; for (i = pants_start;i < pants_end;i++) palette_bgra_nocolormapnofullbrights[i] = 0; for (i = shirt_start;i < shirt_end;i++) palette_bgra_nocolormapnofullbrights[i] = 0; for (i = fullbright_start;i < fullbright_end;i++) palette_bgra_nocolormapnofullbrights[i] = 0; for (i = 0;i < 256;i++) palette_bgra_nocolormap[i] = palette_bgra_complete[i]; for (i = pants_start;i < pants_end;i++) palette_bgra_nocolormap[i] = 0; for (i = shirt_start;i < shirt_end;i++) palette_bgra_nocolormap[i] = 0; for (i = 0;i < 256;i++) palette_bgra_pantsaswhite[i] = 0; for (i = pants_start;i < pants_end;i++) { if (i >= reversed_start && i < reversed_end) palette_bgra_pantsaswhite[i] = palette_bgra_complete[15 - (i - pants_start)]; else palette_bgra_pantsaswhite[i] = palette_bgra_complete[i - pants_start]; } for (i = 0;i < 256;i++) palette_bgra_shirtaswhite[i] = 0; for (i = shirt_start;i < shirt_end;i++) { if (i >= reversed_start && i < reversed_end) palette_bgra_shirtaswhite[i] = palette_bgra_complete[15 - (i - shirt_start)]; else palette_bgra_shirtaswhite[i] = palette_bgra_complete[i - shirt_start]; } for (i = 0;i < 256;i++) palette_bgra_alpha[i] = 0xFFFFFFFF; u.i = 0xFFFFFFFF; u.b[3] = 0; palette_bgra_alpha[transparentcolor] = u.i; for (i = 0;i < 256;i++) palette_bgra_font[i] = palette_bgra_complete[i]; palette_bgra_font[0] = 0; }
/** * @brief Load material definitions for each map that has one * @param[in] map the base name of the map to load the material for */ void R_LoadMaterials (const char *map) { char path[MAX_QPATH]; byte *fileBuffer; const char *buffer; bool inmaterial; image_t *image; material_t *m; materialStage_t *ss; /* clear previously loaded materials */ R_ImageClearMaterials(); if (map[0] == '+' || map[0] == '-') map++; else if (map[0] == '-') return; /* load the materials file for parsing */ Com_sprintf(path, sizeof(path), "materials/%s.mat", Com_SkipPath(map)); if (FS_LoadFile(path, &fileBuffer) < 1) { Com_DPrintf(DEBUG_RENDERER, "Couldn't load %s\n", path); return; } else { Com_Printf("load material file: '%s'\n", path); if (!r_materials->integer) Com_Printf("...ignore materials (r_materials is deactivated)\n"); } buffer = (const char *)fileBuffer; inmaterial = false; image = nullptr; m = nullptr; while (true) { const char *c = Com_Parse(&buffer); if (c[0] == '\0') break; if (*c == '{' && !inmaterial) { inmaterial = true; continue; } if (Q_streq(c, "material")) { c = Com_Parse(&buffer); image = R_GetImage(va("textures/%s", c)); if (image == nullptr) Com_DPrintf(DEBUG_RENDERER, "R_LoadMaterials: skip texture: %s - not used in the map\n", c); continue; } if (!image) continue; m = &image->material; if (Q_streq(c, "normalmap")){ c = Com_Parse(&buffer); image->normalmap = R_FindImage(va("textures/%s", c), it_normalmap); if (image->normalmap == r_noTexture){ Com_Printf("R_LoadMaterials: Failed to resolve normalmap: %s\n", c); image->normalmap = nullptr; } } if (Q_streq(c, "glowmap")){ c = Com_Parse(&buffer); image->glowmap = R_FindImage(va("textures/%s", c), it_glowmap); if (image->glowmap == r_noTexture){ Com_Printf("R_LoadMaterials: Failed to resolve glowmap: %s\n", c); image->glowmap = nullptr; } } if (Q_streq(c, "bump")) { m->bump = atof(Com_Parse(&buffer)); if (m->bump < 0.0) { Com_Printf("R_LoadMaterials: Invalid bump value for %s\n", image->name); m->bump = defaultMaterial.bump; } } if (Q_streq(c, "parallax")) { m->parallax = atof(Com_Parse(&buffer)); if (m->parallax < 0.0) { Com_Printf("R_LoadMaterials: Invalid parallax value for %s\n", image->name); m->parallax = defaultMaterial.parallax; } } if (Q_streq(c, "hardness")) { m->hardness = atof(Com_Parse(&buffer)); if (m->hardness < 0.0) { Com_Printf("R_LoadMaterials: Invalid hardness value for %s\n", image->name); m->hardness = defaultMaterial.hardness; } } if (Q_streq(c, "specular")) { m->specular = atof(Com_Parse(&buffer)); if (m->specular < 0.0) { Com_Printf("R_LoadMaterials: Invalid specular value for %s\n", image->name); m->specular = defaultMaterial.specular; } } if (Q_streq(c, "glowscale")) { m->glowscale = atof(Com_Parse(&buffer)); if (m->glowscale < 0.0) { Com_Printf("R_LoadMaterials: Invalid glowscale value for %s\n", image->name); m->glowscale = defaultMaterial.glowscale; } } if (*c == '{' && inmaterial) { materialStage_t* const s = Mem_PoolAllocType(materialStage_t, vid_imagePool); s->glowscale = defaultMaterial.glowscale; if (R_ParseStage(s, &buffer) == -1) { Mem_Free(s); continue; } /* load animation frame images */ if (s->flags & STAGE_ANIM) { if (R_LoadAnimImages(s) == -1) { Mem_Free(s); continue; } } /* append the stage to the chain */ if (!m->stages) m->stages = s; else { ss = m->stages; while (ss->next) ss = ss->next; ss->next = s; } m->flags |= s->flags; m->num_stages++; continue; } if (*c == '}' && inmaterial) { Com_DPrintf(DEBUG_RENDERER, "Parsed material %s with %d stages\n", image->name, m->num_stages); inmaterial = false; image = nullptr; /* multiply stage glowscale values by material glowscale */ ss = m->stages; while (ss) { ss->glowscale *= m->glowscale; ss = ss->next; } } } FS_FreeFile(fileBuffer); R_CreateMaterialData(); }
void R_ParseDetailTextures( const char *filename ) { char *afile, *pfile; string token, texname, detail_texname; float xScale, yScale; texture_t *tex; int i; if( r_detailtextures->integer >= 2 && !FS_FileExists( filename, false )) { // use built-in generator for detail textures R_CreateDetailTexturesList( filename ); } afile = FS_LoadFile( filename, NULL, false ); if( !afile ) return; pfile = afile; // format: 'texturename' 'detailtexture' 'xScale' 'yScale' while(( pfile = COM_ParseFile( pfile, token )) != NULL ) { texname[0] = '\0'; // read texname if( token[0] == '{' ) { // NOTE: COM_ParseFile handled some symbols seperately // this code will be fix it pfile = COM_ParseFile( pfile, token ); Q_strncat( texname, "{", sizeof( texname )); Q_strncat( texname, token, sizeof( texname )); } else Q_strncpy( texname, token, sizeof( texname )); // read detailtexture name pfile = COM_ParseFile( pfile, token ); Q_snprintf( detail_texname, sizeof( detail_texname ), "gfx/%s.tga", token ); // read scales pfile = COM_ParseFile( pfile, token ); xScale = Q_atof( token ); pfile = COM_ParseFile( pfile, token ); yScale = Q_atof( token ); if( xScale <= 0.0f || yScale <= 0.0f ) continue; // search for existing texture and uploading detail texture for( i = 0; i < cl.worldmodel->numtextures; i++ ) { tex = cl.worldmodel->textures[i]; if( Q_stricmp( tex->name, texname )) continue; tex->dt_texturenum = GL_LoadTexture( detail_texname, NULL, 0, TF_FORCE_COLOR ); // texture is loaded if( tex->dt_texturenum ) { gltexture_t *glt; GL_SetTextureType( tex->dt_texturenum, TEX_DETAIL ); glt = R_GetTexture( tex->gl_texturenum ); glt->xscale = xScale; glt->yscale = yScale; } break; } } Mem_Free( afile ); }
void LoadPNG (char *name, byte **pic, int *width, int *height) { int i, rowptr; png_structp png_ptr; png_infop info_ptr; png_infop end_info; unsigned char **row_pointers; TPngFileBuffer PngFileBuffer = {NULL,0}; *pic = NULL; FS_LoadFile (name, &PngFileBuffer.Buffer); if (!PngFileBuffer.Buffer) return; if ((png_check_sig(PngFileBuffer.Buffer, 8)) == 0) { FS_FreeFile (PngFileBuffer.Buffer); VID_Printf (PRINT_ALL, "Not a PNG file: %s\n", name); return; } PngFileBuffer.Pos=0; png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { FS_FreeFile (PngFileBuffer.Buffer); VID_Printf (PRINT_ALL, "Bad PNG file: %s\n", name); return; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); FS_FreeFile (PngFileBuffer.Buffer); VID_Printf (PRINT_ALL, "Bad PNG file: %s\n", name); return; } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); FS_FreeFile (PngFileBuffer.Buffer); VID_Printf (PRINT_ALL, "Bad PNG file: %s\n", name); return; } png_set_read_fn (png_ptr,(png_voidp)&PngFileBuffer,(png_rw_ptr)PngReadFunc); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); row_pointers = png_get_rows(png_ptr, info_ptr); rowptr = 0; *pic = malloc (info_ptr->width * info_ptr->height * sizeof(int)); if (info_ptr->channels == 4) { for (i = 0; i < info_ptr->height; i++) { memcpy (*pic + rowptr, row_pointers[i], info_ptr->rowbytes); rowptr += info_ptr->rowbytes; } } else { int j, x; memset (*pic, 255, info_ptr->width * info_ptr->height * sizeof(int)); x = 0; for (i = 0; i < info_ptr->height; i++) { for (j = 0; j < info_ptr->rowbytes; j+=info_ptr->channels) { memcpy (*pic + x, row_pointers[i] + j, info_ptr->channels); x+= sizeof(int); } rowptr += info_ptr->rowbytes; } } *width = info_ptr->width; *height = info_ptr->height; png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); FS_FreeFile (PngFileBuffer.Buffer); }
/* ============== LoadPCX ============== */ void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height) { byte *raw; pcx_t *pcx; int x, y; int len; int dataByte, runLength; byte *out, *pix; *pic = NULL; *palette = NULL; // // load the file // len = FS_LoadFile (filename, (void **)&raw); if (!raw) { VID_Printf (PRINT_DEVELOPER, "Bad pcx file %s\n", filename); return; } // // parse the PCX file // pcx = (pcx_t *)raw; pcx->xmin = LittleShort(pcx->xmin); pcx->ymin = LittleShort(pcx->ymin); pcx->xmax = LittleShort(pcx->xmax); pcx->ymax = LittleShort(pcx->ymax); pcx->hres = LittleShort(pcx->hres); pcx->vres = LittleShort(pcx->vres); pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); pcx->palette_type = LittleShort(pcx->palette_type); raw = &pcx->data; if (pcx->manufacturer != 0x0a || pcx->version != 5 || pcx->encoding != 1 || pcx->bits_per_pixel != 8 || pcx->xmax >= 640 || pcx->ymax >= 480) { VID_Printf (PRINT_ALL, "Bad pcx file %s\n", filename); return; } out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) ); *pic = out; pix = out; if (palette) { *palette = malloc(768); memcpy (*palette, (byte *)pcx + len - 768, 768); } if (width) *width = pcx->xmax+1; if (height) *height = pcx->ymax+1; for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1) { for (x=0 ; x<=pcx->xmax ; ) { dataByte = *raw++; if((dataByte & 0xC0) == 0xC0) { runLength = dataByte & 0x3F; dataByte = *raw++; } else runLength = 1; while(runLength-- > 0) pix[x++] = dataByte; } } if ( raw - (byte *)pcx > len) { VID_Printf (PRINT_DEVELOPER, "PCX file %s was malformed", filename); free (*pic); *pic = NULL; } FS_FreeFile (pcx); }
/** * @sa M_Stop */ static void M_Start (const char* file) { if (Q_strnull(file)) return; if (!s_env.initialized) { Com_Printf("M_Start: No sound started!\n"); return; } if (music.playingStream || !music.playing) return; char name[MAX_QPATH]; Com_StripExtension(file, name, sizeof(name)); const size_t len = strlen(name); if (len + 4 >= MAX_QPATH) { Com_Printf("M_Start: MAX_QPATH exceeded: " UFO_SIZE_T "\n", len + 4); return; } /* we are already playing that track */ if (Q_streq(name, music.currentTrack) && music.data && Mix_PlayingMusic()) return; /* we are still playing some background track - fade it out */ if (music.data && Mix_PlayingMusic()) { if (!Mix_FadeOutMusic(1500)) M_Stop(); Q_strncpyz(music.nextTrack, name, sizeof(music.nextTrack)); return; } /* make really sure the last track is closed and freed */ M_Stop(); /* load it in */ byte* musicBuf; const int size = FS_LoadFile(va("music/%s.ogg", name), &musicBuf); if (size == -1) { Com_Printf("M_Start: Could not load '%s' background track!\n", name); return; } SDL_RWops* rw = SDL_RWFromMem(musicBuf, size); if (!rw) { Com_Printf("M_Start: Could not load music: 'music/%s'!\n", name); FS_FreeFile(musicBuf); return; } #if SDL_VERSION_ATLEAST(2,0,0) music.data = Mix_LoadMUS_RW(rw, 1); #else music.data = Mix_LoadMUS_RW(rw); #endif if (!music.data) { Com_Printf("M_Start: Could not load music: 'music/%s' (%s)!\n", name, Mix_GetError()); SDL_FreeRW(rw); FS_FreeFile(musicBuf); return; } Q_strncpyz(music.currentTrack, name, sizeof(music.currentTrack)); music.buffer = musicBuf; if (Mix_FadeInMusic(music.data, 1, 1500) == -1) Com_Printf("M_Start: Could not play music: 'music/%s' (%s)!\n", name, Mix_GetError()); }
/* ============== S_LoadWavFile ============== */ qboolean S_LoadWavFile (const char *filename, sfx_t *sfx) { fs_offset_t filesize; unsigned char *data; wavinfo_t info; int i, len; const unsigned char *inb; unsigned char *outb; // Already loaded? if (sfx->fetcher != NULL) return true; // Load the file data = FS_LoadFile(filename, snd_mempool, false, &filesize); if (!data) return false; // Don't try to load it if it's not a WAV file if (memcmp (data, "RIFF", 4) || memcmp (data + 8, "WAVE", 4)) { Mem_Free(data); return false; } if (developer_loading.integer >= 2) Con_Printf ("Loading WAV file \"%s\"\n", filename); info = GetWavinfo (sfx->name, data, (int)filesize); if (info.channels < 1 || info.channels > 2) // Stereo sounds are allowed (intended for music) { Con_Printf("%s has an unsupported number of channels (%i)\n",sfx->name, info.channels); Mem_Free(data); return false; } //if (info.channels == 2) // Log_Printf("stereosounds.log", "%s\n", sfx->name); sfx->format.speed = info.rate; sfx->format.width = info.width; sfx->format.channels = info.channels; sfx->fetcher = &wav_fetcher; sfx->fetcher_data = Mem_Alloc(snd_mempool, info.samples * sfx->format.width * sfx->format.channels); sfx->total_length = info.samples; sfx->memsize += filesize; len = info.samples * sfx->format.channels * sfx->format.width; inb = data + info.dataofs; outb = (unsigned char *)sfx->fetcher_data; if (info.width == 2) { if (mem_bigendian) { // we have to byteswap the data at load (better than doing it while mixing) for (i = 0;i < len;i += 2) { outb[i] = inb[i+1]; outb[i+1] = inb[i]; } } else { // we can just copy it straight memcpy(outb, inb, len); } } else { // convert unsigned byte sound data to signed bytes for quicker mixing for (i = 0;i < len;i++) outb[i] = inb[i] - 0x80; } if (info.loopstart < 0) sfx->loopstart = sfx->total_length; else sfx->loopstart = info.loopstart; sfx->loopstart = min(sfx->loopstart, sfx->total_length); sfx->flags &= ~SFXFLAG_STREAMED; return true; }
static qboolean Parse_File(const char *path, int depth) { char *raw, *data, *p, *cmd; int argc; menuFrameWork_t *menu = NULL; qerror_t ret; ret = FS_LoadFile(path, (void **)&raw); if (!raw) { if (ret != Q_ERR_NOENT || depth) { Com_WPrintf("Couldn't %s %s: %s\n", depth ? "include" : "load", path, Q_ErrorString(ret)); } return qfalse; } data = raw; COM_Compress(data); while (*data) { p = strchr(data, '\n'); if (p) { *p = 0; } Cmd_TokenizeString(data, qtrue); argc = Cmd_Argc(); if (argc) { cmd = Cmd_Argv(0); if (menu) { if (!strcmp(cmd, "end")) { if (menu->nitems) { List_Append(&ui_menus, &menu->entry); } else { Com_WPrintf("Menu entry without items\n"); menu->free(menu); } menu = NULL; } else if (!strcmp(cmd, "title")) { if (menu->title) { Z_Free(menu->title); } menu->title = UI_CopyString(Cmd_Argv(1)); } else if (!strcmp(cmd, "plaque")) { Parse_Plaque(menu); } else if (!strcmp(cmd, "banner")) { Parse_Banner(menu); } else if (!strcmp(cmd, "background")) { Parse_Background(menu); } else if (!strcmp(cmd, "style")) { Parse_Style(menu); } else if (!strcmp(cmd, "values")) { Parse_Spin(menu, MTYPE_SPINCONTROL); } else if (!strcmp(cmd, "strings")) { Parse_Spin(menu, MTYPE_STRINGS); } else if (!strcmp(cmd, "pairs")) { Parse_Pairs(menu); } else if (!strcmp(cmd, "range")) { Parse_Range(menu); } else if (!strcmp(cmd, "action")) { Parse_Action(menu); } else if (!strcmp(cmd, "bitmap")) { Parse_Bitmap(menu); } else if (!strcmp(cmd, "bind")) { Parse_Bind(menu); } else if (!strcmp(cmd, "savegame")) { Parse_Savegame(menu, MTYPE_SAVEGAME); } else if (!strcmp(cmd, "loadgame")) { Parse_Savegame(menu, MTYPE_LOADGAME); } else if (!strcmp(cmd, "toggle")) { Parse_Toggle(menu); } else if (!strcmp(cmd, "field")) { Parse_Field(menu); } else if (!strcmp(cmd, "blank")) { Parse_Blank(menu); } else { Com_WPrintf("Unknown keyword '%s'\n", cmd); } } else { if (!strcmp(cmd, "begin")) { char *s = Cmd_Argv(1); if (!*s) { Com_WPrintf("Expected menu name after '%s'\n", cmd); break; } menu = UI_FindMenu(s); if (menu) { if (menu->free) { menu->free(menu); } List_Remove(&menu->entry); } menu = UI_Mallocz(sizeof(*menu)); menu->name = UI_CopyString(s); menu->push = Menu_Push; menu->pop = Menu_Pop; menu->free = Menu_Free; menu->image = uis.backgroundHandle; menu->color.u32 = uis.color.background.u32; menu->transparent = uis.transparent; } else if (!strcmp(cmd, "include")) { char *s = Cmd_Argv(1); if (!*s) { Com_WPrintf("Expected file name after '%s'\n", cmd); break; } if (depth == 16) { Com_WPrintf("Includes too deeply nested\n"); } else { Parse_File(s, depth + 1); } } else if (!strcmp(cmd, "color")) { Parse_Color(); } else if (!strcmp(cmd, "background")) { char *s = Cmd_Argv(1); if (SCR_ParseColor(s, &uis.color.background)) { uis.backgroundHandle = 0; uis.transparent = uis.color.background.u8[3] != 255; } else { uis.backgroundHandle = R_RegisterPic(s); uis.transparent = R_GetPicSize(NULL, NULL, uis.backgroundHandle); } } else if (!strcmp(cmd, "font")) { uis.fontHandle = R_RegisterFont(Cmd_Argv(1)); } else if (!strcmp(cmd, "cursor")) { uis.cursorHandle = R_RegisterPic(Cmd_Argv(1)); R_GetPicSize(&uis.cursorWidth, &uis.cursorHeight, uis.cursorHandle); } else if (!strcmp(cmd, "weapon")) { Cmd_ArgvBuffer(1, uis.weaponModel, sizeof(uis.weaponModel)); } else { Com_WPrintf("Unknown keyword '%s'\n", cmd); break; } } } if (!p) { break; } data = p + 1; } FS_FreeFile(raw); if (menu) { Com_WPrintf("Menu entry without 'end' terminator\n"); menu->free(menu); } return qtrue; }
/* ================== SV_BeginDownload_f ================== */ void SV_BeginDownload_f(void){ char *name; extern cvar_t *allow_download; extern cvar_t *allow_download_players; extern cvar_t *allow_download_models; extern cvar_t *allow_download_sounds; extern cvar_t *allow_download_maps; extern int file_from_pak; // ZOID did file come from pak? int offset = 0; name = Cmd_Argv(1); if(Cmd_Argc() > 2) offset = atoi(Cmd_Argv(2)); // downloaded offset // hacked by zoid to allow more conrol over download // first off, no .. or global allow check if(strstr(name, "..") || strstr(name, "\\/") || !allow_download->value // leading dot is no good || *name == '.' // leading slash bad as well, must be in subdir || *name == '/' // next up, skin check ||(strncmp(name, "players/", 6) == 0 && !allow_download_players->value) // now models ||(strncmp(name, "models/", 6) == 0 && !allow_download_models->value) // now sounds ||(strncmp(name, "sound/", 6) == 0 && !allow_download_sounds->value) // now maps(note special case for maps, must not be in pak) ||(strncmp(name, "maps/", 6) == 0 && !allow_download_maps->value) // MUST be in a subdirectory || !strstr(name, "/")){ // don't allow anything with .. path MSG_WriteByte(&sv_client->netchan.message, svc_download); MSG_WriteShort(&sv_client->netchan.message, -1); MSG_WriteByte(&sv_client->netchan.message, 0); return; } if(sv_client->download) FS_FreeFile(sv_client->download); sv_client->downloadsize = FS_LoadFile(name, (void **)(char *)&sv_client->download); sv_client->downloadcount = offset; if(offset > sv_client->downloadsize) sv_client->downloadcount = sv_client->downloadsize; if(!sv_client->download // special check for maps, if it came from a pak file, don't allow // download ZOID ||(strncmp(name, "maps/", 5) == 0 && file_from_pak)){ Com_DPrintf("Couldn't download %s to %s\n", name, sv_client->name); if(sv_client->download){ FS_FreeFile(sv_client->download); sv_client->download = NULL; } MSG_WriteByte(&sv_client->netchan.message, svc_download); MSG_WriteShort(&sv_client->netchan.message, -1); MSG_WriteByte(&sv_client->netchan.message, 0); return; } SV_NextDownload_f(); Com_DPrintf("Downloading %s to %s\n", name, sv_client->name); }
/* =============== CL_Download_f Request a download from the server =============== */ void CL_Download_f (void) { char filename[MAX_OSPATH]; int len; if (Cmd_Argc() != 2) { Com_Printf("Usage: download <filename>\n"); return; } Com_sprintf(filename, sizeof(filename), "%s", Cmd_Argv(1)); if (strstr (filename, "..")) { Com_Printf ("Refusing to download a path with ..\n"); return; } // NeVo - hack to not download if we have the image (any type) len = strlen(filename); if ((!strcmp(filename+len-4, ".pcx")) || (!strcmp(filename+len-4, ".wal"))) { COM_StripExtension (filename, filename); strcat (filename, ".tga"); if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download Com_Printf("File already exists.\n"); return; } else { COM_StripExtension (filename, filename); strcat (filename, ".jpg"); if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download Com_Printf("File already exists.\n"); return; } else { COM_StripExtension (filename, filename); strcat (filename, ".m32"); if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download Com_Printf("File already exists.\n"); return; } else { COM_StripExtension (filename, filename); strcat (filename, ".pcx"); if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download Com_Printf("File already exists.\n"); return; } else { COM_StripExtension (filename, filename); strcat (filename, ".wal"); if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download Com_Printf("File already exists.\n"); return; } } } } } } else if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download return; } strcpy (cls.downloadname, filename); Com_Printf ("Downloading %s\n", cls.downloadname); // download to a temp name, and only rename // to the real name when done, so if interrupted // a runt file wont be left COM_StripExtension (cls.downloadname, cls.downloadtempname); strcat (cls.downloadtempname, ".tmp"); MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname)); cls.downloadnumber++; }
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; }
/* =============== CL_CheckOrDownloadFile Returns 1 if the file exists, otherwise it attempts to start a download from the server. =============== */ int CL_CheckOrDownloadFile (char *filename) { FILE *fp; char name[MAX_OSPATH]; int len; if (strstr (filename, "..")) { Com_Printf ("Refusing to download a path with ..\n"); return 1; } // NeVo - hack to not download if we have the image (any type) len = strlen(filename); if ((!strcmp(filename+len-4, ".pcx")) || (!strcmp(filename+len-4, ".wal"))) { COM_StripExtension (filename, filename); strcat (filename, ".tga"); if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download return 1; } else { COM_StripExtension (filename, filename); strcat (filename, ".jpg"); if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download return 1; } else { COM_StripExtension (filename, filename); strcat (filename, ".m32"); if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download return 1; } else { COM_StripExtension (filename, filename); strcat (filename, ".pcx"); if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download return 1; } else { COM_StripExtension (filename, filename); strcat (filename, ".wal"); if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download return 1; } } } } } } else if (FS_LoadFile (filename, NULL) != -1) { // it exists, no need to download return 1; } strcpy (cls.downloadname, filename); // download to a temp name, and only rename // to the real name when done, so if interrupted // a runt file wont be left COM_StripExtension (cls.downloadname, cls.downloadtempname); strcat (cls.downloadtempname, ".tmp"); //ZOID // check to see if we already have a tmp for this file, if so, try to resume // open the file if not opened yet CL_DownloadFileName(name, sizeof(name), cls.downloadtempname); // FS_CreatePath (name); fp = fopen (name, "r+b"); if (fp) { // it exists int len; fseek(fp, 0, SEEK_END); len = ftell(fp); cls.download = fp; // give the server an offset to start the download Com_Printf ("Resuming %s\n", cls.downloadname); MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("download %s %i", cls.downloadname, len)); } else { Com_Printf ("Downloading %s\n", cls.downloadname); MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname)); } cls.downloadnumber++; return 0; }
/* ==================== ModPlug_LoadmodplugFile Load an modplug file into memory ==================== */ qboolean ModPlug_LoadModPlugFile (const char *filename, sfx_t *sfx) { unsigned char *data; fs_offset_t filesize; ModPlugFile *mf; modplug_stream_persfx_t* per_sfx; ModPlug_Settings s; if (!modplug_dll) return false; // Already loaded? if (sfx->fetcher != NULL) return true; // Load the file data = FS_LoadFile (filename, snd_mempool, false, &filesize); if (data == NULL) return false; if (developer_loading.integer >= 2) Con_Printf ("Loading ModPlug file \"%s\"\n", filename); qModPlug_GetSettings(&s); s.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION | MODPLUG_ENABLE_REVERB; s.mChannels = 2; s.mBits = 16; s.mFrequency = 44100; s.mResamplingMode = MODPLUG_RESAMPLE_SPLINE; s.mLoopCount = -1; qModPlug_SetSettings(&s); // Open it with the modplugFile API if (!(mf = qModPlug_Load (data, filesize))) { Con_Printf ("error while opening ModPlug file \"%s\"\n", filename); Mem_Free(data); return false; } #ifndef SND_MODPLUG_STATIC if(qModPlug_SetMasterVolume) #endif qModPlug_SetMasterVolume(mf, 512); // max volume, DP scales down! if (developer_loading.integer >= 2) Con_Printf ("\"%s\" will be streamed\n", filename); per_sfx = (modplug_stream_persfx_t *)Mem_Alloc (snd_mempool, sizeof (*per_sfx)); per_sfx->file = data; per_sfx->filesize = filesize; sfx->memsize += sizeof(*per_sfx); sfx->memsize += filesize; sfx->format.speed = 44100; // modplug always works at that rate sfx->format.width = 2; // We always work with 16 bits samples sfx->format.channels = 2; // stereo rulez ;) (MAYBE default to mono because Amiga MODs sound better then?) sfx->fetcher_data = per_sfx; sfx->fetcher = &modplug_fetcher; sfx->flags |= SFXFLAG_STREAMED; sfx->total_length = 1<<30; // 2147384647; // they always loop (FIXME this breaks after 6 hours, we need support for a real "infinite" value!) sfx->loopstart = sfx->total_length; // modplug does it return true; }
/* * ML_InitFromCache * Fills map list array from cache, much faster */ static void ML_InitFromCache( void ) { int count, i, total, len; size_t size = 0; char *buffer, *chr, *current, *curend; char *temp, *maps, *map; mapdir_t *dir, *curmap, *prev; if( ml_initialized ) return; total = FS_GetFileListExt( "maps", ".bsp", NULL, &size, 0, 0 ); if( !total ) return; // load maps from directory reading into a list maps = temp = ( char* )Mem_TempMalloc( size + sizeof( mapdir_t ) * total ); temp += size; FS_GetFileList( "maps", ".bsp", maps, size, 0, 0 ); len = 0; prev = NULL; dir = NULL; for( i = 0; i < total; i++ ) { map = maps + len; len += strlen( map ) + 1; curmap = ( mapdir_t * )temp; temp += sizeof( mapdir_t ); COM_StripExtension( map ); if( !i ) dir = curmap; else { prev->next = curmap; curmap->prev = prev; } curmap->filename = map; prev = curmap; } FS_LoadFile( MLIST_CACHE, (void **)&buffer, NULL, 0 ); if( !buffer ) { Mem_TempFree( maps ); return; } current = curend = buffer; count = 0; for( chr = buffer; *chr; chr++ ) { // current character is a delimiter if( *chr == '\n' ) { if( *(chr-1) == '\r' ) *(chr-1) = '\0'; // clear the CR too *chr = '\0'; // clear the LF // if we have got both params if( !( ++count & 1 ) ) { // check if its in the maps directory for( curmap = dir; curmap; curmap = curmap->next ) { if( !Q_stricmp( curmap->filename, current ) ) { if( curmap->prev ) curmap->prev->next = curmap->next; else dir = curmap->next; if( curmap->next ) curmap->next->prev = curmap->prev; break; } } // if we found it in the maps directory if( curmap ) { COM_SanitizeFilePath( current ); // well, if we've got a map with an unknown fullname, load it from map if( !strcmp( curend + 1, MLIST_UNKNOWN_MAPNAME ) ) ML_AddMap( current, NULL ); else ML_AddMap( current, curend + 1 ); } current = chr + 1; } else curend = chr; } } // we've now loaded the mapcache, but there may be files which // have been added to maps directory, and the mapcache isnt aware // these will be left over in our directory list for( curmap = dir; curmap; curmap = curmap->next ) ML_AddMap( curmap->filename, NULL ); Mem_TempFree( maps ); FS_FreeFile( buffer ); }
/* ============== S_LoadSound ============== */ sfxcache_t *S_LoadSound (sfx_t *s) { char namebuffer[MAX_QPATH]; byte *data; wavinfo_t info; int len; float stepscale; sfxcache_t *sc; int size; char *name; if (s->name[0] == '*') return NULL; // see if still in memory sc = s->cache; if (sc) return sc; //S_Printf(PRINT_ALL, "S_LoadSound: %x\n", (int)stackbuf); // load it in if (s->truename) name = s->truename; else name = s->name; if (name[0] == '#') strcpy(namebuffer, &name[1]); else Com_sprintf (namebuffer, sizeof(namebuffer), "sound/%s", name); // S_Printf(PRINT_ALL, "loading %s\n",namebuffer); size = FS_LoadFile (namebuffer, (void **)&data); if (!data) { S_Printf(PRINT_DEVELOPER, "Couldn't load %s\n", namebuffer); return NULL; } info = GetWavinfo (s->name, data, size); if (info.channels != 1) { S_Printf(PRINT_ALL, "%s is a stereo sample\n",s->name); FS_FreeFile (data); return NULL; } stepscale = (float)info.rate / dma.speed; len = info.samples / stepscale; len = len * info.width * info.channels; sc = s->cache = Z_Malloc (len + sizeof(sfxcache_t)); if (!sc) { FS_FreeFile (data); return NULL; } sc->length = info.samples; sc->loopstart = info.loopstart; sc->speed = info.rate; sc->width = info.width; sc->stereo = info.channels; ResampleSfx (s, sc->speed, sc->width, data + info.dataofs); FS_FreeFile (data); return sc; }
void SV_BeginDownload_f(void) { char *name; extern cvar_t *allow_download; extern cvar_t *allow_download_players; extern cvar_t *allow_download_models; extern cvar_t *allow_download_sounds; extern cvar_t *allow_download_maps; extern int file_from_pak; int offset = 0; name = Cmd_Argv(1); if (Cmd_Argc() > 2) { offset = (int)strtol(Cmd_Argv(2), (char **)NULL, 10); /* downloaded offset */ } /* hacked by zoid to allow more conrol over download first off, no .. or global allow check */ if (strstr(name, "..") || strstr(name, "\\") || !allow_download->value /* leading dot is no good */ || (*name == '.') /* leading slash bad as well, must be in subdir */ || (*name == '/') /* next up, skin check */ || ((strncmp(name, "players/", 6) == 0) && !allow_download_players->value) /* now models */ || ((strncmp(name, "models/", 6) == 0) && !allow_download_models->value) /* now sounds */ || ((strncmp(name, "sound/", 6) == 0) && !allow_download_sounds->value) /* now maps (note special case for maps, must not be in pak) */ || ((strncmp(name, "maps/", 6) == 0) && !allow_download_maps->value) /* MUST be in a subdirectory */ || !strstr(name, "/")) { MSG_WriteByte(&sv_client->netchan.message, svc_download); MSG_WriteShort(&sv_client->netchan.message, -1); MSG_WriteByte(&sv_client->netchan.message, 0); return; } if (sv_client->download) { FS_FreeFile(sv_client->download); } sv_client->downloadsize = FS_LoadFile(name, (void **)&sv_client->download); sv_client->downloadcount = offset; if (offset > sv_client->downloadsize) { sv_client->downloadcount = sv_client->downloadsize; } if (!sv_client->download || ((strncmp(name, "maps/", 5) == 0) && file_from_pak)) { Com_DPrintf("Couldn't download %s to %s\n", name, sv_client->name); if (sv_client->download) { FS_FreeFile(sv_client->download); sv_client->download = NULL; } MSG_WriteByte(&sv_client->netchan.message, svc_download); MSG_WriteShort(&sv_client->netchan.message, -1); MSG_WriteByte(&sv_client->netchan.message, 0); return; } SV_NextDownload_f(); Com_DPrintf("Downloading %s to %s\n", name, sv_client->name); }
/** * @brief Tries to load a mdx file that contains the normals and the tangents for a model. * @sa R_ModCalcNormalsAndTangents * @sa R_ModCalcUniqueNormalsAndTangents * @param mod The model to load the mdx file for */ qboolean R_ModLoadMDX (model_t *mod) { int i; for (i = 0; i < mod->alias.num_meshes; i++) { mAliasMesh_t *mesh = &mod->alias.meshes[i]; char mdxFileName[MAX_QPATH]; byte *buffer = NULL, *buf; const int32_t *intbuf; uint32_t version; int sharedTris[MAX_ALIAS_VERTS]; Com_StripExtension(mod->name, mdxFileName, sizeof(mdxFileName)); Com_DefaultExtension(mdxFileName, sizeof(mdxFileName), ".mdx"); if (FS_LoadFile(mdxFileName, &buffer) == -1) return qfalse; buf = buffer; if (strncmp((const char *) buf, IDMDXHEADER, strlen(IDMDXHEADER))) Com_Error(ERR_DROP, "No mdx file buffer given"); buffer += strlen(IDMDXHEADER) * sizeof(char); version = LittleLong(*(uint32_t*) buffer); if (version != MDX_VERSION) Com_Error(ERR_DROP, "Invalid version of the mdx file, expected %i, found %i", MDX_VERSION, version); buffer += sizeof(uint32_t); intbuf = (const int32_t *) buffer; mesh->num_verts = LittleLong(*intbuf); if (mesh->num_verts <= 0 || mesh->num_verts > MAX_ALIAS_VERTS) Com_Error(ERR_DROP, "mdx file for %s has to many (or no) vertices: %i", mod->name, mesh->num_verts); intbuf++; mesh->num_indexes = LittleLong(*intbuf); intbuf++; mesh->indexes = (int32_t *)Mem_PoolAlloc(sizeof(int32_t) * mesh->num_indexes, vid_modelPool, 0); mesh->revIndexes = (mIndexList_t *)Mem_PoolAlloc(sizeof(mIndexList_t) * mesh->num_verts, vid_modelPool, 0); mesh->vertexes = (mAliasVertex_t *)Mem_PoolAlloc(sizeof(mAliasVertex_t) * mod->alias.num_frames * mesh->num_verts, vid_modelPool, 0); /* load index that maps triangle verts to Vertex objects */ for (i = 0; i < mesh->num_indexes; i++) { mesh->indexes[i] = LittleLong(*intbuf); intbuf++; } for (i = 0; i < mesh->num_verts; i++) sharedTris[i] = 0; /* set up reverse-index that maps Vertex objects to a list of triangle verts */ for (i = 0; i < mesh->num_indexes; i++) sharedTris[mesh->indexes[i]]++; for (i = 0; i < mesh->num_verts; i++) { mesh->revIndexes[i].length = 0; mesh->revIndexes[i].list = (int32_t *)Mem_PoolAlloc(sizeof(int32_t) * sharedTris[i], vid_modelPool, 0); } for (i = 0; i < mesh->num_indexes; i++) mesh->revIndexes[mesh->indexes[i]].list[mesh->revIndexes[mesh->indexes[i]].length++] = i; FS_FreeFile(buf); } return qtrue; }
/** * @sa CM_AddMapTile * @sa R_ModBeginLoading * @param[in] name The name of the map. Relative to maps/ and without extension * @param[in] day Load the day lightmap * @param[in] sX Shift x grid units * @param[in] sY Shift y grid units * @param[in] sZ Shift z grid units * @sa UNIT_SIZE */ static void R_ModAddMapTile (const char *name, qboolean day, int sX, int sY, int sZ) { int i; byte *buffer; dBspHeader_t *header; const int lightingLump = day ? LUMP_LIGHTING_DAY : LUMP_LIGHTING_NIGHT; /* get new model */ if (r_numModels < 0 || r_numModels >= MAX_MOD_KNOWN) Com_Error(ERR_DROP, "R_ModAddMapTile: r_numModels >= MAX_MOD_KNOWN"); if (r_numMapTiles < 0 || r_numMapTiles >= MAX_MAPTILES) Com_Error(ERR_DROP, "R_ModAddMapTile: Too many map tiles"); /* alloc model and tile */ r_worldmodel = &r_models[r_numModels++]; r_mapTiles[r_numMapTiles++] = r_worldmodel; OBJZERO(*r_worldmodel); Com_sprintf(r_worldmodel->name, sizeof(r_worldmodel->name), "maps/%s.bsp", name); /* load the file */ FS_LoadFile(r_worldmodel->name, &buffer); if (!buffer) Com_Error(ERR_DROP, "R_ModAddMapTile: %s not found", r_worldmodel->name); /* init */ r_worldmodel->type = mod_bsp; /* prepare shifting */ VectorSet(shift, sX * UNIT_SIZE, sY * UNIT_SIZE, sZ * UNIT_SIZE); /* test version */ header = (dBspHeader_t *) buffer; i = LittleLong(header->version); if (i != BSPVERSION) Com_Error(ERR_DROP, "R_ModAddMapTile: %s has wrong version number (%i should be %i)", r_worldmodel->name, i, BSPVERSION); /* swap all the lumps */ mod_base = (byte *) header; for (i = 0; i < (int)sizeof(dBspHeader_t) / 4; i++) ((int *) header)[i] = LittleLong(((int *) header)[i]); /* load into heap */ R_ModLoadVertexes(&header->lumps[LUMP_VERTEXES]); R_ModLoadNormals(&header->lumps[LUMP_NORMALS]); R_ModLoadEdges(&header->lumps[LUMP_EDGES]); R_ModLoadSurfedges(&header->lumps[LUMP_SURFEDGES]); R_ModLoadLighting(&header->lumps[lightingLump]); R_ModLoadPlanes(&header->lumps[LUMP_PLANES]); R_ModLoadTexinfo(&header->lumps[LUMP_TEXINFO]); R_ModLoadSurfaces(day, &header->lumps[LUMP_FACES]); R_ModLoadLeafs(&header->lumps[LUMP_LEAFS]); R_ModLoadNodes(&header->lumps[LUMP_NODES]); R_ModLoadSubmodels(&header->lumps[LUMP_MODELS]); R_SetupSubmodels(); R_LoadBspVertexArrays(r_worldmodel); /* in case of random map assembly shift some vectors */ if (VectorNotEmpty(shift)) R_ModShiftTile(); FS_FreeFile(buffer); }
/* =============== CL_ReadPointFile_f =============== */ void CL_ReadPointFile_f( void ) { char *afile, *pfile; vec3_t org; int count; particle_t *p; char filename[64]; string token; Q_snprintf( filename, sizeof( filename ), "maps/%s.pts", clgame.mapname ); afile = (char *)FS_LoadFile( filename, NULL, false ); if( !afile ) { MsgDev( D_ERROR, "couldn't open %s\n", filename ); return; } Msg( "Reading %s...\n", filename ); count = 0; pfile = afile; while( 1 ) { pfile = COM_ParseFile( pfile, token ); if( !pfile ) break; org[0] = Q_atof( token ); pfile = COM_ParseFile( pfile, token ); if( !pfile ) break; org[1] = Q_atof( token ); pfile = COM_ParseFile( pfile, token ); if( !pfile ) break; org[2] = Q_atof( token ); count++; if( !cl_free_particles ) { MsgDev( D_ERROR, "CL_ReadPointFile: not enough free particles!\n" ); break; } // NOTE: can't use CL_AllocateParticles because running from the console p = cl_free_particles; cl_free_particles = p->next; p->next = cl_active_particles; cl_active_particles = p; p->ramp = 0; p->die = 99999; p->color = (-count) & 15; p->type = pt_static; VectorClear( p->vel ); VectorCopy( org, p->org ); } Mem_Free( afile ); if( count ) Msg( "%i points read\n", count ); else Msg( "map %s has no leaks!\n", clgame.mapname ); }
static qboolean SV_AntiCheat_ReadFile (const char *filename, void (*func)(char *, int, const char *)) { int len; char line[256]; char *q; char *buff, *ptr; int line_number; len = FS_LoadFile (filename, (void **)&buff); if (len == -1) return false; ptr = buff; q = buff; line_number = 1; while (len) { switch (buff[0]) { case '\n': case '\r': buff[0] = 0; if (q) { qboolean parse; char *p; Q_strncpy (line, q, sizeof(line)-1); parse = true; p = strchr (line, '\n'); if (p) p[0] = 0; p = strchr (line, '\r'); if (p) p[0] = 0; if (line[0] == '#' || line[0] == '/' || line[0] == '\0') parse = false; else if (line[0] == '\\') { if (!strncmp (line + 1, "include ", 8)) { char *path; path = line + 9; if (!SV_AntiCheat_ReadFile (path, func)) Com_Printf ("ANTICHEAT WARNING: Unable to read included file '%s' from line %d of %s\n", LOG_WARNING|LOG_ANTICHEAT|LOG_SERVER, path, line_number, filename); } else { Com_Printf ("ANTICHEAT WARNING: Unknown directive '%s' on line %d of %s\n", LOG_WARNING|LOG_ANTICHEAT|LOG_SERVER, line + 1, line_number, filename); } parse = false; } if (parse) func (line, line_number, filename); q = NULL; line_number++; } buff++; break; case '\0': buff++; break; default: if (!q) q = buff; buff++; break; } len--; } FS_FreeFile (ptr); return true; }
/** * @brief Do our own preprocessing to the shader file, before the * GLSL implementation calls it's preprocessor. * * "#if/#endif" pairs, "#unroll", "#endunroll", "#include", "#replace" are handled by our * preprocessor, not the GLSL implementation's preprocessor (except "#include" which may * also be handled by the implementation's preprocessor). "#if" operates off * of the value of a cvar interpreted as a bool. Note the GLSL implementation * preprocessor handles "#ifdef" and "#ifndef", not "#if". * @param[in] name The file name of the shader (e.g. "world_fs.glsl"). * @param[in] inPtr The non-preprocessed shader string. * @param[in,out] out The preprocessed shader string, nullptr if we don't want to write to it. * @param[in,out] remainingOutChars The number of characters left in the out buffer. * @param[in] nested If true, parsing a part of "#if" clause, so "#else" and "#endif" tokens are allowed * @param[in] inElse If true, parsing an "#else" clause and shouldn't expect another "#else" * @return The number of characters added to the buffer pointed to by out. */ static size_t R_PreprocessShaderR (const char* name, const char** inPtr, char* out, long* remainingOutChars, bool nested, bool inElse) { const size_t INITIAL_REMAINING_OUT_CHARS = (size_t)*remainingOutChars; /* Keep looping till we reach the end of the shader string, or a parsing error.*/ while (**inPtr) { if ('#' == **inPtr) { bool endBlockToken; (*inPtr)++; endBlockToken = !strncmp(*inPtr, "endif", 5); if (!strncmp(*inPtr, "else", 4)) { if (inElse) { /* Error in shader! Print a message saying our preprocessor failed parsing.*/ Com_Error(ERR_DROP, "R_PreprocessShaderR: #else without #if: %s", name); } endBlockToken = true; } if (endBlockToken) { if (!nested) { /* Error in shader! Print a message saying our preprocessor failed parsing.*/ Com_Error(ERR_DROP, "R_PreprocessShaderR: Unmatched #endif/#else: %s", name); } /* Whoever called us will have to deal with closing the block */ return (INITIAL_REMAINING_OUT_CHARS - (size_t)*remainingOutChars); } if (!strncmp((*inPtr), "if ", 3)) { /* The line looks like "#if r_postprocess".*/ (*inPtr) += 3; /* Get the corresponding cvar value.*/ float f = Cvar_GetValue(Com_Parse(inPtr)); if (f) { /* Condition is true, recursively preprocess #if block, and skip over #else block, if any */ int size = R_PreprocessShaderR(name, inPtr, out, remainingOutChars, true, false); if (out) out += size; if (!strncmp((*inPtr), "else", 4)) {/* Preprocess and skip #else block */ (*inPtr) +=4 ; R_PreprocessShaderR(name, inPtr, (char*)0, remainingOutChars, true, true); } } else { /* The cvar was false, don't add to out. Lets look and see if we hit a #else, or #endif.*/ R_PreprocessShaderR(name, inPtr, (char*)0, remainingOutChars, true, false); if (!strncmp((*inPtr), "else", 4)) { int size; /* All right, we want to add this to out.*/ (*inPtr) +=4 ; size = R_PreprocessShaderR(name, inPtr, out, remainingOutChars, true, true); if (out) out += size; } } /* skip #endif, if any (could also get here by unexpected EOF */ if (!strncmp((*inPtr), "endif", 5)) (*inPtr) +=5 ; } else if (!strncmp((*inPtr), "ifndef", 6) || !strncmp((*inPtr), "ifdef", 5)) { /* leave those for GLSL compiler, but follow #else/#endif nesting */ int size; if (out) { if (*remainingOutChars <= 0) Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name); *out++ = '#'; (*remainingOutChars)--; } size = R_PreprocessShaderR(name, inPtr, out, remainingOutChars, true, false); if (out) out += size; if (!strncmp((*inPtr), "else", 4)) { if (out) { if (*remainingOutChars <= 0) Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name); *out++ = '#'; (*remainingOutChars)--; } size = R_PreprocessShaderR(name, inPtr, out, remainingOutChars, true, true); if (out) out += size; } if (out) { if (*remainingOutChars <= 0) Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name); *out++ = '#'; (*remainingOutChars)--; } } else if (!strncmp((*inPtr), "include", 7)) { char path[MAX_QPATH]; byte* buf = (byte*)0; const char* bufAsChar = (const char*)0; const char** bufAsCharPtr = (const char**)0; (*inPtr) += 8; Com_sprintf(path, sizeof(path), "shaders/%s", Com_Parse(inPtr)); if (FS_LoadFile(path, &buf) == -1) { Com_Printf("Failed to resolve #include: %s.\n", path); continue; } bufAsChar = (const char*)buf; bufAsCharPtr = &bufAsChar; if (out) { out += R_PreprocessShaderR(name, bufAsCharPtr, out, remainingOutChars, nested, false); } else { R_PreprocessShaderR(name, bufAsCharPtr, out, remainingOutChars, nested, false); } FS_FreeFile(buf); } else if (!strncmp((*inPtr), "unroll", 6)) { /* loop unrolling */ size_t subLength = 0; byte* const buffer = Mem_PoolAllocTypeN(byte, SHADER_BUF_SIZE, vid_imagePool); (*inPtr) += 6; int z = Cvar_GetValue(Com_Parse(inPtr)); while (*(*inPtr)) { if (!strncmp((*inPtr), "#endunroll", 10)) { (*inPtr) += 10; break; } buffer[subLength++] = *(*inPtr)++; if (subLength >= SHADER_BUF_SIZE) Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name); } if (out) { for (int j = 0; j < z; j++) { for (int l = 0; l < subLength; l++) { if (buffer[l] == '$') { byte insertedLen = (j / 10) + 1; if (!Com_sprintf(out, (size_t)*remainingOutChars, "%d", j)) Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name); out += insertedLen; (*remainingOutChars) -= insertedLen; } else { if (*remainingOutChars <= 0) Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name); *out++ = buffer[l]; (*remainingOutChars)--; } } } } Mem_Free(buffer); } else if (!strncmp((*inPtr), "replace", 7)) { int r = 0; (*inPtr) += 8; r = Cvar_GetValue(Com_Parse(inPtr)); if (out) { byte insertedLen = 0; if (!Com_sprintf(out, (size_t)*remainingOutChars, "%d", r)) Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name); insertedLen = (r / 10) + 1; out += insertedLen; (*remainingOutChars) -= insertedLen; } } else { /* general case is to copy so long as the buffer has room */ if (out) { if (*remainingOutChars <= 0) Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name); *out++ = '#'; (*remainingOutChars)--; } } } else { /* general case is to copy so long as the buffer has room */ if (out) { if (*remainingOutChars <= 0) Com_Error(ERR_FATAL, "R_PreprocessShaderR: Overflow in shader loading '%s'", name); *out++ = *(*inPtr); (*remainingOutChars)--; } (*inPtr)++; } } /* Return the number of characters added to the buffer.*/ return (INITIAL_REMAINING_OUT_CHARS - *remainingOutChars); }
/* ================== Mod_ForName Loads in a model for the given name ================== */ model_t *Mod_ForName (char *name, qboolean crash) { model_t *mod; unsigned *buf; int i; if (!name[0]) VID_Printf (ERR_DROP, "Mod_ForName: NULL name"); // // inline models are grabbed only from worldmodel // if (name[0] == '*') { i = atoi(name+1); if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels) VID_Printf (ERR_DROP, "bad inline model number"); return &mod_inline[i]; } // // search the currently loaded models // for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) { if (!mod->name[0]) continue; if (!strcmp (mod->name, name) ) return mod; } // // find a free model slot spot // for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) { if (!mod->name[0]) break; // free spot } if (i == mod_numknown) { if (mod_numknown == MAX_MOD_KNOWN) VID_Printf (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN"); mod_numknown++; } strcpy (mod->name, name); // // load the file // modfilelen = FS_LoadFile (mod->name, &buf); if (!buf) { if (crash) VID_Printf (ERR_DROP, "Mod_NumForName: %s not found", mod->name); memset (mod->name, 0, sizeof(mod->name)); return NULL; } loadmodel = mod; // // fill it in // // call the apropriate loader switch (LittleLong(*(unsigned *)buf)) { case IDALIASHEADER: loadmodel->extradata = Hunk_Begin (0x200000); Mod_LoadAliasModel (mod, buf); break; case IDSPRITEHEADER: loadmodel->extradata = Hunk_Begin (0x10000); Mod_LoadSpriteModel (mod, buf); break; case IDBSPHEADER: loadmodel->extradata = Hunk_Begin (0x1000000); Mod_LoadBrushModel (mod, buf); break; default: VID_Printf (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name); break; } loadmodel->extradatasize = Hunk_End (); FS_FreeFile (buf); return mod; }