tools: decb tool
authorAlan Cox <alan@linux.intel.com>
Thu, 30 Aug 2018 21:47:59 +0000 (22:47 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 30 Aug 2018 21:47:59 +0000 (22:47 +0100)
Kernel/tools/decb.c [new file with mode: 0644]

diff --git a/Kernel/tools/decb.c b/Kernel/tools/decb.c
new file mode 100644 (file)
index 0000000..6fb719c
--- /dev/null
@@ -0,0 +1,150 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static enum {
+  NEW_BLOCK,
+  PREAMBLE_1,
+  PREAMBLE_2,
+  PREAMBLE_3,
+  PREAMBLE_4,
+  POSTAMBLE_1,
+  POSTAMBLE_2,
+  POSTAMBLE_3,
+  POSTAMBLE_4,
+  DONE,
+  BYTESTREAM
+} state = NEW_BLOCK;
+
+static int copying = 0;
+
+static unsigned char roms[32768];
+static unsigned char decb[16384];
+static unsigned char *decbptr = decb;
+
+static void write_rom(char *path, unsigned char *buf, int len)
+{
+  int fd = creat(path, 0666);
+  if (fd == -1) {
+    perror(path);
+    exit(1);
+  }
+  if (write(fd, buf, len) != len) {
+    perror(path);
+    exit(1);
+  }
+  if (close(fd) != 0) {
+    perror(path);
+    exit(1);
+  }
+}
+
+int main(int argc, char *argv[])
+{
+  unsigned int c;
+  unsigned int base, size;
+
+  if (argc != 5) {
+    fprintf(stderr, "%s: [bootrom] [secondrom] [cart1rom] [cart2rom]\n",
+      argv[0]);
+    exit(1);
+  }  
+  while(state != DONE && (c = getchar()) != EOF) {
+    switch(state) {
+      case NEW_BLOCK:
+        if (c == 0xFF) {
+          state = POSTAMBLE_1;
+          break;
+        }
+        if (c == 0x00) {
+          state = PREAMBLE_1;
+          break;
+        }
+        fprintf(stderr, "Corrupt DECB (%d)\n", c);
+        exit(1);
+        break;
+
+      case POSTAMBLE_1:
+        if (c != 0x00) {
+          fprintf(stderr, "DECB postamble byte 0 not 0x00\n");
+          exit(1);
+        }
+        state = POSTAMBLE_2;
+        break;
+      case POSTAMBLE_2:
+        if (c != 0x00) {
+          fprintf(stderr, "DECB postamble byte 2 not 0x00\n");
+          exit(1);
+        }
+        state = POSTAMBLE_3;
+        break;
+      case POSTAMBLE_3:
+        state = POSTAMBLE_4;
+        break;
+      case POSTAMBLE_4:
+        *decbptr++ = 0xFF;
+        *decbptr++ = 0x00;
+        *decbptr++ = 0x00;
+        *decbptr++ = 0x80;
+        *decbptr++ = 0x00;
+        state = DONE;
+        break;
+      case PREAMBLE_1:
+        size = c << 8;
+        state = PREAMBLE_2;
+        break;
+      case PREAMBLE_2:
+        size += c;
+        state = PREAMBLE_3;
+        break;
+      case PREAMBLE_3:
+        base = c << 8;
+        state = PREAMBLE_4;
+        break;
+      case PREAMBLE_4:
+        base += c;
+        state = BYTESTREAM;
+        if (base < 0x8000 && base + size > 0x8000) {
+          fprintf(stderr, "Split block\n");
+          exit(1);
+        }
+        if (base < 0x8000) {
+          copying = 1;
+          fprintf(stderr, "Copy block at %04x for %04x\n", base, size);
+          *decbptr++ = 0x00;
+          *decbptr++ = size >> 8;
+          *decbptr++ = size & 0xff;
+          *decbptr++ = base >> 8;
+          *decbptr++ = base & 0xff;
+        }
+        else {
+          fprintf(stderr, "ROM block at %04x for %04x\n", base, size);
+          copying = 0;
+        }
+        break;
+      case BYTESTREAM:
+        if (copying)
+          *decbptr++ = c;
+        else
+          roms[base++ - 0x8000] = c;
+        size--;
+        if (size == 0)
+          state = NEW_BLOCK;
+        break;
+      default:
+        fprintf(stderr, "State machine horked.\n");
+        exit(1);
+    }
+  }
+  if (state != DONE) {
+    fprintf(stderr, "Unexpected EOF in state %d\n", state);
+    exit(1);
+  }
+  write_rom(argv[1], decb, decbptr-decb);
+  write_rom(argv[2], roms, 0x4000);
+  write_rom(argv[3], roms + 0x4000, 0x2000);
+  write_rom(argv[4], roms + 0x6000, 0x2000);
+  
+  exit(0);
+}