//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void AASOuputFile( quakefile_t *qf, char *outputpath, char *filename ) { char ext[MAX_PATH]; // if ( strlen( outputpath ) ) { strcpy( filename, outputpath ); //append the bsp file base AppendPathSeperator( filename, MAX_PATH ); ExtractFileBase( qf->origname, &filename[strlen( filename )] ); // Ridah, add extension strcat( filename, aas_extension ); // done. //append .aas strcat( filename, ".aas" ); return; } //end if // ExtractFileExtension( qf->filename, ext ); if ( !stricmp( ext, "pk3" ) || !stricmp( ext, "pak" ) || !stricmp( ext, "sin" ) ) { strcpy( filename, qf->filename ); while ( strlen( filename ) && filename[strlen( filename ) - 1] != '\\' && filename[strlen( filename ) - 1] != '/' ) { filename[strlen( filename ) - 1] = '\0'; } //end while strcat( filename, "maps" ); if ( access( filename, 0x04 ) ) { CreatePath( filename ); } //append the bsp file base AppendPathSeperator( filename, MAX_PATH ); ExtractFileBase( qf->origname, &filename[strlen( filename )] ); // Ridah, add extension strcat( filename, aas_extension ); // done. //append .aas strcat( filename, ".aas" ); } //end if else { strcpy( filename, qf->filename ); while ( strlen( filename ) && filename[strlen( filename ) - 1] != '.' ) { filename[strlen( filename ) - 1] = '\0'; } //end while // Ridah, add extension strcat( filename, aas_extension ); // done. strcat( filename, "aas" ); } //end else } //end of the function AASOutputFile
void SC_OpenFile (const char *name) { SC_Close (); ScriptSize = M_ReadFile (name, (byte **)&ScriptBuffer); ExtractFileBase (name, ScriptName); FreeScript = true; SC_PrepareScript (); }
bool VMPI_Stats_Init_Master( const char *pHostName, const char *pDBName, const char *pUserName, const char *pBSPFilename, unsigned long *pDBJobID ) { Assert( !g_pDB ); g_bMaster = true; // Connect the database. g_pDB = new CMySqlDatabase; if ( !g_pDB || !g_pDB->Initialize() || !( g_pSQL = InitMySQL( pDBName, pHostName, pUserName ) ) ) { delete g_pDB; g_pDB = NULL; return false; } DWORD size = sizeof( g_MachineName ); GetComputerName( g_MachineName, &size ); // Create the job_master_start row. ExtractFileBase( pBSPFilename, g_BSPFilename, sizeof( g_BSPFilename ) ); g_JobPrimaryID = 0; CMySQLQuery query; query.Format( "insert into job_master_start ( BSPFilename, StartTime, MachineName, RunningTimeMS ) values ( \"%s\", null, \"%s\", %lu )", g_BSPFilename, g_MachineName, RUNNINGTIME_MS_SENTINEL ); g_pSQL->Execute( query ); g_JobPrimaryID = g_pSQL->InsertID(); if ( g_JobPrimaryID == 0 ) { delete g_pDB; g_pDB = NULL; return false; } // Now init the worker portion. *pDBJobID = g_JobPrimaryID; return VMPI_Stats_Init_Worker( NULL, NULL, NULL, g_JobPrimaryID ); }
void FShaderManager::CompileShaders() { mActiveShader = NULL; mTextureEffects.Clear(); mTextureEffectsNAT.Clear(); for (int i = 0; i < MAX_EFFECTS; i++) { mEffectShaders[i] = NULL; } for(int i=0;defaultshaders[i].ShaderName != NULL;i++) { FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, true); mTextureEffects.Push(shc); if (i <= 3) { FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, false); mTextureEffectsNAT.Push(shc); } } for(unsigned i = 0; i < usershaders.Size(); i++) { FString name = ExtractFileBase(usershaders[i]); FName sfn = name; FShader *shc = Compile(sfn, usershaders[i], true); mTextureEffects.Push(shc); } for(int i=0;i<MAX_EFFECTS;i++) { FShader *eff = new FShader(effectshaders[i].ShaderName); if (!eff->Load(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].defines)) { delete eff; } else mEffectShaders[i] = eff; } }
bool FLumpFile::Open(bool quiet) { FString name(ExtractFileBase (Filename)); Lumps = new FUncompressedLump[1]; // must use array allocator uppercopy(Lumps->Name, name); Lumps->Name[8] = 0; Lumps->Owner = this; Lumps->Position = 0; Lumps->LumpSize = Reader->GetLength(); Lumps->Namespace = ns_global; Lumps->Flags = 0; Lumps->FullName = NULL; NumLumps = 1; if (!quiet) { Printf("\n"); } return true; }
void FShaderManager::CompileShaders() { mActiveShader = mEffectShaders[0] = mEffectShaders[1] = NULL; if (gl.shadermodel > 0) { for(int i=0;defaultshaders[i].ShaderName != NULL;i++) { FShaderContainer * shc = new FShaderContainer(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc); mTextureEffects.Push(shc); if (gl.shadermodel <= 2) return; // SM2 will only initialize the default shader } for(unsigned i = 0; i < usershaders.Size(); i++) { FString name = ExtractFileBase(usershaders[i]); FName sfn = name; if (gl.shadermodel > 2) { FShaderContainer * shc = new FShaderContainer(sfn, usershaders[i]); mTextureEffects.Push(shc); } } if (gl.shadermodel > 2) { for(int i=0;i<NUM_EFFECTS;i++) { FShader *eff = new FShader(); if (!eff->Load(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].defines)) { delete eff; } else mEffectShaders[i] = eff; } } } }
/* ============== LoadScreenBMP ============== */ void LoadScreenBMP(char *pszName) { char *pszExpanded; char basename[64]; pszExpanded = ExpandPathAndArchive(pszName); printf("grabbing from %s...\n", pszExpanded); if (LoadBMP(pszExpanded, &byteimage, &lbmpalette)) Error ("Failed to load!", pszExpanded); if ( byteimage == NULL || lbmpalette == NULL ) Error("FAIL!",pszExpanded); byteimagewidth = bmhd.w; byteimageheight = bmhd.h; ExtractFileBase (token, basename); // Files that start with '$' have color (0,0,255) transparent, if ( basename[0] == '{' ) { // move to last palette entry. fTransparent255 = true; TransparentByteImage(); } }
void OvrVideosMetaData::ExtractExtendedData( const JsonReader & jsonDatum, OvrMetaDatum & datum ) const { OvrVideosMetaDatum * videoData = static_cast< OvrVideosMetaDatum * >( &datum ); if ( videoData ) { videoData->Title = jsonDatum.GetChildStringByName( TITLE_INNER ); videoData->Author = jsonDatum.GetChildStringByName( AUTHOR_INNER ); videoData->ThumbnailUrl = jsonDatum.GetChildStringByName( THUMBNAIL_URL_INNER ); videoData->StreamingType = jsonDatum.GetChildStringByName( STREAMING_TYPE_INNER ); videoData->StreamingProxy = jsonDatum.GetChildStringByName( STREAMING_PROXY_INNER ); videoData->StreamingSecurityLevel = jsonDatum.GetChildStringByName( STREAMING_SECURITY_LEVEL_INNER ); if ( videoData->Title.IsEmpty() ) { videoData->Title = ExtractFileBase( datum.Url.ToCStr() ); } if ( videoData->Author.IsEmpty() ) { videoData->Author = DEFAULT_AUTHOR_NAME; } } }
void WriteFile (void) { FILE *modelouthandle; int total = 0; int i; pStart = kalloc( 1, FILEBUFFER ); StripExtension (outname); for (i = 1; i < numseqgroups; i++) { // write the non-default sequence group data to separate files char groupname[128], localname[128]; sprintf( groupname, "%s%02d.mdl", outname, i ); printf ("writing %s:\n", groupname); modelouthandle = SafeOpenWrite (groupname); pseqhdr = (studioseqhdr_t *)pStart; pseqhdr->id = IDSTUDIOSEQHEADER; pseqhdr->version = STUDIO_VERSION; pData = pStart + sizeof( studioseqhdr_t ); pData = WriteAnimations( pData, pStart, i ); ExtractFileBase( groupname, localname ); sprintf( sequencegroup[i].name, "models\\%s.mdl", localname ); strcpy( pseqhdr->name, sequencegroup[i].name ); pseqhdr->length = pData - pStart; printf("total %6d\n", pseqhdr->length ); SafeWrite( modelouthandle, pStart, pseqhdr->length ); fclose (modelouthandle); memset( pStart, 0, pseqhdr->length ); } if (split_textures) { // write textures out to a separate file char texname[128]; sprintf( texname, "%sT.mdl", outname ); printf ("writing %s:\n", texname); modelouthandle = SafeOpenWrite (texname); phdr = (studiohdr_t *)pStart; phdr->id = IDSTUDIOHEADER; phdr->version = STUDIO_VERSION; pData = (byte *)phdr + sizeof( studiohdr_t ); WriteTextures( ); phdr->length = pData - pStart; printf("textures %6d bytes\n", phdr->length ); SafeWrite( modelouthandle, pStart, phdr->length ); fclose (modelouthandle); memset( pStart, 0, phdr->length ); pData = pStart; } // // write the model output file // strcat (outname, ".mdl"); printf ("---------------------\n"); printf ("writing %s:\n", outname); modelouthandle = SafeOpenWrite (outname); phdr = (studiohdr_t *)pStart; phdr->id = IDSTUDIOHEADER; phdr->version = STUDIO_VERSION; strcpy( phdr->name, outname ); VectorCopy( eyeposition, phdr->eyeposition ); VectorCopy( bbox[0], phdr->min ); VectorCopy( bbox[1], phdr->max ); VectorCopy( cbox[0], phdr->bbmin ); VectorCopy( cbox[1], phdr->bbmax ); phdr->flags = gflags; pData = (byte *)phdr + sizeof( studiohdr_t ); WriteBoneInfo( ); printf("bones %6d bytes (%d)\n", pData - pStart - total, numbones ); total = pData - pStart; pData = WriteAnimations( pData, pStart, 0 ); WriteSequenceInfo( ); printf("sequences %6d bytes (%d frames) [%d:%02d]\n", pData - pStart - total, totalframes, (int)totalseconds / 60, (int)totalseconds % 60 ); total = pData - pStart; WriteModel( ); printf("models %6d bytes\n", pData - pStart - total ); total = pData - pStart; if (!split_textures) { WriteTextures( ); printf("textures %6d bytes\n", pData - pStart - total ); } phdr->length = pData - pStart; printf("total %6d\n", phdr->length ); SafeWrite( modelouthandle, pStart, phdr->length ); fclose (modelouthandle); }
// // W_AddFile // All files are optional, but at least one file must be // found (PWAD, if all required lumps are present). // Files with a .wad extension are wadlink files // with multiple lumps. // Other files are single lumps with the base filename // for the lump name. wad_file_t *W_AddFile(char *filename, dboolean automatic) { wadinfo_t header; lumpindex_t i; int startlump; filelump_t *fileinfo; filelump_t *filerover; lumpinfo_t *filelumps; int numfilelumps; // open the file and add to directory wad_file_t *wad_file = W_OpenFile(filename); if (!wad_file) return NULL; M_StringCopy(wad_file->path, filename, sizeof(wad_file->path)); wad_file->freedoom = IsFreedoom(filename); if (!M_StringCompare(filename + strlen(filename) - 3, "wad")) { // single lump file // fraggle: Swap the filepos and size here. The WAD directory // parsing code expects a little-endian directory, so will swap // them back. Effectively we're constructing a "fake WAD directory" // here, as it would appear on disk. fileinfo = Z_Malloc(sizeof(filelump_t), PU_STATIC, NULL); fileinfo->filepos = LONG(0); fileinfo->size = LONG(wad_file->length); // Name the lump after the base of the filename (without the // extension). ExtractFileBase(filename, fileinfo->name); numfilelumps = 1; } else { int length; // WAD file W_Read(wad_file, 0, &header, sizeof(header)); // Homebrew levels? if (strncmp(header.identification, "IWAD", 4) && strncmp(header.identification, "PWAD", 4)) I_Error("Wad file %s doesn't have IWAD or PWAD id\n", filename); wad_file->type = (!strncmp(header.identification, "IWAD", 4) ? IWAD : PWAD); header.numlumps = LONG(header.numlumps); header.infotableofs = LONG(header.infotableofs); length = header.numlumps * sizeof(filelump_t); fileinfo = Z_Malloc(length, PU_STATIC, NULL); W_Read(wad_file, header.infotableofs, fileinfo, length); numfilelumps = header.numlumps; } // Increase size of numlumps array to accommodate the new file. filelumps = calloc(numfilelumps, sizeof(lumpinfo_t)); if (!filelumps) I_Error("Failed to allocate array for lumps from new file."); startlump = numlumps; numlumps += numfilelumps; lumpinfo = Z_Realloc(lumpinfo, numlumps * sizeof(lumpinfo_t *)); if (!lumpinfo) I_Error("Failed to increase lumpinfo[] array size."); filerover = fileinfo; for (i = startlump; i < numlumps; ++i) { lumpinfo_t *lump_p = &filelumps[i - startlump]; lump_p->wad_file = wad_file; lump_p->position = LONG(filerover->filepos); lump_p->size = LONG(filerover->size); lump_p->cache = NULL; strncpy(lump_p->name, filerover->name, 8); lumpinfo[i] = lump_p; ++filerover; } Z_Free(fileinfo); if (lumphash) { Z_Free(lumphash); lumphash = NULL; } C_Output("%s %s lump%s from %.4s file %s.", (automatic ? "Automatically added" : "Added"), commify(numlumps - startlump), (numlumps - startlump == 1 ? "" : "s"), header.identification, uppercase(filename)); return wad_file; }
static void DoParse(const char *filename) { if (TokenMap.CountUsed() == 0) { InitTokenMap(); } FScanner sc; void *parser; int tokentype; int lump; bool failed; ZCCToken value; lump = Wads.CheckNumForFullName(filename, true); if (lump >= 0) { sc.OpenLumpNum(lump); } else if (FileExists(filename)) { sc.OpenFile(filename); } else { Printf("Could not find script lump '%s'\n", filename); return; } parser = ZCCParseAlloc(malloc); failed = false; #ifdef _DEBUG FILE *f = fopen("trace.txt", "w"); char prompt = '\0'; ZCCParseTrace(f, &prompt); #endif ZCCParseState state(sc); while (sc.GetToken()) { value.SourceLoc = sc.GetMessageLine(); switch (sc.TokenType) { case TK_StringConst: value.String = state.Strings.Alloc(sc.String, sc.StringLen); tokentype = ZCC_STRCONST; break; case TK_NameConst: value.Int = sc.Name; tokentype = ZCC_NAMECONST; break; case TK_IntConst: value.Int = sc.Number; tokentype = ZCC_INTCONST; break; case TK_UIntConst: value.Int = sc.Number; tokentype = ZCC_UINTCONST; break; case TK_FloatConst: value.Float = sc.Float; tokentype = ZCC_FLOATCONST; break; case TK_Identifier: value.Int = FName(sc.String); tokentype = ZCC_IDENTIFIER; break; case TK_NonWhitespace: value.Int = FName(sc.String); tokentype = ZCC_NWS; break; default: TokenMapEntry *zcctoken = TokenMap.CheckKey(sc.TokenType); if (zcctoken != NULL) { tokentype = zcctoken->TokenType; value.Int = zcctoken->TokenName; } else { sc.ScriptMessage("Unexpected token %s.\n", sc.TokenName(sc.TokenType).GetChars()); goto parse_end; } break; } ZCCParse(parser, tokentype, value, &state); if (failed) { sc.ScriptMessage("Parse failed\n"); goto parse_end; } } parse_end: value.Int = -1; ZCCParse(parser, ZCC_EOF, value, &state); ZCCParse(parser, 0, value, &state); ZCCParseFree(parser, free); PSymbolTable symbols(&GlobalSymbols); ZCCCompiler cc(state, NULL, symbols); cc.Compile(); #ifdef _DEBUG if (f != NULL) { fclose(f); } FString ast = ZCC_PrintAST(state.TopNode); FString astfile = ExtractFileBase(filename, false); astfile << ".ast"; f = fopen(astfile, "w"); if (f != NULL) { fputs(ast.GetChars(), f); fclose(f); } #endif }
void W_AddFile ( const char *filename) { wadinfo_t header; lumpinfo_t* lump_p; int i; idFile * handle; int length; int startlump; std::vector<filelump_t> fileinfo( 1 ); // open the file and add to directory if ( (handle = fileSystem->OpenFileRead(filename)) == 0) { I_Printf (" couldn't open %s\n",filename); return; } I_Printf (" adding %s\n",filename); startlump = numlumps; if ( idStr::Icmp( filename+strlen(filename)-3 , "wad" ) ) { // single lump file fileinfo[0].filepos = 0; fileinfo[0].size = 0; ExtractFileBase (filename, fileinfo[0].name); numlumps++; } else { // WAD file handle->Read( &header, sizeof( header ) ); if ( idStr::Cmpn( header.identification,"IWAD",4 ) ) { // Homebrew levels? if ( idStr::Cmpn( header.identification, "PWAD", 4 ) ) { I_Error ("Wad file %s doesn't have IWAD " "or PWAD id\n", filename); } // ???modifiedgame = true; } header.numlumps = LONG(header.numlumps); header.infotableofs = LONG(header.infotableofs); length = header.numlumps*sizeof(filelump_t); fileinfo.resize(header.numlumps); handle->Seek( header.infotableofs, FS_SEEK_SET ); handle->Read( &fileinfo[0], length ); numlumps += header.numlumps; } // Fill in lumpinfo if (lumpinfo == NULL) { lumpinfo = (lumpinfo_t*)malloc( numlumps*sizeof(lumpinfo_t) ); } else { lumpinfo = (lumpinfo_t*)realloc( lumpinfo, numlumps*sizeof(lumpinfo_t) ); } if (!lumpinfo) I_Error ("Couldn't realloc lumpinfo"); lump_p = &lumpinfo[startlump]; ::g->wadFileHandles[ ::g->numWadFiles++ ] = handle; filelump_t * filelumpPointer = &fileinfo[0]; for (i=startlump ; i<numlumps ; i++,lump_p++, filelumpPointer++) { lump_p->handle = handle; lump_p->position = LONG(filelumpPointer->filepos); lump_p->size = LONG(filelumpPointer->size); strncpy (lump_p->name, filelumpPointer->name, 8); } }
void STAT_ChangeLevel(const char *newl) { // record the current level's stats. StoreLevelStats(); level_info_t *thisinfo = level.info; level_info_t *nextinfo = NULL; if (strncmp(newl, "enDSeQ", 6)) { level_info_t *l = FindLevelInfo (newl); nextinfo = l->CheckLevelRedirect (); if (nextinfo == NULL) nextinfo = l; } if (savestatistics == 1) { if ((nextinfo == NULL || (nextinfo->flags2 & LEVEL2_ENDGAME)) && StartEpisode != NULL) { // we reached the end of this episode int wad = 0; MapData * map = P_OpenMapData(StartEpisode->mEpisodeMap, false); if (map != NULL) { wad = Wads.GetLumpFile(map->lumpnum); delete map; } const char * name = Wads.GetWadName(wad); FString section = ExtractFileBase(name) + "." + StartEpisode->mEpisodeMap; section.ToUpper(); const char *ep_name = StartEpisode->mEpisodeName; if (*ep_name == '$') ep_name = GStrings[ep_name+1]; FStatistics *sl = GetStatisticsList(EpisodeStatistics, section, ep_name); int statvals[4] = {0,0,0,0}; FString infostring; int validlevels = LevelData.Size(); for(unsigned i = 0; i < LevelData.Size(); i++) { statvals[0] += LevelData[i].killcount; statvals[1] += LevelData[i].totalkills; statvals[2] += LevelData[i].secretcount; statvals[3] += LevelData[i].totalsecrets; } infostring.Format("%4d/%4d, %3d/%3d, %2d", statvals[0], statvals[1], statvals[2], statvals[3], validlevels); FSessionStatistics *es = StatisticsEntry(sl, infostring, AdjustTics(level.totaltime)); for(unsigned i = 0; i < LevelData.Size(); i++) { FString lsection = LevelData[i].Levelname; lsection.ToUpper(); infostring.Format("%4d/%4d, %3d/%3d", LevelData[i].killcount, LevelData[i].totalkills, LevelData[i].secretcount, LevelData[i].totalsecrets); LevelStatEntry(es, lsection, infostring, LevelData[i].leveltime); } SaveStatistics(statfile, EpisodeStatistics); } } else if (savestatistics == 2) // todo: handle single level statistics. { } }
// // W_AddFile // All files are optional, but at least one file must be // found (PWAD, if all required lumps are present). // Files with a .wad extension are wadlink files // with multiple lumps. // Other files are single lumps with the base filename // for the lump name. // // Reload hack removed by Lee Killough // CPhipps - source is an enum // // proff - changed using pointer to wadfile_info_t static void W_AddFile(wadfile_info_t *wadfile) // killough 1/31/98: static, const { wadinfo_t header; lumpinfo_t* lump_p; unsigned i; int length; int startlump; filelump_t *fileinfo, *fileinfo2free=NULL; //killough filelump_t singleinfo; int flags = 0; // open the file and add to directory wadfile->handle = open(wadfile->name,O_RDONLY | O_BINARY); #ifdef HAVE_NET if (wadfile->handle == -1 && D_NetGetWad(wadfile->name)) // CPhipps wadfile->handle = open(wadfile->name,O_RDONLY | O_BINARY); #endif if (wadfile->handle == -1 && strlen(wadfile->name) > 4 && wadfile->src == source_pwad && !strcasecmp(wadfile->name + strlen(wadfile->name) - 4 , ".wad") && D_TryGetWad(wadfile->name)) { wadfile->handle = open(wadfile->name, O_RDONLY | O_BINARY); } if (wadfile->handle == -1) { if ( strlen(wadfile->name)<=4 || // add error check -- killough (strcasecmp(wadfile->name+strlen(wadfile->name)-4 , ".lmp" ) && strcasecmp(wadfile->name+strlen(wadfile->name)-4 , ".gwa" ) ) ) I_Error("W_AddFile: couldn't open %s",wadfile->name); return; } //jff 8/3/98 use logical output routine lprintf (LO_INFO," adding %s\n",wadfile->name); startlump = numlumps; // mark lumps from internal resource if (wadfile->src == source_auto_load) { int len = strlen(PACKAGE_TARNAME ".wad"); int len_file = strlen(wadfile->name); if (len_file >= len) { if (!strcasecmp(wadfile->name + len_file - len, PACKAGE_TARNAME ".wad")) { flags = LUMP_PRBOOM; } } } if ( strlen(wadfile->name)<=4 || ( strcasecmp(wadfile->name+strlen(wadfile->name)-4,".wad") && strcasecmp(wadfile->name+strlen(wadfile->name)-4,".gwa") ) ) { // single lump file fileinfo = &singleinfo; singleinfo.filepos = 0; singleinfo.size = LittleLong(I_Filelength(wadfile->handle)); ExtractFileBase(wadfile->name, singleinfo.name); numlumps++; } else { // WAD file I_Read(wadfile->handle, &header, sizeof(header)); if (strncmp(header.identification,"IWAD",4) && strncmp(header.identification,"PWAD",4)) I_Error("W_AddFile: Wad file %s doesn't have IWAD or PWAD id", wadfile->name); header.numlumps = LittleLong(header.numlumps); header.infotableofs = LittleLong(header.infotableofs); length = header.numlumps*sizeof(filelump_t); fileinfo2free = fileinfo = malloc(length); // killough lseek(wadfile->handle, header.infotableofs, SEEK_SET), I_Read(wadfile->handle, fileinfo, length); numlumps += header.numlumps; } // Fill in lumpinfo lumpinfo = realloc(lumpinfo, numlumps*sizeof(lumpinfo_t)); lump_p = &lumpinfo[startlump]; for (i=startlump ; (int)i<numlumps ; i++,lump_p++, fileinfo++) { lump_p->flags = flags; lump_p->wadfile = wadfile; // killough 4/25/98 lump_p->position = LittleLong(fileinfo->filepos); lump_p->size = LittleLong(fileinfo->size); if (wadfile->src == source_lmp) { // Modifications to place command-line-added demo lumps // into a separate "ns_demos" namespace so that they cannot // conflict with other lump names lump_p->li_namespace = ns_demos; } else { lump_p->li_namespace = ns_global; // killough 4/17/98 } strncpy (lump_p->name, fileinfo->name, 8); lump_p->source = wadfile->src; // Ty 08/29/98 // IWAD file used as recource PWAD must not override TEXTURE1 or PNAMES if (wadfile->src != source_iwad && !strncmp(header.identification,"IWAD",4) && (!strnicmp(fileinfo->name,"TEXTURE1",8) || !strnicmp(fileinfo->name,"PNAMES",6))) { strncpy (lump_p->name, "-IGNORE-", 8); } } free(fileinfo2free); // killough }
void W_AddFile(char *filename) { wadinfo_t header; lumpinfo_t *lump_p; unsigned i; int handle; int length; int startlump; filelump_t *fileinfo; filelump_t singleinfo; int storehandle; // open the file and add to directory // handle reload indicator. if (filename[0] == '~') { filename++; reloadname = filename; reloadlump = numlumps; } if ((handle = open(filename, O_RDONLY | O_BINARY)) == -1) { // AYM 1998-08-29 if (errno == ENOENT && *filename != '/') { const char *const path = "/usr/local/share/doom/"; char *newname; newname = malloc(strlen(path) + strlen(filename) + 1); if (newname == NULL) I_Error("W_AddFile(): not enough memory to build path\n"); sprintf(newname, "%s%s", path, filename); handle = open(newname, O_RDONLY | O_BINARY); free(newname); if (handle == -1 && errno == ENOENT) { const char *const path = "/usr/share/doom/"; char *newname; newname = malloc(strlen(path) + strlen(filename) + 1); if (newname == NULL) I_Error("W_AddFile(): not enough memory to build path\n"); sprintf(newname, "%s%s", path, filename); handle = open(newname, O_RDONLY | O_BINARY); free(newname); } } if (handle == -1) { printf (" couldn't open %s\n", filename); return; } // AYM 1998-08-29 } printf (" adding %s\n",filename); startlump = numlumps; if (strcasecmp(filename + strlen(filename) - 3, "wad")) { // single lump file fileinfo = &singleinfo; singleinfo.filepos = 0; singleinfo.size = LONG(filelength(handle)); ExtractFileBase(filename, singleinfo.name); numlumps++; } else { // WAD file read(handle, &header, sizeof(header)); if (strncmp(header.identification, "IWAD", 4)) { // Homebrew levels? if (strncmp(header.identification, "PWAD", 4)) { I_Error("Wad file %s doesn't have IWAD " "or PWAD id\n", filename); } } header.numlumps = LONG(header.numlumps); header.infotableofs = LONG(header.infotableofs); length = header.numlumps * sizeof(filelump_t); fileinfo = (filelump_t *)alloca(length); lseek(handle, header.infotableofs, SEEK_SET); read(handle, fileinfo, length); numlumps += header.numlumps; } // Fill in lumpinfo lumpinfo = realloc(lumpinfo, numlumps * sizeof(lumpinfo_t)); if (!lumpinfo) I_Error("Couldn't realloc lumpinfo"); lump_p = &lumpinfo[startlump]; storehandle = reloadname ? -1 : handle; for (i = startlump; i < numlumps; i++, lump_p++, fileinfo++) { lump_p->handle = storehandle; lump_p->position = LONG(fileinfo->filepos); lump_p->size = LONG(fileinfo->size); strncpy(lump_p->name, fileinfo->name, 8); } if (reloadname) close(handle); }
int main (int argc, char **argv) { int i, comp = 0; char outputpath[MAX_PATH] = ""; char filename[MAX_PATH] = "unknown"; quakefile_t *qfiles = NULL, *qf; double start_time; myargc = argc; myargv = argv; start_time = I_FloatTime(); Log_Open("bspc.log"); //open a log file Log_Print(BSPC_NAME" version "BSPC_VERSION", %s %s\n", __DATE__, __TIME__); #ifdef ZTMAUTOARGS calcgrapplereach = true; forcesidesvisible = true; // Currently always required or BSPC fails? #endif DefaultCfg(); for (i = 1; i < argc; i++) { if (!stricmp(argv[i],"-threads")) { if (i + 1 >= argc) {i = 0; break;} numthreads = atoi(argv[++i]); Log_Print("threads = %d\n", numthreads); } //end if else if (!stricmp(argv[i], "-noverbose")) { Log_Print("verbose = false\n"); verbose = false; } //end else if else if (!stricmp(argv[i], "-nocsg")) { Log_Print("nocsg = true\n"); nocsg = true; } //end else if else if (!stricmp(argv[i], "-optimize")) { Log_Print("optimize = true\n"); optimize = true; } //end else if /* else if (!stricmp(argv[i], "-noweld")) { Log_Print("noweld = true\n"); noweld = true; } //end else if else if (!stricmp(argv[i], "-noshare")) { Log_Print("noshare = true\n"); noshare = true; } //end else if else if (!stricmp(argv[i], "-notjunc")) { Log_Print("notjunc = true\n"); notjunc = true; } //end else if else if (!stricmp(argv[i], "-nowater")) { Log_Print("nowater = true\n"); nowater = true; } //end else if else if (!stricmp(argv[i], "-noprune")) { Log_Print("noprune = true\n"); noprune = true; } //end else if else if (!stricmp(argv[i], "-nomerge")) { Log_Print("nomerge = true\n"); nomerge = true; } //end else if else if (!stricmp(argv[i], "-nosubdiv")) { Log_Print("nosubdiv = true\n"); nosubdiv = true; } //end else if else if (!stricmp(argv[i], "-nodetail")) { Log_Print("nodetail = true\n"); nodetail = true; } //end else if else if (!stricmp(argv[i], "-fulldetail")) { Log_Print("fulldetail = true\n"); fulldetail = true; } //end else if else if (!stricmp(argv[i], "-onlyents")) { Log_Print("onlyents = true\n"); onlyents = true; } //end else if else if (!stricmp(argv[i], "-micro")) { if (i + 1 >= argc) {i = 0; break;} microvolume = atof(argv[++i]); Log_Print("microvolume = %f\n", microvolume); } //end else if else if (!stricmp(argv[i], "-leaktest")) { Log_Print("leaktest = true\n"); leaktest = true; } //end else if else if (!stricmp(argv[i], "-verboseentities")) { Log_Print("verboseentities = true\n"); verboseentities = true; } //end else if else if (!stricmp(argv[i], "-chop")) { if (i + 1 >= argc) {i = 0; break;} subdivide_size = atof(argv[++i]); Log_Print("subdivide_size = %f\n", subdivide_size); } //end else if else if (!stricmp (argv[i], "-tmpout")) { strcpy (outbase, "/tmp"); Log_Print("temp output\n"); } //end else if */ else if (!stricmp(argv[i], "-freetree")) { freetree = true; Log_Print("freetree = true\n"); } //end else if else if (!stricmp(argv[i], "-grapplereach")) { calcgrapplereach = true; Log_Print("grapplereach = true\n"); } //end else if #ifdef ZTMAUTOARGS else if (!stricmp(argv[i], "-nograpplereach")) { calcgrapplereach = false; Log_Print("grapplereach = false\n"); } //end else if #endif else if (!stricmp(argv[i], "-nobrushmerge")) { nobrushmerge = true; Log_Print("nobrushmerge = true\n"); } //end else if else if (!stricmp(argv[i], "-noliquids")) { noliquids = true; Log_Print("noliquids = true\n"); } //end else if else if (!stricmp(argv[i], "-forcesidesvisible")) { forcesidesvisible = true; Log_Print("forcesidesvisible = true\n"); } //end else if #ifdef ZTMAUTOARGS else if (!stricmp(argv[i], "-noforcesidesvisible")) { forcesidesvisible = false; Log_Print("forcesidesvisible = false\n"); } //end else if #endif else if (!stricmp(argv[i], "-output")) { if (i + 1 >= argc) {i = 0; break;} if (access(argv[i+1], 0x04)) Warning("the folder %s does not exist", argv[i+1]); strcpy(outputpath, argv[++i]); } //end else if else if (!stricmp(argv[i], "-breadthfirst")) { use_nodequeue = true; Log_Print("breadthfirst = true\n"); } //end else if else if (!stricmp(argv[i], "-capsule")) { capsule_collision = true; Log_Print("capsule_collision = true\n"); } //end else if else if (!stricmp(argv[i], "-cfg")) { if (i + 1 >= argc) {i = 0; break;} if (!LoadCfgFile(argv[++i])) exit(0); } //end else if else if (!stricmp(argv[i], "-bsp2map")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_BSP2MAP; qfiles = GetArgumentFiles(argc, argv, &i, "bsp"); } //end else if else if (!stricmp(argv[i], "-bsp2aas")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_BSP2AAS; qfiles = GetArgumentFiles(argc, argv, &i, "bsp"); } //end else if else if (!stricmp(argv[i], "-aasall")) { if (i + 1 >= argc) {i = 0; break;} CreateAASFilesForAllBSPFiles(argv[++i]); } //end else if else if (!stricmp(argv[i], "-reach")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_REACH; qfiles = GetArgumentFiles(argc, argv, &i, "bsp"); } //end else if else if (!stricmp(argv[i], "-cluster")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_CLUSTER; qfiles = GetArgumentFiles(argc, argv, &i, "bsp"); } //end else if else if (!stricmp(argv[i], "-aasinfo")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_AASINFO; qfiles = GetArgumentFiles(argc, argv, &i, "aas"); } //end else if else if (!stricmp(argv[i], "-aasopt")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_AASOPTIMIZE; qfiles = GetArgumentFiles(argc, argv, &i, "aas"); } //end else if else { Log_Print("unknown parameter %s\n", argv[i]); break; } //end else } //end for //if there are parameters and there's no mismatch in one of the parameters if (argc > 1 && i == argc) { switch(comp) { case COMP_BSP2MAP: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { //copy the output path strcpy(filename, outputpath); //append the bsp file base AppendPathSeperator(filename, MAX_PATH); ExtractFileBase(qf->origname, &filename[strlen(filename)]); //append .map strcat(filename, ".map"); // Log_Print("bsp2map: %s to %s\n", qf->origname, filename); if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname); // LoadMapFromBSP(qf); //write the map file WriteMapFile(filename); } //end for break; } //end case case COMP_BSP2AAS: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { AASOuputFile(qf, outputpath, filename); // Log_Print("bsp2aas: %s to %s\n", qf->origname, filename); if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname); //set before map loading create_aas = 1; LoadMapFromBSP(qf); //create the AAS file AAS_Create(filename); //calculate the reachabilities and clusters AAS_CalcReachAndClusters(qf); // if (optimize) AAS_Optimize(); // //write out the stored AAS file if (!AAS_WriteAASFile(filename)) { Error("error writing %s\n", filename); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_REACH: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { AASOuputFile(qf, outputpath, filename); // Log_Print("reach: %s to %s\n", qf->origname, filename); if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname); //if the AAS file exists in the output directory if (!access(filename, 0x04)) { if (!AAS_LoadAASFile(filename)) { Error("error loading aas file %s\n", filename); } //end if } //end if else { Warning("AAS file %s not found in output folder\n", filename); Log_Print("creating %s...\n", filename); //set before map loading create_aas = 1; LoadMapFromBSP(qf); //create the AAS file AAS_Create(filename); } //end else //calculate the reachabilities and clusters AAS_CalcReachAndClusters(qf); // if (optimize) AAS_Optimize(); //write out the stored AAS file if (!AAS_WriteAASFile(filename)) { Error("error writing %s\n", filename); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_CLUSTER: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { AASOuputFile(qf, outputpath, filename); // Log_Print("cluster: %s to %s\n", qf->origname, filename); if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname); //if the AAS file exists in the output directory if (!access(filename, 0x04)) { if (!AAS_LoadAASFile(filename)) { Error("error loading aas file %s\n", filename); } //end if //calculate the clusters AAS_RecalcClusters(); } //end if else { Warning("AAS file %s not found in output folder\n", filename); Log_Print("creating %s...\n", filename); //set before map loading create_aas = 1; LoadMapFromBSP(qf); //create the AAS file AAS_Create(filename); //calculate the reachabilities and clusters AAS_CalcReachAndClusters(qf); } //end else // if (optimize) AAS_Optimize(); //write out the stored AAS file if (!AAS_WriteAASFile(filename)) { Error("error writing %s\n", filename); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_AASOPTIMIZE: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { AASOuputFile(qf, outputpath, filename); // Log_Print("optimizing: %s to %s\n", qf->origname, filename); if (qf->type != QFILETYPE_AAS) Warning("%s is probably not a AAS file\n", qf->origname); // AAS_InitBotImport(); // if (!AAS_LoadAASFile(qf->filename)) { Error("error loading aas file %s\n", qf->filename); } //end if AAS_Optimize(); //write out the stored AAS file if (!AAS_WriteAASFile(filename)) { Error("error writing %s\n", filename); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_AASINFO: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { AASOuputFile(qf, outputpath, filename); // Log_Print("aas info for: %s\n", filename); if (qf->type != QFILETYPE_AAS) Warning("%s is probably not a AAS file\n", qf->origname); // AAS_InitBotImport(); // if (!AAS_LoadAASFile(qf->filename)) { Error("error loading aas file %s\n", qf->filename); } //end if AAS_ShowTotals(); } //end for break; } //end case default: { Log_Print("don't know what to do\n"); break; } //end default } //end switch } //end if else { Log_Print("Usage: bspc [-<switch> [-<switch> ...]]\n" #ifdef _WIN32 "Example 1: bspc -bsp2aas d:\\quake3\\baseq3\\maps\\mymap?.bsp\n" "Example 2: bspc -bsp2aas d:\\quake3\\baseq3\\pak0.pk3\\maps/q3dm*.bsp\n" #else "Example 1: bspc -bsp2aas /quake3/baseq3/maps/mymap?.bsp\n" "Example 2: bspc -bsp2aas /quake3/baseq3/pak0.pk3/maps/q3dm*.bsp\n" #endif "\n" "Switches:\n" //" bsp2map <[pakfilter/]filter.bsp> = convert BSP to MAP\n" //" aasall <quake3folder> = create AAS files for all BSPs\n" " bsp2aas <[pakfilter/]filter.bsp> = convert BSP to AAS\n" " reach <filter.bsp> = compute reachability & clusters\n" " cluster <filter.bsp> = compute clusters\n" " aasopt <filter.aas> = optimize aas file\n" " aasinfo <filter.aas> = show AAS file info\n" " output <output path> = set output path\n" " threads <X> = set number of threads to X\n" " cfg <filename> = use this cfg file\n" " optimize = enable optimization\n" " noverbose = disable verbose output\n" " breadthfirst = breadth first bsp building\n" " nobrushmerge = don't merge brushes\n" " noliquids = don't write liquids to map\n" " freetree = free the bsp tree\n" " nocsg = disables brush chopping\n" #ifdef ZTMAUTOARGS " noforcesidesvisible = don't force all sides to be visible\n" " nograpplereach = don't calculate grapple reachabilities\n" #else " forcesidesvisible = force all sides to be visible\n" " grapplereach = calculate grapple reachabilities\n" #endif /* " noweld = disables weld\n" " noshare = disables sharing\n" " notjunc = disables juncs\n" " nowater = disables water brushes\n" " noprune = disables node prunes\n" " nomerge = disables face merging\n" " nosubdiv = disables subdeviding\n" " nodetail = disables detail brushes\n" " fulldetail = enables full detail\n" " onlyents = only compile entities with bsp\n" " micro <volume>\n" " = sets the micro volume to the given float\n" " leaktest = perform a leak test\n" " verboseentities\n" " = enable entity verbose mode\n" " chop <subdivide_size>\n" " = sets the subdivide size to the given float\n"*/ "\n"); } //end else Log_Print("BSPC run time is %5.0f seconds\n", I_FloatTime() - start_time); Log_Close(); //close the log file return 0; } //end of the function main
/* Loads and parses material. Returns false on complete failure. */ Material_t *Material_Load(const char *ccPath) { Material_t *mNewMaterial; void *cData; char cPath[PLATFORM_MAX_PATH], cMaterialName[64] = { 0 }; // Ensure that the given material names are correct! if (ccPath[0] == ' ') Sys_Error("Invalid material path! (%s)\n", ccPath); if (!material_initialized) { Con_Warning("Attempted to load material, before initialization! (%s)\n", ccPath); return NULL; } // Update the given path with the base path plus extension. sprintf(cPath, "%s%s.material", g_state.cMaterialPath, ccPath); // Check if it's been cached already... mNewMaterial = Material_GetByPath(cPath); if(mNewMaterial) return mNewMaterial; cData = COM_LoadHeapFile(cPath); if(!cData) { Con_Warning("Failed to load material! (%s) (%s)\n", cPath, ccPath); return NULL; } Script_StartTokenParsing((char*)cData); if(!Script_GetToken(true)) { Con_Warning("Failed to get initial token! (%s) (%i)\n",ccPath,iScriptLine); return NULL; } else if (cToken[0] != '{') { if (!strcmp(cToken, "material_version")) { Script_GetToken(false); } else // Probably a name... { // Copy over the given name. strncpy(cMaterialName, cToken, sizeof(cMaterialName)); if (cMaterialName[0] == ' ') Sys_Error("Invalid material name!\n"); // Check if it's been cached already... mNewMaterial = Material_GetByName(cMaterialName); if (mNewMaterial) { Con_Warning("Attempted to load duplicate material! (%s) (%s) vs (%s) (%s)\n", ccPath, cMaterialName, mNewMaterial->cPath, mNewMaterial->cName); free(cData); return mNewMaterial; } } Script_GetToken(true); if (cToken[0] != '{') { Con_Warning("Missing '{'! (%s) (%i)\n", ccPath, iScriptLine); goto MATERIAL_LOAD_ERROR; } } // Assume that the material hasn't been cached yet, so allocate a new copy of one. mNewMaterial = Material_Allocate(); if (!mNewMaterial) { Con_Warning("Failed to allocate material! (%s)\n",ccPath); goto MATERIAL_LOAD_ERROR; } if (cMaterialName[0]) strncpy(mNewMaterial->cName, cMaterialName, sizeof(mNewMaterial->cName)); else { char cIn[PLATFORM_MAX_PATH]; strncpy(cIn, ccPath, sizeof(cIn)); // Otherwise just use the filename. ExtractFileBase(cIn, mNewMaterial->cName); } strncpy(mNewMaterial->cPath, ccPath, sizeof(mNewMaterial->cPath)); for (;;) { if(!Script_GetToken(true)) { Con_Warning("End of field without closing brace! (%s) (%i)\n",ccPath,iScriptLine); goto MATERIAL_LOAD_ERROR; } material_currentcontext = MATERIAL_FUNCTION_MATERIAL; // End if (cToken[0] == '}') { // TODO: Load material data at the END! return mNewMaterial; } // Start else if (cToken[0] == SCRIPT_SYMBOL_FUNCTION) Material_CheckFunctions(mNewMaterial); } MATERIAL_LOAD_ERROR: free(cData); return NULL; }
void FFont::ReadSheetFont(TArray<FolderEntry> &folderdata, int width, int height, const DVector2 &Scale) { // all valid lumps must be named with a hex number that represents the Unicode character index for its first character, TArray<TexPart> part(1, true); TMap<int, FTexture*> charMap; int minchar = INT_MAX; int maxchar = INT_MIN; for (auto &entry : folderdata) { char *endp; auto base = ExtractFileBase(entry.name); auto position = strtoll(base.GetChars(), &endp, 16); if ((*endp == 0 || (*endp == '.' && position >= 0 && position < 0xffff))) // Sheet fonts may fill in the low control chars. { auto lump = TexMan.CheckForTexture(entry.name, ETextureType::MiscPatch); if (lump.isValid()) { auto tex = TexMan.GetTexture(lump); int numtex_x = tex->GetWidth() / width; int numtex_y = tex->GetHeight() / height; int maxinsheet = int(position) + numtex_x * numtex_y - 1; if (minchar > position) minchar = int(position); if (maxchar < maxinsheet) maxchar = maxinsheet; for (int y = 0; y < numtex_y; y++) { for (int x = 0; x < numtex_x; x++) { part[0].OriginX = -width * x; part[0].OriginY = -height * y; part[0].Image = tex->GetImage(); FMultiPatchTexture *image = new FMultiPatchTexture(width, height, part, false, false); FImageTexture *tex = new FImageTexture(image, ""); tex->SetUseType(ETextureType::FontChar); tex->bMultiPatch = true; tex->Width = width; tex->Height = height; tex->_LeftOffset[0] = tex->_LeftOffset[1] = tex->_TopOffset[0] = tex->_TopOffset[1] = 0; tex->Scale = Scale; tex->bMasked = true; tex->bTranslucent = -1; tex->bWorldPanning = true; tex->bNoDecals = false; tex->SourceLump = -1; // We do not really care. TexMan.AddTexture(tex); charMap.Insert(int(position) + x + y * numtex_x, tex); } } } } } FirstChar = minchar; bool map1252 = false; if (minchar < 0x80 && maxchar >= 0xa0) // should be a settable option, but that'd probably cause more problems than it'd solve. { if (maxchar < 0x2122) maxchar = 0x2122; map1252 = true; } LastChar = maxchar; auto count = maxchar - minchar + 1; Chars.Resize(count); int fontheight = 0; for (int i = 0; i < count; i++) { auto lump = charMap.CheckKey(FirstChar + i); if (lump != nullptr) { FTexture *pic = *lump; auto b = pic->Get8BitPixels(false); Chars[i].OriginalPic = pic; Chars[i].TranslatedPic = new FImageTexture(new FFontChar1(pic->GetImage()), ""); Chars[i].TranslatedPic->CopySize(pic); Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar); TexMan.AddTexture(Chars[i].TranslatedPic); } Chars[i].XMove = width; } if (map1252) { // Move the Windows-1252 characters to their proper place. for (int i = 0x80; i < 0xa0; i++) { if (win1252map[i - 0x80] != i && Chars[i - minchar].TranslatedPic != nullptr && Chars[win1252map[i - 0x80] - minchar].TranslatedPic == nullptr) { std::swap(Chars[i - minchar], Chars[win1252map[i - 0x80] - minchar]); } } } SpaceWidth = width; }
/*! This looks at each eclass_t, if it has a "modelpath" set then it leaves it alone if it's not set it checks to see if a file called "sprites/<eclassname>.*" exists, and if it does exist then it sets the "modelpath" to "sprites/<eclassname>.spr" */ void Eclass_CreateSpriteModelPaths(){ int Counts[4] = { 0, 0, 0, 0 }; char filename[512]; // should be big enough, ExtractFileBase doesn't take a buffer size... eclass_t *e; // get a list of all sprite/*>* files in all sprite/ directories Sys_Printf( "Searching VFS for files in sprites/*.* that match entity names...\n" ); GSList *pFiles = vfsGetFileList( "sprites", NULL ); GSList *pFile; if ( pFiles ) { // find an eclass without a modelpath. for ( e = eclass ; e ; e = e->next ) { Counts[0]++; if ( e->modelpath ) { #ifdef _DEBUG Sys_Printf( "Ignoring sprite for entity %s (modelpath: \"%s\")\n",e->name,e->modelpath ); #endif Counts[1]++; continue; // ignore this eclass, it's already got a model } // TODO: remove this check when we can have sprites for non-fixed size entities. if ( !e->fixedsize ) { #ifdef _DEBUG Sys_Printf( "Ignoring sprite for non-fixed-size entity %s\n",e->name ); #endif Counts[2]++; continue; // can't have sprites for non-fixed size entities (yet!) } Sys_Printf( "Searching for sprite for fixed-size entity %s...",e->name ); pFile = pFiles; // point to start of list // look for a file that has the same name, with any extension. bool Found = FALSE; while ( pFile ) { // strip the path/ and the .extension. ExtractFileBase( (char *)pFile->data,filename ); // does the eclass name match the filename? if ( stricmp( e->name,filename ) == 0 ) { // yes, so generate a sprite filename using the all-encompasing .spr extension // so that the model wrapper knows the sprite model plugin will be the model // plugin used to render it. CString strSpriteName; strSpriteName.Format( "sprites/%s.spr",e->name ); e->modelpath = strdup( strSpriteName.GetBuffer() ); Sys_Printf( "Found! (\"%s\")\n",(char *)pFile->data ); Counts[3]++; Found = TRUE; } pFile = pFile->next; } if ( !Found ) { Sys_Printf( "not found\n" ); } } vfsClearFileDirList( &pFiles ); } Sys_Printf( "%d entities were scanned\n" "%d entities that already had models/sprites were ignored\n" "%d non-fixed-size entities were ignored\n" "%d entities did not have matching sprite files\n" "%d entities had sprite files and have been attached\n", Counts[0],Counts[1],Counts[2],Counts[0] - Counts[3],Counts[3] ); }
OvrVideosMetaDatum::OvrVideosMetaDatum( const String& url ) : Author( DEFAULT_AUTHOR_NAME ) { Title = ExtractFileBase( url ); }
int FIWadManager::IdentifyVersion (TArray<FString> &wadfiles, const char *iwad, const char *zdoom_wad) { TArray<WadStuff> wads; TArray<size_t> foundwads; const char *iwadparm = Args->CheckValue ("-iwad"); size_t numwads; int pickwad; size_t i; bool iwadparmfound = false; FString custwad; ParseIWadInfos(zdoom_wad); wads.Resize(mIWadNames.Size()); foundwads.Resize(mIWads.Size()); memset(&foundwads[0], 0, foundwads.Size() * sizeof(foundwads[0])); if (iwadparm == NULL && iwad != NULL && *iwad != 0) { iwadparm = iwad; } if (iwadparm) { custwad = iwadparm; FixPathSeperator (custwad); if (CheckIWAD (custwad, &wads[0])) { // -iwad parameter was a directory iwadparm = NULL; } else { DefaultExtension (custwad, ".wad"); iwadparm = custwad; mIWadNames[0] = custwad; CheckIWAD ("", &wads[0]); } } if (iwadparm == NULL || wads[0].Path.IsEmpty() || mIWads[wads[0].Type].Required.IsNotEmpty()) { if (GameConfig->SetSection ("IWADSearch.Directories")) { const char *key; const char *value; while (GameConfig->NextInSection (key, value)) { if (stricmp (key, "Path") == 0) { FString nice = NicePath(value); FixPathSeperator(nice); CheckIWAD(nice, &wads[0]); } } } #ifdef _WIN32 FString steam_path = I_GetSteamPath(); if (steam_path.IsNotEmpty()) { static const char *const steam_dirs[] = { "doom 2/base", "final doom/base", "heretic shadow of the serpent riders/base", "hexen/base", "hexen deathkings of the dark citadel/base", "ultimate doom/base", "DOOM 3 BFG Edition/base/wads" }; steam_path += "/SteamApps/common/"; for (i = 0; i < countof(steam_dirs); ++i) { CheckIWAD (steam_path + steam_dirs[i], &wads[0]); } } #endif } if (iwadparm != NULL && !wads[0].Path.IsEmpty()) { iwadparmfound = true; } for (i = numwads = 0; i < mIWadNames.Size(); i++) { if (!wads[i].Path.IsEmpty()) { if (i != numwads) { wads[numwads] = wads[i]; } foundwads[wads[numwads].Type] = numwads + 1; numwads++; } } for (unsigned i=0; i<mIWads.Size(); i++) { if (mIWads[i].Required.IsNotEmpty() && foundwads[i]) { bool found = false; // needs to be loaded with another IWAD (HexenDK) for (unsigned j=0; j<mIWads.Size(); j++) { if (!mIWads[i].Required.Compare(mIWads[j].Name)) { if (foundwads[j]) { found = true; mIWads[i].preload = j; } break; } } // The required WAD is not there so this one can't be used and must be deleted from the list if (!found) { size_t kill = foundwads[i]; for (size_t j = kill; j < numwads; ++j) { wads[j - 1] = wads[j]; } numwads--; foundwads[i] = 0; for (unsigned j = 0; j < foundwads.Size(); ++j) { if (foundwads[j] > kill) { foundwads[j]--; } } } } } if (numwads == 0) { I_FatalError ("Cannot find a game IWAD (doom.wad, doom2.wad, heretic.wad, etc.).\n" "Did you install ZDoom properly? You can do either of the following:\n" "\n" "1. Place one or more of these wads in the same directory as ZDoom.\n" "2. Edit your zdoom-username.ini and add the directories of your iwads\n" "to the list beneath [IWADSearch.Directories]"); } pickwad = 0; if ((!iwadparmfound && numwads > 1) || I_ForcePickIWAD()) { int defiwad = 0; // Locate the user's prefered IWAD, if it was found. if (defaultiwad[0] != '\0') { for (i = 0; i < numwads; ++i) { FString basename = ExtractFileBase (wads[i].Path); if (stricmp (basename, defaultiwad) == 0) { defiwad = (int)i; break; } } } pickwad = I_PickIWad (&wads[0], (int)numwads, queryiwad, defiwad); if (pickwad >= 0) { // The newly selected IWAD becomes the new default FString basename = ExtractFileBase (wads[pickwad].Path); defaultiwad = basename; } } if (pickwad < 0) exit (0); // zdoom.pk3 must always be the first file loaded and the IWAD second. wadfiles.Clear(); D_AddFile (wadfiles, zdoom_wad); if (mIWads[wads[pickwad].Type].preload >= 0) { D_AddFile (wadfiles, wads[foundwads[mIWads[wads[pickwad].Type].preload]-1].Path); } D_AddFile (wadfiles, wads[pickwad].Path); for (unsigned i=0; i < mIWads[wads[pickwad].Type].Load.Size(); i++) { long lastslash = wads[pickwad].Path.LastIndexOf ('/'); FString path; if (lastslash == -1) { path = "";// wads[pickwad].Path; } else { path = FString (wads[pickwad].Path.GetChars(), lastslash + 1); } path += mIWads[wads[pickwad].Type].Load[i]; D_AddFile (wadfiles, path); } return wads[pickwad].Type; }
FFont::FFont (const char *name, const char *nametemplate, const char *filetemplate, int lfirst, int lcount, int start, int fdlump, int spacewidth, bool notranslate, bool iwadonly) { int i; FTextureID lump; char buffer[12]; int maxyoffs; bool doomtemplate = (nametemplate && (gameinfo.gametype & GAME_DoomChex)) ? strncmp (nametemplate, "STCFN", 5) == 0 : false; DVector2 Scale = { 1, 1 }; noTranslate = notranslate; Lump = fdlump; GlobalKerning = false; FontName = name; Next = FirstFont; FirstFont = this; Cursor = '_'; ActiveColors = 0; SpaceWidth = 0; FontHeight = 0; uint8_t pp = 0; for (auto &p : PatchRemap) p = pp++; translateUntranslated = false; int FixedWidth = 0; maxyoffs = 0; TMap<int, FTexture*> charMap; int minchar = INT_MAX; int maxchar = INT_MIN; // Read the font's configuration. // This will not be done for the default fonts, because they are not atomic and the default content does not need it. TArray<FolderEntry> folderdata; if (filetemplate != nullptr) { FStringf path("fonts/%s/", filetemplate); // If a name template is given, collect data from all resource files. // For anything else, each folder is being treated as an atomic, self-contained unit and mixing from different glyph sets is blocked. Wads.GetLumpsInFolder(path, folderdata, nametemplate == nullptr); //if (nametemplate == nullptr) { FStringf infpath("fonts/%s/font.inf", filetemplate); unsigned index = folderdata.FindEx([=](const FolderEntry &entry) { return infpath.CompareNoCase(entry.name) == 0; }); if (index < folderdata.Size()) { FScanner sc; sc.OpenLumpNum(folderdata[index].lumpnum); while (sc.GetToken()) { sc.TokenMustBe(TK_Identifier); if (sc.Compare("Kerning")) { sc.MustGetValue(false); GlobalKerning = sc.Number; } else if (sc.Compare("Scale")) { sc.MustGetValue(true); Scale.Y = Scale.X = sc.Float; if (sc.CheckToken(',')) { sc.MustGetValue(true); Scale.Y = sc.Float; } } else if (sc.Compare("SpaceWidth")) { sc.MustGetValue(false); SpaceWidth = sc.Number; } else if (sc.Compare("FontHeight")) { sc.MustGetValue(false); FontHeight = sc.Number; } else if (sc.Compare("CellSize")) { sc.MustGetValue(false); FixedWidth = sc.Number; sc.MustGetToken(','); sc.MustGetValue(false); FontHeight = sc.Number; } else if (sc.Compare("Translationtype")) { sc.MustGetToken(TK_Identifier); if (sc.Compare("console")) { TranslationType = 1; } else if (sc.Compare("standard")) { TranslationType = 0; } else { sc.ScriptError("Unknown translation type %s", sc.String); } } } } } } if (FixedWidth > 0) { ReadSheetFont(folderdata, FixedWidth, FontHeight, Scale); Type = Folder; } else { if (nametemplate != nullptr) { if (!iwadonly) { for (i = 0; i < lcount; i++) { int position = lfirst + i; mysnprintf(buffer, countof(buffer), nametemplate, i + start); lump = TexMan.CheckForTexture(buffer, ETextureType::MiscPatch); if (doomtemplate && lump.isValid() && i + start == 121) { // HACKHACK: Don't load STCFN121 in doom(2), because // it's not really a lower-case 'y' but a '|'. // Because a lot of wads with their own font seem to foolishly // copy STCFN121 and make it a '|' themselves, wads must // provide STCFN120 (x) and STCFN122 (z) for STCFN121 to load as a 'y'. if (!TexMan.CheckForTexture("STCFN120", ETextureType::MiscPatch).isValid() || !TexMan.CheckForTexture("STCFN122", ETextureType::MiscPatch).isValid()) { // insert the incorrectly named '|' graphic in its correct position. position = 124; } } if (lump.isValid()) { Type = Multilump; if (position < minchar) minchar = position; if (position > maxchar) maxchar = position; charMap.Insert(position, TexMan.GetTexture(lump)); } } } else { FTexture *texs[256] = {}; if (lcount > 256 - start) lcount = 256 - start; for (i = 0; i < lcount; i++) { TArray<FTextureID> array; mysnprintf(buffer, countof(buffer), nametemplate, i + start); TexMan.ListTextures(buffer, array, true); for (auto entry : array) { FTexture *tex = TexMan.GetTexture(entry, false); if (tex && tex->SourceLump >= 0 && Wads.GetLumpFile(tex->SourceLump) <= Wads.GetIwadNum() && tex->UseType == ETextureType::MiscPatch) { texs[i] = tex; } } } if (doomtemplate) { // Handle the misplaced '|'. if (texs[121 - '!'] && !texs[120 - '!'] && !texs[122 - '!'] && !texs[124 - '!']) { texs[124 - '!'] = texs[121 - '!']; texs[121 - '!'] = nullptr; } } for (i = 0; i < lcount; i++) { if (texs[i]) { int position = lfirst + i; Type = Multilump; if (position < minchar) minchar = position; if (position > maxchar) maxchar = position; charMap.Insert(position, texs[i]); } } } } if (folderdata.Size() > 0) { // all valid lumps must be named with a hex number that represents its Unicode character index. for (auto &entry : folderdata) { char *endp; auto base = ExtractFileBase(entry.name); auto position = strtoll(base.GetChars(), &endp, 16); if ((*endp == 0 || (*endp == '.' && position >= '!' && position < 0xffff))) { auto lump = TexMan.CheckForTexture(entry.name, ETextureType::MiscPatch); if (lump.isValid()) { if ((int)position < minchar) minchar = (int)position; if ((int)position > maxchar) maxchar = (int)position; auto tex = TexMan.GetTexture(lump); tex->SetScale(Scale); charMap.Insert((int)position, tex); Type = Folder; } } } } FirstChar = minchar; LastChar = maxchar; auto count = maxchar - minchar + 1; Chars.Resize(count); int fontheight = 0; for (i = 0; i < count; i++) { auto lump = charMap.CheckKey(FirstChar + i); if (lump != nullptr) { FTexture *pic = *lump; if (pic != nullptr) { int height = pic->GetDisplayHeight(); int yoffs = pic->GetDisplayTopOffset(); if (yoffs > maxyoffs) { maxyoffs = yoffs; } height += abs(yoffs); if (height > fontheight) { fontheight = height; } } pic->SetUseType(ETextureType::FontChar); if (!noTranslate) { Chars[i].OriginalPic = pic; Chars[i].TranslatedPic = new FImageTexture(new FFontChar1(pic->GetImage()), ""); Chars[i].TranslatedPic->CopySize(pic); Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar); TexMan.AddTexture(Chars[i].TranslatedPic); } else { Chars[i].TranslatedPic = pic; } Chars[i].XMove = Chars[i].TranslatedPic->GetDisplayWidth(); } else { Chars[i].TranslatedPic = nullptr; Chars[i].XMove = INT_MIN; } } if (SpaceWidth == 0) // An explicit override from the .inf file must always take precedence { if (spacewidth != -1) { SpaceWidth = spacewidth; } else if ('N' - FirstChar >= 0 && 'N' - FirstChar < count && Chars['N' - FirstChar].TranslatedPic != nullptr) { SpaceWidth = (Chars['N' - FirstChar].XMove + 1) / 2; } else { SpaceWidth = 4; } } if (FontHeight == 0) FontHeight = fontheight; FixXMoves(); } if (!noTranslate) LoadTranslations(); }
static EIWADType IdentifyVersion (TArray<FString> &wadfiles, const char *iwad, const char *zdoom_wad) { WadStuff wads[countof(IWADNames)]; size_t foundwads[NUM_IWAD_TYPES] = { 0 }; const char *iwadparm = Args->CheckValue ("-iwad"); size_t numwads; int pickwad; size_t i; bool iwadparmfound = false; FString custwad; if (iwadparm == NULL && iwad != NULL && *iwad != 0) { iwadparm = iwad; } if (iwadparm) { custwad = iwadparm; FixPathSeperator (custwad); if (CheckIWAD (custwad, wads)) { // -iwad parameter was a directory iwadparm = NULL; } else { DefaultExtension (custwad, ".wad"); iwadparm = custwad; IWADNames[0] = iwadparm; CheckIWAD ("", wads); } } if (iwadparm == NULL || wads[0].Path.IsEmpty()) { if (GameConfig->SetSection ("IWADSearch.Directories")) { const char *key; const char *value; while (GameConfig->NextInSection (key, value)) { if (stricmp (key, "Path") == 0) { FString nice = NicePath(value); FixPathSeperator(nice); CheckIWAD(nice, wads); } } } #ifdef _WIN32 FString steam_path = I_GetSteamPath(); if (steam_path.IsNotEmpty()) { static const char *const steam_dirs[] = { "doom 2/base", "final doom/base", "heretic shadow of the serpent riders/base", "hexen/base", "hexen deathkings of the dark citadel/base", "ultimate doom/base" }; steam_path += "/SteamApps/common/"; for (i = 0; i < countof(steam_dirs); ++i) { CheckIWAD (steam_path + steam_dirs[i], wads); } } #endif } if (iwadparm != NULL && !wads[0].Path.IsEmpty()) { iwadparmfound = true; } for (i = numwads = 0; i < countof(IWADNames); i++) { if (!wads[i].Path.IsEmpty()) { if (i != numwads) { wads[numwads] = wads[i]; } foundwads[wads[numwads].Type] = numwads + 1; numwads++; } } if (foundwads[IWAD_HexenDK] && !foundwads[IWAD_Hexen]) { // Cannot play Hexen DK without Hexen size_t kill = foundwads[IWAD_HexenDK]; for (i = kill; i < numwads; ++i) { wads[i - 1] = wads[i]; } numwads--; foundwads[IWAD_HexenDK] = 0; for (i = 0; i < NUM_IWAD_TYPES; ++i) { if (foundwads[i] > kill) { foundwads[i]--; } } } if (numwads == 0) // [BB] Skulltag uses Rivecoder's IWAD setup screen now (only available under Windows). #ifdef _WIN32 throw CNoIWADError(); // [RC] #else { I_FatalError ("Cannot find a game IWAD (doom.wad, doom2.wad, heretic.wad, etc.).\n" "Did you install "GAMENAME" properly? You can do either of the following:\n" "\n" "1. Place one or more of these wads in the same directory as "GAMENAME".\n" "2. Edit your "GAMENAMELOWERCASE"-username.ini and add the directories of your iwads\n" "to the list beneath [IWADSearch.Directories]"); } #endif pickwad = 0; if (!iwadparmfound && numwads > 1) { int defiwad = 0; // Locate the user's prefered IWAD, if it was found. if (defaultiwad[0] != '\0') { for (i = 0; i < numwads; ++i) { FString basename = ExtractFileBase (wads[i].Path); if (stricmp (basename, defaultiwad) == 0) { defiwad = (int)i; break; } } } pickwad = I_PickIWad (wads, (int)numwads, queryiwad, defiwad); if (pickwad >= 0) { // The newly selected IWAD becomes the new default FString basename = ExtractFileBase (wads[pickwad].Path); defaultiwad = basename; } } if (pickwad < 0) exit (0); // zdoom.pk3 must always be the first file loaded and the IWAD second. D_AddFile (wadfiles, zdoom_wad); if (wads[pickwad].Type == IWAD_HexenDK) { // load hexen.wad before loading hexdd.wad D_AddFile (wadfiles, wads[foundwads[IWAD_Hexen]-1].Path); } D_AddFile (wadfiles, wads[pickwad].Path); if (wads[pickwad].Type == IWAD_Strife) { // Try to load voices.wad along with strife1.wad long lastslash = wads[pickwad].Path.LastIndexOf ('/'); FString path; if (lastslash == -1) { path = "";// wads[pickwad].Path; } else { path = FString (wads[pickwad].Path.GetChars(), lastslash + 1); } path += "voices.wad"; D_AddFile (wadfiles, path); } return wads[pickwad].Type; }
void W_AddFile (char *filename) { wadinfo_t header; lumpinfo_t *lump_p; unsigned i; int handle, length; int startlump; filelump_t *fileinfo, singleinfo; // // open the file and add to directory // if ( (handle = open (filename,O_RDONLY | O_BINARY)) == -1) return; startlump = numlumps; if (strcmpi (filename+strlen(filename)-3 , "wad" ) ) { // single lump file fileinfo = &singleinfo; singleinfo.filepos = 0; singleinfo.size = LONG(filelength(handle)); ExtractFileBase (filename, singleinfo.name); numlumps++; } else { // WAD file read (handle, &header, sizeof(header)); if (strncmp(header.identification,"IWAD",4)) { if (strncmp(header.identification,"PWAD",4)) I_Error ("Wad file %s doesn't have IWAD or PWAD id\n" ,filename); } header.numlumps = LONG(header.numlumps); header.infotableofs = LONG(header.infotableofs); length = header.numlumps*sizeof(filelump_t); fileinfo = alloca (length); lseek (handle, header.infotableofs, SEEK_SET); read (handle, fileinfo, length); numlumps += header.numlumps; } // // Fill in lumpinfo // lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t)); if (!lumpinfo) I_Error ("Couldn't realloc lumpinfo"); lump_p = &lumpinfo[startlump]; for (i=startlump ; i<numlumps ; i++,lump_p++, fileinfo++) { lump_p->handle = handle; lump_p->position = LONG(fileinfo->filepos); lump_p->size = LONG(fileinfo->size); strncpy (lump_p->name, fileinfo->name, 8); } }
void W_AddFile (char *filename) { wadinfo_t header; lumpinfo_t* lump_p; unsigned i; int handle; int length; int startlump; filelump_t* fileinfo; filelump_t singleinfo; int storehandle; // open the file and add to directory // handle reload indicator. if (filename[0] == '~') { filename++; reloadname = filename; reloadlump = numlumps; } if ( (handle = open (filename,O_RDONLY | O_BINARY)) == -1) { printf (" couldn't open %s\n",filename); return; } printf (" adding %s\n",filename); startlump = numlumps; if (strcmpi (filename+strlen(filename)-3 , "wad" ) ) { // single lump file fileinfo = &singleinfo; singleinfo.filepos = 0; singleinfo.size = LONG(filelength(handle)); ExtractFileBase (filename, singleinfo.name); numlumps++; } else { // WAD file read (handle, &header, sizeof(header)); if (strncmp(header.identification,"IWAD",4)) { // Homebrew levels? if (strncmp(header.identification,"PWAD",4)) { I_Error ("Wad file %s doesn't have IWAD " "or PWAD id\n", filename); } // ???modifiedgame = true; } header.numlumps = LONG(header.numlumps); header.infotableofs = LONG(header.infotableofs); length = header.numlumps*sizeof(filelump_t); fileinfo = alloca (length); lseek (handle, header.infotableofs, SEEK_SET); read (handle, fileinfo, length); numlumps += header.numlumps; } // Fill in lumpinfo lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t)); if (!lumpinfo) I_Error ("Couldn't realloc lumpinfo"); lump_p = &lumpinfo[startlump]; storehandle = reloadname ? -1 : handle; for (i=startlump ; i<numlumps ; i++,lump_p++, fileinfo++) { lump_p->handle = storehandle; lump_p->position = LONG(fileinfo->filepos); lump_p->size = LONG(fileinfo->size); strncpy (lump_p->name, fileinfo->name, 8); } if (reloadname) close (handle); }
// // W_AddFile // All files are optional, but at least one file must be // found (PWAD, if all required lumps are present). // Files with a .wad extension are wadlink files // with multiple lumps. // Other files are single lumps with the base filename // for the lump name. // // Reload hack removed by Lee Killough // CPhipps - source is an enum // // proff - changed using pointer to wadfile_info_t static void W_AddFile(wadfile_info_t *wadfile) // killough 1/31/98: static, const { wadinfo_t header; lumpinfo_t* lump_p; unsigned i; int length; int startlump; filelump_t *fileinfo, *fileinfo2free=NULL; //killough filelump_t singleinfo; // open the file and add to directory wadfile->handle = open(wadfile->name,O_RDONLY | O_BINARY); #ifdef HAVE_NET if (wadfile->handle == -1 && D_NetGetWad(wadfile->name)) // CPhipps wadfile->handle = open(wadfile->name,O_RDONLY | O_BINARY); #endif if (wadfile->handle == -1) { if ( strlen(wadfile->name)<=4 || // add error check -- killough (strcasecmp(wadfile->name+strlen(wadfile->name)-4 , ".lmp" ) && strcasecmp(wadfile->name+strlen(wadfile->name)-4 , ".gwa" ) ) ) I_Error("W_AddFile: couldn't open %s",wadfile->name); return; } //jff 8/3/98 use logical output routine lprintf (LO_INFO," adding %s\n",wadfile->name); startlump = numlumps; if ( strlen(wadfile->name)<=4 || ( strcasecmp(wadfile->name+strlen(wadfile->name)-4,".wad") && strcasecmp(wadfile->name+strlen(wadfile->name)-4,".gwa") ) ) { // single lump file fileinfo = &singleinfo; singleinfo.filepos = 0; singleinfo.size = LONG(I_Filelength(wadfile->handle)); ExtractFileBase(wadfile->name, singleinfo.name); numlumps++; } else { // WAD file I_Read(wadfile->handle, &header, sizeof(header)); if (strncmp(header.identification,"IWAD",4) && strncmp(header.identification,"PWAD",4)) I_Error("W_AddFile: Wad file %s doesn't have IWAD or PWAD id", wadfile->name); header.numlumps = LONG(header.numlumps); header.infotableofs = LONG(header.infotableofs); length = header.numlumps*sizeof(filelump_t); fileinfo2free = fileinfo = malloc(length); // killough lseek(wadfile->handle, header.infotableofs, SEEK_SET); I_Read(wadfile->handle, fileinfo, length); numlumps += header.numlumps; } // Fill in lumpinfo lumpinfo = realloc(lumpinfo, numlumps*sizeof(lumpinfo_t)); lump_p = &lumpinfo[startlump]; for (i=startlump ; (int)i<numlumps ; i++,lump_p++, fileinfo++) { lump_p->wadfile = wadfile; // killough 4/25/98 lump_p->position = LONG(fileinfo->filepos); lump_p->size = LONG(fileinfo->size); lump_p->li_namespace = ns_global; // killough 4/17/98 strncpy (lump_p->name, fileinfo->name, 8); lump_p->source = wadfile->src; // Ty 08/29/98 } free(fileinfo2free); // killough }
int ConvertBSPToASE( char *bspName ) { int i, modelNum; FILE *f; bspShader_t *shader; bspModel_t *model; entity_t *e; vec3_t origin; const char *key; char name[ 1024 ], base[ 1024 ]; /* note it */ Sys_Printf( "--- Convert BSP to ASE ---\n" ); /* create the ase filename from the bsp name */ strcpy( name, bspName ); StripExtension( name ); strcat( name, ".ase" ); Sys_Printf( "writing %s\n", name ); ExtractFileBase( bspName, base ); strcat( base, ".bsp" ); /* open it */ f = fopen( name, "wb" ); if( f == NULL ) Error( "Open failed on %s\n", name ); /* print header */ fprintf( f, "*3DSMAX_ASCIIEXPORT\t200\r\n" ); fprintf( f, "*COMMENT\t\"Generated by Q3Map2 (ydnar) -convert -format ase\"\r\n" ); fprintf( f, "*SCENE\t{\r\n" ); fprintf( f, "\t*SCENE_FILENAME\t\"%s\"\r\n", base ); fprintf( f, "\t*SCENE_FIRSTFRAME\t0\r\n" ); fprintf( f, "\t*SCENE_LASTFRAME\t100\r\n" ); fprintf( f, "\t*SCENE_FRAMESPEED\t30\r\n" ); fprintf( f, "\t*SCENE_TICKSPERFRAME\t160\r\n" ); fprintf( f, "\t*SCENE_BACKGROUND_STATIC\t0.0000\t0.0000\t0.0000\r\n" ); fprintf( f, "\t*SCENE_AMBIENT_STATIC\t0.0000\t0.0000\t0.0000\r\n" ); fprintf( f, "}\r\n" ); /* print materials */ fprintf( f, "*MATERIAL_LIST\t{\r\n" ); fprintf( f, "\t*MATERIAL_COUNT\t%d\r\n", numBSPShaders ); for( i = 0; i < numBSPShaders; i++ ) { shader = &bspShaders[ i ]; ConvertShader( f, shader, i ); } fprintf( f, "}\r\n" ); /* walk entity list */ for( i = 0; i < numEntities; i++ ) { /* get entity and model */ e = &entities[ i ]; if( i == 0 ) modelNum = 0; else { key = ValueForKey( e, "model" ); if( key[ 0 ] != '*' ) continue; modelNum = atoi( key + 1 ); } model = &bspModels[ modelNum ]; /* get entity origin */ key = ValueForKey( e, "origin" ); if( key[ 0 ] == '\0' ) VectorClear( origin ); else GetVectorForKey( e, "origin", origin ); /* convert model */ ConvertModel( f, model, modelNum, origin ); } /* close the file and return */ fclose( f ); /* return to sender */ return 0; }
// // W_AddFile // All files are optional, but at least one file must be // found (PWAD, if all required lumps are present). // Files with a .wad extension are wadlink files // with multiple lumps. // Other files are single lumps with the base filename // for the lump name. // // Reload hack removed by Lee Killough // CPhipps - source is an enum // // proff - changed using pointer to wadfile_info_t static void W_AddFile(wadfile_info_t *wadfile) // killough 1/31/98: static, const { wadinfo_t header; lumpinfo_t* lump_p; unsigned i; int length; int startlump; filelump_t *fileinfo, *fileinfo2free=NULL; //killough filelump_t singleinfo; // open the file and add to directory //e6y #ifdef ALL_IN_ONE unsigned char *handle; dboolean predefined_lump = (wadfile->src == source_pre); if(predefined_lump) handle = GetAllInOneLumpHandle(); else { #endif //ROBO: Precache wadfile->handle = fopen(wadfile->name, "rb"); #ifdef HAVE_NET if (wadfile->handle == 0 && D_NetGetWad(wadfile->name)) // CPhipps wadfile->handle = fopen(wadfile->name, "rb"); #endif if (wadfile->handle == 0 && strlen(wadfile->name) > 4 && wadfile->src == source_pwad && !strcasecmp(wadfile->name + strlen(wadfile->name) - 4 , ".wad") && D_TryGetWad(wadfile->name)) { wadfile->handle = fopen(wadfile->name, "rb"); } if (wadfile->handle == 0) { if ( strlen(wadfile->name)<=4 || // add error check -- killough (strcasecmp(wadfile->name+strlen(wadfile->name)-4 , ".lmp" ) && strcasecmp(wadfile->name+strlen(wadfile->name)-4 , ".gwa" ) ) ) I_Error("W_AddFile: couldn't open %s",wadfile->name); return; } { struct stat statbuf; stat(wadfile->name, &statbuf); wadfile->length = statbuf.st_size; wadfile->data = malloc(statbuf.st_size); fread(wadfile->data, statbuf.st_size, 1, wadfile->handle); } //e6y #ifdef ALL_IN_ONE } #endif //jff 8/3/98 use logical output routine lprintf (LO_INFO," adding %s\n",wadfile->name); startlump = numlumps; if ( strlen(wadfile->name)<=4 || ( strcasecmp(wadfile->name+strlen(wadfile->name)-4,".wad") && strcasecmp(wadfile->name+strlen(wadfile->name)-4,".gwa") ) ) { // single lump file fileinfo = &singleinfo; singleinfo.filepos = 0; singleinfo.size = wadfile->length; //LittleLong(I_Filelength(wadfile->handle)); ExtractFileBase(wadfile->name, singleinfo.name); numlumps++; } else { // WAD file //e6y #ifdef ALL_IN_ONE if(predefined_lump) memcpy(&header, handle, sizeof(header)); else #endif memcpy(&header, wadfile->data, sizeof(header)); // I_Read(wadfile->handle, &header, sizeof(header)); if (strncmp(header.identification,"IWAD",4) && strncmp(header.identification,"PWAD",4)) I_Error("W_AddFile: Wad file %s doesn't have IWAD or PWAD id", wadfile->name); header.numlumps = LittleLong(header.numlumps); header.infotableofs = LittleLong(header.infotableofs); length = header.numlumps*sizeof(filelump_t); fileinfo2free = fileinfo = malloc(length); // killough //e6y #ifdef ALL_IN_ONE if(predefined_lump) memcpy(fileinfo, handle + header.infotableofs, length); else #endif // lseek(wadfile->handle, header.infotableofs, SEEK_SET), // I_Read(wadfile->handle, fileinfo, length); memcpy(fileinfo, &wadfile->data[header.infotableofs], length); numlumps += header.numlumps; } // Fill in lumpinfo lumpinfo = realloc(lumpinfo, numlumps*sizeof(lumpinfo_t)); lump_p = &lumpinfo[startlump]; for (i=startlump ; (int)i<numlumps ; i++,lump_p++, fileinfo++) { lump_p->flags = 0; //e6y lump_p->wadfile = wadfile; // killough 4/25/98 lump_p->position = LittleLong(fileinfo->filepos); lump_p->size = LittleLong(fileinfo->size); if (wadfile->src == source_lmp) { // Modifications to place command-line-added demo lumps // into a separate "ns_demos" namespace so that they cannot // conflict with other lump names lump_p->li_namespace = ns_demos; } else { lump_p->li_namespace = ns_global; // killough 4/17/98 } strncpy (lump_p->name, fileinfo->name, 8); lump_p->source = wadfile->src; // Ty 08/29/98 } free(fileinfo2free); // killough }
int main( int argc, char **argv ) { int i, comp = 0; char outputpath[MAX_PATH] = ""; char filename[MAX_PATH] = "unknown"; quakefile_t *qfiles, *qf; // Ridah, allow to specify an extension for multiple AAS files per map int has_ext = 0; // done. // Ridah, set the world pointer up for reachabilities aasworld = aasworlds; AAS_SetWorldPointer( &( *aasworld ) ); // done. myargc = argc; myargv = argv; Log_Open( "bspc.log" ); //open a log file Log_Print( "BSPC version " BSPC_VERSION ", %s %s by Mr Elusive\n", __DATE__, __TIME__ ); DefaultCfg(); for ( i = 1; i < argc; i++ ) { if ( !stricmp( argv[i],"-threads" ) ) { if ( i + 1 >= argc ) { i = 0; break; } numthreads = atoi( argv[++i] ); Log_Print( "threads = %d\n", numthreads ); } //end if else if ( !stricmp( argv[i], "-noverbose" ) ) { Log_Print( "verbose = false\n" ); verbose = false; } //end else if else if ( !stricmp( argv[i], "-nocsg" ) ) { Log_Print( "nocsg = true\n" ); nocsg = true; } //end else if else if ( !stricmp( argv[i], "-optimize" ) ) { Log_Print( "optimize = true\n" ); optimize = true; } //end else if /* else if (!stricmp(argv[i],"-glview")) { glview = true; } //end else if else if (!stricmp(argv[i], "-draw")) { Log_Print("drawflag = true\n"); drawflag = true; } //end else if else if (!stricmp(argv[i], "-noweld")) { Log_Print("noweld = true\n"); noweld = true; } //end else if else if (!stricmp(argv[i], "-noshare")) { Log_Print("noshare = true\n"); noshare = true; } //end else if else if (!stricmp(argv[i], "-notjunc")) { Log_Print("notjunc = true\n"); notjunc = true; } //end else if else if (!stricmp(argv[i], "-nowater")) { Log_Print("nowater = true\n"); nowater = true; } //end else if else if (!stricmp(argv[i], "-noprune")) { Log_Print("noprune = true\n"); noprune = true; } //end else if else if (!stricmp(argv[i], "-nomerge")) { Log_Print("nomerge = true\n"); nomerge = true; } //end else if else if (!stricmp(argv[i], "-nosubdiv")) { Log_Print("nosubdiv = true\n"); nosubdiv = true; } //end else if else if (!stricmp(argv[i], "-nodetail")) { Log_Print("nodetail = true\n"); nodetail = true; } //end else if else if (!stricmp(argv[i], "-fulldetail")) { Log_Print("fulldetail = true\n"); fulldetail = true; } //end else if else if (!stricmp(argv[i], "-onlyents")) { Log_Print("onlyents = true\n"); onlyents = true; } //end else if else if (!stricmp(argv[i], "-micro")) { if (i + 1 >= argc) {i = 0; break;} microvolume = atof(argv[++i]); Log_Print("microvolume = %f\n", microvolume); } //end else if else if (!stricmp(argv[i], "-leaktest")) { Log_Print("leaktest = true\n"); leaktest = true; } //end else if else if (!stricmp(argv[i], "-verboseentities")) { Log_Print("verboseentities = true\n"); verboseentities = true; } //end else if else if (!stricmp(argv[i], "-chop")) { if (i + 1 >= argc) {i = 0; break;} subdivide_size = atof(argv[++i]); Log_Print("subdivide_size = %f\n", subdivide_size); } //end else if else if (!stricmp (argv[i], "-tmpout")) { strcpy (outbase, "/tmp"); Log_Print("temp output\n"); } //end else if */ #ifdef ME else if ( !stricmp( argv[i], "-freetree" ) ) { freetree = true; Log_Print( "freetree = true\n" ); } //end else if else if ( !stricmp( argv[i], "-grapplereach" ) ) { calcgrapplereach = true; Log_Print( "grapplereach = true\n" ); } //end else if else if ( !stricmp( argv[i], "-nobrushmerge" ) ) { nobrushmerge = true; Log_Print( "nobrushmerge = true\n" ); } //end else if else if ( !stricmp( argv[i], "-noliquids" ) ) { noliquids = true; Log_Print( "noliquids = true\n" ); } //end else if else if ( !stricmp( argv[i], "-forcesidesvisible" ) ) { forcesidesvisible = true; Log_Print( "forcesidesvisible = true\n" ); } //end else if else if ( !stricmp( argv[i], "-output" ) ) { if ( i + 1 >= argc ) { i = 0; break; } if ( access( argv[i + 1], 0x04 ) ) { Warning( "the folder %s does not exist", argv[i + 1] ); } strcpy( outputpath, argv[++i] ); } //end else if else if ( !stricmp( argv[i], "-breadthfirst" ) ) { use_nodequeue = true; Log_Print( "breadthfirst = true\n" ); } //end else if else if ( !stricmp( argv[i], "-cfg" ) ) { if ( i + 1 >= argc ) { i = 0; break; } if ( !LoadCfgFile( argv[++i] ) ) { exit( 0 ); } } //end else if else if ( !stricmp( argv[i], "-bsp2map" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_BSP2MAP; qfiles = GetArgumentFiles( argc, argv, &i, "bsp" ); } //end else if else if ( !stricmp( argv[i], "-bsp2aas" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_BSP2AAS; qfiles = GetArgumentFiles( argc, argv, &i, "bsp" ); } //end else if else if ( !stricmp( argv[i], "-aasall" ) ) { if ( i + 1 >= argc ) { i = 0; break; } CreateAASFilesForAllBSPFiles( argv[++i] ); } //end else if else if ( !stricmp( argv[i], "-reach" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_REACH; qfiles = GetArgumentFiles( argc, argv, &i, "bsp" ); } //end else if else if ( !stricmp( argv[i], "-cluster" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_CLUSTER; qfiles = GetArgumentFiles( argc, argv, &i, "bsp" ); } //end else if else if ( !stricmp( argv[i], "-aasinfo" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_AASINFO; qfiles = GetArgumentFiles( argc, argv, &i, "aas" ); } //end else if else if ( !stricmp( argv[i], "-aasopt" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_AASOPTIMIZE; qfiles = GetArgumentFiles( argc, argv, &i, "aas" ); } //end else if else if ( !stricmp( argv[i], "-tetra" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_TETRA; qfiles = GetArgumentFiles( argc, argv, &i, "aas" ); } //end else if // Ridah, allow to specify an extension for multiple AAS files per map else if ( !stricmp( argv[i], "-ext" ) ) { if ( i + 1 >= argc ) { i = 0; break; } strcpy( aas_extension, argv[++i] ); has_ext = 1; } //end else if // done. #endif //ME else { Log_Print( "unknown parameter %s\n", argv[i] ); break; } //end else } //end for //if there are parameters and there's no mismatch in one of the parameters if ( argc > 1 && i == argc ) { switch ( comp ) { case COMP_BSP2MAP: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { //copy the output path strcpy( filename, outputpath ); //append the bsp file base AppendPathSeperator( filename, MAX_PATH ); ExtractFileBase( qf->origname, &filename[strlen( filename )] ); //append .map strcat( filename, ".map" ); // Log_Print( "bsp2map: %s to %s\n", qf->origname, filename ); if ( qf->type != QFILETYPE_BSP ) { Warning( "%s is probably not a BSP file\n", qf->origname ); } // LoadMapFromBSP( qf ); //write the map file WriteMapFile( filename ); } //end for break; } //end case case COMP_BSP2AAS: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { AASOuputFile( qf, outputpath, filename ); // Log_Print( "bsp2aas: %s to %s\n", qf->origname, filename ); if ( qf->type != QFILETYPE_BSP ) { Warning( "%s is probably not a BSP file\n", qf->origname ); } //set before map loading create_aas = 1; LoadMapFromBSP( qf ); //create the AAS file AAS_Create( filename ); //if it's a Quake3 map calculate the reachabilities and clusters if ( loadedmaptype == MAPTYPE_QUAKE3 ) { AAS_CalcReachAndClusters( qf ); } // if ( optimize ) { AAS_Optimize(); } // //write out the stored AAS file if ( !AAS_WriteAASFile( filename ) ) { Error( "error writing %s\n", filename ); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_REACH: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { AASOuputFile( qf, outputpath, filename ); // Log_Print( "reach: %s to %s\n", qf->origname, filename ); if ( qf->type != QFILETYPE_BSP ) { Warning( "%s is probably not a BSP file\n", qf->origname ); } //if the AAS file exists in the output directory if ( !access( filename, 0x04 ) ) { if ( !AAS_LoadAASFile( filename, 0, 0 ) ) { Error( "error loading aas file %s\n", filename ); } //end if //assume it's a Quake3 BSP file loadedmaptype = MAPTYPE_QUAKE3; } //end if else { Warning( "AAS file %s not found in output folder\n", filename ); Log_Print( "creating %s...\n", filename ); //set before map loading create_aas = 1; LoadMapFromBSP( qf ); //create the AAS file AAS_Create( filename ); } //end else //if it's a Quake3 map calculate the reachabilities and clusters if ( loadedmaptype == MAPTYPE_QUAKE3 ) { AAS_CalcReachAndClusters( qf ); } //end if // if ( optimize ) { AAS_Optimize(); } //write out the stored AAS file if ( !AAS_WriteAASFile( filename ) ) { Error( "error writing %s\n", filename ); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_CLUSTER: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { AASOuputFile( qf, outputpath, filename ); // Log_Print( "cluster: %s to %s\n", qf->origname, filename ); if ( qf->type != QFILETYPE_BSP ) { Warning( "%s is probably not a BSP file\n", qf->origname ); } //if the AAS file exists in the output directory if ( !access( filename, 0x04 ) ) { if ( !AAS_LoadAASFile( filename, 0, 0 ) ) { Error( "error loading aas file %s\n", filename ); } //end if //assume it's a Quake3 BSP file loadedmaptype = MAPTYPE_QUAKE3; //if it's a Quake3 map calculate the clusters if ( loadedmaptype == MAPTYPE_QUAKE3 ) { ( *aasworld ).numclusters = 0; AAS_InitBotImport(); AAS_InitClustering(); } //end if } //end if else { Warning( "AAS file %s not found in output folder\n", filename ); Log_Print( "creating %s...\n", filename ); //set before map loading create_aas = 1; LoadMapFromBSP( qf ); //create the AAS file AAS_Create( filename ); //if it's a Quake3 map calculate the reachabilities and clusters if ( loadedmaptype == MAPTYPE_QUAKE3 ) { AAS_CalcReachAndClusters( qf ); } } //end else // if ( optimize ) { AAS_Optimize(); } //write out the stored AAS file if ( !AAS_WriteAASFile( filename ) ) { Error( "error writing %s\n", filename ); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_AASOPTIMIZE: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { AASOuputFile( qf, outputpath, filename ); // Log_Print( "optimizing: %s to %s\n", qf->origname, filename ); if ( qf->type != QFILETYPE_AAS ) { Warning( "%s is probably not a AAS file\n", qf->origname ); } // AAS_InitBotImport(); // if ( !AAS_LoadAASFile( qf->filename, qf->offset, qf->length ) ) { Error( "error loading aas file %s\n", qf->filename ); } //end if AAS_Optimize(); //write out the stored AAS file if ( !AAS_WriteAASFile( filename ) ) { Error( "error writing %s\n", filename ); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_AASINFO: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { AASOuputFile( qf, outputpath, filename ); // Log_Print( "aas info for: %s\n", filename ); if ( qf->type != QFILETYPE_AAS ) { Warning( "%s is probably not a AAS file\n", qf->origname ); } // AAS_InitBotImport(); // if ( !AAS_LoadAASFile( qf->filename, qf->offset, qf->length ) ) { Error( "error loading aas file %s\n", qf->filename ); } //end if AAS_ShowTotals(); } //end for } //end case case COMP_TETRA: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { //TH_AASToTetrahedrons(qf->filename); } //end for break; } //end case default: { Log_Print( "don't know what to do\n" ); break; } //end default } //end switch } //end if else { Log_Print( "Usage: bspc [-<switch> [-<switch> ...]]\n" #if defined( WIN32 ) || defined( _WIN32 ) "Example 1: bspc -bsp2aas d:\\quake3\\baseq3\\maps\\mymap?.bsp\n" "Example 2: bspc -bsp2aas d:\\quake3\\baseq3\\pak0.pk3\\maps/q3dm*.bsp\n" #else "Example 1: bspc -bsp2aas /quake3/baseq3/maps/mymap?.bsp\n" "Example 2: bspc -bsp2aas /quake3/baseq3/pak0.pk3/maps/q3dm*.bsp\n" #endif "\n" "Switches:\n" //" bsp2map <[pakfilter/]filter.bsp> = convert BSP to MAP\n" " bsp2aas <[pakfilter/]filter.bsp> = convert BSP to AAS\n" //" aasall <quake3folder> = create AAS files for all BSPs\n" " reach <filter.bsp> = compute reachability & clusters\n" " cluster <filter.aas> = compute clusters\n" " aasopt <filter.aas> = optimize aas file\n" //" tetra <filter.aas> = tetrahedral decomposition\n" " output <output path> = set output path\n" " threads <X> = set number of threads to X\n" " cfg <filename> = use this cfg file\n" " optimize = enable optimization\n" " noverbose = disable verbose output\n" " breadthfirst = breadth first bsp building\n" " nobrushmerge = don't merge brushes\n" " noliquids = don't write liquids to map\n" " freetree = free the bsp tree\n" " nocsg = disables brush chopping\n" " forcesidesvisible = force all sides to be visible\n" " grapplereach = calculate grapple reachabilities\n" /* " glview = output a GL view\n" " draw = enables drawing\n" " noweld = disables weld\n" " noshare = disables sharing\n" " notjunc = disables juncs\n" " nowater = disables water brushes\n" " noprune = disables node prunes\n" " nomerge = disables face merging\n" " nosubdiv = disables subdeviding\n" " nodetail = disables detail brushes\n" " fulldetail = enables full detail\n" " onlyents = only compile entities with bsp\n" " micro <volume>\n" " = sets the micro volume to the given float\n" " leaktest = perform a leak test\n" " verboseentities\n" " = enable entity verbose mode\n" " chop <subdivide_size>\n" " = sets the subdivide size to the given float\n"*/ "\n" ); } //end else Log_Close(); //close the log file return 0; } //end of the function main
wad_file_t *W_AddFile (char *filename) { wadinfo_t header; lumpinfo_t *lump_p; unsigned int i; wad_file_t *wad_file; int length; int startlump; filelump_t *fileinfo; filelump_t *filerover; // open the file and add to directory wad_file = W_OpenFile(filename); if (wad_file == NULL) return NULL; startlump = numlumps; if (strcasecmp(filename + strlen(filename) - 3, "wad")) { // single lump file // fraggle: Swap the filepos and size here. The WAD directory // parsing code expects a little-endian directory, so will swap // them back. Effectively we're constructing a "fake WAD directory" // here, as it would appear on disk. fileinfo = (filelump_t *)Z_Malloc(sizeof(filelump_t), PU_STATIC, 0); fileinfo->filepos = LONG(0); fileinfo->size = LONG(wad_file->length); // Name the lump after the base of the filename (without the // extension). ExtractFileBase(filename, fileinfo->name); numlumps++; } else { // WAD file W_Read(wad_file, 0, &header, sizeof(header)); if (strncmp(header.identification, "IWAD", 4)) { // Homebrew levels? if (strncmp(header.identification, "PWAD", 4)) I_Error("Wad file %s doesn't have IWAD or PWAD id\n", filename); } header.numlumps = LONG(header.numlumps); header.infotableofs = LONG(header.infotableofs); length = header.numlumps * sizeof(filelump_t); fileinfo = (filelump_t *)Z_Malloc(length, PU_STATIC, 0); W_Read(wad_file, header.infotableofs, fileinfo, length); numlumps += header.numlumps; } // Fill in lumpinfo lumpinfo = (lumpinfo_t *)realloc(lumpinfo, numlumps * sizeof(lumpinfo_t)); if (lumpinfo == NULL) I_Error("Couldn't realloc lumpinfo"); lump_p = &lumpinfo[startlump]; filerover = fileinfo; for (i = startlump; i < numlumps; ++i) { lump_p->wad_file = wad_file; lump_p->position = LONG(filerover->filepos); lump_p->size = LONG(filerover->size); lump_p->cache = NULL; strncpy(lump_p->name, filerover->name, 8); ++lump_p; ++filerover; } Z_Free(fileinfo); if (lumphash != NULL) { Z_Free(lumphash); lumphash = NULL; } return wad_file; }