DEADSOFTWARE

first commit
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Wed, 13 Jul 2016 17:31:11 +0000 (20:31 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Wed, 13 Jul 2016 17:31:11 +0000 (20:31 +0300)
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
dis.c [new file with mode: 0644]
dis.h [new file with mode: 0644]
dis_att.c [new file with mode: 0644]
dis_aw.c [new file with mode: 0644]
dis_intel.c [new file with mode: 0644]
dis_syn.h [new file with mode: 0644]
unpk.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..2fa0e39
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+all: unpk dis
+
+unpk:
+       cc -o unpk unpk.c
+
+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
+
+distclean:
+       rm -f unpk dis view
+
+workclean:
+       rm -f file*.snd file*.mus file*.bmp file*.pal file*.obj file*.spr file*.unk
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..5e3ab35
--- /dev/null
+++ b/README
@@ -0,0 +1,19 @@
+Another World (Out of This World) tools:
+       unpk - Resource unpacker
+       dis - Script disassembler
+
+unpk
+       No options. Just pwd into directory with MEMLIST.BIN and BANKs and run
+       programm.
+
+dis [-a | -i | -u] [-p] OBJECT OUTFILE
+       OBJECT - Binary script(fileXX.obj)
+       OUTFILE - Out assembler listing
+       -a | -i | -u - Generate with AnotherWorld/Intel/AT&T syntax
+       -p - print opcode address
+
+Licence: GPLv3
+
+Links:
+       https://www.anotherworld.fr/anotherworld_uk/another_world.htm
+       https://github.com/cyxx/rawgl
\ No newline at end of file
diff --git a/dis.c b/dis.c
new file mode 100644 (file)
index 0000000..e259e8f
--- /dev/null
+++ b/dis.c
@@ -0,0 +1,309 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "dis.h"
+#include "dis_syn.h"
+
+/*
+ * Another World script disassembler
+ *   Only DOS version are supported
+ */
+
+#define MSG_USAGE "usage: disasm [-a | -i | -u] [-p] OBJECT OUTFILE\n"
+#define MSG_OPENERR "can't open file %s.\n"
+#define MSG_WRITEERR "can't create file %s.\n"
+#define MSG_INVALIDOP "invalid opcode 0x%X\n"
+#define MSG_INVALIDJMP "invalid jump opcode %u\n"
+
+char *input, *output;
+
+FILE *fp;
+
+uint8_t *code;
+uint16_t codesize;
+uint16_t pc, adr;
+
+struct labelinfo label[MAX_LABEL];
+int labelnum;
+bool printcode;
+bool printadr;
+
+void (*printlabel)(int);
+void (*printopcode)(uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, int);
+
+static uint8_t ubyte() {
+       return code[pc++];
+}
+
+static uint16_t uword() {
+       return (ubyte() << 8) | ubyte();
+}
+
+static int addlabel(uint16_t adr, int type) {
+       for(int i = 0; i < labelnum; i++) {
+               if(label[i].adr == adr)
+                       return i;
+       }
+       
+       label[labelnum].adr = adr;
+       label[labelnum].type = type;
+       ++labelnum;
+       return labelnum - 1;
+}
+
+static void fndlabel() {
+       for(int i = 0; i < labelnum; i++) {
+               if(label[i].adr == pc) {
+                       printlabel(i);
+                       return;
+               }
+       }
+       
+       printlabel(-1);
+}
+
+static void step() {
+       adr = pc;
+
+       if(printcode)
+               fndlabel();
+
+       uint8_t op = ubyte();
+       uint16_t x = -1, y = -1, z = -1, w = -1;
+       int label = -666;
+       
+       if(op & 0x80) { /* spr */
+               w = (((op << 8) | ubyte()) << 1) & 0x7FFF;
+               x = ubyte();
+               y = ubyte();
+       } else if(op & 0x40) { /* spr */
+               w = (uword() << 1) & 0x7FFF;
+               
+               x = ubyte();
+               if((op & 48) == 0)
+                       x = (x << 8) | ubyte();
+               else if((op & 48) == 48)
+                       x = x + 256;
+               
+               y = ubyte();
+               if((op & 12) == 0)
+                       y = (y << 8) | ubyte();
+               
+               if((op & 3) == 1 || (op & 3) == 2)
+                       z = ubyte();
+               else
+                       z = 64;
+       } else {
+               switch(op) {
+               case 0x0: /* seti */
+                       x = ubyte();
+                       y = uword();
+                       break;
+               case 0x1: /* set */
+                       x = ubyte();
+                       y = ubyte();
+                       break;
+               case 0x2: /* add */
+                       x = ubyte();
+                       y = ubyte();
+                       break;
+               case 0x3: /* addi */
+                       x = ubyte();
+                       y = uword();
+                       break;
+               case 0x4: /* jsr */
+                       x = uword();
+                       label = addlabel(x, LT_CALL);
+                       break;
+               case 0x5: /* return */
+                       break;
+               case 0x6: /* break */
+                       break;
+               case 0x7: /* jmp */
+                       x = uword();
+                       label = addlabel(x, LT_JUMP);
+                       break;
+               case 0x8: /* setvec */
+                       x = ubyte();
+                       y = uword();
+                       label = addlabel(y, LT_VEC);
+                       break;
+               case 0x9: /* dbra */
+                       x = ubyte();
+                       y = uword();
+                       label = addlabel(y, LT_JUMP);
+                       break;
+               case 0xA: /* si */
+                       w = ubyte();
+                       x = ubyte();
+                       
+                       if(w & 0x80)
+                               y = ubyte();
+                       else if(w & 0x40)
+                               y = uword();
+                       else
+                               y = ubyte();
+                       
+                       if((w & 7) > 5) {
+                               printf(MSG_INVALIDJMP, w & 0x7);
+                               exit(1);
+                       }
+                       
+                       z = uword();
+                       label = addlabel(z, LT_JUMP);
+                       break;
+               case 0xB: /* fade */
+                       x = uword() >> 8;
+                       break;
+               case 0xC: /* vec */
+                       x = ubyte();
+                       y = ubyte();            
+                       z = ubyte();
+                       break;
+               case 0xD: /* setws */
+                       x = ubyte();
+                       break;
+               case 0xE: /* clr */
+                       x = ubyte();
+                       y = ubyte();
+                       break;
+               case 0xF: /* copy */
+                       x = ubyte();
+                       y = ubyte();
+                       break;
+               case 0x10: /* show */
+                       x = ubyte();
+                       break;
+               case 0x11: /* bigend */
+                       break;
+               case 0x12: /* text */
+                       z = uword();
+                       x = ubyte();
+                       y = ubyte();
+                       w = ubyte();
+                       break;
+               case 0x13: /* sub */
+                       x = ubyte();
+                       y = ubyte();
+                       break;
+               case 0x14: /* andi */
+                       x = ubyte();
+                       y = uword();
+                       break;
+               case 0x15: /* ori */
+                       x = ubyte();
+                       y = uword();
+                       break;
+               case 0x16: /* lsl */
+                       x = ubyte();
+                       y = uword();
+                       break;
+               case 0x17: /* lsr */
+                       x = ubyte();
+                       y = uword();
+                       break;
+               case 0x18: /* play */
+                       z = uword();
+                       x = ubyte();
+                       y = ubyte();
+                       w = ubyte();
+                       break;
+               case 0x19: /* load */
+                       x = uword();
+                       break;
+               case 0x1A: /* song */
+                       x = uword();
+                       y = uword();
+                       z = ubyte();
+                       break;
+               default:
+                       printf(MSG_INVALIDOP, op);
+                       exit(1);
+               }
+       }
+       
+       if(printcode)
+               printopcode(op, x, y, z, w, label);
+}
+
+static void readarg(int argc, char **argv) {
+       if(argc < 3)
+               goto error;
+       
+       printadr = false;
+       printlabel = aw_printlabel;
+       printopcode = aw_printopcode;
+       
+       int i = 1;
+       while((i < argc) && (argv[i][0] == '-')) {
+               if(strcmp("-a", argv[i]) == 0) {
+                       printlabel = aw_printlabel;
+                       printopcode = aw_printopcode;
+               } else if(strcmp("-i", argv[i]) == 0) {
+                       printlabel = intel_printlabel;
+                       printopcode = intel_printopcode;
+               } else if(strcmp("-u", argv[i]) == 0) {
+                       printlabel = att_printlabel;
+                       printopcode = att_printopcode;
+               } else if(strcmp("-p", argv[i]) == 0) {
+                       printadr = true;
+               } else {
+                       goto error;
+               }
+               
+               ++i;
+       }
+       
+       if((argc - i) != 2)
+               goto error;
+               
+       input = argv[i];
+       output = argv[i + 1];
+       return;
+       
+error:
+       printf(MSG_USAGE);
+       exit(1);        
+}
+
+int main(int argc, char **argv) {
+       readarg(argc, argv);
+               
+       if((fp = fopen(input, "r")) == NULL) {
+               printf(MSG_OPENERR, input);
+               exit(1);
+       }
+       
+       fseek(fp, 0, SEEK_END);
+       codesize = ftell(fp);
+       fseek(fp, 0, SEEK_SET);
+       
+       code = malloc(codesize);
+       fread(code, codesize, 1, fp);
+       fclose(fp);
+       
+       if((fp = fopen(output, "w")) == NULL) {
+               printf(MSG_WRITEERR, output);
+               exit(1);
+       }
+       
+       labelnum = 0;
+       
+       pc = 0;
+       printcode = false;
+       while(pc < codesize)
+               step(); /* read labels */
+       
+       pc = 0;
+       printcode = true;
+       while(pc < codesize)
+               step(); /* print code */
+       
+       fclose(fp);
+       free(code);
+       
+       return 0;
+}
diff --git a/dis.h b/dis.h
new file mode 100644 (file)
index 0000000..97a8a21
--- /dev/null
+++ b/dis.h
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#define MAX_LABEL 4096
+
+#define LT_JUMP 0
+#define LT_CALL 1
+#define LT_VEC 2
+
+struct labelinfo {
+       uint16_t adr;
+       int type;
+};
+
+extern FILE *fp;
+extern uint16_t adr;
+extern struct labelinfo label[MAX_LABEL];
+extern bool printadr;
diff --git a/dis_att.c b/dis_att.c
new file mode 100644 (file)
index 0000000..4e6c28c
--- /dev/null
+++ b/dis_att.c
@@ -0,0 +1,227 @@
+#include <stdio.h>
+#include <stdint.h>
+#include "dis.h"
+
+/*
+ * AT&T style target
+ * 
+ * This target uses another mnemonics:
+ *   spr = spr1, spr2
+ *   mov = set, seti
+ *   add = add, addi
+ *   jsr = jsr
+ *   ret = return
+ *   wait = break
+ *   jmp = jmp
+ *   setv = setvec
+ *   jnz = dbra
+ *   je, jne, jg, jge, jl, jle = si (=, !=, >, >=, <, <=)
+ *   pal = fade
+ *   vec = vec
+ *   page = setws
+ *   clr = clr
+ *   copy = copy
+ *   show = show
+ *   kill = bigend
+ *   text = text
+ *   sub = sub
+ *   and = andi
+ *   or = ori
+ *   shl = lsl
+ *   shr = lsr
+ *   snd = play
+ *   ld = load
+ *   mus = song
+ */
+
+void att_printlabel(int i) {
+       if(i != -1) {
+               if(label[i].type != LT_JUMP && adr != 0)
+                       fputc('\n', fp);
+               
+               if(label[i].type == LT_CALL)
+                       fprintf(fp, "# Procedure code\n");
+               else if(label[i].type == LT_VEC)
+                       fprintf(fp, "# Task code\n");
+               
+               fprintf(fp, ".L%X:\n", i);
+       }
+       
+       if(printadr)
+               fprintf(fp, "/* %5u */", adr);
+       
+       fprintf(fp, "\t");
+}
+
+void att_printopcode(uint16_t op, uint16_t x, uint16_t y, uint16_t z, uint16_t w, int label) {
+       char *s;
+       char c1[16], c2[16], c3[16];
+       
+       if(op & 0x80) {
+               fprintf(fp, "spr\t0x%x, $%u, $%u\n", w, x, y);
+       } else if(op & 0x40) {
+               char *seg = "";
+               
+               switch(op & 48) {
+               case 0:
+                       snprintf(c1, 16, "$%i", (int16_t)x);
+                       break;
+               case 16:
+                       snprintf(c1, 16, "%%v%u", x);
+                       break;
+               case 32:
+                       snprintf(c1, 16, "$%u", x);
+                       break;
+               case 48:
+                       snprintf(c1, 16, "%%%u", x+256);
+                       break;
+               }
+               
+               switch(op & 12) {
+               case 0:
+                       snprintf(c2, 16, "$%i", (int16_t)y);
+                       break;
+               case 4:
+                       snprintf(c2, 16, "%%v%u", y);
+                       break;
+               case 8:
+               case 12:
+                       snprintf(c2, 16, "$%u", y);
+                       break;
+               }
+               
+               switch(op & 3) {
+               case 0:
+                       snprintf(c3, 16, "$64");
+                       break;
+               case 1:
+                       snprintf(c3, 16, "%%v%u", z);
+                       break;
+               case 2:
+                       snprintf(c3, 16, "$%u", z);
+                       break;
+               case 3:
+                       seg = "(%vid2)";
+                       snprintf(c3, 16, "$64");
+                       break;
+               }
+               
+               fprintf(fp, "spr\t0x%x%s, %s, %s, %s\n", w, seg, c1, c2, c3);
+       } else {
+               switch(op) {
+               case 0x0:
+                       fprintf(fp, "mov\t$%i, %%v%u\n", (int16_t)y, x);
+                       break;
+               case 0x1:
+                       fprintf(fp, "mov\t%%v%u, %%v%u\n", y, x);
+                       break;
+               case 0x2:
+                       fprintf(fp, "add\t%%v%u, %%v%u\n", y, x);
+                       break;
+               case 0x3:
+                       fprintf(fp, "add\t$%u, %%v%u\n", y, x);
+                       break;
+               case 0x4:
+                       fprintf(fp, "jsr\t.L%X\n", label);
+                       break;
+               case 0x5:
+                       fprintf(fp, "ret\n");
+                       break;
+               case 0x6:
+                       fprintf(fp, "wait\n");
+                       break;
+               case 0x7:
+                       fprintf(fp, "jmp\t.L%X\n", label);
+                       break;
+               case 0x8:
+                       fprintf(fp, "setv\t$%u, .L%X\n", x, label);
+                       break;
+               case 0x9:
+                       fprintf(fp, "jnz\t%%v%u, .L%X\n", x, label);
+                       break;
+               case 0xA:               
+                       if(w & 0x80)
+                               snprintf(c1, 16, "%%v%u", y);
+                       else if(w & 0x40)
+                               snprintf(c1, 16, "$%i", (int16_t)y);
+                       else
+                               snprintf(c1, 16, "$%u", y);
+                       
+                       switch(w & 0x7) {
+                       case 0:
+                               s = "je";
+                               break;
+                       case 1:
+                               s = "jne";
+                               break;
+                       case 2:
+                               s = "jg";
+                               break;
+                       case 3:
+                               s = "jge";
+                               break;
+                       case 4:
+                               s = "jl";
+                               break;
+                       case 5:
+                               s = "jle";
+                               break;
+                       default:
+                               s = "unk_jmp";
+                       }
+                       
+                       fprintf(fp, "%s\t%%v%u, %s, .L%X\n", s, x, c1, label);
+                       break;
+               case 0xB:
+                       fprintf(fp, "pal\t$%u\n", x);
+                       break;
+               case 0xC:
+                       fprintf(fp, "vec\t$%u, $%u, $%u\n", x, y, z);
+                       break;
+               case 0xD:
+                       fprintf(fp, "page\t$%u\n", x);
+                       break;
+               case 0xE:
+                       fprintf(fp, "clr\t$%u, $%u\n", x, y);
+                       break;
+               case 0xF:
+                       fprintf(fp, "copy\t$%u, $%u\n", x, y);
+                       break;
+               case 0x10:
+                       fprintf(fp, "show\t$%u\n", x);
+                       break;
+               case 0x11:
+                       fprintf(fp, "kill\n");
+                       break;
+               case 0x12:
+                       fprintf(fp, "text\t$%u, $%u, $%u, $%u\n", z, x, y, w);
+                       break;
+               case 0x13:
+                       fprintf(fp, "sub\t%%v%u, %%v%u\n", y, x);
+                       break;
+               case 0x14:
+                       fprintf(fp, "and\t$%u, %%v%u\n", y, x);
+                       break;
+               case 0x15:
+                       fprintf(fp, "or\t$%u, %%v%u\n", y, x);
+                       break;
+               case 0x16:
+                       fprintf(fp, "shl\t$%u, %%v%u\n", y, x);
+                       break;
+               case 0x17:
+                       fprintf(fp, "shr\t$%u, %%v%u\n", y, x);
+                       break;
+               case 0x18:
+                       fprintf(fp, "snd\t$%u, $%u, $%u, $%u\n", z, x, y, w);
+                       break;
+               case 0x19:
+                       fprintf(fp, "ld\t$%u\n", x);
+                       break;
+               case 0x1A:
+                       fprintf(fp, "mus\t$%u, $%u, $%u\n", x, y, z);
+                       break;
+               default:
+                       fprintf(fp, "unk_%x\n", op);
+               }
+       }
+}
diff --git a/dis_aw.c b/dis_aw.c
new file mode 100644 (file)
index 0000000..66803ad
--- /dev/null
+++ b/dis_aw.c
@@ -0,0 +1,192 @@
+#include <stdio.h>
+#include <stdint.h>
+#include "dis.h"
+
+/*
+ * Eric Chahi's style target
+ *    i.e. native Another World script syntax
+ */
+
+void aw_printlabel(int i) {
+       if(printadr)
+               fprintf(fp, "%u\t", adr);
+                       
+       if(i == -1)
+               fprintf(fp, "\t");
+       else
+               fprintf(fp, "L%i\t", i);
+}
+
+void aw_printopcode(uint16_t op, uint16_t x, uint16_t y, uint16_t z, uint16_t w, int label) {
+       char *s;
+       char c1[16], c2[16], c3[16];
+       
+       if(op & 0x80) {
+               fprintf(fp, "spr1\t%u\t%u\t%u\n", w, x, y);
+       } else if(op & 0x40) {
+               char seg = '1';
+               
+               switch(op & 48) {
+               case 0:
+                       snprintf(c1, 16, "%i", (int16_t)x);
+                       break;
+               case 16:
+                       snprintf(c1, 16, "v%u", x);
+                       break;
+               case 32:
+                       snprintf(c1, 16, "%u", x);
+                       break;
+               case 48:
+                       snprintf(c1, 16, "%u", x+256);
+                       break;
+               }
+               
+               switch(op & 12) {
+               case 0:
+                       snprintf(c2, 16, "%i", (int16_t)y);
+                       break;
+               case 4:
+                       snprintf(c2, 16, "v%u", y);
+                       break;
+               case 8:
+               case 12:
+                       snprintf(c2, 16, "%u", y);
+                       break;
+               }
+               
+               switch(op & 3) {
+               case 0:
+                       snprintf(c3, 16, "64");
+                       break;
+               case 1:
+                       snprintf(c3, 16, "v%u", z);
+                       break;
+               case 2:
+                       snprintf(c3, 16, "%u", z);
+                       break;
+               case 3:
+                       seg = '2';
+                       snprintf(c3, 16, "64");
+                       break;
+               }
+
+               /* Maybe graphics segmet is changed using file name */          
+               fprintf(fp, "spr%c\t%u\t%s\t%s\t%s\n", seg, w, c1, c2, c3);
+       } else {
+               switch(op) {
+               case 0x0:
+                       fprintf(fp, "seti\tv%u\t%i\n", x, (int16_t)y);
+                       break;
+               case 0x1:
+                       fprintf(fp, "set\tv%u\tv%u\n", x, y);
+                       break;
+               case 0x2:
+                       fprintf(fp, "add\tv%u\tv%u\n", x, y);
+                       break;
+               case 0x3:
+                       fprintf(fp, "addi\tv%u\t%u\n", x, y);
+                       break;
+               case 0x4:
+                       fprintf(fp, "jsr\tL%u\n", label);
+                       break;
+               case 0x5:
+                       fprintf(fp, "return\n");
+                       break;
+               case 0x6:
+                       fprintf(fp, "break\n");
+                       break;
+               case 0x7:
+                       fprintf(fp, "jmp\tL%u\n", label);
+                       break;
+               case 0x8:
+                       fprintf(fp, "setvec\t%u\tL%u\n", x, label);
+                       break;
+               case 0x9:
+                       fprintf(fp, "dbra\tv%u\tL%u\n", x, label);
+                       break;
+               case 0xA:               
+                       if(w & 0x80)
+                               snprintf(c1, 16, "v%u", y);
+                       else if(w & 0x40)
+                               snprintf(c1, 16, "%i", (int16_t)y);
+                       else
+                               snprintf(c1, 16, "%u", y);
+               
+                       switch(w & 0x7) {
+                       case 0:
+                               s = "=";
+                               break;
+                       case 1:
+                               s = "<>";
+                               break;
+                       case 2:
+                               s = ">";
+                               break;
+                       case 3:
+                               s = ">=";
+                               break;
+                       case 4:
+                               s = "<";
+                               break;
+                       case 5:
+                               s = "<=";
+                               break;
+                       default:
+                               s = "unk";
+                       }
+               
+                       fprintf(fp, "si\tv%u\t%s\t%s\tL%u\n", x, s, c1, label);
+                       break;
+               case 0xB:
+                       fprintf(fp, "fade\t%u\n", x);
+                       break;
+               case 0xC:
+                       fprintf(fp, "vec\t%u\t%u\t%u\n", x, y, z);
+                       break;
+               case 0xD:
+                       fprintf(fp, "setws\t%u\n", x);
+                       break;
+               case 0xE:
+                       fprintf(fp, "clr\t%u\t%u\n", x, y);
+                       break;
+               case 0xF:
+                       fprintf(fp, "copy\t%u\t%u\n", x, y);
+                       break;
+               case 0x10:
+                       fprintf(fp, "show\t%u\n", x);
+                       break;
+               case 0x11:
+                       fprintf(fp, "bigend\n");
+                       break;
+               case 0x12:
+                       fprintf(fp, "text\t%u\t%u\t%u\t%u\n", z, x, y, w);
+                       break;
+               case 0x13:
+                       fprintf(fp, "sub\tv%u\tv%u\n", x, y);
+                       break;
+               case 0x14:
+                       fprintf(fp, "andi\tv%u\t%u\n", x, y);
+                       break;
+               case 0x15:
+                       fprintf(fp, "ori\tv%u\t%u\n", x, y);
+                       break;
+               case 0x16:
+                       fprintf(fp, "lsl\tv%u\t%u\n", x, y);
+                       break;
+               case 0x17:
+                       fprintf(fp, "lsr\tv%u\t%u\n", x, y);
+                       break;
+               case 0x18:
+                       fprintf(fp, "play\t%u\t%u\t%u\t%u\n", z, x, y, w);
+                       break;
+               case 0x19:
+                       fprintf(fp, "load\t%u\n", x);
+                       break;
+               case 0x1A:
+                       fprintf(fp, "song\t%u\t%u\t%u\n", x, y, z);
+                       break;
+               default:
+                       fprintf(fp, "unk_%x\n", op);
+               }
+       }
+}
diff --git a/dis_intel.c b/dis_intel.c
new file mode 100644 (file)
index 0000000..adc28dc
--- /dev/null
@@ -0,0 +1,227 @@
+#include <stdio.h>
+#include <stdint.h>
+#include "dis.h"
+
+/*
+ * Intel style target
+ *
+ * This target uses another mnemonics:
+ *   spr = spr1, spr2
+ *   mov = set, seti
+ *   add = add, addi
+ *   jsr = jsr
+ *   ret = return
+ *   wait = break
+ *   jmp = jmp
+ *   setv = setvec
+ *   jnz = dbra
+ *   je, jne, jg, jge, jl, jle = si (=, !=, >, >=, <, <=)
+ *   pal = fade
+ *   vec = vec
+ *   page = setws
+ *   clr = clr
+ *   copy = copy
+ *   show = show
+ *   kill = bigend
+ *   text = text
+ *   sub = sub
+ *   and = andi
+ *   or = ori
+ *   shl = lsl
+ *   shr = lsr
+ *   snd = play
+ *   ld = load
+ *   mus = song
+ */
+
+void intel_printlabel(int i) {
+       if(i != -1) {
+               if(label[i].type != LT_JUMP && adr != 0)
+                       fputc('\n', fp);
+               
+               if(label[i].type == LT_CALL)
+                       fprintf(fp, "; Procedure code\n");
+               else if(label[i].type == LT_VEC)
+                       fprintf(fp, "; Task code\n");
+               
+               fprintf(fp, "L%i:\n", i);
+       }
+       
+       if(printadr)
+               fprintf(fp, "/* %5u */", adr);
+       
+       fprintf(fp, "\t");
+}
+
+void intel_printopcode(uint16_t op, uint16_t x, uint16_t y, uint16_t z, uint16_t w, int label) {
+       char *s;
+       char c1[16], c2[16], c3[16];
+       
+       if(op & 0x80) {
+               fprintf(fp, "spr\t[%xh], %u, %u\n", w, x, y);
+       } else if(op & 0x40) {
+               char *seg = "";
+               
+               switch(op & 48) {
+               case 0:
+                       snprintf(c1, 16, "%i", (int16_t)x);
+                       break;
+               case 16:
+                       snprintf(c1, 16, "v%u", x);
+                       break;
+               case 32:
+                       snprintf(c1, 16, "%u", x);
+                       break;
+               case 48:
+                       snprintf(c1, 16, "%u", x+256);
+                       break;
+               }
+               
+               switch(op & 12) {
+               case 0:
+                       snprintf(c2, 16, "%i", (int16_t)y);
+                       break;
+               case 4:
+                       snprintf(c2, 16, "v%u", y);
+                       break;
+               case 8:
+               case 12:
+                       snprintf(c2, 16, "%u", y);
+                       break;
+               }
+               
+               switch(op & 3) {
+               case 0:
+                       snprintf(c3, 16, "%u", z);
+                       break;
+               case 1:
+                       snprintf(c3, 16, "v%u", z);
+                       break;
+               case 2:
+                       snprintf(c3, 16, "%u", z);
+                       break;
+               case 3:
+                       seg = "2:";
+                       snprintf(c3, 16, "%u", z);
+                       break;
+               }
+               
+               fprintf(fp, "spr\t[%s%xh], %s, %s, %s\n", seg, w, c1, c2, c3);
+       } else {
+               switch(op) {
+               case 0x0:
+                       fprintf(fp, "mov\tv%u, %i\n", x, (int16_t)y);
+                       break;
+               case 0x1:
+                       fprintf(fp, "mov\tv%u, v%u\n", x, y);
+                       break;
+               case 0x2:
+                       fprintf(fp, "add\tv%u, v%u\n", x, y);
+                       break;
+               case 0x3:
+                       fprintf(fp, "add\tv%u, %u\n", x, y);
+                       break;
+               case 0x4:
+                       fprintf(fp, "jsr\tL%u\n", label);
+                       break;
+               case 0x5:
+                       fprintf(fp, "ret\n");
+                       break;
+               case 0x6:
+                       fprintf(fp, "wait\n");
+                       break;
+               case 0x7:
+                       fprintf(fp, "jmp\tL%u\n", label);
+                       break;
+               case 0x8:
+                       fprintf(fp, "setv\t%u, L%u\n", x, label);
+                       break;
+               case 0x9:
+                       fprintf(fp, "jnz\tv%u, L%u\n", x, label);
+                       break;
+               case 0xA:               
+                       if(w & 0x80)
+                               snprintf(c1, 16, "v%u", y);
+                       else if(w & 0x40)
+                               snprintf(c1, 16, "%i", (int16_t)y);
+                       else
+                               snprintf(c1, 16, "%u", y);
+                       
+                       switch(w & 0x7) {
+                       case 0:
+                               s = "je";
+                               break;
+                       case 1:
+                               s = "jne";
+                               break;
+                       case 2:
+                               s = "jg";
+                               break;
+                       case 3:
+                               s = "jge";
+                               break;
+                       case 4:
+                               s = "jl";
+                               break;
+                       case 5:
+                               s = "jle";
+                               break;
+                       default:
+                               s = "unk_jmp";
+                       }
+                       
+                       fprintf(fp, "%s\tv%u, %s, L%u\n", s, x, c1, label);
+                       break;
+               case 0xB:
+                       fprintf(fp, "pal\t%u\n", x);
+                       break;
+               case 0xC:
+                       fprintf(fp, "vec\t%u, %u, %u\n", x, y, z);
+                       break;
+               case 0xD:
+                       fprintf(fp, "page\t%u\n", x);
+                       break;
+               case 0xE:
+                       fprintf(fp, "clr\t%u, %u\n", x, y);
+                       break;
+               case 0xF:
+                       fprintf(fp, "copy\t%u, %u\n", x, y);
+                       break;
+               case 0x10:
+                       fprintf(fp, "show\t%u\n", x);
+                       break;
+               case 0x11:
+                       fprintf(fp, "kill\n");
+                       break;
+               case 0x12:
+                       fprintf(fp, "text\t%u, %u, %u, %u\n", z, x, y, w);
+                       break;
+               case 0x13:
+                       fprintf(fp, "sub\tv%u, v%u\n", x, y);
+                       break;
+               case 0x14:
+                       fprintf(fp, "and\tv%u, %u\n", x, y);
+                       break;
+               case 0x15:
+                       fprintf(fp, "or\tv%u, %u\n", x, y);
+                       break;
+               case 0x16:
+                       fprintf(fp, "shl\tv%u, %u\n", x, y);
+                       break;
+               case 0x17:
+                       fprintf(fp, "shr\tv%u, %u\n", x, y);
+                       break;
+               case 0x18:
+                       fprintf(fp, "snd\t%u, %u, %u, %u\n", z, x, y, w);
+                       break;
+               case 0x19:
+                       fprintf(fp, "ld\t%u\n", x);
+                       break;
+               case 0x1A:
+                       fprintf(fp, "mus\t%u, %u, %u\n", x, y, z);
+                       break;
+               default:
+                       fprintf(fp, "unk_%x\n", op);
+               }
+       }
+}
diff --git a/dis_syn.h b/dis_syn.h
new file mode 100644 (file)
index 0000000..e9a3108
--- /dev/null
+++ b/dis_syn.h
@@ -0,0 +1,6 @@
+void aw_printlabel(int);
+void aw_printopcode(uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, int);
+void intel_printlabel(int);
+void intel_printopcode(uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, int);
+void att_printlabel(int);
+void att_printopcode(uint16_t, uint16_t, uint16_t, uint16_t, uint16_t, int);
\ No newline at end of file
diff --git a/unpk.c b/unpk.c
new file mode 100644 (file)
index 0000000..ca77dea
--- /dev/null
+++ b/unpk.c
@@ -0,0 +1,238 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <arpa/inet.h>
+
+/*
+ * Another World game data unpacker
+ *   Only DOS version are supported
+ */
+
+#define MAX_MEMINFO 256
+#define MSG_OPENERR "can't open file %s.\n"
+#define MSG_WRITEERR "can't create file %s.\n"
+#define MSG_UNPKERR "error while unpack file %s.\n"
+
+struct __attribute__ ((__packed__)) memrec {
+       uint8_t state;
+       uint8_t type;
+       uint32_t unk0;
+       uint8_t unk1;
+       uint8_t bank;
+       uint32_t offset;
+       uint16_t unk2;
+       uint16_t pksize;
+       uint16_t unk3;
+       uint16_t size;
+};
+
+FILE *fp;
+struct memrec meminfo[MAX_MEMINFO];
+int count;
+
+uint8_t *pk;
+uint32_t size, datasize;
+uint32_t start, idx, oidx;
+uint32_t crc, chk;
+
+uint32_t pkint(int adr) {
+       return ((pk[adr]) << 24) |
+               ((pk[adr + 1]) << 16) |
+               ((pk[adr + 2]) << 8) |
+               (pk[adr + 3]);
+}
+
+bool rcr(bool cf) {
+       bool rcf = chk & 1;
+       chk >>= 1;
+       if(cf)
+               chk |= 0x80000000;
+       return rcf;
+}
+
+bool nextChunk() {
+       bool cf = rcr(false);
+       if(chk == 0) {
+               chk = pkint(idx);
+               idx -= 4;
+               crc ^= chk;
+               cf = rcr(true);
+       }
+       return cf;
+}
+
+int getCode(int numChunks) {
+       int c = 0;
+       while(numChunks--) {
+               c <<= 1;
+               if(nextChunk())
+                       c |= 1;
+       }
+       return c;
+}
+
+void decUnk1(int numChunks, int addCount) {
+       int count = getCode(numChunks) + addCount + 1;
+       datasize -= count;
+       while(count--) {
+               pk[oidx] = getCode(8);
+               --oidx;
+       }
+}
+
+void decUnk2(int numChunks) {
+       int i = getCode(numChunks);
+       int count = size + 1;
+       datasize -= count;
+       while(count--) {
+               pk[oidx] = pk[oidx + i];
+               --oidx;
+       }
+}
+
+bool unpack() {
+       size = 0;
+       datasize = pkint(idx);
+       idx -= 4;
+       oidx = start + datasize - 1;
+       crc = pkint(idx);
+       idx -= 4;
+       chk = pkint(idx);
+       idx -= 4;
+       crc ^= chk;
+       
+       do {
+               if(!nextChunk()) {
+                       size = 1;
+                       if(!nextChunk())
+                               decUnk1(3, 0);
+                       else
+                               decUnk2(8);
+               } else {
+                       int c = getCode(2);
+                       if(c == 3) {
+                               decUnk1(8, 8);
+                       } else {
+                               if(c < 2) {
+                                       size = c + 2;
+                                       decUnk2(c + 9);
+                               } else {
+                                       size = getCode(8);
+                                       decUnk2(12);
+                               }
+                       }
+               }
+       } while(datasize > 0);
+       
+       return crc == 0;
+}
+
+bool pkload(int i) {
+       struct memrec *r = &meminfo[i];
+       
+       char name[64];
+       char *nnum = (r->bank <= 0xF)?"0":"";
+       snprintf(name, 64, "BANK%s%X", nnum, r->bank);
+       
+       if((fp = fopen(name, "r")) == NULL) {
+               printf(MSG_OPENERR, name);
+               return 0;
+       }
+       
+       pk = malloc(r->size);
+       
+       fseek(fp, r->offset, SEEK_SET);
+       fread(pk, r->pksize, 1, fp);
+       fclose(fp);
+       
+       if(r->pksize == r->size) {
+               return true;
+       } else {
+               start = 0;
+               idx = start + r->pksize - 4;
+               return unpack();
+       }
+}
+
+void readmem() {
+       count = 0;
+       
+       printf("NUM STATE TYPE BANK   OFFSET PKSIZE  SIZE\n");
+       
+       while(count < MAX_MEMINFO) {
+               struct memrec *r = &meminfo[count];
+               fread(r, sizeof(struct memrec), 1, fp);
+               r->offset = ntohl(r->offset);
+               r->pksize = ntohs(r->pksize);
+               r->size = ntohs(r->size);
+               printf("%3i %5u %4u %4X %8X %6u %5u\n", count, r->state, r->type,
+                       r->bank, r->offset, r->pksize, r->size);                
+               
+               if(r->state == 0xFF)
+                       break;
+               
+               ++count;
+       }
+}
+
+int main(int argc, char **argv) {
+       if((fp = fopen("MEMLIST.BIN", "r")) == NULL) {
+               printf(MSG_OPENERR, "MEMLIST.BIN");
+               exit(1);
+       }
+       
+       readmem();
+       
+       fclose(fp);
+       
+       for(int i = 0; i < count - 1; i++) {
+               char name[64];
+               char *ext;
+               
+               switch(meminfo[i].type) {
+               case 0: /* sound */
+                       ext = "snd";
+                       break;
+               case 1: /* music */
+                       ext = "mus";
+                       break;
+               case 2: /* bitmap */
+                       ext = "bmp";
+                       break;
+               case 3: /* palette */
+                       ext = "pal";
+                       break;
+               case 4: /* code */
+                       ext = "obj";
+                       break;
+               case 5: /* polygons */
+                       ext = "spr";
+                       break;
+               default: /* other */
+                       ext = "unk";
+                       break;
+               }
+               
+               snprintf(name, 64, "file%i.%s", i, ext);
+               
+               if(!pkload(i)) {
+                       printf(MSG_UNPKERR, name);
+                       goto error;
+               }
+               
+               if((fp = fopen(name, "w")) == NULL) {
+                       printf(MSG_WRITEERR, name);
+                       goto error;
+               }
+               
+               fwrite(pk, meminfo[i].size, 1, fp);
+               
+               fclose(fp);
+       error:
+               free(pk);
+       }
+       
+       return 0;
+}