/* ** ** convert raw data (as read from wad) into Textures ** Data= texture entry ** if PatchSz>0, Patch defines the patch list */ void TXUreadTEXTURE(char *Data,Int32 DataSz,char *Patch, Int32 PatchSz,Bool Redefn) { Int32 Pos, Numtex, Numpat, dummy; /* texture data*/ Int16 t,p,i, Xsize, Ysize; /* size x and y */ /* nb of wall patches used to build it */ /* wall patch inside a texture */ Int16 Xofs, Yofs,Pindex; /* x,y coordinate in texture space*/ /* patch name index in PNAMES table */ Int32 MaxPindex; static char tname[8]; /*texture name*/ static char pname[8]; /*patch name*/ size_t header_size; size_t item_size; int have_texture_name; int have_header_dummies; if (input_texture_format == TF_NAMELESS) { header_size = 14; item_size = 10; have_texture_name = 0; have_header_dummies = 1; } else if (input_texture_format == TF_NONE) { Warning ("No texture definitions to read."); return; /* FIXME is it OK to do that ? */ } else if (input_texture_format == TF_NORMAL) { header_size = 22; item_size = 10; have_texture_name = 1; have_header_dummies = 1; } else if (input_texture_format == TF_STRIFE11) { header_size = 18; item_size = 6; have_texture_name = 1; have_header_dummies = 0; } else { Bug ("TXUreadTEXTURE: bad itf %d", (int) input_texture_format); } /*get number of patches*/ if(PatchSz>0) { MaxPindex = peek_i32_le (Patch); dummy=4L+(MaxPindex*8L); if(dummy>PatchSz) ProgError("Bad PNAMES format"); } else { MaxPindex = PNMgetNbOfPatch(); } if((MaxPindex<0)||(MaxPindex>0x7FFF)) ProgError("Bad PNAMES entry"); /*get number of textures*/ Numtex = peek_i32_le (Data); if(Numtex<0) ProgError("Bad TEXTURE entry"); if(Numtex>MAXTEXTURES) ProgError("Too many TEXTUREs"); /*read textures*/ for (t = 0; t <Numtex; t++) { Pos = peek_i32_le (Data + 4L + t * 4L); if (Pos + header_size > DataSz) ProgError("TEXTURE entry too small"); if (have_texture_name) { Normalise (tname, Data + Pos); Pos += 8; } else /* No name. Make one up (TEXnnnn)*/ { if (t > 9999) { Warning ("More than 10000 textures. Ignoring excess."); break; } sprintf (tname, "TEX%04d", (int) t); } Pos += 4; /* Skip 2 dummy unused fields */ Xsize = peek_i16_le (Data + Pos); Pos += 2; if((Xsize<0)||(Xsize>4096)) ProgError ("Texture %s: width out of bound (%d)", lump_name (tname), (int) Xsize); Ysize = peek_i16_le (Data + Pos); Pos += 2; if((Ysize<0)||(Ysize>4096)) ProgError ("Texture %s: height out of bound (%d)", lump_name (tname), (int) Ysize); if (have_header_dummies) Pos += 4; /* Skip 2 dummy unused fields */ Numpat = peek_i16_le (Data + Pos)&0xFFFF; Pos += 2; if((Numpat<0)||(Numpat>MAXPATCHPERTEX)) ProgError("Texture %s: too many patches (%d)", lump_name (tname), (int) Numpat); /* declare texture */ TXUdefineCurTex(tname,Xsize,Ysize,Redefn); if (Pos + (long) Numpat * item_size > DataSz) ProgError("TEXTURE entry too small"); for (p = 0; p < Numpat; p++, Pos += item_size) { Xofs = peek_i16_le (Data + Pos); if((Xofs<-4096)||(Xofs>4096)) ProgError("Texture %s(%d/%d): bad patch X-offset %d", lump_name (tname), (int) p, (int) Numpat, (int) Xofs); Yofs = peek_i16_le (Data + Pos + 2); if((Yofs<-4096)||(Yofs>4096)) ProgError("Texture %s(%d/%d): bad patch Y-offset %d", lump_name (tname), (int) p, (int) Numpat, (int) Yofs); Pindex = peek_i16_le (Data + Pos + 4); if((Pindex<0)||(Pindex>MaxPindex)) ProgError("Texture %s(%d/%d): bad patch index %d", lump_name (tname), (int) p, (int) Numpat, (int) Pindex); /*if new patch list, recalculate Pindex*/ if(PatchSz>0) { for(dummy=(4L+(Pindex*8L)),i=0;i<8;i++) pname[i]=Patch[dummy+i]; Pindex=PNMgetPatchIndex(pname); } /*declare patch*/ TXUaddPatchToCurTex(Pindex,Xofs,Yofs); } } }
void CMPOmakePWAD(const char *doomwad,WADTYPE type, const char *PWADname, const char *DataDir, const char *texin, NTRYB select, char trnR, char trnG, char trnB, Bool George) { /* ** type PWAD as we are generating a real PWAD */ Int32 start=0, size=0; static char name[8]; static char filenam[8]; /*PNAMES */ Int16 nbPatchs,p; Bool NeedPNAME=FALSE; Bool FoundOne=FALSE; Bool Repeat; IMGTYPE Picture; /*optional insertion point*/ Int16 X,Y; /*text file to read*/ static struct TXTFILE *TXT; /*DOOM wad*/ static struct WADINFO iwad,pwad; /*result wad file*/ static struct WADINFO rwad; /*for Pnames*/ Int16 entry;char *EntryP;Int32 EntrySz=0; /* initialisation*/ Info("CM01", "Composing %cWAD %s from %s", (type==IWAD) ? 'I' : 'P', fname (PWADname), texin); /*open iwad,get iwad directory*/ iwad.ok=0; WADRopenR(&iwad,doomwad); TXT= TXTopenR(texin, 0); WADRopenW(&rwad,PWADname,type, 1); /* fake IWAD or real PWAD */ /* ** dirty: set error handler to delete the wad out file, ** if an error occurs. */ CMPOrwad = &rwad; CMPOwadout = PWADname; ProgErrorAction(CMPOerrorAction); /* ** levels! add your own new levels to DOOM! ** read level from a PWAD file */ if(select&BLEVEL) { if(TXTseekSection(TXT,"LEVELS")) { while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) { p=IDENTlevel(name); if(p<0) ProgError("CM11", "Illegal level name %s", lump_name (name)); if(MakeFileName(file,DataDir,"LEVELS","",filenam,"WAD")!=TRUE) ProgError("CM12", "Can't find level WAD %s", fname (file)); Detail("CM13", "Reading level WAD file %s", fname (file)); WADRwriteWADlevel(&rwad,file,name); } } } /* ** prepare palette for graphics */ /*find PLAYPAL*/ if(select&(BGRAPHIC|BSPRITE|BPATCH|BFLAT)) { /* If wadinfo.txt mentions a custom PLAYPAL, use that. Otherwise, use the one in the iwad. */ char *paldata = NULL; const char *playpal_pathname = NULL; const char *playpal_lumpname = NULL; if (TXTseekSection (TXT, "LUMPS")) { while (TXTentryParse(name, filenam, &X, &Y, &Repeat, TXT, FALSE) == TRUE) { if (strcmp (name, "PLAYPAL") == 0) { FILE *playpal_fp; MakeFileName (file, DataDir, "LUMPS", "", filenam, "LMP"); playpal_pathname = file; playpal_lumpname = NULL; EntrySz = 768; paldata = Malloc (EntrySz); playpal_fp = fopen (file, FOPEN_RB); if (playpal_fp == NULL) ProgError ("CM21", "%s: %s", fname (file), strerror (errno)); EntrySz = fread (paldata, 1, EntrySz, playpal_fp); if (EntrySz != 768) /* DEBUG was ProgError */ Warning ("CM22", "%s: short read", fname (file)); fclose (playpal_fp); break; } } } if (paldata == NULL) { playpal_pathname = iwad.filename; playpal_lumpname = palette_lump; entry = WADRfindEntry(&iwad, palette_lump); if (entry < 0) ProgError ("CM23", "Can't find %s in main WAD", lump_name (palette_lump)); paldata = WADRreadEntry (&iwad, entry, &EntrySz); } COLinit (trnR, trnG, trnB, paldata, (Int16) EntrySz, playpal_pathname, playpal_lumpname); Free (paldata); } /* ** ** lumps. non graphic raw data for DOOM */ if(select&BLUMP) { start=size=0; if(TXTseekSection(TXT,"LUMPS")) { Phase("CM30", "Making lumps"); while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) { if(Repeat!=TRUE) { WADRalign4(&rwad); /*align entry on Int32 word*/ start=WADRposition(&rwad); if(MakeFileName(file,DataDir,"LUMPS","",filenam,"LMP")==TRUE) { size=WADRwriteLump(&rwad,file); } else { Picture=CMPOloadPic(&size,&rwad,file,DataDir,"LUMPS",name, filenam,PLUMP,X,Y); if(Picture==PICNONE) if(CMPOcopyFromWAD(&size,&rwad,DataDir,"LUMPS",name,filenam) !=TRUE) ProgError("CM31", "Can't find lump or picture file %s",file); } } WADRdirAddEntry(&rwad,start,size,name); } } } /* ** initialise list of patch names */ if(select&(BTEXTUR|BPATCH)) { entry=WADRfindEntry(&iwad,"PNAMES"); if(entry<0) ProgError("CM40", "Can't find PNAMES in main WAD"); EntryP=WADRreadEntry(&iwad,entry,&EntrySz); PNMinit(EntryP,EntrySz); Free(EntryP); NeedPNAME = FALSE; } /* ** read texture1 */ if(select&BTEXTUR) { if(TXTseekSection(TXT,"TEXTURE1")) { Phase("CM50", "Making TEXTURE1"); TXUinit(); entry=WADRfindEntry(&iwad,"TEXTURE1"); if(entry>=0) { EntryP=WADRreadEntry(&iwad,entry,&EntrySz); TXUreadTEXTURE("TEXTURE1", EntryP, EntrySz, NULL, 0, TRUE); Free(EntryP); } else Warning("CM51", "Can't find TEXTURE1 in main WAD"); FoundOne=FALSE; /*read TEXTURES composing TEXTURE1*/ while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) { if(MakeFileName(file,DataDir,"TEXTURES","",name,"TXT")==TRUE) { Detail("CM52", "Reading texture file %s", fname (file)); TXUreadTexFile(file,TRUE); NeedPNAME=TRUE; FoundOne=TRUE; } else if(MakeFileName(file,DataDir,"TEXTURES","",name,"WAD")==TRUE) { Detail("CM53", "Reading texture WAD %s", fname (file)); WADRopenR(&pwad,file); entry=WADRfindEntry(&pwad,"TEXTURE1"); if(entry>=0) { EntryP=WADRreadEntry(&pwad,entry,&EntrySz); TXUreadTEXTURE("TEXTURE1", EntryP, EntrySz, NULL, 0, TRUE); Free(EntryP); NeedPNAME=TRUE; FoundOne=TRUE; } WADRclose(&pwad); } else ProgError("CM54", "Can't find texture list %s", file); } /*write texture*/ if(FoundOne==TRUE) { WADRalign4(&rwad); /*align entry on Int32 word*/ start= WADRposition(&rwad); size = TXUwriteTEXTUREtoWAD(&rwad); WADRdirAddEntry(&rwad,start,size,"TEXTURE1"); } TXUfree(); } } /* ** read texture2 */ if(select&BTEXTUR) { if(TXTseekSection(TXT,"TEXTURE2")) { Phase("CM55", "Making TEXTURE2"); TXUinit(); entry=WADRfindEntry(&iwad,"TEXTURE2"); if(entry>=0) { EntryP=WADRreadEntry(&iwad,entry,&EntrySz); TXUreadTEXTURE("TEXTURE2", EntryP, EntrySz, NULL, 0, TRUE); Free(EntryP); } else Warning("CM56", "Can't find TEXTURE2 in main WAD"); FoundOne=FALSE; /*read TEXTURES composing TEXTURE2*/ while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) { if(MakeFileName(file,DataDir,"TEXTURES","",name,"TXT")==TRUE) { Detail("CM57", "Reading texture file %s", fname (file)); TXUreadTexFile(file,TRUE); NeedPNAME=TRUE; FoundOne=TRUE; } else if(MakeFileName(file,DataDir,"TEXTURES","",name,"WAD")==TRUE) { Detail("CM58", "Reading texture WAD %s", fname (file)); WADRopenR(&pwad,file); entry=WADRfindEntry(&pwad,"TEXTURE2"); if(entry>=0) { EntryP=WADRreadEntry(&pwad,entry,&EntrySz); TXUreadTEXTURE("TEXTURE2", EntryP, EntrySz, NULL, 0, TRUE); Free(EntryP); NeedPNAME=TRUE; FoundOne=TRUE; } WADRclose(&pwad); } else ProgError("CM59", "Can't find texture list %s", file); } /*write texture*/ if(FoundOne==TRUE) { WADRalign4(&rwad); /*align entry on Int32 word*/ start= WADRposition(&rwad); size = TXUwriteTEXTUREtoWAD(&rwad); WADRdirAddEntry(&rwad,start,size,"TEXTURE2"); } TXUfree(); } } /* ** PNAME */ if(select&BTEXTUR) { if(NeedPNAME) /*write PNAME in PWAD*/ { /*write entry PNAME*/ Phase("CM41", "Making PNAMES"); WADRalign4(&rwad); /*align entry on Int32 word*/ start=WADRposition(&rwad); size =PNMwritePNAMEtoWAD(&rwad); WADRdirAddEntry(&rwad,start,size,"PNAMES"); } } /* ** ** sounds. all sounds entries */ if(select&BSOUND) { start=size=0; if(TXTseekSection(TXT,"SOUNDS")) { Phase("CM60", "Making sounds"); while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) { if(Repeat!=TRUE) { WADRalign4(&rwad); /*align entry on Int32 word*/ start=WADRposition(&rwad); if(MakeFileName(file,DataDir,"SOUNDS","",filenam,"TXT")==TRUE) { size=SNDcopyPCSoundInWAD(&rwad,file); Detail("CM62", "Reading PC sound from file %s", fname (file)); } else { if(MakeFileName(file,DataDir,"SOUNDS","",filenam,"WAV")==TRUE) { size=SNDcopyInWAD(&rwad,file,SNDWAV); } else if(MakeFileName(file,DataDir,"SOUNDS","",filenam,"AU")==TRUE) { size=SNDcopyInWAD(&rwad,file,SNDAU); } else if(MakeFileName(file,DataDir,"SOUNDS","",filenam,"VOC")==TRUE) { size=SNDcopyInWAD(&rwad,file,SNDVOC); } else if(CMPOcopyFromWAD(&size,&rwad,DataDir,"SOUNDS",name, filenam)!=TRUE) ProgError("CM63", "Can't find sound %s, AU or WAV or VOC",file); Detail("CM64", "Reading sound file %s", fname (file)); } } WADRdirAddEntry(&rwad,start,size,name); } } } /* ** ** Musics */ if(select&BMUSIC) { start=size=0; if(TXTseekSection(TXT,"MUSICS")) { Phase("CM65", "Making musics"); while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) { if(Repeat!=TRUE) { WADRalign4(&rwad); /*align entry on Int32 word*/ start=WADRposition(&rwad); /*Music*/ if(MakeFileName(file,DataDir,"MUSICS","",filenam,"MUS")==TRUE) { size=WADRwriteLump(&rwad,file); Detail("CM66", "Reading music file %s", fname (file)); } else if(CMPOcopyFromWAD(&size,&rwad,DataDir,"MUSICS",name, filenam)!=TRUE) ProgError("CM67", "Can't find music %s",file); } WADRdirAddEntry(&rwad,start,size,name); } } } /* ** ordinary graphics */ if(select&BGRAPHIC) { start=size=0; if(TXTseekSection(TXT,"GRAPHICS")) { Phase("CM70", "Making graphics"); while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,TRUE)==TRUE) { if(Repeat!=TRUE) { WADRalign4(&rwad); /*align entry on Int32 word*/ start=WADRposition(&rwad); Picture=CMPOloadPic(&size,&rwad,file,DataDir,"GRAPHICS",name, filenam,PGRAPH,X,Y); } WADRdirAddEntry(&rwad,start,size,name); } } } /* ** SS_START ** sprites ** SS_END */ if(select&BSPRITE) { start=size=0; if(TXTseekSection(TXT,"SPRITES")) { Phase("CM75", "Making sprites"); FoundOne=FALSE; while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,TRUE)==TRUE) { /* first sprite seen? */ if((Repeat!=TRUE)||(FoundOne!=TRUE)) { WADRalign4(&rwad); /*align entry on Int32 word*/ start=WADRposition(&rwad); if(FoundOne!=TRUE) { if(type==IWAD) WADRdirAddEntry(&rwad,start,0L,"S_START"); else WADRdirAddEntry(&rwad,start,0L,"SS_START"); } FoundOne=TRUE; CMPOloadPic(&size,&rwad,file,DataDir,"SPRITES",name, filenam,PSPRIT,X,Y); } WADRdirAddEntry(&rwad,start,size,name); } if(FoundOne==TRUE) { WADRalign4(&rwad); start=WADRposition(&rwad); if((type==IWAD)||(George==TRUE)) WADRdirAddEntry(&rwad,start,0L,"S_END"); else WADRdirAddEntry(&rwad,start,0L,"SS_END"); } } } /* ** Try to load patches ** even if no new textures (old patches could be redefined) */ /* write new patches in PWAD*/ /* read the name of the new textures and insert them*/ /* between P_START and P_END for future completion*/ if(select&BPATCH) { FoundOne=FALSE; /* ** First look for patches in [PATCHES] */ start=size=0; if(TXTseekSection(TXT,"PATCHES")) { Phase("CM80", "Making patches"); while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,TRUE)==TRUE) { if((Repeat!=TRUE)||(FoundOne!=TRUE)) { WADRalign4(&rwad); /*align entry on Int32 word*/ start=WADRposition(&rwad); if(FoundOne==FALSE) { if(type==IWAD) { WADRdirAddEntry(&rwad,start,0L,"P_START"); WADRdirAddEntry(&rwad,start,0L,"P1_START"); } else { WADRdirAddEntry(&rwad,start,0L,"PP_START"); } } FoundOne=TRUE; CMPOloadPic(&size,&rwad,file,DataDir,"PATCHES",name, filenam,PPATCH,X,Y); } WADRdirAddEntry(&rwad,start,size,name); } } /* ** Check if all the needed patches are defined. */ nbPatchs=PNMgetNbOfPatch(); for(p=0;p<nbPatchs;p++) { if(PNMisNew(p)!=TRUE) { continue;/*if old patch, forget it*/ } PNMgetPatchName(name,p); Normalise(filenam,name); /*search in main IWAD directory*/ if(WADRfindEntry(&iwad,name)>=0) { Output("Reusing DOOM entry %s as patch\n", lump_name (name)); } /*search in current PWAD*/ else if(WADRfindEntry(&rwad,name)<0) { /*PATCH not found in current WAD, load automatically **from the PATCH directory */ WADRalign4(&rwad); /*align entry on Int32 word*/ start=WADRposition(&rwad); Picture=CMPOloadPic(&size,&rwad,file,DataDir,"PATCHES",name, filenam,PPATCH,INVALIDINT,INVALIDINT); if(Picture!=PICNONE) { if(FoundOne==FALSE) { Phase("CM82", "Making patches"); if(type==IWAD) { WADRdirAddEntry(&rwad,start,0L,"P_START"); WADRdirAddEntry(&rwad,start,0L,"P1_START"); } else WADRdirAddEntry(&rwad,start,0L,"PP_START"); } FoundOne=TRUE; WADRdirAddEntry(&rwad,start,size,name); } } } if(FoundOne==TRUE) { WADRalign4(&rwad); /*align entry on Int32 word*/ start=WADRposition(&rwad); if(type==IWAD) { WADRdirAddEntry(&rwad,start,0L,"P1_END"); WADRdirAddEntry(&rwad,start,0L,"P2_START"); WADRdirAddEntry(&rwad,start,0L,"P2_END"); WADRdirAddEntry(&rwad,start,0L,"P3_START"); WADRdirAddEntry(&rwad,start,0L,"P3_END"); WADRdirAddEntry(&rwad,start,0L,"P_END"); } else WADRdirAddEntry(&rwad,start,0L,"PP_END"); } } /* ** clear off Pnames */ if(select&(BTEXTUR|BPATCH)) { PNMfree(); } /* FF_START ** Flats ** F_END AYM 1998-12-22 (was FF_END) */ if(select&BFLAT) { if(TXTseekSection(TXT,"FLATS")) { Phase("CM85", "Making flats"); FoundOne=FALSE; while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) { if((Repeat!=TRUE)||(FoundOne!=TRUE)) { WADRalign4(&rwad); /*align entry on Int32 word*/ start=WADRposition(&rwad); if(FoundOne==FALSE) { if(type==IWAD) { WADRdirAddEntry(&rwad,start,0L,"F_START"); WADRdirAddEntry(&rwad,start,0L,"F1_START"); } else WADRdirAddEntry(&rwad,start,0L,"FF_START"); } FoundOne=TRUE; CMPOloadPic(&size,&rwad,file,DataDir,"FLATS",name, filenam,PFLAT,INVALIDINT,INVALIDINT); } WADRdirAddEntry(&rwad,start,size,name); } if(FoundOne==TRUE) { start=WADRposition(&rwad); if(type==IWAD) { WADRdirAddEntry(&rwad,start,0L,"F1_END"); WADRdirAddEntry(&rwad,start,0L,"F2_START"); WADRdirAddEntry(&rwad,start,0L,"F2_END"); WADRdirAddEntry(&rwad,start,0L,"F3_START"); WADRdirAddEntry(&rwad,start,0L,"F3_END"); WADRdirAddEntry(&rwad,start,0L,"F_END"); } else WADRdirAddEntry(&rwad,start,0L,"F_END"); /* AYM 1998-12-22 */ } } } /* ** exit from graphic */ if(select&(BGRAPHIC|BSPRITE|BPATCH|BFLAT)) COLfree(); /* ** iwad not needed anymore */ WADRclose(&iwad); /* ** the end */ TXTcloseR(TXT); WADRwriteDir(&rwad, 1); /* write the WAD directory */ ProgErrorCancel(); WADRclose(&rwad); /*add some junk at end of wad file, for DEU 5.21*/ if(type==PWAD) AddSomeJunk(PWADname); }