author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Wed, 13 Jul 2016 17:31:11 +0000 (20:31 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Wed, 13 Jul 2016 17:31:11 +0000 (20:31 +0300) |
Makefile | [new file with mode: 0644] | patch | blob |
README | [new file with mode: 0644] | patch | blob |
dis.c | [new file with mode: 0644] | patch | blob |
dis.h | [new file with mode: 0644] | patch | blob |
dis_att.c | [new file with mode: 0644] | patch | blob |
dis_aw.c | [new file with mode: 0644] | patch | blob |
dis_intel.c | [new file with mode: 0644] | patch | blob |
dis_syn.h | [new file with mode: 0644] | patch | blob |
unpk.c | [new file with mode: 0644] | patch | blob |
diff --git a/Makefile b/Makefile
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /dev/null
+++ b/dis_intel.c
@@ -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
--- /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
--- /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;
+}