diff --git a/mtsread.c b/mtsread.c
index acdf4d9..7e8fef6 100644
--- a/mtsread.c
+++ b/mtsread.c
@@ -28,6 +28,11 @@
 #define MTSCHEM_FILE_SIGNATURE  0x4d54534d /* 'MTSM' */
 #define MTSCHEM_FILE_VERSION    4
 
+#define BUFSIZE 512
+
+#define is_newline(c) ((c) == '\n' || (c) == '\r')
+#define is_whitespace(c) (is_newline(c) || (c) == '\t' || (c) == ' ')
+
 typedef struct mts_header {
   uint32_t signature;
   uint16_t version;
@@ -46,6 +51,13 @@ typedef struct mts {
   uint8_t   *param2; /* param2 (length X*Y*Z, offset 3*X*Y*Z) */
 } mts;
 
+typedef struct colour {
+  uint8_t red;
+  uint8_t green;
+  uint8_t blue;
+  uint8_t override;
+} colour;
+
 #define foreach_node(schematic, x, y, z)                        \
   for (uint16_t x = 0; x < schematic.header.size_x; x++)        \
     for (uint16_t y = 0; y < schematic.header.size_y; y++)      \
@@ -188,6 +200,53 @@ size_t lookup_name_by_id(mts_header *header, uint16_t id, char **name) {
   return 2;
 }
 
+void read_colour(char *s, colour *c) {
+  uint32_t i = strtol(s, NULL, 16);
+  while (i > 0xffffff)
+    i = i >> 4;
+  c->red = (i & 0xff0000) >> 16;
+  c->green = (i & 0x00ff00) >> 8;
+  c->blue = i & 0x0000ff;
+}
+
+colour *read_colourmap(FILE *stream, mts_header *header) {
+  char buf[BUFSIZE] = {0};
+  colour *colourmap = calloc_or_fail(header->name_id_count, sizeof(colour));
+  while (fgets(buf, BUFSIZE, stream)) {
+    colour c;
+    uint16_t id;
+    size_t name_end = 0;
+    for (size_t i = 0; i < BUFSIZE; i++) {
+      if (is_whitespace(buf[i])) {
+        buf[i] = '\0';
+        name_end = i;
+        break;
+      }
+    }
+    if (!lookup_id_by_name(header, &id, buf)) {
+      if (strcmp(buf, "?")) {
+        fprintf(stderr, "Invalid name: %s\n", buf);
+        continue;
+      }
+      c.override = 0;
+    } else c.override = 1;
+    for (size_t i = name_end; i < BUFSIZE; i++) {
+      if (is_newline(buf[i])) {
+        buf[i] = '\0';
+        break;
+      }
+    }
+    read_colour(&buf[name_end + 1], &c);
+    if (c.override)
+      colourmap[id] = c;
+    else
+      for (id = 0; id < header->name_id_count; id++)
+        if (!colourmap[id].override)
+          colourmap[id] = c;
+  }
+  return colourmap;
+}
+
 void print_node(mts *schematic, uint16_t x, uint16_t y, uint16_t z) {
   char *name;
   uint16_t param0 = index_param0(schematic, x, y, z);
@@ -208,7 +267,8 @@ void usage(int status) {
           "\tdump <x> <y> <z>\tDump param0-2 for a single node\n"
           "\tlist <name>\tList all nodes of a certain type by name\n"
           "\tcountall\tCount all nodes by name\n"
-          "\tcount <name>\tCount all nodes of a certain type by name\n");
+          "\tcount <name>\tCount all nodes of a certain type by name\n"
+          "\tmap <depth>\tMake a PBM map of all nodes in a single layer. Takes name->colour map from stdin\n");
   exit(status);
 }
 
@@ -315,6 +375,26 @@ int main(int argc, char *argv[]) {
       if (index_param0(&schematic, x, y, z) == id)
         count++;
     printf("%lu\n", count);
+  } else if (!strcmp(argv[2], "map") && argc > 3) {
+    colour *colourmap;
+    int y = atoi(argv[3]);
+    if (y < 0 || y >= schematic.header.size_y) {
+      fprintf(stderr, "Depth must be between 0 and %d\n", schematic.header.size_y - 1);
+      return 1;
+    }
+    read_nodedefs(fd, &schematic);
+    colourmap = read_colourmap(stdin, &schematic.header);
+    printf("P3\n%d %d\n255\n",
+           schematic.header.size_x,
+           schematic.header.size_z);
+    for (uint16_t x = 0; x < schematic.header.size_x; x++) {
+      for (uint16_t z = 0; z < schematic.header.size_z; z++) {
+        colour c = colourmap[index_param0(&schematic, x, y, z)];
+        printf("%hhu %hhu %hhu ", c.red, c.green, c.blue);
+      }
+      printf("\n");
+    }
+    free(colourmap);
   } else usage(1);
   return 0;
 }