DEADSOFTWARE

portability: avoid errors on some compilers
[flatwaifu.git] / src / common / wadres.c
1 #include <stdint.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <assert.h>
6 #include "common/wadres.h"
7 #include "common/streams.h"
8 #include "common/cp866.h"
10 typedef struct Entry {
11 long offset, size;
12 char name[8];
13 int f;
14 } Entry;
16 typedef struct Block {
17 int id;
18 int ref;
19 char data[];
20 } Block;
22 static int n_wads;
23 static int n_resources;
24 static Stream *wads[MAX_WADS];
25 static Entry resources[MAX_RESOURCES];
26 static Block *blocks[MAX_RESOURCES];
28 static int s_start, s_end;
30 static int check_header (Stream *r) {
31 char ident[4];
32 assert(r != NULL);
33 stream_setpos(r, 0); // !!!
34 stream_read(ident, 4, 1, r);
35 return (memcmp(ident, "IWAD", 4) == 0) || (memcmp(ident, "PWAD", 4) == 0);
36 }
38 int WADRES_addwad (Stream *r) {
39 assert(r != NULL);
40 if (n_wads < MAX_WADS && check_header(r)) {
41 wads[n_wads] = r;
42 n_wads += 1;
43 return 1;
44 } else {
45 return 0;
46 }
47 }
49 static int WADRES_addresource (const Entry *e) {
50 int i;
51 assert(e != NULL);
52 for (i = 0; i < n_resources; ++i) {
53 if (cp866_strncasecmp(resources[i].name, e->name, 8) == 0) {
54 memcpy(&resources[i], e, sizeof(Entry));
55 return i;
56 }
57 }
58 if (n_resources < MAX_RESOURCES) {
59 memcpy(&resources[n_resources], e, sizeof(Entry));
60 n_resources += 1;
61 return n_resources - 1;
62 }
63 return -1;
64 }
66 static int WADRES_read (int f) {
67 int ok = 1;
68 int32_t n, dir, i;
69 Stream *r = wads[f];
70 stream_setpos(r, 4); // skip magic
71 n = stream_read32(r);
72 dir = stream_read32(r);
73 stream_setpos(r, dir);
74 for (i = 0; ok && i < n; ++i) {
75 Entry e;
76 e.offset = stream_read32(r);
77 e.size = stream_read32(r);
78 e.f = f;
79 stream_read(e.name, 8, 1, r);
80 ok = WADRES_addresource(&e) != -1;
81 }
82 return ok;
83 }
85 int WADRES_rehash (void) {
86 int i;
87 int ok = 1;
88 for (i = 0; i < n_wads; ++i) {
89 if (!WADRES_read(i)) {
90 ok = 0;
91 }
92 }
93 s_start = WADRES_find("S_START");
94 s_end = WADRES_find("S_END");
95 return ok;
96 }
98 int WADRES_find (const char name[8]) {
99 int i = n_resources - 1;
100 while (i >= 0 && cp866_strncasecmp(name, resources[i].name, 8) != 0) {
101 i -= 1;
103 return i;
106 int WADRES_maxids (void) {
107 return n_resources;
110 int WADRES_findsprite (const char n[4], int s, int d, char *dir) {
111 int i;
112 s += 'A';
113 d += '0';
114 for (i = s_start + 1; i < s_end; i++) {
115 char a, b;
116 char *wn = resources[i].name;
117 if (cp866_strncasecmp(wn, n, 4) == 0 && (wn[4] == s || wn[6] == s)) {
118 a = wn[4] == s ? wn[5] : 0;
119 b = wn[6] == s ? wn[7] : 0;
120 if (a == '0' || b == '0' || a == d || b == d) {
121 if (dir != NULL) {
122 *dir = (a != '0' && b == '0') || (a != d && b == d);
124 return i;
128 return -1;
131 Stream *WADRES_getbasereader (int id) {
132 assert(id >= 0 && id < n_resources);
133 return wads[resources[id].f];
136 long WADRES_getoffset (int id) {
137 assert(id >= 0 && id < n_resources);
138 return resources[id].offset;
141 long WADRES_getsize (int id) {
142 assert(id >= 0 && id < n_resources);
143 return resources[id].size;
146 void WADRES_getname (int id, char *name) {
147 assert(id >= 0 && id < n_resources);
148 strncpy(name, resources[id].name, 8);
151 void WADRES_getdata (int id, void *data) {
152 long pos;
153 Stream *r;
154 assert(id >= 0 && id < n_resources);
155 r = wads[resources[id].f];
156 pos = stream_getpos(r);
157 stream_setpos(r, resources[id].offset);
158 stream_read(data, resources[id].size, 1, r);
159 stream_setpos(r, pos);
162 void *WADRES_lock (int id) {
163 assert(id >= -1 && id < MAX_RESOURCES);
164 if (id >= 0) {
165 Block *x = blocks[id];
166 if (x) {
167 x->ref += 1;
168 return x->data;
169 } else {
170 x = malloc(sizeof(Block) + WADRES_getsize(id));
171 if (x) {
172 x->id = id;
173 x->ref = 1;
174 WADRES_getdata(id, x->data);
175 blocks[id] = x;
176 return x->data;
180 return NULL;
183 void WADRES_unlock (void *data) {
184 int id;
185 Block *x;
186 if (data) {
187 x = (Block*)((uintptr_t)data - sizeof(Block));
188 id = x->id;
189 assert(id >= 0 && id < MAX_RESOURCES);
190 x->ref -= 1;
191 assert(x->ref >= 0);
192 #if 0
193 if (x->ref == 0) {
194 blocks[id] = NULL;
195 free(x);
197 #endif
201 int WADRES_locked (int id) {
202 assert(id >= -1 && id < MAX_RESOURCES);
203 return (id >= 0) && (blocks[id] != NULL) && (blocks[id]->ref >= 1);
206 int WADRES_was_locked (int id) {
207 assert(id >= -1 && id < MAX_RESOURCES);
208 return (id >= 0) && (blocks[id] != NULL) && (blocks[id]->ref >= 0);