DEADSOFTWARE

wadres: fix initialization
[flatwaifu.git] / src / common / wadres.c
1 #include <stdint.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <assert.h>
6 #include "wadres.h"
7 #include "streams.h"
8 #include "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 check_header (Stream *r) {
29 assert(r != NULL);
30 char ident[4];
31 stream_setpos(r, 0); // !!!
32 stream_read(ident, 4, 1, r);
33 return (memcmp(ident, "IWAD", 4) == 0) || (memcmp(ident, "PWAD", 4) == 0);
34 }
36 int WADRES_addwad (Stream *r) {
37 assert(r != NULL);
38 if (n_wads < MAX_WADS && check_header(r)) {
39 wads[n_wads] = r;
40 n_wads += 1;
41 return 1;
42 } else {
43 return 0;
44 }
45 }
47 static int WADRES_addresource (const Entry *e) {
48 assert(e != NULL);
49 for (int i = 0; i < n_resources; ++i) {
50 if (cp866_strncasecmp(resources[i].name, e->name, 8) == 0) {
51 memcpy(&resources[i], e, sizeof(Entry));
52 return i;
53 }
54 }
55 if (n_resources < MAX_RESOURCES) {
56 memcpy(&resources[n_resources], e, sizeof(Entry));
57 n_resources += 1;
58 return n_resources - 1;
59 }
60 return -1;
61 }
63 static int WADRES_read (int f) {
64 Stream *r = wads[f];
65 stream_setpos(r, 4); // skip magic
66 int32_t n = stream_read32(r);
67 int32_t dir = stream_read32(r);
68 stream_setpos(r, dir);
69 int ok = 1;
70 for (int32_t i = 0; ok && i < n; ++i) {
71 Entry e;
72 e.offset = stream_read32(r);
73 e.size = stream_read32(r);
74 e.f = f;
75 stream_read(e.name, 8, 1, r);
76 ok = WADRES_addresource(&e) != -1;
77 }
78 return ok;
79 }
81 int WADRES_rehash (void) {
82 int ok = 1;
83 for (int i = 0; i < n_wads; ++i) {
84 if (!WADRES_read(i)) {
85 ok = 0;
86 }
87 }
88 return ok;
89 }
91 int WADRES_find (const char name[8]) {
92 int i = n_resources - 1;
93 while (i >= 0 && cp866_strncasecmp(name, resources[i].name, 8) != 0) {
94 i -= 1;
95 }
96 return i;
97 }
99 int WADRES_maxids (void) {
100 return n_resources;
103 Stream *WADRES_getbasereader (int id) {
104 assert(id >= 0 && id < n_resources);
105 return wads[resources[id].f];
108 long WADRES_getoffset (int id) {
109 assert(id >= 0 && id < n_resources);
110 return resources[id].offset;
113 long WADRES_getsize (int id) {
114 assert(id >= 0 && id < n_resources);
115 return resources[id].size;
118 void WADRES_getname (int id, char *name) {
119 assert(id >= 0 && id < n_resources);
120 strncpy(name, resources[id].name, 8);
123 void WADRES_getdata (int id, void *data) {
124 assert(id >= 0 && id < n_resources);
125 Stream *r = wads[resources[id].f];
126 long pos = stream_getpos(r);
127 stream_setpos(r, resources[id].offset);
128 stream_read(data, resources[id].size, 1, r);
129 stream_setpos(r, pos);
132 void *WADRES_lock (int id) {
133 assert(id >= -1 && id < MAX_RESOURCES);
134 if (id >= 0) {
135 Block *x = blocks[id];
136 if (x) {
137 x->ref += 1;
138 return x->data;
139 } else {
140 x = malloc(sizeof(Block) + WADRES_getsize(id));
141 if (x) {
142 x->id = id;
143 x->ref = 1;
144 WADRES_getdata(id, x->data);
145 blocks[id] = x;
146 return x->data;
150 return NULL;
153 void WADRES_unlock (void *data) {
154 if (data) {
155 Block *x = data - sizeof(Block);
156 int id = x->id;
157 assert(id >= 0 && id < MAX_RESOURCES);
158 x->ref -= 1;
159 assert(x->ref >= 0);
160 #if 0
161 if (x->ref == 0) {
162 blocks[id] = NULL;
163 free(x);
165 #endif
169 int WADRES_locked (int id) {
170 assert(id >= -1 && id < MAX_RESOURCES);
171 return (id >= 0) && (blocks[id] != NULL) && (blocks[id]->ref >= 1);
174 int WADRES_was_locked (int id) {
175 assert(id >= -1 && id < MAX_RESOURCES);
176 return (id >= 0) && (blocks[id] != NULL) && (blocks[id]->ref >= 0);