1 /*
2  *-----------------------------------------------------------------------------
3  *
4  * $Log: wadread.c,v $
5  *
6  * Revision 2.0  1999/01/24 00:52:12  Andre Wertmann
7  * changed to work with Heretic
8  *
9  * Revision 1.7  1998/06/23 13:23:06  rafaj
10  * findlump() now always returns defined int as result
11  *
12  * Revision 1.6  1998/05/17 00:13:58  chris
13  * removed debug messages; cleaned up
14  *
15  * Revision 1.5  1998/04/24 23:37:36  chris
16  * read_pwads() and support functions - now sounds from PWAD
17  * files are played
18  *
19  * Revision 1.4  1998/04/24 21:09:04  chris
20  * ID's released version
21  *
22  * Revision 1.3  1997/01/30 19:54:23  b1
23  * Final reformatting run. All the remains (ST, W, WI, Z).
24  *
25  * Revision 1.2  1997/01/21 19:00:10  b1
26  * First formatting run:
27  *  using Emacs cc-mode.el indentation for C++ now.
28  *
29  * Revision 1.1  1997/01/19 17:22:51  b1
30  * Initial check in DOOM sources as of Jan. 10th, 1997
31  *
32  *
33  * DESCRIPTION:
34  *	WAD and Lump I/O, the second.
35  *	This time for soundserver only.
36  *	Welcome to Department of Redundancy Department. Again :-).
37  *
38  *-----------------------------------------------------------------------------
39  */
40 
41 
42 #include <stdlib.h>
43 #include <fcntl.h>
44 #include <sys/stat.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <ctype.h>
49 #include <unistd.h>
50 #include <assert.h>
51 
52 #include "soundsrv.h"
53 #include "wadread.h"
54 
55 #ifndef HOMEDIR
56 #define HOMEDIR "/.heretic"
57 #endif /* HOMEDIR */
58 
59 
60 int*		sfxlengths;
61 
62 typedef struct wadinfo_struct
63 {
64   char	identification[4];
65   int   numlumps;
66   int	infotableofs;
67 } wadinfo_t;
68 
69 typedef struct filelump_struct
70 {
71   int		filepos;
72   int		size;
73   char	        name[8];
74 } filelump_t;
75 
76 typedef struct lumpinfo_struct
77 {
78   int		handle;
79   int		filepos;
80   int		size;
81   char	        name[8];
82 } lumpinfo_t;
83 
84 lumpinfo_t*	lumpinfo;
85 int		numlumps;
86 
87 void**		lumpcache;
88 
89 
90 #define stricmp strcasecmp
91 #define strnicmp strncasecmp
92 
93 
94 /*
95  * Something new.
96  * This version of w_wad.c does handle endianess.
97  */
98 #ifdef __BIG_ENDIAN__
99 
100 #define SHORT(x) ((short)( \
101 (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) \
102 | \
103 (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) ))
104 
105 #define LONG(x) ((int)( \
106 (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) \
107 | \
108 (((unsigned int)(x) & (unsigned int)0x0000ff00UL) <<  8) \
109 | \
110 (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >>  8) \
111 | \
112 (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))
113 
114 #else
115 #define LONG(x) (x)
116 #define SHORT(x) (x)
117 #endif
118 
119 
120 /* Way too many of those... */
derror(char * msg)121 static void derror(char* msg)
122 {
123   fprintf(stderr, "\nwadread error: %s\n", msg);
124   exit(-1);
125 }
126 
127 
strupr(char * s)128 void strupr (char *s)
129 {
130   while (*s)
131     *s++ = toupper(*s);
132 }
133 
filelength(int handle)134 int filelength (int handle)
135 {
136   struct stat	fileinfo;
137 
138   if (fstat (handle,&fileinfo) == -1)
139     fprintf (stderr, "Error fstating\n");
140 
141   return fileinfo.st_size;
142 }
143 
accesswad(char * wadname)144 char* accesswad( char* wadname)
145 {
146     char* fn;
147     char* envhome;
148 
149     if ((envhome = getenv("HERETICHOME")) != NULL)
150 	{
151 	    fn = (char*) malloc(strlen(envhome)+strlen("/")+strlen(wadname)+1);
152 	    assert(fn);
153 	    sprintf(fn, "%s/%s", envhome, wadname);
154 	    if (!access(fn, R_OK))
155 		return fn;
156 	    else
157 		free(fn);
158 	}
159     if ((envhome = getenv("HOME")) != NULL)
160 	{
161 	    fn = (char*) malloc(strlen(envhome)+strlen(HOMEDIR"/")
162 				+strlen(wadname)+1);
163 	    assert(fn);
164 	    sprintf(fn, "%s"HOMEDIR"/%s", envhome, wadname);
165 	    if (!access(fn, R_OK))
166 		return fn;
167 	    else
168 		free(fn);
169 	}
170     if ((envhome = getenv("PATH")))
171         {
172             char *path = strdup(envhome), *curentry;
173             assert(path);
174             while (strlen(path))
175                 {
176                     if (!(curentry = strrchr(path, ':')))
177                         curentry = path;
178                     else
179                         *curentry++ = 0;
180                     fn = (char*)malloc(strlen(curentry)+19+strlen(wadname));   /* Add space for /, ../share/heretic/ */
181                     assert(fn);
182                     sprintf(fn, "%s/%s", curentry, wadname);
183                     if (!access(fn, R_OK))
184                         {
185                             free(path);
186                             return fn;
187                         }
188                     /* check ../share/heretic */
189                     sprintf(fn, "%s/../share/heretic/%s", curentry, wadname);
190                     if (!access(fn, R_OK))
191                         {
192                             free(path);
193                             return fn;
194                         }
195                     free(fn);
196                     *curentry = 0;
197                 }
198             free(path);
199         }
200     if (!access(wadname, R_OK))
201 	    return wadname;
202 
203     fn = (char*) malloc(strlen("./")+strlen(wadname)+1);
204     assert(fn);
205     sprintf(fn,"%s", wadname);
206     if (!access(fn ,R_OK))
207 	return fn;
208     else
209 	free(fn);
210 
211     return NULL;
212 }
213 
openwad(char * wadname)214 void openwad(char* wadname)
215 {
216 
217   int		wadfile;
218   int		tableoffset;
219   int		tablelength;
220   int		tablefilelength;
221   int		i;
222   wadinfo_t	header;
223   filelump_t*	filetable;
224 
225   /* open and read the wadfile header */
226   wadfile = open(wadname, O_RDONLY);
227 
228   if (wadfile < 0)
229     derror("Could not open wadfile");
230 
231   read(wadfile, &header, sizeof header);
232 
233   if (strncmp(header.identification, "IWAD", 4))
234     derror("wadfile has weirdo header");
235 
236   numlumps = LONG(header.numlumps);
237   tableoffset = LONG(header.infotableofs);
238   tablelength = numlumps * sizeof(lumpinfo_t);
239   tablefilelength = numlumps * sizeof(filelump_t);
240   lumpinfo = (lumpinfo_t *) malloc(tablelength);
241   assert(lumpinfo);
242   filetable = (filelump_t *) ((char*)lumpinfo + tablelength - tablefilelength);
243 
244   /* get the lumpinfo table */
245   lseek(wadfile, tableoffset, SEEK_SET);
246   read(wadfile, filetable, tablefilelength);
247 
248   /* process the table to make the endianness right and shift it down */
249   for (i=0 ; i<numlumps ; i++)
250     {
251       strncpy(lumpinfo[i].name, filetable[i].name, 8);
252       lumpinfo[i].handle = wadfile;
253       lumpinfo[i].filepos = LONG(filetable[i].filepos);
254       lumpinfo[i].size = LONG(filetable[i].size);
255       /* fprintf(stderr, "lump [%.8s] exists\n", lumpinfo[i].name); */
256     }
257 
258 }
259 
loadlump(char * lumpname,int * size)260 void* loadlump( char* lumpname, int* size )
261 {
262   int		i;
263   void*	        lump;
264 
265   for (i=0 ; i<numlumps ; i++)
266     {
267       if (!strncasecmp(lumpinfo[i].name, lumpname, 8))
268 	break;
269     }
270 
271   if (i == numlumps)
272     {
273       /*
274        * fprintf(stderr,
275        *   "Could not find lumpname [%s]\n", lumpname);
276        */
277       lump = 0;
278     }
279   else
280     {
281 	lump = (void *) malloc(lumpinfo[i].size);
282 	assert(lump);
283 	lseek(lumpinfo[i].handle, lumpinfo[i].filepos, SEEK_SET);
284 	read(lumpinfo[i].handle, lump, lumpinfo[i].size);
285 	*size = lumpinfo[i].size;
286     }
287   return lump;
288 }
289 
getsfx(char * sfxname,int * len)290 void* getsfx( char* sfxname, int* len )
291 {
292   unsigned char*	sfx;
293   unsigned char*	paddedsfx;
294   int			i;
295   int			size;
296   int			paddedsize;
297   char		        name[20];
298 
299   /* sprintf(name, "ds%s", sfxname); */
300   sprintf(name, "%s", sfxname);
301 #ifdef _DEBUGSOUND
302   fprintf(stderr, "Name: %s ; Sfxname: %s\n", name, sfxname );
303 #endif
304 
305   sfx = (unsigned char *) loadlump(name, &size);
306 #ifdef _DEBUGSOUND
307   fprintf(stderr, "Sfxsize: %d\n", size );
308 #endif
309 
310   /* pad the sound effect out to the mixing buffer size */
311   paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT;
312   paddedsfx = (unsigned char *) realloc(sfx, paddedsize+8);
313   for (i=size ; i<paddedsize+8 ; i++)
314     paddedsfx[i] = 128;
315 
316   *len = paddedsize;
317   return (void *) (paddedsfx + 8);
318 }
319 
findlump(char * lumpname)320 static int findlump(char *lumpname)
321 {
322   int i;
323 
324   for (i=0; i<numlumps; i++)
325     if (!strnicmp(lumpname,lumpinfo[i].name,6))
326       return(i);
327   return(-1);
328 }
329 
do_pwad(char * wadname)330 static void do_pwad(char* wadname)
331 {
332   int		wadfile;
333   int		tableoffset;
334   int		tablelength;
335   int		tablefilelength;
336   int		i,j;
337   int           _numlumps;
338   lumpinfo_t    *_lumpinfo;
339   wadinfo_t	header;
340   filelump_t*	filetable;
341 
342   /* open and read the wadfile header */
343   wadfile = open(wadname, O_RDONLY);
344 
345   if (wadfile < 0)
346     derror("Could not open wadfile");
347 
348   read(wadfile, &header, sizeof header);
349 
350   if (strncmp(header.identification, "PWAD", 4) &&
351       strncmp(header.identification, "IWAD", 4)) /* e.g. tnt.wad is a IWAD */
352     derror("wadfile has weirdo header");
353 
354   _numlumps = LONG(header.numlumps);
355   tableoffset = LONG(header.infotableofs);
356   tablelength = numlumps * sizeof(lumpinfo_t);
357   tablefilelength = numlumps * sizeof(filelump_t);
358   _lumpinfo = (lumpinfo_t *) malloc(tablelength);
359   assert(_lumpinfo);
360   filetable = (filelump_t *) ((char*)_lumpinfo + tablelength - tablefilelength);
361 
362   /* get the lumpinfo table */
363   lseek(wadfile, tableoffset, SEEK_SET);
364   read(wadfile, filetable, tablefilelength);
365 
366   /* process the table to make the endianness right and shift it down */
367   for (i=0 ; i<_numlumps ; i++)
368     {
369       if (strnicmp(filetable[i].name,"DS",2)) continue;
370       j=findlump(filetable[i].name);
371       if (j == -1) {
372 	char lname[7];
373 	strncpy(lname,filetable[i].name,6);
374 	fprintf(stderr,"sndserver: unidentified lump '%s' -- ignored\n",lname);
375 	continue;
376       }
377       else {
378 	char lname[7],lname2[7];
379 	strncpy(lname,filetable[i].name,6);
380 	strncpy(lname2,lumpinfo[j].name,6);
381 	lname[6]=lname2[6]=0;
382 	/* fprintf(stderr,"sndserver: replacing '%s' '%s'\n",lname,lname2); */
383       }
384       lumpinfo[j].handle = wadfile;
385       lumpinfo[j].filepos = LONG(filetable[i].filepos);
386       lumpinfo[j].size = LONG(filetable[i].size);
387       /* fprintf(stderr, "lump [%.8s] exists\n", lumpinfo[i].name); */
388     }
389   free(_lumpinfo);
390 }
391 
392 /*
393  * inspired/stolen by/from read_extra_wads() from musserver-1.22
394  * this shouldn't be needed, doom should tell sndserver  which
395  * wads to use.
396  */
397 
read_pwads(void)398 void read_pwads(void)
399 {
400     pid_t ppid;
401     char filename[100];
402     FILE *fp;
403 
404     ppid=getppid();    /* heretic's pid */
405     sprintf(filename,"/proc/%d/cmdline",(int)ppid);
406 
407     /* fprintf(stderr,"sndserver: in read_pwads\n"); */
408 
409     if ((fp = fopen(filename, "r"))) {
410       char *s;
411       static char buff[256];
412       int len, active = 0;
413       len = fread(buff, 1, 256, fp);
414       fclose(fp);
415       for (s = buff; s < buff+len;) {
416 	if (*s == '-')
417 	  active = 0;
418 	if (active)
419                 do_pwad(s);
420 	else if (!strcmp(s, "-file"))
421 	  active = 1;
422             s += strlen(s) + 1;
423       }
424     }
425 }
426 
427