-
Notifications
You must be signed in to change notification settings - Fork 1
/
wad.c
112 lines (92 loc) · 3.1 KB
/
wad.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "wad.h"
#include "texture.h"
#include "utils.h"
// for "exit"
#include <stdlib.h>
// for "memcmp"
#include <string.h>
// for "tolower"
#include <ctype.h>
struct s_wad * read_wad(const char* path)
{
struct dir_entry
{
unsigned int offset;
unsigned int diskSize;
unsigned int size;
unsigned char type;
unsigned char compression;
char name[16];
};
unsigned char buf[40];
// open the provided file
FILE *fp = u_fopen(path, "rb");
// read WAD3 header
u_fread(buf, 12, fp);
if ( memcmp(buf, "WAD3", 4) ) {
fprintf(stderr, "%s does not appear to be in WAD3 format\n", path );
exit(EXIT_FAILURE);
}
unsigned int numEntries = parseU32(buf+4);
unsigned int dirOffset = parseU32(buf+8);
// initialize a structure to hold our data
struct s_wad* ret = (struct s_wad *)u_calloc(sizeof(struct s_wad));
// copy base path into name
// HL tends to use lowercased WAD names and uppercased texture names
const char *base = path + strlen(path);
do {
base--;
} while (base > path && *base != '/' && *base != '\\');
ret->name = (char *)u_calloc(strlen(base) + 1);
for (unsigned int i = 0; i < strlen(base); i ++)
ret->name[i] = (char)tolower(base[i]);
unsigned int texture_limit = 0;
// read directory entries
printf("WAD3 '%s': %u entries beginning at offset %u\n", ret->name, numEntries, dirOffset);
u_fseek( fp, dirOffset );
struct dir_entry* directory = (struct dir_entry *)u_calloc(numEntries * sizeof(struct dir_entry));
for (unsigned int i = 0; i < numEntries; i ++)
{
u_fread(buf, 32, fp);
directory[i].offset = parseU32(buf);
directory[i].diskSize = parseU32(buf+4);
directory[i].size = parseU32(buf+8);
directory[i].type = buf[12];
directory[i].compression = buf[13];
// two dummy bytes skipped here
strncpy(directory[i].name, (const char*)buf+16, 15);
}
// iterate through directory and read every texture
for (unsigned int i = 0; i < numEntries; i ++)
{
// reject some entries for problems
if (directory[i].type != 0x43) {
fprintf( stderr, "WAD %s, entry %u ('%s'): skipping object type %u\n", path, i, directory[i].name, directory[i].type );
continue;
}
else if (directory[i].compression) {
fprintf( stderr, "WAD %s, entry %u ('%s'): compressed entries are not supported\n", path, i, directory[i].name );
continue;
}
else if (directory[i].diskSize != directory[i].size) {
fprintf( stderr, "WAD %s, entry %u ('%s'): diskSize %u != size %u\n", path, i, directory[i].name, directory[i].diskSize, directory[i].size );
continue;
}
// get the miptex from this point
struct s_texture *tex = read_texture(fp, directory[i].offset);
// add it to the list
if (ret->texture_count == texture_limit) {
texture_limit = (texture_limit << 1) + 1;
ret->textures = (struct s_texture **)u_realloc(ret->textures, texture_limit * sizeof(struct s_texture*));
}
ret->textures[ret->texture_count] = tex;
ret->texture_count ++;
}
// shrink texture list
//ret->textures = u_realloc(ret->textures, ret->texture_count * sizeof(struct s_texture*));
// we are done with the directory now
free(directory);
// also done with the ret
fclose(fp);
return ret;
}