10 typedef struct Entry
{
16 typedef struct Block
{
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
) {
33 stream_setpos(r
, 0); // !!!
34 stream_read(ident
, 4, 1, r
);
35 return (memcmp(ident
, "IWAD", 4) == 0) || (memcmp(ident
, "PWAD", 4) == 0);
38 int WADRES_addwad (Stream
*r
) {
40 if (n_wads
< MAX_WADS
&& check_header(r
)) {
49 static int WADRES_addresource (const Entry
*e
) {
51 for (int i
= 0; i
< n_resources
; ++i
) {
52 if (cp866_strncasecmp(resources
[i
].name
, e
->name
, 8) == 0) {
53 memcpy(&resources
[i
], e
, sizeof(Entry
));
57 if (n_resources
< MAX_RESOURCES
) {
58 memcpy(&resources
[n_resources
], e
, sizeof(Entry
));
60 return n_resources
- 1;
65 static int WADRES_read (int f
) {
67 stream_setpos(r
, 4); // skip magic
68 int32_t n
= stream_read32(r
);
69 int32_t dir
= stream_read32(r
);
70 stream_setpos(r
, dir
);
72 for (int32_t i
= 0; ok
&& i
< n
; ++i
) {
74 e
.offset
= stream_read32(r
);
75 e
.size
= stream_read32(r
);
77 stream_read(e
.name
, 8, 1, r
);
78 ok
= WADRES_addresource(&e
) != -1;
83 int WADRES_rehash (void) {
85 for (int i
= 0; i
< n_wads
; ++i
) {
86 if (!WADRES_read(i
)) {
90 s_start
= WADRES_find("S_START");
91 s_end
= WADRES_find("S_END");
95 int WADRES_find (const char name
[8]) {
96 int i
= n_resources
- 1;
97 while (i
>= 0 && cp866_strncasecmp(name
, resources
[i
].name
, 8) != 0) {
103 int WADRES_maxids (void) {
107 int WADRES_findsprite (const char n
[4], int s
, int d
, char *dir
) {
110 for (int i
= s_start
+ 1; i
< s_end
; i
++) {
112 char *wn
= resources
[i
].name
;
113 if (cp866_strncasecmp(wn
, n
, 4) == 0 && (wn
[4] == s
|| wn
[6] == s
)) {
114 a
= wn
[4] == s
? wn
[5] : 0;
115 b
= wn
[6] == s
? wn
[7] : 0;
116 if (a
== '0' || b
== '0' || a
== d
|| b
== d
) {
118 *dir
= (a
!= '0' && b
== '0') || (a
!= d
&& b
== d
);
127 Stream
*WADRES_getbasereader (int id
) {
128 assert(id
>= 0 && id
< n_resources
);
129 return wads
[resources
[id
].f
];
132 long WADRES_getoffset (int id
) {
133 assert(id
>= 0 && id
< n_resources
);
134 return resources
[id
].offset
;
137 long WADRES_getsize (int id
) {
138 assert(id
>= 0 && id
< n_resources
);
139 return resources
[id
].size
;
142 void WADRES_getname (int id
, char *name
) {
143 assert(id
>= 0 && id
< n_resources
);
144 strncpy(name
, resources
[id
].name
, 8);
147 void WADRES_getdata (int id
, void *data
) {
148 assert(id
>= 0 && id
< n_resources
);
149 Stream
*r
= wads
[resources
[id
].f
];
150 long pos
= stream_getpos(r
);
151 stream_setpos(r
, resources
[id
].offset
);
152 stream_read(data
, resources
[id
].size
, 1, r
);
153 stream_setpos(r
, pos
);
156 void *WADRES_lock (int id
) {
157 assert(id
>= -1 && id
< MAX_RESOURCES
);
159 Block
*x
= blocks
[id
];
164 x
= malloc(sizeof(Block
) + WADRES_getsize(id
));
168 WADRES_getdata(id
, x
->data
);
177 void WADRES_unlock (void *data
) {
179 Block
*x
= data
- sizeof(Block
);
181 assert(id
>= 0 && id
< MAX_RESOURCES
);
193 int WADRES_locked (int id
) {
194 assert(id
>= -1 && id
< MAX_RESOURCES
);
195 return (id
>= 0) && (blocks
[id
] != NULL
) && (blocks
[id
]->ref
>= 1);
198 int WADRES_was_locked (int id
) {
199 assert(id
>= -1 && id
< MAX_RESOURCES
);
200 return (id
>= 0) && (blocks
[id
] != NULL
) && (blocks
[id
]->ref
>= 0);