DEADSOFTWARE

portability: avoid errors on some compilers
[flatwaifu.git] / src / common / wadres.c
index 99524cc1ed81ff2725e05221799f6151f6cf1a46..6ff943ab03d876ba682ab436f22bc6af66b29567 100644 (file)
@@ -1,10 +1,11 @@
 #include <stdint.h>
 #include <string.h>
+#include <stdlib.h>
 #include <assert.h>
 
 #include "common/wadres.h"
 #include "common/streams.h"
-#include "cp866.h"
+#include "common/cp866.h"
 
 typedef struct Entry {
   long offset, size;
@@ -12,20 +13,29 @@ typedef struct Entry {
   int f;
 } Entry;
 
+typedef struct Block {
+  int id;
+  int ref;
+  char data[];
+} Block;
+
 static int n_wads;
 static int n_resources;
-static Reader *wads[MAX_WADS];
+static Stream *wads[MAX_WADS];
 static Entry resources[MAX_RESOURCES];
+static Block *blocks[MAX_RESOURCES];
 
-static int check_header (Reader *r) {
-  assert(r != NULL);
+static int s_start, s_end;
+
+static int check_header (Stream *r) {
   char ident[4];
-  r->setpos(r, 0);
+  assert(r != NULL);
+  stream_setpos(r, 0); // !!!
   stream_read(ident, 4, 1, r);
   return (memcmp(ident, "IWAD", 4) == 0) || (memcmp(ident, "PWAD", 4) == 0);
 }
 
-int WADRES_addwad (Reader *r) {
+int WADRES_addwad (Stream *r) {
   assert(r != NULL);
   if (n_wads < MAX_WADS && check_header(r)) {
     wads[n_wads] = r;
@@ -37,8 +47,9 @@ int WADRES_addwad (Reader *r) {
 }
 
 static int WADRES_addresource (const Entry *e) {
+  int i;
   assert(e != NULL);
-  for (int i = 0; i < n_resources; ++i) {
+  for (i = 0; i < n_resources; ++i) {
     if (cp866_strncasecmp(resources[i].name, e->name, 8) == 0) {
       memcpy(&resources[i], e, sizeof(Entry));
       return i;
@@ -52,16 +63,19 @@ static int WADRES_addresource (const Entry *e) {
   return -1;
 }
 
-static int WADRES_read (Reader *r) {
-  r->setpos(r, 4); // skip magic
-  int32_t n = stream_read32(r);
-  int32_t dir = stream_read32(r);
-  r->setpos(r, dir);
+static int WADRES_read (int f) {
   int ok = 1;
-  for (int32_t i = 0; ok && i < n; ++i) {
+  int32_t n, dir, i;
+  Stream *r = wads[f];
+  stream_setpos(r, 4); // skip magic
+  n = stream_read32(r);
+  dir = stream_read32(r);
+  stream_setpos(r, dir);
+  for (i = 0; ok && i < n; ++i) {
     Entry e;
     e.offset = stream_read32(r);
     e.size = stream_read32(r);
+    e.f = f;
     stream_read(e.name, 8, 1, r);
     ok = WADRES_addresource(&e) != -1;
   }
@@ -69,12 +83,15 @@ static int WADRES_read (Reader *r) {
 }
 
 int WADRES_rehash (void) {
+  int i;
   int ok = 1;
-  for (int i = 0; i < n_wads; ++i) {
-    if (!WADRES_read(wads[i])) {
+  for (i = 0; i < n_wads; ++i) {
+    if (!WADRES_read(i)) {
       ok = 0;
     }
   }
+  s_start = WADRES_find("S_START");
+  s_end = WADRES_find("S_END");
   return ok;
 }
 
@@ -90,7 +107,28 @@ int WADRES_maxids (void) {
   return n_resources;
 }
 
-Reader *WADRES_getbasereader (int id) {
+int WADRES_findsprite (const char n[4], int s, int d, char *dir) {
+  int i;
+  s += 'A';
+  d += '0';
+  for (i = s_start + 1; i < s_end; i++) {
+    char a, b;
+    char *wn = resources[i].name;
+    if (cp866_strncasecmp(wn, n, 4) == 0 && (wn[4] == s || wn[6] == s)) {
+      a = wn[4] == s ? wn[5] : 0;
+      b = wn[6] == s ? wn[7] : 0;
+      if (a == '0' || b == '0' || a == d || b == d) {
+        if (dir != NULL) {
+          *dir = (a != '0' && b == '0') || (a != d && b == d);
+        }
+        return i;
+      }
+    }
+  }
+  return -1;
+}
+
+Stream *WADRES_getbasereader (int id) {
   assert(id >= 0 && id < n_resources);
   return wads[resources[id].f];
 }
@@ -111,10 +149,61 @@ void WADRES_getname (int id, char *name) {
 }
 
 void WADRES_getdata (int id, void *data) {
+  long pos;
+  Stream *r;
   assert(id >= 0 && id < n_resources);
-  Reader *r = wads[resources[id].f];
-  long pos = r->getpos(r);
-  r->setpos(r, resources[id].offset);
+  r = wads[resources[id].f];
+  pos = stream_getpos(r);
+  stream_setpos(r, resources[id].offset);
   stream_read(data, resources[id].size, 1, r);
-  r->setpos(r, pos);
+  stream_setpos(r, pos);
+}
+
+void *WADRES_lock (int id) {
+  assert(id >= -1 && id < MAX_RESOURCES);
+  if (id >= 0) {
+    Block *x = blocks[id];
+    if (x) {
+      x->ref += 1;
+      return x->data;
+    } else {
+      x = malloc(sizeof(Block) + WADRES_getsize(id));
+      if (x) {
+        x->id = id;
+        x->ref = 1;
+        WADRES_getdata(id, x->data);
+        blocks[id] = x;
+        return x->data;
+      }
+    }
+  }
+  return NULL;
+}
+
+void WADRES_unlock (void *data) {
+  int id;
+  Block *x;
+  if (data) {
+    x = (Block*)((uintptr_t)data - sizeof(Block));
+    id = x->id;
+    assert(id >= 0 && id < MAX_RESOURCES);
+    x->ref -= 1;
+    assert(x->ref >= 0);
+#if 0
+    if (x->ref == 0) {
+      blocks[id] = NULL;
+      free(x);
+    }
+#endif
+  }
+}
+
+int WADRES_locked (int id) {
+  assert(id >= -1 && id < MAX_RESOURCES);
+  return (id >= 0) && (blocks[id] != NULL) && (blocks[id]->ref >= 1);
+}
+
+int WADRES_was_locked (int id) {
+  assert(id >= -1 && id < MAX_RESOURCES);
+  return (id >= 0) && (blocks[id] != NULL) && (blocks[id]->ref >= 0);
 }