doom

a minimalistic implementation of doom
git clone git://ssnf.xyz/doom
Log | Files | Refs

w_wad.c (3999B)


      1 #include <ctype.h>
      2 #include <sys/types.h>
      3 #include <string.h>
      4 #include <stdarg.h>
      5 #include <unistd.h>
      6 #include <malloc.h>
      7 #include <fcntl.h>
      8 #include <sys/stat.h>
      9 #include <alloca.h>
     10 
     11 #include "doomdef.h"
     12 #include "i_system.h"
     13 #include "z_zone.h"
     14 #include "w_wad.h"
     15 
     16 #define O_BINARY		0
     17 
     18 lumpinfo_t* lumpinfo_g;
     19 void**      lumpcache_g;
     20 char*       reloadname;
     21 int         numlumps_g;
     22 int         reloadlump;
     23 int         info[2500][10];
     24 int         profilecount;
     25 
     26 void
     27 unpack(uchar** buf, char* fmt, ...)
     28 {
     29 	va_list ap;
     30 	char*   p, *q, *s;
     31 	ulong*  l;
     32 	uchar*	b;
     33 	uint    i;
     34 	
     35 	p = q = fmt;
     36 	b = *buf;
     37 	i = 0;
     38 	va_start(ap, fmt);
     39 	for (;*p;) {
     40 		switch (*p++) {
     41 			case 'l':
     42 				l = va_arg(ap, ulong*);
     43 				*l = *b++;
     44 				*l += *b++ << 8;
     45 				*l += *b++ << 16;
     46 				*l += *b++ << 24;
     47 				break;
     48 			case 's':
     49 				s = va_arg(ap, char*);
     50 				if (*p++ == ':') {
     51 					i = *p - 0x30;
     52 
     53 					for (;isdigit(*(++p));) {
     54 						i *= 10;
     55 						i += *p - 0x30;
     56 					}
     57 					while (i--)
     58 						*s++ = *b++;
     59 				}
     60 		}
     61 	}
     62 	*buf = b;
     63 }
     64 
     65 void
     66 unpack_wadinfo(uchar** buf, wadinfo_t* p)
     67 {
     68 	unpack(buf, "s:4ll", p->identification, &p->numlumps, &p->infotableofs);
     69 }
     70 
     71 void
     72 unpack_filelump(uchar** buf, filelump_t* p)
     73 {
     74 	unpack(buf, "lls:8", &p->filepos, &p->size, p->name);
     75 }
     76 
     77 void
     78 W_AddFile(char* filename)
     79 {
     80 	lumpinfo_t* lumpinfo_p;
     81 	filelump_t* filelump_p;
     82 	wadinfo_t   header;
     83 	FILE*       f;
     84 	uchar*      file, *p;
     85 	ulong       l;
     86 	unsigned    i;
     87 	int         startlump;
     88 
     89 	f = fopen(filename, "r");
     90 	if (!f) {
     91 		printf(" couldn't open %s\n", filename);
     92 		return;
     93 	}
     94 	printf(" adding %s\n",filename);
     95 	fseek(f, 0, SEEK_END);
     96 	l = ftell(f);
     97 	p = file = malloc(l * sizeof(*file) + 1);
     98 	fseek(f, 0, SEEK_SET);
     99 	fread(file, l, 1, f);
    100 	fclose(f);
    101 	startlump = numlumps_g;
    102 	unpack_wadinfo(&p, &header);
    103 	numlumps_g += header.numlumps;
    104 	lumpinfo_g = realloc(lumpinfo_g, numlumps_g * sizeof(lumpinfo_t));
    105 	if (!lumpinfo_g)
    106 		I_Error("Couldn't realloc lumpinfo_g");
    107 	filelump_p = alloca(header.numlumps * sizeof(filelump_t));
    108 	p = file + header.infotableofs;
    109 	for (i = 0; i < header.numlumps; ++i)
    110 		unpack_filelump(&p, filelump_p+i);
    111 	lumpinfo_p = lumpinfo_g + startlump;
    112 	for (i = startlump; i < numlumps_g; ++i) {
    113 		lumpinfo_p[i].cache = file;
    114 		lumpinfo_p[i].position = filelump_p[i].filepos;
    115 		lumpinfo_p[i].size = filelump_p[i].size;
    116 		strncpy(lumpinfo_p[i].name, filelump_p[i].name, 8);
    117 	}
    118 }
    119 
    120 void
    121 W_InitMultipleFiles(char** filenames)
    122 {
    123 	int size;
    124 
    125 	numlumps_g = 0;
    126 	lumpinfo_g = malloc(1);
    127 	for (;*filenames; ++filenames)
    128 		W_AddFile(*filenames);
    129 	if (!numlumps_g)
    130 		I_Error("W_InitFiles: no files found");
    131 	size = numlumps_g * sizeof(*lumpcache_g);
    132 	lumpcache_g = malloc(size);
    133 	if (!lumpcache_g)
    134 		I_Error("Couldn't allocate lumpcache_g");
    135 	memset(lumpcache_g, 0, size);
    136 }
    137 
    138 int
    139 W_CheckNumForName(char* name)
    140 {
    141 	lumpinfo_t*	p;
    142 	char        buf[8], *q;
    143 
    144 	strncpy(buf, name, 8);
    145 	for (q = buf; *q; ++q)
    146 		if (*q > 0x60)
    147 			*q -= 0x20;
    148 	for (p = lumpinfo_g + numlumps_g - 1; p >= lumpinfo_g; --p)
    149 		if (!memcmp(buf, p->name, 8))
    150 			return p - lumpinfo_g;
    151 	return -1;
    152 }
    153 
    154 int
    155 W_GetNumForName(char* name)
    156 {
    157 	int i;
    158 
    159 	i = W_CheckNumForName(name);
    160 	if (i == -1)
    161 		I_Error("W_GetNumForName: %s not found!", name);
    162 	return i;
    163 }
    164 
    165 int
    166 W_LumpLength(int lump)
    167 {
    168 	if (lump >= numlumps_g)
    169 		I_Error("W_LumpLength: %i >= numlumps_g", lump);
    170 	return lumpinfo_g[lump].size;
    171 }
    172 
    173 void
    174 W_ReadLump(int lump, void* dest)
    175 {
    176 	lumpinfo_t* l;
    177 	uchar*      src;
    178 
    179 	if (lump >= numlumps_g)
    180 		I_Error("W_ReadLump: %i >= numlumps_g",lump);
    181 	l = lumpinfo_g + lump;
    182 	src = l->cache + l->position;
    183 	memcpy(dest, src, l->size);
    184 }
    185 
    186 void*
    187 W_CacheLumpNum(int lump, int tag)
    188 {
    189 	if ((unsigned)lump >= numlumps_g)
    190 		I_Error("W_CacheLumpNum: %i >= numlumps_g",lump);
    191 	if (!lumpcache_g[lump]) {
    192 		Z_Malloc(W_LumpLength(lump), tag, &lumpcache_g[lump]);
    193 		W_ReadLump(lump, lumpcache_g[lump]);
    194 	} else
    195 		Z_ChangeTag(lumpcache_g[lump],tag);
    196 	return lumpcache_g[lump];
    197 }
    198 
    199 void*
    200 W_CacheLumpName(char* name, int tag)
    201 {
    202 	return W_CacheLumpNum(W_GetNumForName(name), tag);
    203 }