DEADSOFTWARE

Add graphics convertor master
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Sun, 16 Apr 2017 11:25:38 +0000 (14:25 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Sun, 16 Apr 2017 11:25:38 +0000 (14:25 +0300)
.gitignore [new file with mode: 0644]
Makefile
README
spr.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..acb4590
--- /dev/null
@@ -0,0 +1,2 @@
+BANK*
+MEMLIST.BIN
index 2fa0e39e51ad63b51a48686168fe426728164e09..4e2c79d44201c6a9e7780ff5a3c48157c12ba569 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-all: unpk dis
+all: unpk dis spr
 
 unpk:
        cc -o unpk unpk.c
@@ -6,11 +6,11 @@ unpk:
 dis:
        cc -o dis dis.c dis_aw.c dis_intel.c dis_att.c
 
-#view:
-#      cc -lSDL2 -o view view.c view_vid.c
+spr:
+       cc -o spr spr.c
 
 distclean:
-       rm -f unpk dis view
+       rm -f unpk dis spr
 
 workclean:
-       rm -f file*.snd file*.mus file*.bmp file*.pal file*.obj file*.spr file*.unk
+       rm -f file*.snd file*.mus file*.bmp file*.pal file*.obj file*.spr file*.unk file*.spr_*.svg
diff --git a/README b/README
index 5e3ab353fdd4a16f881fc842d0c389bfea7ccc90..7e3116e028d5afbe0a9bb50e1971a4093555220a 100644 (file)
--- a/README
+++ b/README
@@ -12,8 +12,11 @@ dis [-a | -i | -u] [-p] OBJECT OUTFILE
        -a | -i | -u - Generate with AnotherWorld/Intel/AT&T syntax
        -p - print opcode address
 
+spr INPUT
+       Convert game graphics into SVG.
+
 Licence: GPLv3
 
 Links:
        https://www.anotherworld.fr/anotherworld_uk/another_world.htm
-       https://github.com/cyxx/rawgl
\ No newline at end of file
+       https://github.com/cyxx/rawgl
diff --git a/spr.c b/spr.c
new file mode 100644 (file)
index 0000000..b983eb7
--- /dev/null
+++ b/spr.c
@@ -0,0 +1,287 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+/*
+ * Another World graphics convertor
+ *   Only DOS version are supported
+ */
+
+#define MAX_POLYGONS 4096
+#define MAX_GROUPS 2048
+#define MSG_USAGE "usage: spr INPUT\n"
+#define MSG_OPENERR "can't open file %s.\n"
+#define MSG_WRITEERR "can't create file %s.\n"
+
+struct polygoninfo {
+       uint16_t offset;
+       uint8_t color, w, h, num;
+       struct {
+               uint8_t x, y;
+       } point[256];
+};
+
+struct groupinfo {
+       uint16_t offset;
+       uint8_t x, y, num;
+       struct {
+               uint16_t offset;
+               uint8_t x, y;
+               uint16_t color;
+               bool group;
+               int id;
+       } child[256];
+};
+
+FILE *fp;
+
+uint8_t *data;
+uint16_t datalen, datapc;
+
+struct polygoninfo poly[MAX_POLYGONS];
+int polycount;
+struct groupinfo group[MAX_GROUPS];
+int groupcount;
+
+uint8_t vbyte() {
+       return data[datapc++];
+}
+
+uint16_t vword() {
+       return (vbyte() << 8) | vbyte();
+}
+
+int findpoly(uint16_t offset) {
+       for(int i = 0; i < polycount; i++) {
+               if(poly[i].offset == offset)
+                       return i;
+       }
+       
+       return -1;
+}
+
+int findgroup(uint16_t offset) {
+       for(int i = 0; i < groupcount; i++) {
+               if(group[i].offset == offset)
+                       return i;
+       }
+       
+       return -1;
+}
+
+void process(bool readgroup) {
+       uint16_t adr = datapc;
+       uint8_t type = vbyte();
+       
+       if(type >= 0xC0) {
+               uint8_t color = (type & 0x80) ? (type & 0x3F) : 0x0;
+               uint8_t w = vbyte();
+               uint8_t h = vbyte();
+               uint8_t num = vbyte();
+               
+               if(!readgroup) {
+                       poly[polycount].offset = adr;
+                       poly[polycount].color = color;
+                       poly[polycount].w = w;
+                       poly[polycount].h = h;
+                       poly[polycount].num = num;
+               }
+               
+               for(int i = 0; i < num; i++) {
+                       uint8_t x = vbyte();
+                       uint8_t y = vbyte();
+                       
+                       if(!readgroup) {
+                               poly[polycount].point[i].x = x;
+                               poly[polycount].point[i].y = y;
+                       }
+               }
+               
+               if(!readgroup)
+                       ++polycount;
+       } else {
+               type &= 0x3F;
+               if(type == 2) {
+                       uint8_t x = vbyte();
+                       uint8_t y = vbyte();
+                       uint8_t childs = vbyte();
+                       
+                       if(readgroup) {
+                               group[groupcount].offset = adr;
+                               group[groupcount].x = x;
+                               group[groupcount].y = y;
+                               group[groupcount].num = childs;
+                       }
+                       
+                       for(int i = 0; i <= childs; i++) {
+                               uint16_t offset = vword();
+                               uint8_t xx = vbyte();
+                               uint8_t yy = vbyte();
+                               uint16_t color = 0xF;
+                               
+                               if(offset & 0x8000)
+                                       color = vword() & 0x7F;
+                               
+                               offset = (offset & 0x7FFF) << 1;
+                               
+                               if(readgroup) {
+                                       group[groupcount].child[i].offset = offset;
+                                       group[groupcount].child[i].x = xx;
+                                       group[groupcount].child[i].y = yy;
+                                       group[groupcount].child[i].color = color;
+                               }
+                       }
+                       
+                       if(readgroup)
+                               ++groupcount;
+               } else {
+                       printf("invalid type %u\n", type);
+                       exit(1);
+               }
+       }
+}
+
+void linkgroups() {
+       for(int i = 0; i < groupcount; i++) {
+               for(int j = 0; j < group[i].num; i++) {
+                       uint16_t offset = group[i].child[j].offset;
+                       
+                       group[i].child[j].group = false;
+                       int id = findpoly(offset);
+                       if(id == -1) {
+                               group[i].child[j].group = true;
+                               id = findgroup(offset);
+                               if(id == -1) {
+                                       printf("grouped polygon 0x%X not found\n", offset);
+                                       exit(1);
+                               }
+                       }
+                       
+                       group[i].child[j].id = id;
+               }
+       }
+}
+
+uint8_t *loadfile(const char *name, uint16_t *size) {
+       FILE *fp;
+       if((fp = fopen(name, "r")) == NULL) {
+               printf(MSG_OPENERR, name);
+               exit(1);
+       }
+       
+       fseek(fp, 0, SEEK_END);
+       int s = ftell(fp);
+       fseek(fp, 0, SEEK_SET);
+       
+       uint8_t *ptr = malloc(s);
+       fread(ptr, s, 1, fp);
+       fclose(fp);
+       
+       *size = s;
+       return ptr;
+}
+
+void svg_poly(char *prefix, int id) {
+       char name[256];
+       snprintf(name, 256, "%s_p%i.svg", prefix, id);
+       if((fp = fopen(name, "w")) == NULL) {
+                       printf(MSG_WRITEERR, name);
+                       exit(1);
+       }
+       
+       int w = poly[id].w;
+       int h = poly[id].h;
+       
+       if(w == 0)
+               w = 1;
+       if(h == 0)
+               h = 1;
+               
+       printf("1px is p%i\n", id);
+       
+       fprintf(fp, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n");
+       fprintf(fp, "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"%upx\" height=\"%upx\">\n", w, h);
+       
+       fprintf(fp, "<polygon fill=\"black\" points=\"");
+       if(poly[id].num == 1) {
+               fprintf(fp, "%u,%u ", poly[id].point[0].x, poly[id].point[0].y);
+       } else if(poly[id].num == 2) {
+               int i = 0;
+               int j = 1;
+               if (poly[id].point[j].x > poly[id].point[i].x) {
+                       fprintf(fp, "%u,%u ", poly[id].point[i].x, poly[id].point[i].y);
+                       fprintf(fp, "%u,%u ", poly[id].point[j].x + 1, poly[id].point[j].y);
+               } else {
+                       fprintf(fp, "%u,%u ", poly[id].point[j].x, poly[id].point[j].y);
+                       fprintf(fp, "%u,%u ", poly[id].point[i].x + 1, poly[id].point[i].y);
+               }
+       } else {
+               for(int i = 0; i < poly[id].num / 2; i++) {
+                       int j = poly[id].num - 1 - i;
+                       if (poly[id].point[j].x > poly[id].point[i].x) {
+                               fprintf(fp, "%u,%u ", poly[id].point[i].x, poly[id].point[i].y);
+                               fprintf(fp, "%u,%u ", poly[id].point[j].x + 1, poly[id].point[j].y);
+                       } else {
+                               fprintf(fp, "%u,%u ", poly[id].point[j].x, poly[id].point[j].y);
+                               fprintf(fp, "%u,%u ", poly[id].point[i].x + 1, poly[id].point[i].y);
+                       }
+               }
+       }
+       fprintf(fp, "\"/>\n");
+       
+       fprintf(fp, "</svg>");
+       
+       fclose(fp);
+}
+
+void svg_group(char *prefix, int id) {
+       char name[256];
+       snprintf(name, 256, "%s_g%i.svg", prefix, id);
+       if((fp = fopen(name, "w")) == NULL) {
+                       printf(MSG_WRITEERR, name);
+                       exit(1);
+       }
+       
+       fprintf(fp, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n");
+       fprintf(fp, "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" width=\"320px\" height=\"200px\">\n");
+       
+       for(int i = 0; i < group[id].num; i++) {
+               char c = group[id].child[i].group ? 'g' : 'p';
+               
+               fprintf(fp, "<image xlink:href=\"%s_%c%i.svg\" x=\"%i\" y=\"%i\"/>", prefix, c, group[id].child[i].id, group[id].child[i].x, group[id].child[i].y);
+       }
+       
+       fprintf(fp, "</svg>");
+       
+       fclose(fp);
+}
+
+int main(int argc, char **argv) {
+       if(argc != 2) {
+               printf(MSG_USAGE);
+               exit(1);
+       }
+
+       data = loadfile(argv[1], &datalen);
+       
+       while(datapc < datalen)
+               process(false);
+       
+       datapc = 0;
+       while(datapc < datalen)
+               process(true);
+       
+       linkgroups();
+       
+       free(data);
+       
+       for(int i = 0; i < polycount; i++)
+               svg_poly(argv[1], i);
+       
+       for(int i = 0; i < groupcount; i++)
+               svg_group(argv[1], i);
+       
+       return 0;
+}