Index: apps/plugins/viewers.config
===================================================================
--- apps/plugins/viewers.config	(revision 12499)
+++ apps/plugins/viewers.config	(working copy)
@@ -16,6 +16,7 @@
 mid,viewers/midiplay, 20 70 70 3F 00 00 
 rmi,viewers/midiplay, 20 70 70 3F 00 00
 rsp,viewers/searchengine, 0e 11 11 31 7e 60
+sb,rocks/sokoban, 00 48 7E 7E 48 00
 ss,rocks/sudoku, 55 55 55 55 55 55
 wav,viewers/wav2wv, 00 00 00 00 00 00
 wav,viewers/mp3_encoder, 00 00 00 00 00 00
Index: apps/plugins/sokoban.c
===================================================================
--- apps/plugins/sokoban.c	(revision 12499)
+++ apps/plugins/sokoban.c	(working copy)
@@ -10,6 +10,8 @@
  * Copyright (C) 2002 Eric Linenberg
  * February 2003: Robert Hak performs a cleanup/rewrite/feature addition.
  *                Eric smiles.  Bjorn cries.  Linus say 'huh?'.
+ * February 2007: Sean Morrisey performs yet another cleanup/rewrite/feature
+                  addition.
  *
  * All files in this archive are subject to the GNU General Public License.
  * See the file COPYING in the source tree root for full license agreement.
@@ -19,6 +21,7 @@
  *
  ****************************************************************************/
 #include "plugin.h"
+#include "lib/playback_control.h"
 
 #ifdef HAVE_LCD_BITMAP
 
@@ -28,44 +31,59 @@
 extern const fb_data sokoban_tiles[];
 #endif
 
-#define SOKOBAN_TITLE       "Sokoban"
+#define SOKOBAN_TITLE        "Sokoban"
 
-#define LEVELS_FILE         PLUGIN_DIR "/sokoban.levels"
+#define SOKOBAN_LEVELS_FILE  PLUGIN_DIR "/sokoban.levels"
+#define SOKOBAN_SAVE_FILE    PLUGIN_DIR "/sokoban.save"
 
-#define ROWS                16
-#define COLS                20
-#define SOKOBAN_LEVEL_SIZE  (ROWS*COLS)
-#define MAX_BUFFERED_BOARDS 500
-/* Use either all but 12k of the plugin buffer for board data
-   or just enough for MAX_BUFFERED_BOARDS, which ever is less */
-#if (PLUGIN_BUFFER_SIZE - 0x3000)/SOKOBAN_LEVEL_SIZE < MAX_BUFFERED_BOARDS
-#define NUM_BUFFERED_BOARDS (PLUGIN_BUFFER_SIZE - 0x3000)/SOKOBAN_LEVEL_SIZE
+#define ROWS                 16
+#define COLS                 20
+
+/* magnify is the number of pixels for each block */
+#if (LCD_HEIGHT >= 224) && (LCD_WIDTH >= 312) || \
+    (LCD_HEIGHT >= 249) && (LCD_WIDTH >= 280) /* ipod 5g */
+#define MAGNIFY 14
+#elif (LCD_HEIGHT >= 144) && (LCD_WIDTH >= 212) || \
+      (LCD_HEIGHT >= 169) && (LCD_WIDTH >= 180-4) /* h3x0, ipod color/photo */
+#define MAGNIFY 9
+#elif (LCD_HEIGHT >= 96) && (LCD_WIDTH >= 152) || \
+      (LCD_HEIGHT >= 121) && (LCD_WIDTH >= 120) /* h1x0, ipod nano/mini */
+#define MAGNIFY 6
+#else /* other */
+#define MAGNIFY 4
+#endif
+
+/* Use either all but 16k of the plugin buffer for level data
+ * or 128k, which ever is less */
+#if PLUGIN_BUFFER_SIZE - 0x4000 < 0x20000
+#define MAX_LEVEL_DATA       (PLUGIN_BUFFER_SIZE - 0x4000)
 #else
-#define NUM_BUFFERED_BOARDS MAX_BUFFERED_BOARDS
+#define MAX_LEVEL_DATA       0x20000
 #endif
-/* Use 4k plus remaining plugin buffer (-8k for prog) for undo, up to 32k */
-#if PLUGIN_BUFFER_SIZE - NUM_BUFFERED_BOARDS*SOKOBAN_LEVEL_SIZE - 0x2000 > \
-    0x7FFF
-#define MAX_UNDOS           0x7FFF
+
+/* Number of levels for which to allocate buffer indexes */
+#define MAX_LEVELS           MAX_LEVEL_DATA/70
+
+/* Use 4k plus remaining plugin buffer (-12k for prog) for undo, up to 64k */
+#if PLUGIN_BUFFER_SIZE - MAX_LEVEL_DATA - 0x3000 > 0x10000
+#define MAX_UNDOS            0x10000
 #else
-#define MAX_UNDOS           PLUGIN_BUFFER_SIZE - \
-                            NUM_BUFFERED_BOARDS*SOKOBAN_LEVEL_SIZE - 0x2000
+#define MAX_UNDOS            (PLUGIN_BUFFER_SIZE - MAX_LEVEL_DATA - 0x3000)
 #endif
 
 /* Move/push definitions for undo */
-enum {
-    SOKOBAN_PUSH_LEFT,
-    SOKOBAN_PUSH_RIGHT,
-    SOKOBAN_PUSH_UP,
-    SOKOBAN_PUSH_DOWN,
-    SOKOBAN_MOVE_LEFT,
-    SOKOBAN_MOVE_RIGHT,
-    SOKOBAN_MOVE_UP,
-    SOKOBAN_MOVE_DOWN
-};
-#define SOKOBAN_MOVE_DIFF   (SOKOBAN_MOVE_LEFT-SOKOBAN_PUSH_LEFT)
-#define SOKOBAN_MOVE_MIN    SOKOBAN_MOVE_LEFT
+#define SOKOBAN_PUSH_LEFT    'L'
+#define SOKOBAN_PUSH_RIGHT   'R'
+#define SOKOBAN_PUSH_UP      'U'
+#define SOKOBAN_PUSH_DOWN    'D'
+#define SOKOBAN_MOVE_LEFT    'l'
+#define SOKOBAN_MOVE_RIGHT   'r'
+#define SOKOBAN_MOVE_UP      'u'
+#define SOKOBAN_MOVE_DOWN    'd'
 
+#define SOKOBAN_MOVE_DIFF    (SOKOBAN_MOVE_LEFT-SOKOBAN_PUSH_LEFT)
+#define SOKOBAN_MOVE_MIN     SOKOBAN_MOVE_DOWN
+
 /* variable button definitions */
 #if CONFIG_KEYPAD == RECORDER_PAD
 #define SOKOBAN_UP BUTTON_UP
@@ -76,6 +94,8 @@
 #define SOKOBAN_LEVEL_UP BUTTON_F3
 #define SOKOBAN_LEVEL_DOWN BUTTON_F1
 #define SOKOBAN_LEVEL_REPEAT BUTTON_F2
+#define BUTTON_SAVE BUTTON_ON
+#define BUTTON_SAVE_NAME "ON"
 
 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
 #define SOKOBAN_UP BUTTON_UP
@@ -86,6 +106,8 @@
 #define SOKOBAN_LEVEL_UP BUTTON_F3
 #define SOKOBAN_LEVEL_DOWN BUTTON_F1
 #define SOKOBAN_LEVEL_REPEAT BUTTON_F2
+#define BUTTON_SAVE BUTTON_ON
+#define BUTTON_SAVE_NAME "ON"
 
 #elif CONFIG_KEYPAD == ONDIO_PAD
 #define SOKOBAN_UP BUTTON_UP
@@ -97,6 +119,8 @@
 #define SOKOBAN_LEVEL_UP (BUTTON_MENU | BUTTON_RIGHT)
 #define SOKOBAN_LEVEL_DOWN (BUTTON_MENU | BUTTON_LEFT)
 #define SOKOBAN_LEVEL_REPEAT (BUTTON_MENU | BUTTON_UP)
+#define BUTTON_SAVE BUTTON_MENU
+#define BUTTON_SAVE_NAME "MENU"
 
 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
       (CONFIG_KEYPAD == IRIVER_H300_PAD)
@@ -108,6 +132,8 @@
 #define SOKOBAN_LEVEL_UP (BUTTON_ON | BUTTON_UP)
 #define SOKOBAN_LEVEL_DOWN (BUTTON_ON | BUTTON_DOWN)
 #define SOKOBAN_LEVEL_REPEAT BUTTON_ON
+#define BUTTON_SAVE BUTTON_MODE
+#define BUTTON_SAVE_NAME "MODE"
 
 #define SOKOBAN_RC_QUIT BUTTON_RC_STOP
 
@@ -121,9 +147,11 @@
 #define SOKOBAN_REDO (BUTTON_SELECT | BUTTON_PLAY)
 #define SOKOBAN_LEVEL_UP (BUTTON_SELECT | BUTTON_RIGHT)
 #define SOKOBAN_LEVEL_DOWN (BUTTON_SELECT | BUTTON_LEFT)
+#define BUTTON_SAVE BUTTON_SELECT
+#define BUTTON_SAVE_NAME "SELECT"
 
-/* fixme: if/when simultaneous button presses work for X5,
-   add redo & level repeat */
+/* FIXME: if/when simultaneous button presses work for X5,
+ * add redo & level repeat */
 #elif (CONFIG_KEYPAD == IAUDIO_X5_PAD)
 #define SOKOBAN_UP BUTTON_UP
 #define SOKOBAN_DOWN BUTTON_DOWN
@@ -132,6 +160,8 @@
 #define SOKOBAN_UNDO (BUTTON_SELECT | BUTTON_REL)
 #define SOKOBAN_LEVEL_UP BUTTON_PLAY
 #define SOKOBAN_LEVEL_DOWN BUTTON_REC
+#define BUTTON_SAVE BUTTON_SELECT
+#define BUTTON_SAVE_NAME "SELECT"
 
 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
 #define SOKOBAN_UP BUTTON_UP
@@ -142,6 +172,8 @@
 #define SOKOBAN_LEVEL_UP (BUTTON_MENU | BUTTON_UP)
 #define SOKOBAN_LEVEL_DOWN (BUTTON_MENU | BUTTON_DOWN)
 #define SOKOBAN_LEVEL_REPEAT BUTTON_MENU
+#define BUTTON_SAVE BUTTON_SELECT
+#define BUTTON_SAVE_NAME "SELECT"
 
 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
 #define SOKOBAN_UP BUTTON_UP
@@ -153,6 +185,8 @@
 #define SOKOBAN_LEVEL_UP (BUTTON_SELECT | BUTTON_UP)
 #define SOKOBAN_LEVEL_DOWN (BUTTON_SELECT | BUTTON_DOWN)
 #define SOKOBAN_LEVEL_REPEAT (BUTTON_SELECT | BUTTON_RIGHT)
+#define BUTTON_SAVE BUTTON_SELECT
+#define BUTTON_SAVE_NAME "SELECT"
 
 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
 #define SOKOBAN_UP BUTTON_SCROLL_UP
@@ -164,27 +198,29 @@
 #define SOKOBAN_LEVEL_UP (BUTTON_PLAY | BUTTON_SCROLL_UP)
 #define SOKOBAN_LEVEL_DOWN (BUTTON_PLAY | BUTTON_SCROLL_DOWN)
 #define SOKOBAN_LEVEL_REPEAT (BUTTON_PLAY | BUTTON_RIGHT)
+#define BUTTON_SAVE BUTTON_PLAY
+#define BUTTON_SAVE_NAME "PLAY"
 
 #endif
 
 #ifdef HAVE_LCD_COLOR
 /* Background color. Default Rockbox light blue. */
 #define BG_COLOR LCD_RGBPACK(181, 199, 231)
-
-#elif LCD_DEPTH >= 2
-#define MEDIUM_GRAY LCD_BRIGHTNESS(127)
 #endif
 
+
 /* The Location, Undo and LevelInfo structs are OO-flavored.
  * (oooh!-flavored as Schnueff puts it.)  It makes more you have to know,
  * but the overall data layout becomes more manageable. */
 
 /* Level data & stats */
 struct LevelInfo {
-    short level;
-    short moves;
-    short pushes;
-    short boxes_to_go;
+    short index;             /* Level index (level number - 1) */
+    int moves;               /* Moves & pushes for the stats */
+    int pushes;
+    short boxes_to_go;       /* Number of unplaced boxes remaining in level */
+    short height;            /* Height & width for centering level display */
+    short width;
 };
 
 struct Location {
@@ -192,39 +228,42 @@
     short col;
 };
 
-struct Board {
-    char spaces[ROWS][COLS];
-};
-
 /* Our full undo history */
 static struct UndoInfo {
-    short count;    /* How many undos are left */
-    short current;  /* Which history is the current undo */
-    short max;      /* Which history is the max redoable */
+    int count;               /* How many undos have been done */
+    int current;             /* Which history is the current undo */
+    int max;                 /* Which history is the max redoable */
     char history[MAX_UNDOS];
 } undo_info;
 
 /* Our playing board */
 static struct BoardInfo {
-    char board[ROWS][COLS];
-    struct LevelInfo level;
-    struct Location player;
-    int max_level;               /* How many levels do we have? */
-    int loaded_level;            /* Which level is in memory */
+    char board[ROWS][COLS];  /* The current board data */
+    struct LevelInfo level;  /* Level data & stats */
+    struct Location player;  /* Where the player is */
+    int max_level;           /* The number of levels we have */
 } current_info;
 
 static struct BufferedBoards {
-    struct Board levels[NUM_BUFFERED_BOARDS];
-    int low;
+    char filename[MAX_PATH];   /* Filename of the levelset we're using */
+    char data[MAX_LEVEL_DATA]; /* Buffered level data */
+    int index[MAX_LEVELS + 1]; /* Where each buffered board begins & ends */
+    int start;                 /* Index of first buffered board */
+    int end;                   /* Index of last buffered board */
+    short prebuffered_boards;  /* Number of boards before current to store */
 } buffered_boards;
 
+
 static struct plugin_api* rb;
 
+static char buf[ROWS*(COLS + 1)]; /* Enough for a whole board or a filename */
+
+
 static void init_undo(void)
 {
     undo_info.count = 0;
-    undo_info.current = -1;
-    undo_info.max = -1;
+    undo_info.current = 0;
+    undo_info.max = 0;
 }
 
 static void get_delta(char direction, short *d_r, short *d_c)
@@ -261,9 +300,17 @@
     bool undo_push = false;
 
     /* If no more undos or we've wrapped all the way around, quit */
-    if (undo_info.count == 0 || undo_info.current-1 == undo_info.max)
+    if (undo_info.count == 0 || undo_info.current - 1 == undo_info.max)
         return;
 
+    /* Move to previous undo in the list */
+    if (undo_info.current == 0 && undo_info.count > 1)
+        undo_info.current = MAX_UNDOS - 1;
+    else
+        undo_info.current--;
+
+    undo_info.count--;
+
     undo = undo_info.history[undo_info.current];
 
     if (undo < SOKOBAN_MOVE_MIN)
@@ -281,17 +328,17 @@
 
     /* Update board info */
     if (undo_push) {
-        /* Moving box from goal to blank */
-        if (*space_next == '%' && *space_cur == '@')
+        /* Moving box from goal to floor */
+        if (*space_next == '*' && *space_cur == '@')
             current_info.level.boxes_to_go++;
-        /* Moving box from blank to goal */
+        /* Moving box from floor to goal */
         else if (*space_next == '$' && *space_cur == '+')
             current_info.level.boxes_to_go--;
 
         /* Move box off of next space... */
-        *space_next = (*space_next == '%' ? '.' : ' ');
+        *space_next = (*space_next == '*' ? '.' : ' ');
         /* ...and on to current space */
-        *space_cur = (*space_cur == '+' ? '%' : '$');
+        *space_cur = (*space_cur == '+' ? '*' : '$');
 
         current_info.level.pushes--;
     } else
@@ -306,27 +353,19 @@
 
     current_info.level.moves--;
 
-    /* Move to previous undo in the list */
-    if (undo_info.current == 0 && undo_info.count > 1)
-        undo_info.current = MAX_UNDOS - 1;
-    else
-        undo_info.current--;
-
-    undo_info.count--;
-
     return;
 }
 
 static void add_undo(char undo)
 {
+    undo_info.history[undo_info.current] = undo;
+
     /* Wrap around if MAX_UNDOS exceeded */
     if (undo_info.current < (MAX_UNDOS - 1))
         undo_info.current++;
     else
         undo_info.current = 0;
 
-    undo_info.history[undo_info.current] = undo;
-
     if (undo_info.count < MAX_UNDOS)
         undo_info.count++;
 }
@@ -353,7 +392,7 @@
     space_next = &current_info.board[r + d_r][c + d_c];
     space_beyond = &current_info.board[r + 2*d_r][c + 2*d_c];
 
-    if (*space_next == '$' || *space_next == '%') {
+    if (*space_next == '$' || *space_next == '*') {
         /* Change direction from move to push for undo */
         if (direction >= SOKOBAN_MOVE_MIN)
             direction -= SOKOBAN_MOVE_DIFF;
@@ -362,10 +401,10 @@
 
     /* Update board info */
     if (push) {
-        /* Moving box from goal to blank */
-        if (*space_next == '%' && *space_beyond == ' ')
+        /* Moving box from goal to floor */
+        if (*space_next == '*' && *space_beyond == ' ')
             current_info.level.boxes_to_go++;
-        /* Moving box from blank to goal */
+        /* Moving box from floor to goal */
         else if (*space_next == '$' && *space_beyond == '.')
             current_info.level.boxes_to_go--;
         /* Check for illegal move */
@@ -373,14 +412,14 @@
             return false;
 
         /* Move player onto next space */
-        *space_next = (*space_next == '%' ? '+' : '@');
+        *space_next = (*space_next == '*' ? '+' : '@');
         /* Move box onto space beyond next */
-        *space_beyond = (*space_beyond == '.' ? '%' : '$');
+        *space_beyond = (*space_beyond == '.' ? '*' : '$');
 
         current_info.level.pushes++;
     } else {
         /* Check for illegal move */
-        if (*space_next == '#' || *space_next == 'X')
+        if (*space_next != '.' && *space_next != ' ')
             return false;
 
         /* Move player onto next space */
@@ -396,19 +435,19 @@
     current_info.level.moves++;
 
     /* Update undo_info.max to current on every normal move,
-       except if it's the same as a redo. */
-    /* normal move */
+     * except if it's the same as a redo. */
+        /* normal move and either */
     if (!redo &&
-          /* moves have been undone */
+          /* moves have been undone... */
         ((undo_info.max != undo_info.current &&
-          /* and the current move is NOT the same as the one in history */
-          undo_info.history[undo_info.current+1] != direction) ||
+          /* ...and the current move is NOT the same as the one in history */
+          undo_info.history[undo_info.current] != direction) ||
          /* or moves have not been undone */
          undo_info.max == undo_info.current)) {
         add_undo(direction);
         undo_info.max = undo_info.current;
     } else /* redo move or move was same as redo */
-        add_undo(direction); /* (just to update current) */
+        add_undo(direction); /* add_undo to update current */
 
     return true;
 }
@@ -420,291 +459,368 @@
     if (undo_info.current == undo_info.max)
         return false;
 
-    return move(undo_info.history[(undo_info.current+1 < MAX_UNDOS ?
-                                              undo_info.current+1 : 0)], true);
+    return move(undo_info.history[(undo_info.current < MAX_UNDOS ?
+                                   undo_info.current : 0)], true);
 }
 #endif
 
 static void init_boards(void)
 {
-    current_info.level.level = 0;
-    current_info.level.moves = 0;
-    current_info.level.pushes = 0;
-    current_info.level.boxes_to_go = 0;
+    rb->strncpy(buffered_boards.filename, SOKOBAN_LEVELS_FILE, MAX_PATH);
+
+    current_info.level.index = 0;
     current_info.player.row = 0;
     current_info.player.col = 0;
     current_info.max_level = 0;
-    current_info.loaded_level = 0;
 
-    buffered_boards.low = 0;
+    buffered_boards.start = 0;
+    buffered_boards.end = 0;
+    buffered_boards.prebuffered_boards = 0;
 
     init_undo();
 }
 
-static int read_levels(int initialize_count)
+static bool read_levels(bool initialize)
 {
     int fd = 0;
-    int len;
-    int lastlen = 0;
-    int row = 0;
+    short len;
+    short lastlen = 0;
+    short row = 0;
     int level_count = 0;
-    char buffer[COLS + 3]; /* COLS plus CR/LF and \0 */
-    int endpoint = current_info.level.level-1;
 
-    if (endpoint < buffered_boards.low)
-        endpoint = current_info.level.level - NUM_BUFFERED_BOARDS;
+    int i = 0;
+    int level_len = 0;
+    bool index_set = false;
 
-    if (endpoint < 0) endpoint = 0;
+    /* Get the index of the first level to buffer */
+    if (current_info.level.index > buffered_boards.prebuffered_boards &&
+        !initialize)
+        buffered_boards.start = current_info.level.index -
+                                buffered_boards.prebuffered_boards;
+    else
+        buffered_boards.start = 0;
 
-    buffered_boards.low = endpoint;
-    endpoint += NUM_BUFFERED_BOARDS;
-
-    if ((fd = rb->open(LEVELS_FILE, O_RDONLY)) < 0) {
-        rb->splash(HZ*2, true, "Unable to open %s", LEVELS_FILE);
-        return -1;
+    if ((fd = rb->open(buffered_boards.filename, O_RDONLY)) < 0) {
+        rb->splash(HZ*2, true, "Unable to open %s", buffered_boards.filename);
+        return false;
     }
 
     do {
-        len = rb->read_line(fd, buffer, sizeof(buffer));
+        len = rb->read_line(fd, buf, sizeof(buf));
+
+        /* Correct len if there are trailing \r's or \n's */
+        if (len > 2 && buf[len - 2] == '\0')
+            len -= 2;
+        else if (len > 1 && buf[len - 1] == '\0')
+            len--;
+
+        /* Skip lines with comments */
+        if (buf[0] == ';')
+            continue;
+
         if (len >= 3) {
-            /* This finds lines that are more than 1 or 2 characters
-             * shorter than they should be.  Due to the possibility of
-             * a mixed unix and dos CR/LF file format, I'm not going to
-             * do a precise check */
-            if (len < COLS) {
-                rb->splash(HZ*2, true, "Error in levels file: short line");
-                return -1;
+            if (level_count >= buffered_boards.start) {
+                /* Set the index of this level */
+                if (!index_set &&
+                    level_count - buffered_boards.start < MAX_LEVELS) {
+                    buffered_boards.index[level_count - buffered_boards.start]
+                                                                           = i;
+                    index_set = true;
+                }
+                /* Copy buffer to board data */
+                if (i + level_len + len < MAX_LEVEL_DATA) {
+                    rb->memcpy(&buffered_boards.data[i + level_len], buf, len);
+                    buffered_boards.data[i + level_len + len] = '\n';
+                }
             }
-            if (level_count >= buffered_boards.low && level_count < endpoint) {
-                int index = level_count - buffered_boards.low;
-                rb->memcpy(
-                      buffered_boards.levels[index].spaces[row], buffer, COLS);
-            }
+            level_len += len + 1;
             row++;
-        } else if (len) {
-            if (lastlen < 3) {
-                /* Two short lines in a row means new level */
-                level_count++;
-                if (level_count >= endpoint && !initialize_count) break;
-                if (level_count && row != ROWS) {
-                    rb->splash(HZ*2, true,
-                               "Error in levels file: short board");
-                    return -1;
-                }
-                row = 0;
+
+        /* If level is tall enough or is RLE */
+        } else if (row > 2 || lastlen > COLS) {
+            level_count++;
+            if (level_count >= buffered_boards.start) {
+                i += level_len;
+                if (i < MAX_LEVEL_DATA)
+                    buffered_boards.end = level_count;
+                else if (!initialize)
+                    break;
             }
+            row = 0;
+            level_len = 0;
+            index_set = false;
         }
-    } while ((lastlen=len));
 
+    } while ((lastlen = len));
+
+    /* Set the index of the end of the last level */
+    if (level_count - buffered_boards.start < MAX_LEVELS)
+        buffered_boards.index[level_count - buffered_boards.start] = i;
+
+    if (initialize) {
+        current_info.max_level = level_count;
+        buffered_boards.prebuffered_boards = buffered_boards.end/2;
+    }
+
     rb->close(fd);
-    if (initialize_count) {
-        /* Plus one because there aren't trailing short lines in the file */
-        current_info.max_level = level_count + 1;
-    }
-    return 0;
+
+    return true;
 }
 
-/* return non-zero on error */
 static void load_level(void)
 {
-    int c = 0;
-    int r = 0;
-    int index = current_info.level.level - buffered_boards.low - 1;
-    struct Board *level;
+    int c, r;
+    int i, n;
+    int level_size;
+    int index = current_info.level.index - buffered_boards.start;
+    char *level;
 
-    if (index < 0 || index >= NUM_BUFFERED_BOARDS) {
+    /* Get the buffered board index of the current level */
+    if (current_info.level.index < buffered_boards.start ||
+        current_info.level.index >= buffered_boards.end) {
         read_levels(false);
-        index = index < 0 ? NUM_BUFFERED_BOARDS-1 : 0;
+        if (current_info.level.index > buffered_boards.prebuffered_boards)
+            index = buffered_boards.prebuffered_boards;
+        else
+            index = current_info.level.index;
     }
-    level = &buffered_boards.levels[index];
+    level = &buffered_boards.data[buffered_boards.index[index]];
 
-    current_info.level.boxes_to_go = 0;
+    /* Reset level info */
     current_info.level.moves = 0;
     current_info.level.pushes = 0;
-    current_info.loaded_level = current_info.level.level;
+    current_info.level.boxes_to_go = 0;
+    current_info.level.width = 0;
 
-    for (r = 0; r < ROWS; r++) {
-        for (c = 0; c < COLS; c++) {
-            current_info.board[r][c] = level->spaces[r][c];
+    /* Clear board */
+    for (r = 0; r < ROWS; r++)
+        for (c = 0; c < COLS; c++)
+            current_info.board[r][c] = 'X';
 
-            if (current_info.board[r][c] == '.' ||
-                current_info.board[r][c] == '+')
-                current_info.level.boxes_to_go++;
+    level_size = buffered_boards.index[index + 1] -
+                 buffered_boards.index[index];
 
-            if (current_info.board[r][c] == '@' ||
-                current_info.board[r][c] == '+') {
-                current_info.player.row = r;
-                current_info.player.col = c;
+    for (r = 0, c = 0, n = 1, i = 0; i < level_size; i++) {
+        if (level[i] == '\n' || level[i] == '|') {
+            if (c > 3) {
+                /* Update max width of level & go to next row */
+                if (c > current_info.level.width)
+                    current_info.level.width = c;
+                c = 0;
+                r++;
+                if (r >= ROWS)
+                    break;
             }
+        } else if (c < COLS) {
+            /* Read RLE character's length into n */
+            if (level[i] >= '0' && level[i] <= '9') {
+                n = level[i++] - '0';
+                if (level[i] >= '0' && level[i] <= '9')
+                    n = n * 10 + level[i++] - '0';
+            }
+
+            /* Cleanup & replace */
+            if (level[i] == '%')
+                level[i] = '*';
+            else if (level[i] == '-' || level[i] == '_')
+                level[i] = ' ';
+
+            if (n > 1) {
+                if (c + n >= COLS)
+                    n = COLS - c;
+
+                if (level[i] == '.')
+                    current_info.level.boxes_to_go += n;
+
+                /* Put RLE character n times */
+                while (n--)
+                    current_info.board[r][c++] = level[i];
+                n = 1;
+
+            } else {
+                if (level[i] == '.' || level[i] == '+')
+                    current_info.level.boxes_to_go++;
+
+                if (level[i] == '@' ||level[i] == '+') {
+                    current_info.player.row = r;
+                    current_info.player.col = c;
+                }
+
+                current_info.board[r][c++] = level[i];
+            }
         }
     }
+
+    current_info.level.height = r;
+
+#if LCD_DEPTH > 2
+    /* Fill in blank space outside level on color targets */
+    for (r = 0; r < ROWS; r++)
+        for (c = 0; current_info.board[r][c] == ' ' && c < COLS; c++)
+            current_info.board[r][c] = 'X';
+
+    for (c = 0; c < COLS; c++) {
+        for (r = 0; (current_info.board[r][c] == ' ' ||
+             current_info.board[r][c] == 'X') && r < ROWS; r++)
+            current_info.board[r][c] = 'X';
+        for (r = ROWS - 1; (current_info.board[r][c] == ' ' ||
+             current_info.board[r][c] == 'X') && r >= 0; r--)
+            current_info.board[r][c] = 'X';
+    }
+#endif
 }
 
 static void update_screen(void)
 {
-    int b = 0, c = 0;
-    int rows = 0, cols = 0;
-    char s[25];
+    int c, r;
+    int rows, cols;
 
-/* magnify is the number of pixels for each block */
-#if (LCD_HEIGHT >= 224) && (LCD_WIDTH >= 312) || \
-    (LCD_HEIGHT >= 249) && (LCD_WIDTH >= 280) /* ipod 5g */
-#define MAGNIFY 14
-#elif (LCD_HEIGHT >= 144) && (LCD_WIDTH >= 212) || \
-      (LCD_HEIGHT >= 169) && (LCD_WIDTH >= 180-4) /* h3x0, ipod color/photo */
-#define MAGNIFY 9
-#elif (LCD_HEIGHT >= 96) && (LCD_WIDTH >= 152) || \
-      (LCD_HEIGHT >= 121) && (LCD_WIDTH >= 120) /* h1x0, ipod nano/mini */
-#define MAGNIFY 6
-#else /* other */
-#define MAGNIFY 4
-#endif
-
 #if LCD_DEPTH < 2
     int i, j;
     int max = MAGNIFY - 1;
-    int middle = max / 2;
-    int ldelta = (middle + 1) / 2;
+    int middle = max/2;
+    int ldelta = (middle + 1)/2;
 #endif
 
-    /* load the board to the screen */
-    for (rows=0; rows < ROWS; rows++) {
-        for (cols = 0; cols < COLS; cols++) {
-            c = cols * MAGNIFY;
-            b = rows * MAGNIFY;
+#if LCD_WIDTH - (COLS*MAGNIFY) < 32
+#define STAT_HEIGHT 25
+#define STAT_X (LCD_WIDTH - 120)/2
+#define STAT_Y (LCD_HEIGHT - STAT_HEIGHT)
+#define BOARD_WIDTH LCD_WIDTH
+#define BOARD_HEIGHT (LCD_HEIGHT - STAT_HEIGHT)
+    rb->lcd_putsxy(STAT_X + 4, STAT_Y + 4, "Level");
+    rb->snprintf(buf, sizeof(buf), "%d", current_info.level.index + 1);
+    rb->lcd_putsxy(STAT_X + 7, STAT_Y + 14, buf);
+    rb->lcd_putsxy(STAT_X + 41, STAT_Y + 4, "Moves");
+    rb->snprintf(buf, sizeof(buf), "%d", current_info.level.moves);
+    rb->lcd_putsxy(STAT_X + 44, STAT_Y + 14, buf);
+    rb->lcd_putsxy(STAT_X + 79, STAT_Y + 4, "Pushes");
+    rb->snprintf(buf, sizeof(buf), "%d", current_info.level.pushes);
+    rb->lcd_putsxy(STAT_X + 82, STAT_Y + 14, buf);
 
-            switch(current_info.board[rows][cols]) {
-            case 'X': /* black space */
-                break;
-
-            case '#': /* this is a wall */
-#if LCD_DEPTH >= 2
-                rb->lcd_bitmap_part(sokoban_tiles, 0, 1*MAGNIFY, MAGNIFY,
-                                    c, b, MAGNIFY, MAGNIFY);
+    rb->lcd_drawrect(STAT_X, STAT_Y, 38, STAT_HEIGHT);
+    rb->lcd_drawrect(STAT_X + 37, STAT_Y, 39, STAT_HEIGHT);
+    rb->lcd_drawrect(STAT_X + 75, STAT_Y, 45, STAT_HEIGHT);
 #else
-                for (i = c; i < c + MAGNIFY; i++)
-                    for (j = b; j < b + MAGNIFY; j++)
-                        if ((i ^ j) & 1)
-                            rb->lcd_drawpixel(i, j);
+#if LCD_WIDTH - (COLS*MAGNIFY) > 40
+#define STAT_X (LCD_WIDTH - 40)
+#else
+#define STAT_X COLS*MAGNIFY
 #endif
-                break;
-
-            case '$': /* this is a box */
-#if LCD_DEPTH >= 2
-                rb->lcd_bitmap_part(sokoban_tiles, 0, 2*MAGNIFY, MAGNIFY,
-                                    c, b, MAGNIFY, MAGNIFY);
+#if LCD_HEIGHT >= 70
+#define STAT_Y (LCD_HEIGHT - 70)/2
 #else
-                /* Free boxes are not filled in */
-                rb->lcd_drawrect(c, b, MAGNIFY, MAGNIFY);
+#define STAT_Y (LCD_HEIGHT - 47)/2
 #endif
-                break;
+#define STAT_WIDTH (LCD_WIDTH - STAT_X)
+#define BOARD_WIDTH (LCD_WIDTH - STAT_WIDTH)
+#define BOARD_HEIGHT LCD_HEIGHT
+    rb->lcd_putsxy(STAT_X + 1, STAT_Y + 3, "Level");
+    rb->snprintf(buf, sizeof(buf), "%d", current_info.level.index + 1);
+    rb->lcd_putsxy(STAT_X + 4, STAT_Y + 13, buf);
+    rb->lcd_putsxy(STAT_X + 1, STAT_Y + 26, "Moves");
+    rb->snprintf(buf, sizeof(buf), "%d", current_info.level.moves);
+    rb->lcd_putsxy(STAT_X + 4, STAT_Y + 36, buf);
 
-            case '*':
-            case '%': /* this is a box on a goal */
+    rb->lcd_drawrect(STAT_X, STAT_Y + 0, STAT_WIDTH, 24);
+    rb->lcd_drawrect(STAT_X, STAT_Y + 23, STAT_WIDTH, 24);
 
-#if LCD_DEPTH >= 2
-                rb->lcd_bitmap_part(sokoban_tiles, 0, 3*MAGNIFY, MAGNIFY,
-                                    c, b, MAGNIFY, MAGNIFY );
-#else
-                rb->lcd_drawrect(c, b, MAGNIFY, MAGNIFY);
-                rb->lcd_drawrect(c+(MAGNIFY/2)-1, b+(MAGNIFY/2)-1, MAGNIFY/2,
-                                 MAGNIFY/2);
-#endif
-                break;
+#if LCD_HEIGHT >= 70
+    rb->lcd_putsxy(STAT_X + 1, STAT_Y + 49, "Pushes");
+    rb->snprintf(buf, sizeof(buf), "%d", current_info.level.pushes);
+    rb->lcd_putsxy(STAT_X + 4, STAT_Y + 59, buf);
 
-            case '.': /* this is a goal */
-#if LCD_DEPTH >= 2
-                rb->lcd_bitmap_part(sokoban_tiles, 0, 4*MAGNIFY, MAGNIFY,
-                                    c, b, MAGNIFY, MAGNIFY);
-#else
-                rb->lcd_drawrect(c+(MAGNIFY/2)-1, b+(MAGNIFY/2)-1, MAGNIFY/2,
-                                 MAGNIFY/2);
+    rb->lcd_drawrect(STAT_X, STAT_Y + 46, STAT_WIDTH, 24);
 #endif
-                break;
 
-            case '@': /* this is you */
-#if LCD_DEPTH >= 2
-                rb->lcd_bitmap_part(sokoban_tiles, 0, 5*MAGNIFY, MAGNIFY,
-                                    c, b, MAGNIFY, MAGNIFY);
-#else
-                rb->lcd_drawline(c, b+middle, c+max, b+middle);
-                rb->lcd_drawline(c+middle, b, c+middle, b+max-ldelta);
-                rb->lcd_drawline(c+max-middle, b,
-                                 c+max-middle, b+max-ldelta);
-                rb->lcd_drawline(c+middle, b+max-ldelta,
-                                 c+middle-ldelta, b+max);
-                rb->lcd_drawline(c+max-middle, b+max-ldelta,
-                                 c+max-middle+ldelta, b+max);
 #endif
-                break;
 
-            case '+': /* this is you on drugs, erm, on a goal */
-#if LCD_DEPTH >= 2
-                rb->lcd_bitmap_part(sokoban_tiles, 0, 6*MAGNIFY, MAGNIFY,
-                                    c, b, MAGNIFY, MAGNIFY );
-#else
-                rb->lcd_drawline(c, b+middle, c+max, b+middle);
-                rb->lcd_drawline(c+middle, b, c+middle, b+max-ldelta);
-                rb->lcd_drawline(c+max-middle, b, c+max-middle, b+max-ldelta);
-                rb->lcd_drawline(c+middle, b+max-ldelta, c+middle-ldelta,
-                                 b+max);
-                rb->lcd_drawline(c+max-middle, b+max-ldelta,
-                                 c+max-middle+ldelta, b+max);
-                rb->lcd_drawline(c+middle-1, b+middle+1, c+max-middle+1,
-                                 b+middle+1);
-#endif
-                break;
+    /* load the board to the screen */
+    for (rows = 0; rows < ROWS; rows++) {
+        for (cols = 0; cols < COLS; cols++) {
+            c = cols * MAGNIFY +
+                (BOARD_WIDTH - current_info.level.width*MAGNIFY)/2;
+            r = rows * MAGNIFY +
+                (BOARD_HEIGHT - current_info.level.height*MAGNIFY)/2;
 
+            switch(current_info.board[rows][cols]) {
+                case 'X': /* blank space outside of level */
+                    break;
+
 #if LCD_DEPTH >= 2
-            default:
-                rb->lcd_bitmap_part(sokoban_tiles, 0, 0*MAGNIFY, MAGNIFY,
-                                    c, b, MAGNIFY, MAGNIFY );
-#endif
-            }
-        }
-    }
+                case ' ': /* floor */
+                    rb->lcd_bitmap_part(sokoban_tiles, 0, 0*MAGNIFY, MAGNIFY,
+                                        c, r, MAGNIFY, MAGNIFY );
+                    break;
 
-#if LCD_WIDTH-(COLS*MAGNIFY) < 32
-#define STAT_SIZE 25
-#define STAT_POS LCD_HEIGHT-STAT_SIZE
-#define STAT_CENTER (LCD_WIDTH-120)/2
+                case '#': /* wall */
+                    rb->lcd_bitmap_part(sokoban_tiles, 0, 1*MAGNIFY, MAGNIFY,
+                                        c, r, MAGNIFY, MAGNIFY);
+                    break;
 
-    rb->lcd_putsxy(4+STAT_CENTER, STAT_POS+4, "Level");
-    rb->snprintf(s, sizeof(s), "%d", current_info.level.level);
-    rb->lcd_putsxy(7+STAT_CENTER, STAT_POS+14, s);
-    rb->lcd_putsxy(41+STAT_CENTER, STAT_POS+4, "Moves");
-    rb->snprintf(s, sizeof(s), "%d", current_info.level.moves);
-    rb->lcd_putsxy(44+STAT_CENTER, STAT_POS+14, s);
-    rb->lcd_putsxy(79+STAT_CENTER, STAT_POS+4, "Pushes");
-    rb->snprintf(s, sizeof(s), "%d", current_info.level.pushes);
-    rb->lcd_putsxy(82+STAT_CENTER, STAT_POS+14, s);
+                case '$': /* box */
+                    rb->lcd_bitmap_part(sokoban_tiles, 0, 2*MAGNIFY, MAGNIFY,
+                                        c, r, MAGNIFY, MAGNIFY);
+                    break;
 
-    rb->lcd_drawrect(STAT_CENTER, STAT_POS, 38, STAT_SIZE);
-    rb->lcd_drawrect(37+STAT_CENTER, STAT_POS, 39, STAT_SIZE);
-    rb->lcd_drawrect(75+STAT_CENTER, STAT_POS, 45, STAT_SIZE);
+                case '*': /* box on goal */
+                    rb->lcd_bitmap_part(sokoban_tiles, 0, 3*MAGNIFY, MAGNIFY,
+                                        c, r, MAGNIFY, MAGNIFY );
+                    break;
 
+                case '.': /* goal */
+                    rb->lcd_bitmap_part(sokoban_tiles, 0, 4*MAGNIFY, MAGNIFY,
+                                        c, r, MAGNIFY, MAGNIFY);
+                    break;
+
+                case '@': /* player */
+                    rb->lcd_bitmap_part(sokoban_tiles, 0, 5*MAGNIFY, MAGNIFY,
+                                        c, r, MAGNIFY, MAGNIFY);
+                    break;
+
+                case '+': /* player on goal */
+                    rb->lcd_bitmap_part(sokoban_tiles, 0, 6*MAGNIFY, MAGNIFY,
+                                        c, r, MAGNIFY, MAGNIFY );
+                    break;
 #else
-#define STAT_POS COLS*MAGNIFY
-#define STAT_SIZE LCD_WIDTH-STAT_POS
+                case '#': /* wall */
+                    for (i = c; i < c + MAGNIFY; i++)
+                        for (j = r; j < r + MAGNIFY; j++)
+                            if ((i ^ j) & 1)
+                                rb->lcd_drawpixel(i, j);
+                    break;
 
-    rb->lcd_putsxy(STAT_POS+1, 3, "Level");
-    rb->snprintf(s, sizeof(s), "%d", current_info.level.level);
-    rb->lcd_putsxy(STAT_POS+4, 13, s);
-    rb->lcd_putsxy(STAT_POS+1, 26, "Moves");
-    rb->snprintf(s, sizeof(s), "%d", current_info.level.moves);
-    rb->lcd_putsxy(STAT_POS+4, 36, s);
+                case '$': /* box */
+                    rb->lcd_drawrect(c, r, MAGNIFY, MAGNIFY);
+                    break;
 
-    rb->lcd_drawrect(STAT_POS, 0, STAT_SIZE, 24);
-    rb->lcd_drawrect(STAT_POS, 23, STAT_SIZE, 24);
+                case '*': /* box on goal */
+                    rb->lcd_drawrect(c, r, MAGNIFY, MAGNIFY);
+                    rb->lcd_drawrect(c + MAGNIFY/2 - 1, r + MAGNIFY/2 - 1,
+                                     MAGNIFY/2, MAGNIFY/2);
+                    break;
 
-#if LCD_HEIGHT >= 70
-    rb->lcd_putsxy(STAT_POS+1, 49, "Pushes");
-    rb->snprintf(s, sizeof(s), "%d", current_info.level.pushes);
-    rb->lcd_putsxy(STAT_POS+4, 59, s);
+                case '.': /* goal */
+                    rb->lcd_drawrect(c + MAGNIFY/2 - 1, r + MAGNIFY/2 - 1,
+                                     MAGNIFY/2, MAGNIFY/2);
+                    break;
 
-    rb->lcd_drawrect(STAT_POS, 46, STAT_SIZE, 24);
+                case '@': /* player */
+                case '+': /* player on goal */
+                    rb->lcd_drawline(c, r + middle, c + max, r + middle);
+                    rb->lcd_drawline(c + middle, r, c + middle,
+                                     r + max - ldelta);
+                    rb->lcd_drawline(c + max - middle, r, c + max - middle,
+                                     r + max - ldelta);
+                    rb->lcd_drawline(c + middle, r + max - ldelta,
+                                     c + middle - ldelta, r + max);
+                    rb->lcd_drawline(c + max - middle, r + max - ldelta,
+                                     c + max - middle + ldelta, r + max);
+                    break;
 #endif
-#endif
+            }
+        }
+    }
 
     /* print out the screen */
     rb->lcd_update();
@@ -717,22 +833,201 @@
     update_screen();
 }
 
+static bool save(char *filename, bool solution)
+{
+    int fd;
+
+    rb->splash(0, true, "Saving...");
+
+    if (filename[0] == 0)
+        return false;
+
+    if ((fd = rb->open(filename, O_WRONLY|O_CREAT|O_TRUNC)) < 0)
+        return false;
+
+    /* SB S/P for solution/progress : level number : current undo */
+    rb->snprintf(buf, sizeof(buf), "SB%c:%d:%d\n", (solution ? 'S' : 'P'),
+                 current_info.level.index + 1, undo_info.current);
+    rb->write(fd, buf, rb->strlen(buf));
+
+    /* Filename of levelset */
+    rb->write(fd, buffered_boards.filename,
+              rb->strlen(buffered_boards.filename));
+    rb->write(fd, "\n", 1);
+
+    /* Full undo history */
+    rb->write(fd, undo_info.history, undo_info.max);
+
+    rb->close(fd);
+
+    return true;
+}
+
+static bool load(char *filename)
+{
+    int fd;
+    int i = 0, n;
+    int len;
+    int button;
+    bool play_solution;
+
+    if (filename[0] == '\0' || (fd = rb->open(filename, O_RDONLY)) < 0)
+        return false;
+
+    /* Read header, level number, & current undo */
+    rb->read_line(fd, buf, sizeof(buf));
+
+    /* If we're opening a level file, not a solution/progress file */
+    if (buf[0] != 'S' && buf[1] != 'B') {
+        rb->close(fd);
+
+        rb->strncpy(buffered_boards.filename, filename, MAX_PATH);
+        if (!read_levels(true))
+            return false;
+
+        current_info.level.index = 0;
+        load_level();
+
+        /* If there aren't any boxes to go or the player position wasn't set,
+         * there was a problem loading the level */
+        return (current_info.level.boxes_to_go > 0 &&
+                current_info.player.row != 0 && current_info.player.col != 0);
+
+    } else {
+
+        /* Read filename of levelset */
+        rb->read_line(fd, buffered_boards.filename,
+                      sizeof(buffered_boards.filename));
+
+        /* Read full undo history */
+        len = rb->read_line(fd, undo_info.history, MAX_UNDOS);
+
+        /* Correct len if there are trailing \r's or \n's */
+        if (len > 2 && undo_info.history[len - 2] == '\0')
+            len -= 2;
+        else if (len > 1 && undo_info.history[len - 1] == '\0')
+            len--;
+
+        rb->close(fd);
+
+        /* Check to see if we're going to play a solution or resume progress */
+        play_solution = (buf[2] == 'S');
+
+        /* Get level number */
+        for (n = 0, i = 4; buf[i] >= '0' && buf[i] <= '9' && i < 9; i++)
+            n = n * 10 + buf[i] - '0';
+        current_info.level.index = n - 1;
+
+        /* Get current undo index */
+        for (n = 0, i++; buf[i] >= '0' && buf[i] <= '9' && i < 15; i++)
+            n = n * 10 + buf[i] - '0';
+        if (n > len)
+            n = len;
+
+        if (current_info.level.index < 0 || !read_levels(true) ||
+            current_info.level.index >= current_info.max_level)
+            return false;
+
+        load_level();
+
+        if (play_solution) {
+            rb->lcd_clear_display();
+            update_screen();
+            rb->sleep(HZ/2);
+
+            /* Replay solution until the end or quit button is pressed */
+            for (i = 0; i < len; i++) {
+                move(undo_info.history[i], true);
+
+                rb->lcd_clear_display();
+                update_screen();
+                rb->sleep(HZ/4);
+
+                /* Ignore keypresses except for quit */
+                while ((button = rb->button_get(false)) != BUTTON_NONE) {
+                    if (button == SOKOBAN_QUIT) {
+                        /* Pretend the level is complete so we'll quit */
+                        current_info.level.boxes_to_go = 0;
+                        return true;
+                    }
+                }
+            }
+
+            /* If level complete, wait for keypress before quitting */
+            if (current_info.level.boxes_to_go == 0)
+                rb->button_get(true);
+
+        } else {
+            /* Advance to current undo */
+            for (i = 0; i < n; i++)
+                move(undo_info.history[i], true);
+
+            rb->button_clear_queue();
+            rb->lcd_clear_display();
+        }
+
+        undo_info.max = len;
+        undo_info.current = n;
+    }
+
+    return true;
+}
+
+static int quit_menu(void)
+{
+    int m;
+    int res;
+
+    static const struct menu_item items[] = {
+        { "Save Progress & Quit", NULL },
+        { "Quit Without Saving", NULL },
+        { "Load Default Level Set", NULL },
+        { "Audio Playback", NULL },
+    };
+
+    m = rb->menu_init(items, sizeof(items) / sizeof(*items),
+                      NULL, NULL, NULL, NULL);
+    res = rb->menu_show(m);
+    rb->menu_exit(m);
+
+    switch (res) {
+        case 0: /* Save & quit */
+            save(SOKOBAN_SAVE_FILE, false);
+            rb->reload_directory();
+
+        case 1: /* Quit */
+#ifdef HAVE_LCD_COLOR   /* reset background color */
+            rb->lcd_set_background(rb->global_settings->bg_color);
+#endif
+            return 1;
+
+        case 2: /* Load default levelset */
+            init_boards();
+            if (!read_levels(true))
+                return 1;
+            load_level();
+            break;
+
+        case 3: /* Audio playback control */
+            playback_control(rb);
+    }
+
+    rb->lcd_setfont(FONT_SYSFIXED); /* Restore font */
+
+    return res;
+}
+
 static bool sokoban_loop(void)
 {
-    bool moved = true;
+    bool moved;
     int i = 0, button = 0, lastbutton = 0;
     short r = 0, c = 0;
     int w, h;
-    char s[25];
+    char *loc;
 
-    current_info.level.level = 1;
+    while (true) {
+        moved = false;
 
-    load_level();
-    update_screen();
-
-    while (1) {
-        moved = true;
-
         r = current_info.player.row;
         c = current_info.player.col;
 
@@ -744,23 +1039,28 @@
             case SOKOBAN_RC_QUIT:
 #endif
             case SOKOBAN_QUIT:
-                /* get out of here */
-#ifdef HAVE_LCD_COLOR /* reset background color */
-                rb->lcd_set_background(rb->global_settings->bg_color);
-#endif
-                return PLUGIN_OK;
+                switch (quit_menu()) {
+                    case 1: /* Quit */
+                        return PLUGIN_OK;
 
+                    case MENU_ATTACHED_USB:
+                        return PLUGIN_USB_CONNECTED;
+                }
+
+                rb->lcd_clear_display();
+                update_screen();
+                break;
+
             case SOKOBAN_UNDO:
 #ifdef SOKOBAN_UNDO_PRE
                 if (lastbutton != SOKOBAN_UNDO_PRE)
                     break;
-#else       /* repeat can't work here for Ondio et al */
+#else       /* repeat can't work here for Ondio, iPod, et al */
             case SOKOBAN_UNDO | BUTTON_REPEAT:
 #endif
                 undo();
                 rb->lcd_clear_display();
                 update_screen();
-                moved = false;
                 break;
 
 #ifdef SOKOBAN_REDO
@@ -776,22 +1076,20 @@
             case SOKOBAN_LEVEL_UP | BUTTON_REPEAT:
                 /* next level */
                 init_undo();
-                if (current_info.level.level < current_info.max_level)
-                    current_info.level.level++;
+                if (current_info.level.index + 1 < current_info.max_level)
+                    current_info.level.index++;
 
                 draw_level();
-                moved = false;
                 break;
 
             case SOKOBAN_LEVEL_DOWN:
             case SOKOBAN_LEVEL_DOWN | BUTTON_REPEAT:
                 /* previous level */
                 init_undo();
-                if (current_info.level.level > 1)
-                    current_info.level.level--;
+                if (current_info.level.index > 0)
+                    current_info.level.index--;
 
                 draw_level();
-                moved = false;
                 break;
 
 #ifdef SOKOBAN_LEVEL_REPEAT
@@ -800,7 +1098,6 @@
                 /* same level */
                 init_undo();
                 draw_level();
-                moved = false;
                 break;
 #endif
 
@@ -827,13 +1124,10 @@
             default:
                 if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
                     return PLUGIN_USB_CONNECTED;
-
-                moved = false;
                 break;
         }
 
-        if (button != BUTTON_NONE)
-            lastbutton = button;
+        lastbutton = button;
 
         if (moved) {
             rb->lcd_clear_display();
@@ -845,58 +1139,107 @@
 
             if (moved) {
                 rb->lcd_clear_display();
-                /* Center level completed message */
-                rb->snprintf(s, sizeof(s), "Level %d Complete!",
-                             current_info.level.level);
-                rb->lcd_getstringsize(s, &w, &h);
-                rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - 16 , s);
-                rb->snprintf(s, sizeof(s), "%4d Moves ",
+
+                /* Show level complete message & stats */
+                rb->snprintf(buf, sizeof(buf), "Level %d Complete!",
+                             current_info.level.index + 1);
+                rb->lcd_getstringsize(buf, &w, &h);
+                rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h*3, buf);
+
+                rb->snprintf(buf, sizeof(buf), "%4d Moves ",
                              current_info.level.moves);
-                rb->lcd_getstringsize(s, &w, &h);
-                rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + 0 , s);
-                rb->snprintf(s, sizeof(s), "%4d Pushes",
+                rb->lcd_getstringsize(buf, &w, &h);
+                rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h, buf);
+
+                rb->snprintf(buf, sizeof(buf), "%4d Pushes",
                              current_info.level.pushes);
-                rb->lcd_getstringsize(s, &w, &h);
-                rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + 8 , s);
+                rb->lcd_getstringsize(buf, &w, &h);
+                rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2, buf);
+
+                if (undo_info.count < MAX_UNDOS) {
+                    rb->snprintf(buf, sizeof(buf), "%s: Save solution",
+                                 BUTTON_SAVE_NAME);
+                    rb->lcd_getstringsize(buf, &w, &h);
+                    rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 + h*2, buf);
+                }
+
                 rb->lcd_update();
-                rb->button_get(false);
+                rb->sleep(HZ/4);
+                rb->button_clear_queue();
 
-                rb->sleep(HZ/2);
-                for (i = 0; i < 30; i++) {
+                /* Display for 3 seconds or until new keypress */
+                for (i = 0; i < 60; i++) {
                     rb->sleep(HZ/20);
                     button = rb->button_get(false);
-                    if (button && ((button & BUTTON_REL) != BUTTON_REL))
+                    if (button && !(button & BUTTON_REL) &&
+                        !(button & BUTTON_REPEAT))
                         break;
                 }
+
+                if (button == BUTTON_SAVE) {
+                    if (undo_info.count < MAX_UNDOS) {
+                        /* Default filename to current levelset plus
+                         * level number and .sb extension */
+                        loc = rb->strrchr(buffered_boards.filename, '.');
+                        if (loc != NULL)
+                            *loc = '\0';
+                        rb->snprintf(buf, sizeof(buf), "%s.%d.sb",
+                                     buffered_boards.filename,
+                                     current_info.level.index + 1);
+                        if (loc != NULL)
+                            *loc = '.';
+
+                        if (!rb->kbd_input(buf, MAX_PATH)) {
+                            if (!save(buf, true))
+                                rb->splash(HZ*2, true,
+                                           "Unable to save solution");
+                        }
+                    } else
+                        rb->splash(HZ*2, true, "Solution too long to save");
+
+                    rb->lcd_setfont(FONT_SYSFIXED); /* Restore font */
+                }
             }
 
-            current_info.level.level++;
+            current_info.level.index++;
 
             /* clear undo stats */
             init_undo();
 
             rb->lcd_clear_display();
 
-            if (current_info.level.level > current_info.max_level) {
-                /* Center "You WIN!!" on all screen sizes */
-                rb->snprintf(s, sizeof(s), "You WIN!!");
-                rb->lcd_getstringsize(s, &w, &h);
-                rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h/2, s);
+            if (current_info.level.index >= current_info.max_level) {
+                /* Show levelset complete message */
+                rb->snprintf(buf, sizeof(buf), "You WIN!!");
+                rb->lcd_getstringsize(buf, &w, &h);
+                rb->lcd_putsxy(LCD_WIDTH/2 - w/2, LCD_HEIGHT/2 - h/2, buf);
 
                 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
                 /* Display for 10 seconds or until keypress */
-                for (i = 0; i < 200; i++) {
+                for (i = 0; i < 100; i++) {
                     rb->lcd_fillrect(0, 0, LCD_WIDTH, LCD_HEIGHT);
                     rb->lcd_update();
-                    rb->sleep(HZ/20);
+                    rb->sleep(HZ/10);
 
                     button = rb->button_get(false);
-                    if (button && ((button & BUTTON_REL) != BUTTON_REL))
+                    if (button && !(button & BUTTON_REL))
                         break;
                 }
                 rb->lcd_set_drawmode(DRMODE_SOLID);
+                rb->lcd_clear_display();
 
-                return PLUGIN_OK;
+                /* Reset to first level & show quit menu */
+                current_info.level.index = 0;
+
+                switch (quit_menu()) {
+                    case 1: /* Quit */
+                        return PLUGIN_OK;
+
+                    case MENU_ATTACHED_USB:
+                        return PLUGIN_USB_CONNECTED;
+                }
+
+                rb->lcd_clear_display();
             }
 
             load_level();
@@ -913,7 +1256,7 @@
 {
     int w, h;
     int i;
-    int button = 0;
+    int button;
 
     (void)(parameter);
     rb = api;
@@ -930,18 +1273,41 @@
     rb->lcd_update();
     rb->sleep(HZ);
 
+    init_boards();
+
+    if (parameter == NULL) {
+        /* Attempt to resume saved progress, otherwise start at beginning */
+        if (!load(SOKOBAN_SAVE_FILE)) {
+            init_boards();
+            if (!read_levels(true))
+                return PLUGIN_OK;
+            load_level();
+        }
+
+    } else {
+        /* The plugin is being used to open a file */
+        if (load((char*) parameter)) {
+            /* If we loaded & played a solution, quit */
+            if (current_info.level.boxes_to_go == 0)
+                return PLUGIN_OK;
+        } else {
+            rb->splash(HZ*2, true, "Error loading file");
+            return PLUGIN_OK;
+        }
+    }
+
     rb->lcd_clear_display();
 
 #if (CONFIG_KEYPAD == RECORDER_PAD) || \
     (CONFIG_KEYPAD == ARCHOS_AV300_PAD)
-    rb->lcd_putsxy(3,  6, "[OFF] Quit");
+    rb->lcd_putsxy(3,  6, "[OFF] Menu");
     rb->lcd_putsxy(3, 16, "[ON] Undo");
     rb->lcd_putsxy(3, 26, "[PLAY] Redo");
     rb->lcd_putsxy(3, 36, "[F1] Down a Level");
     rb->lcd_putsxy(3, 46, "[F2] Restart Level");
     rb->lcd_putsxy(3, 56, "[F3] Up a Level");
 #elif CONFIG_KEYPAD == ONDIO_PAD
-    rb->lcd_putsxy(3,  6, "[OFF] Quit");
+    rb->lcd_putsxy(3,  6, "[OFF] Menu");
     rb->lcd_putsxy(3, 16, "[MODE] Undo");
     rb->lcd_putsxy(3, 26, "[MODE+DOWN] Redo");
     rb->lcd_putsxy(3, 36, "[MODE+LEFT] Down a Level");
@@ -949,7 +1315,7 @@
     rb->lcd_putsxy(3, 56, "[MODE+RIGHT] Up Level");
 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
       (CONFIG_KEYPAD == IRIVER_H300_PAD)
-    rb->lcd_putsxy(3,  6, "[STOP] Quit");
+    rb->lcd_putsxy(3,  6, "[STOP] Menu");
     rb->lcd_putsxy(3, 16, "[REC] Undo");
     rb->lcd_putsxy(3, 26, "[MODE] Redo");
     rb->lcd_putsxy(3, 36, "[PLAY+DOWN] Down a Level");
@@ -957,32 +1323,32 @@
     rb->lcd_putsxy(3, 56, "[PLAY+UP] Up a Level");
 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
       (CONFIG_KEYPAD == IPOD_3G_PAD)
-    rb->lcd_putsxy(3,  6, "[SELECT+MENU] Quit");
+    rb->lcd_putsxy(3,  6, "[SELECT+MENU] Menu");
     rb->lcd_putsxy(3, 16, "[SELECT] Undo");
     rb->lcd_putsxy(3, 26, "[SELECT+PLAY] Redo");
     rb->lcd_putsxy(3, 36, "[SELECT+LEFT] Down a Level");
     rb->lcd_putsxy(3, 46, "[SELECT+RIGHT] Up a Level");
 #elif CONFIG_KEYPAD == IAUDIO_X5_PAD
-    rb->lcd_putsxy(3,  6, "[POWER] Quit");
+    rb->lcd_putsxy(3,  6, "[POWER] Menu");
     rb->lcd_putsxy(3, 16, "[SELECT] Undo");
     rb->lcd_putsxy(3, 26, "[REC] Down a Level");
     rb->lcd_putsxy(3, 36, "[PLAY] Up Level");
 #elif CONFIG_KEYPAD == GIGABEAT_PAD
-    rb->lcd_putsxy(3,  6, "[A] Quit");
+    rb->lcd_putsxy(3,  6, "[A] Menu");
     rb->lcd_putsxy(3, 16, "[SELECT] Undo");
     rb->lcd_putsxy(3, 26, "[POWER] Redo");
     rb->lcd_putsxy(3, 36, "[MENU+DOWN] Down a Level");
     rb->lcd_putsxy(3, 46, "[MENU] Restart Level");
     rb->lcd_putsxy(3, 56, "[MENU+UP] Up Level");
 #elif CONFIG_KEYPAD == SANSA_E200_PAD
-    rb->lcd_putsxy(3,  6, "[POWER] Quit");
+    rb->lcd_putsxy(3,  6, "[POWER] Menu");
     rb->lcd_putsxy(3, 16, "[SELECT] Undo");
     rb->lcd_putsxy(3, 26, "[REC] Redo");
     rb->lcd_putsxy(3, 36, "[SELECT+DOWN] Down a Level");
     rb->lcd_putsxy(3, 46, "[SELECT+RIGHT] Restart Level");
     rb->lcd_putsxy(3, 56, "[SELECT+UP] Up Level");
 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
-    rb->lcd_putsxy(3,  6, "[POWER] Quit");
+    rb->lcd_putsxy(3,  6, "[POWER] Menu");
     rb->lcd_putsxy(3, 16, "[REW] Undo");
     rb->lcd_putsxy(3, 26, "[FF] Redo");
     rb->lcd_putsxy(3, 36, "[PLAY+DOWN] Down a Level");
@@ -991,21 +1357,19 @@
 #endif
 
     rb->lcd_update();
-    rb->button_get(false);
+    rb->button_clear_queue();
+
     /* Display for 3 seconds or until keypress */
     for (i = 0; i < 60; i++) {
         rb->sleep(HZ/20);
         button = rb->button_get(false);
-        if (button && ((button & BUTTON_REL) != BUTTON_REL))
+        if (button && !(button & BUTTON_REL) && !(button & BUTTON_REPEAT))
             break;
     }
+
     rb->lcd_clear_display();
+    update_screen();
 
-    init_boards();
-
-    if (read_levels(1) != 0)
-        return PLUGIN_OK;
-
     return sokoban_loop();
 }
 
Index: apps/plugins/sokoban.levels
===================================================================
--- apps/plugins/sokoban.levels	(revision 12499)
+++ apps/plugins/sokoban.levels	(working copy)
@@ -1,1816 +1,201 @@
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX###XXXXXXXXX
-XXXXXXXX#.#XXXXXXXXX
-XXXXXXXX# ####XXXXXX
-XXXXXX###$ $.#XXXXXX
-XXXXXX#. $@###XXXXXX
-XXXXXX####$#XXXXXXXX
-XXXXXXXXX#.#XXXXXXXX
-XXXXXXXXX###XXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+--3#|--#.#|--#-4#|3#$-$.#|#.-$@3#|4#$#|3-#.#|3-3#
 
+5#|#3-#|#@$$#-3#|#-$-#-#.#|3#-3#.#|-##4-.#|-#3-#--#|-#3-4#|-5#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXX#####XXXXXXXXXX
-XXXXX#   #XXXXXXXXXX
-XXXXX#@$$#X###XXXXXX
-XXXXX# $ #X#.#XXXXXX
-XXXXX### ###.#XXXXXX
-XXXXXX##    .#XXXXXX
-XXXXXX#   #  #XXXXXX
-XXXXXX#   ####XXXXXX
-XXXXXX#####XXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+-7#|-#5-3#|##$3#3-#|#-@-$--$-#|#-..#-$-##|##..#3-#|-8#
 
+3-5#|4#--.#|#3-$-*#|#-$$-$.#|##@##..#|-7#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX#######XXXXXXX
-XXXXXX#     ###XXXXX
-XXXXX##$###   #XXXXX
-XXXXX# @ $  $ #XXXXX
-XXXXX# ..# $ ##XXXXX
-XXXXX##..#   #XXXXXX
-XXXXXX########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+-4#|-#@-3#|-#-$--#|3#-#-##|#.#-#--#|#.$--#-#|#.3-$-#|8#
 
+3-7#|--##--#-@#|--#3-#--#|--#$-$-$-#|--#-$##--#|3#-$-#-##|#5.--#|9#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXX#####XXXXXX
-XXXXXX####  .#XXXXXX
-XXXXXX#   $ %#XXXXXX
-XXXXXX# $$ $.#XXXXXX
-XXXXXX##@##..#XXXXXX
-XXXXXXX#######XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+3-6#|-3#4-#|##.-$##-##|#..$-$--@#|#..-$-$-##|6#--#|5-4#
 
+--6#|--#4-#|3#3$-#|#@-$..-#|#-$3.##|4#--#|3-4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXX####XXXXXXXXX
-XXXXXXX#@ ###XXXXXXX
-XXXXXXX# $  #XXXXXXX
-XXXXXX### # ##XXXXXX
-XXXXXX#.# #  #XXXXXX
-XXXXXX#.$  # #XXXXXX
-XXXXXX#.   $ #XXXXXX
-XXXXXX########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+--4#|--#..#|-##-.##|-#--$.#|##-$--##|#--#$$-#|#--@3-#|8#
 
+--5#|3#--@#|#--$.-##|#--.$.-#|3#-*$-#|--#3-##|--5#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX#######XXXXX
-XXXXXXX##  # @#XXXXX
-XXXXXXX#   #  #XXXXX
-XXXXXXX#$ $ $ #XXXXX
-XXXXXXX# $##  #XXXXX
-XXXXX### $ # ##XXXXX
-XXXXX#.....  #XXXXXX
-XXXXX#########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+8#|#--#3-#|#-$..$-#|#@$.*-##|#-$..$-#|#--#3-#|8#
 
+--6#|--#4-3#|--#-$4-#|3#-$-##-#|#3.-$3-#|#3.$#$-##|4#-#-$-#|3-#--@--#|3-7#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX######XXXXXX
-XXXXXX###    #XXXXXX
-XXXXX##. $## ##XXXXX
-XXXXX#..$ $  @#XXXXX
-XXXXX#.. $ $ ##XXXXX
-XXXXX######  #XXXXXX
-XXXXXXXXXX####XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+6#|#4-#|#-3$##|#--#..3#|##--..$-#|-#-@4-#|-8#
 
+--8#|--#3-#.-#|-##--$3.#|-#--$-#*.#|##-##$#-##|#3-$--$-#|#3-#4-#|7#@-#|6-4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX######XXXXXX
-XXXXXXXX#    #XXXXXX
-XXXXXX###$$$ #XXXXXX
-XXXXXX#@ $.. #XXXXXX
-XXXXXX# $...##XXXXXX
-XXXXXX####  #XXXXXXX
-XXXXXXXXX####XXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+-7#|-#4.-#|3#3.$3#|#--$#$-$-#|#-$$--#$-#|#4-#3-#|4#-@-3#|3-5#
 
+8#|#..4-#|#..$-$@#|#$#3$##|#..$-$-#|#..4-#|8#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX####XXXXXXXX
-XXXXXXXX#..#XXXXXXXX
-XXXXXXX## .##XXXXXXX
-XXXXXXX#  $.#XXXXXXX
-XXXXXX## $  ##XXXXXX
-XXXXXX#  #$$ #XXXXXX
-XXXXXX#  @   #XXXXXX
-XXXXXX########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+8#|#6-#|#-#$$--#|#-3.#-#|##3.$-##|-#-##-$-#|-#$--$--#|-#--#--@#|-8#
 
+--5#|3#3-4#|#3-$-$--#|#-$3-$-@#|3#$$5#|--#--..#|--#4.#|--6#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX#####XXXXXXX
-XXXXXX###  @#XXXXXXX
-XXXXXX#  $. ##XXXXXX
-XXXXXX#  .$. #XXXXXX
-XXXXXX### %$ #XXXXXX
-XXXXXXXX#   ##XXXXXX
-XXXXXXXX#####XXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+9#|#3-*3-#|#-$.$.-@#|#-.$.$.-#|#-$.$.$-#|#3-*3-#|9#
 
+-9#|##7-#|#3-#$#$-#|#-$$--.$.#|#-@3#3.#|4#-5#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX########XXXXXX
-XXXXXX#  #   #XXXXXX
-XXXXXX# $..$ #XXXXXX
-XXXXXX#@$.% ##XXXXXX
-XXXXXX# $..$ #XXXXXX
-XXXXXX#  #   #XXXXXX
-XXXXXX########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+-6#|-#.-..#|-#.-$.#|3#--$##|#-$--$-#|#-#$##-#|#3-@--#|8#
 
+-5#|-#3-4#|##-#$3-#|#-$--$$-#|#-#$#.*.#|#3-@3.#|9#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXX######XXXXXXX
-XXXXXXX#    ###XXXXX
-XXXXXXX# $    #XXXXX
-XXXXX### $ ## #XXXXX
-XXXXX#... $   #XXXXX
-XXXXX#...$#$ ##XXXXX
-XXXXX#### # $ #XXXXX
-XXXXXXXX#  @  #XXXXX
-XXXXXXXX#######XXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+3-5#|4#3-##|#-$-$3-#|#@#.*.#-#|#-#.*.#-#|#3-$-$-#|##3-4#|-5#
 
+3-5#|4#.--##|#-$.$.--#|#@$#-#$-#|#-$.-.--#|4#$#$-#|--#.-.--#|--7#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX######XXXXXXXX
-XXXXXX#    #XXXXXXXX
-XXXXXX# $$$##XXXXXXX
-XXXXXX#  #..###XXXXX
-XXXXXX##  ..$ #XXXXX
-XXXXXXX# @    #XXXXX
-XXXXXXX########XXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+3-8#|4#4-.-#|#--$-$-$.-#|#--.4#.##|#-$.$-$-@#|#--.4-##|9#
 
+7#|#5-5#|#-$-.*.-$-#|#@$.*-*.$-#|#-$-.*.-$-#|6#4-#|5-6#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXX########XXXXX
-XXXXXXX#   #. #XXXXX
-XXXXXX##  $...#XXXXX
-XXXXXX#  $ #%.#XXXXX
-XXXXX## ##$# ##XXXXX
-XXXXX#   $  $ #XXXXX
-XXXXX#   #    #XXXXX
-XXXXX#######@ #XXXXX
-XXXXXXXXXXX####XXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+6#|#4-#|#-$--4#|#-$*..*-#|#-*..*$-#|4#--$-#|3-#-@--#|3-6#
 
+3-6#|4#.--@#|#--3$--#|#.##.##.#|#3-$3-#|#--$.#-##|4#3-#|3-5#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX#######XXXXXXX
-XXXXXX#.... #XXXXXXX
-XXXXX###...$###XXXXX
-XXXXX#  $#$ $ #XXXXX
-XXXXX# $$  #$ #XXXXX
-XXXXX#    #   #XXXXX
-XXXXX#### @ ###XXXXX
-XXXXXXXX#####XXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+9#|#.--$.-@#|#-.$.$--#|##$.$-$##|#-.$.$--#|#.--$.--#|9#
 
+7#|#--@--#|##$-$-#|#--$$##|#4.#|6#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX########XXXXXX
-XXXXXX#..    #XXXXXX
-XXXXXX#..$ $@#XXXXXX
-XXXXXX#$#$$$##XXXXXX
-XXXXXX#..$ $ #XXXXXX
-XXXXXX#..    #XXXXXX
-XXXXXX########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+-4#|-#--5#|##$-##--#|#--$@$--#|#3-##$-#|3#.##-3#|-#3.$-$-#|-##..4-#|--8#
 
+8#|#--#..-##|#-$.-$*-#|#--$@$--#|#-*$-.$-#|##-..#--#|-8#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXX########XXXXXXX
-XXXXX#      #XXXXXXX
-XXXXX# #$$  #XXXXXXX
-XXXXX# ...# #XXXXXXX
-XXXXX##...$ ##XXXXXX
-XXXXXX# ## $ #XXXXXX
-XXXXXX#$  $  #XXXXXX
-XXXXXX#  #  @#XXXXXX
-XXXXXX########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+-7#|##--*--##|#-.-.-.-#|#-$-*3-#|#*$$*$$*#|#3-*-$-#|#-.-.@.-#|##--*--##|-7#
 
+9#|#3-.$-@#|#-$-*-$-#|#*3.*.*#|#-$$*3-#|#3-.-$-#|9#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXX#####XXXXXXXX
-XXXXX###   ####XXXXX
-XXXXX#   $ $  #XXXXX
-XXXXX# $   $ @#XXXXX
-XXXXX###$$#####XXXXX
-XXXXXXX#  ..#XXXXXXX
-XXXXXXX#....#XXXXXXX
-XXXXXXX######XXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+5-6#|-5#.3-#|-#--#..##-#|-#--$..3-#|-#--#-.#-##|3#-##$#--#|#-$4-$$-#|#-#$#--#--#|#@--7#|5#
 
+3-6#|3-#-3.#|4#4.#|#--3#$-3#|#-$-$--$$-#|#@-$-$4-#|#--4#3-#|4#--5#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXX#########XXXXXX
-XXXXX#   %   #XXXXXX
-XXXXX# $.$. @#XXXXXX
-XXXXX# .$.$. #XXXXXX
-XXXXX# $.$.$ #XXXXXX
-XXXXX#   %   #XXXXXX
-XXXXX#########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+-9#|-#--##3-#|-#3-$3-#|-#$-3#-$#|-#-#3.#-#|##-#3.#-##|#-$--$--$-#|#5-#-@-#|11#
 
+3-7#|-3#5-#|##3-#-#-#|#--#.3$-#|#-#.*#-3#|#--..#-#|3#..$-##|--#.#-$-#|-##-#-#@#|-#-$--$-#|-#4-3#|-6#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX#########XXXXX
-XXXXX##       #XXXXX
-XXXXX#   #$#$ #XXXXX
-XXXXX# $$  .$.#XXXXX
-XXXXX# @###...#XXXXX
-XXXXX####X#####XXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+-10#|##8-#|#@-3$-$--#|##-$--$-$-#|-##-4#-##|--#4-$-##|3#-##$-$-#|#4-#4-#|#4-6#|#4-##|#5.#|#5.#|7#
 
+8#|#6-#|#-@-$#-#|##-#3-#|#-$#.#-#|#--.*.$#|##-#.#-#|-#-#.--##|##-$.#--#|#--#-$--#|#-$3-3#|#--4#|4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXX######XXXXXXX
-XXXXXXX#. ..#XXXXXXX
-XXXXXXX#. $.#XXXXXXX
-XXXXXX###  $##XXXXXX
-XXXXXX# $  $ #XXXXXX
-XXXXXX# #$## #XXXXXX
-XXXXXX#   @  #XXXXXX
-XXXXXX########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+7-4#|7-#@-#|3-5#--#|4#6-#|#3-.3#-##|#-#-#4-##|#-#-$-$#.-#|#-#--*--#-#|#-.#$-$-#-#|##4-#-#-#|-#-3#.3-#|-#5-4#|-7#
 
+5#|#3-##|#--$-#|#-$-@#|3#.-#|--#.##|--#.-#|3#.-#|#--$-#|#-$--#|##--##|-4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX#####XXXXXXXXX
-XXXXXX#   ####XXXXXX
-XXXXX## #$   #XXXXXX
-XXXXX# $  $$ #XXXXXX
-XXXXX# #$#.%.#XXXXXX
-XXXXX#   @...#XXXXXX
-XXXXX#########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+4#|#--5#|#--#3-#|#-.--#-#|##$#--.#|-#-#$#-#|##.--.-#|#--##--#|#--#--*#|#-$--$-#|#-$#*-@#|#--#.3#|6#
 
+3-3#|3-#.6#|-3#.$-#--#|-#3.--#$-#|-#.##-$3-#|##.$-$##-##|#.$-#-##-#|#.#$5-#|#.$--#$-$#|#.-$##-@-#|#.$4-$-#|#.-7#|4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXX#####XXXXXX
-XXXXXX####   ##XXXXX
-XXXXXX# $ $   #XXXXX
-XXXXXX#@#.%.# #XXXXX
-XXXXXX# #.%.# #XXXXX
-XXXXXX#   $ $ #XXXXX
-XXXXXX##   ####XXXXX
-XXXXXXX#####XXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+4-4#|--3#--##|-##5-##|-#3-#-..#|##-$#*#$.#|#--$-#-$.#|#--$-@-$.#|#--$-#-$.#|##$$#*#$.#|-#.--#-..#|-##.4-##|--3#--##|4-4#
 
+9#|#7-#|#-#-3#-#|#-$$--#-#|#@$3-#-#|##-##-#-#|#3-$-$-#|#-$##-#-#|#3-#$#-#|#3.#3-#|#.#.#$3#|#3.--#|7#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX#####XXXXXXX
-XXXXX####.  ##XXXXXX
-XXXXX# $.$.  #XXXXXX
-XXXXX#@$# #$ #XXXXXX
-XXXXX# $. .  #XXXXXX
-XXXXX####$#$ #XXXXXX
-XXXXXXX#. .  #XXXXXX
-XXXXXXX#######XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+8#|#5-.#|#-#$#..##|#3-$3.#|##-##.$.#|-#-##--##|-#$##--#|##3-#$#|#--#3-#|#3-$-4#|#-$-$3-@#|#--3#3-#|4#-5#
 
+4#|#--4#|#--$--#|#-#.#-#|#-#-#-#|#.$.$.#|#-#-#-#|#-#.#-#|#--$$-#|##-@--#|-#--3#|-4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX########XXXX
-XXXXX####    . #XXXX
-XXXXX#  $ $ $. #XXXX
-XXXXX#  .####.##XXXX
-XXXXX# $.$ $ @#XXXXX
-XXXXX#  .    ##XXXXX
-XXXXX#########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+6#-4#|#4-3#--#|#-$$--##--#|#--#-$4-#|##-##-$#--#|-#-#3.--##|-#--3.#$##|-#-#3.#--#|##-#-3#@-#|#--$-$--$-#|#-#$4#--#|#3-#--4#|5#
 
+10#|#..$-$-*.#|#.*-$-$..#|##.$-$-*##|-#*-$-$.#|-#.$-$-.#|-#.-$-$.#|-#.$@$-*#|##*-$-$.##|#..$-$-*.#|#.*-$-$..#|10#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXX#######XXXXXXXX
-XXXXX#     #####XXXX
-XXXXX# $ .%. $ #XXXX
-XXXXX#@$.% %.$ #XXXX
-XXXXX# $ .%. $ #XXXX
-XXXXX######    #XXXX
-XXXXXXXXXX######XXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+4-5#|4-#3-#|4-#$--#|--3#--$##|--#--$-$-#|3#-#-##-#3-6#|#3-#-##-5#--..#|#-$--$10-..#|5#-3#-#@##--..#|4-#5-9#|4-7#
 
+12#|#..--#5-3#|#..--#-$--$--#|#..--#$4#--#|#..4-@-##--#|#..--#4-$-##|6#-##$-$-#|--#-$--$-$-$-#|--#4-#5-#|--12#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXX######XXXXXXXXX
-XXXXX#    #XXXXXXXXX
-XXXXX# $  ####XXXXXX
-XXXXX# $%..% #XXXXXX
-XXXXX# %..%$ #XXXXXX
-XXXXX####  $ #XXXXXX
-XXXXXXXX# @  #XXXXXX
-XXXXXXXX######XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+8-8#|8-#5-@#|8-#-$#$-##|8-#-$--$#|8-##$-$-#|9#-$-#-3#|#4.--##-$--$--#|##3.4-$--$3-#|#4.--10#|8#
 
+11-8#|11-#--4.#|12#--4.#|#4-#--$-$3-4.#|#-3$#$--$-#--4.#|#--$5-$-#--4.#|#-$$-#$-$-$8#|#--$-#5-#|##-9#|#4-#4-##|#5-$3-##|#--$$#$$--@#|#4-#4-##|11#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXX######XXXXX
-XXXXXX####.  @#XXXXX
-XXXXXX#  $$$  #XXXXX
-XXXXXX#.##.##.#XXXXX
-XXXXXX#   $   #XXXXX
-XXXXXX#  $.# ##XXXXX
-XXXXXX####   #XXXXXX
-XXXXXXXXX#####XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+8-5#|8-#3-5#|8-#-#$##--#|8-#5-$-#|9#-3#3-#|#4.--##-$--$3#|#4.4-$-$$-##|#4.--##$--$-@#|9#--$--##|8-#-$-$--#|8-3#-##-#|10-#4-#|10-6#
 
+6#--3#|#..--#-##@##|#..--3#3-#|#..5-$$-#|#..--#-#-$-#|#..3#-#-$-#|4#-$-#$--#|3-#--$#-$-#|3-#-$--$--#|3-#--##3-#|3-9#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX#########XXXXX
-XXXXXX#.  $. @#XXXXX
-XXXXXX# .$.$  #XXXXX
-XXXXXX##$.$ $##XXXXX
-XXXXXX# .$.$  #XXXXX
-XXXXXX#.  $.  #XXXXX
-XXXXXX#########XXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+7-5#|-7#3-##|##-#-@##-$$-#|#4-$6-#|#--$--3#3-#|3#-5#$3#|#-$--3#-..#|#-$-$-$-3.#|#4-3#3.#|#-$$-#-#3.#|#--3#-5#|4#
 
+--4#|--#--11#|--#4-$3-$-$-#|--#-$#-$-#--$--#|--#--$-$--#4-#|3#-$#-#--4#-#|#@#$-$-$--##3-#|#4-$-#$#3-#-#|#3-$4-$-$-$-#|5#--9#|--#6-#|--#6.#|--#6.#|--#6.#|--8#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXX#######XXXXXX
-XXXXXXX#  @  #XXXXXX
-XXXXXXX##$ $ #XXXXXX
-XXXXXXX#  $$##XXXXXX
-XXXXXXX#....#XXXXXXX
-XXXXXXX######XXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+10-7#|10-#--3.#|6-5#--3.#|6-#6-.-.#|6-#--##--3.#|6-##-##--3.#|5-3#-8#|5-#-3$-##|-5#--$-$-5#|##3-#$-$3-#3-#|#@-$--$4-$--$-#|6#-$$-$-5#|5-#6-#|5-8#
 
+-3#--13#|##@4#7-#3-#|#-$$3-$$--$-$-3.#|#--3$#4-$--#3.#|#-$3-#-$$-$$-#3.#|3#3-#--$4-#3.#|#5-#-$-$-$-#3.#|#4-6#-3#3.#|##-#--#--$-$--#3.#|#--##-#-$$-$-$##..#|#-..#-#--$6-#.#|#-..#-#-3$-3$-#.#|5#-#7-#-#.#|4-#-9#-#.#|4-#11-#.#|4-15#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX####XXXXXXXXXX
-XXXXXX#  #####XXXXXX
-XXXXX##$ ##  #XXXXXX
-XXXXX#  $@$  #XXXXXX
-XXXXX#   ##$ #XXXXXX
-XXXXX###.## ###XXXXX
-XXXXXX#...$ $ #XXXXX
-XXXXXX##..    #XXXXX
-XXXXXXX########XXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+10-4#|5-4#-#--#|3-3#--3#$-#|--##3-@--$--#|-##--$-$$##-##|-#--#$##5-#|-#-#-$-$$-#-3#|-#3-$-#--#-$-5#|4#4-#--$$-#3-#|4#-##-$9-#|#.4-3#--8#|#..-..#-4#|#3.#.#|#5.#|7#
 
+16#|#14-#|#-#-6#5-#|#-#--$-$-$-$#--#|#-#3-$@$3-##-##|#-#-#$-$-$3#3.#|#-#3-$-$--##3.#|#-3#3$-$-##3.#|#5-#-##-##3.#|5#3-##-##3.#|4-5#5-3#|8-#5-#|8-7#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX########XXXXXX
-XXXXXX#  #.. ##XXXXX
-XXXXXX# $. $% #XXXXX
-XXXXXX#  $@$  #XXXXX
-XXXXXX# %$ .$ #XXXXX
-XXXXXX## ..#  #XXXXX
-XXXXXXX########XXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+3-9#|--##3-##--6#|3#5-#--#4-3#|#--$-#$-#--#--3.-#|#-#-$#@$##-#-#.#.-#|#--#-#$--#4-.-.-#|#-$4-$-#-#-#.#.-#|#3-##--##$-$-.-.-#|#-$-#3-#--#$#.#.-#|##-$--$3-$--$3.-#|-#$-6#4-##--#|-#--#4-10#|-4#
 
+7-7#|-7#5-#|-#5-#-$@$-#|-#$$-#3-9#|-#-3#6.##3-#|-#3-$6.##-#-#|-#-3#6.5-#|##3-4#-3#-#$##|#--#$3-#--$--#-#|#--$-3$--#-$##-#|#3-$-$-3#$$-#-#|5#5-$3-#-#|4-3#-3#3-#-#|6-#5-#3-#|6-8#--#|13-4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX#######XXXXXXX
-XXXXX##  %  ##XXXXXX
-XXXXX# . . . #XXXXXX
-XXXXX# $ %   #XXXXXX
-XXXXX#%$$%$$%#XXXXXX
-XXXXX#   % $ #XXXXXX
-XXXXX# . .@. #XXXXXX
-XXXXX##  %  ##XXXXXX
-XXXXXX#######XXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+3-8#|3-#3-#--#|3-#--$3-#|-3#-#$3-4#|-#--$--##$3-#|-#--#-@-$-#-$#|-#--#6-$-4#|-##-4#$##5-#|-#-$#5.#-#3-#|-#--$..**.-$#-3#|##--#5.#3-#|#3-3#-7#|#-$$--#--#|#--#5-#|6#3-#|5-5#
 
+5#|#3-##|#4-#--4#|#-$--4#--#|#--$$-$3-$#|3#@-#$4-##|-#--##--$-$-##|-#-$--##-##-.#|-#--#$##$--#.#|-3#3-$..##.#|--#4-#.*3.#|--#-$$-#5.#|--#--9#|--#--#|--4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXX#########XXXXXX
-XXXXX#   .$ @#XXXXXX
-XXXXX# $ % $ #XXXXXX
-XXXXX#%...%.%#XXXXXX
-XXXXX# $$%   #XXXXXX
-XXXXX#   . $ #XXXXXX
-XXXXX#########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+3-10#|3-#..--#3-#|3-#..6-#|3-#..--#--4#|--7#--#--##|--#12-#|--#--#--##--#--#|4#-##--4#-##|#--$--5#-#--#|#-#-$--$--#-$--#|#-@$--$3-#3-##|4#-##-7#|3-#4-#|3-6#
 
+5-11#|5-#--.--#3-#|5-#-#.4-@-#|-5#-##..#-4#|##--#-..3#5-3#|#-$-#3.3-$-#--$-#|#4-..-##--##-##-#|4#$##$#-$-#3-#-#|--##-#4-#$-$$-#-#|--#--$-#-#--#-$##-#|--#15-#|--#--11#--#|--4#9-4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXX######XXXXX
-XXXXX#####.   #XXXXX
-XXXXX#  #..## #XXXXX
-XXXXX#  $..   #XXXXX
-XXXXX#  # .# ##XXXXX
-XXXX### ##$#  #XXXXX
-XXXX# $    $$ #XXXXX
-XXXX# #$#  #  #XXXXX
-XXXX#@  #######XXXXX
-XXXX#####XXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+--6#|--#3-@4#|5#-$3-#|#3-##4-4#|#-$-#--##4-#|#-$-#--5#-#|##-$--$4-#-#|##-$-$-3#-#-#|##-#--$--#-#-#|##-#-#$#3-#-#|##-3#3-#-#-6#|#--$--4#-#-#4.#|#4-$4-$3-..#.#|4#$--$#-$3-4.#|#7-#--##-4.#|19#
 
+4-10#|5#8-4#|#5-#3-$--#@-#|#-7#$4#--3#|#-#4-##-#--#$-..#|#-#-$--$--#--#--#.#|#-#-$--#5-#$-..#|#-#--3#-##5-#.#|#-3#--#--#--#$-..#|#-#4-#-$4#--#.#|#-#$3-$--$--#*-..#|#4-$-#-$-$-#--#.#|4#-$3#4-#*-..#|3-#4-$$-3#4.#|3-#6-##-6#|3-8#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXX######XXXXXXX
-XXXXXXX# ...#XXXXXXX
-XXXX####....#XXXXXXX
-XXXX#  ###$ ###XXXXX
-XXXX# $ $  $$ #XXXXX
-XXXX#@ $ $    #XXXXX
-XXXX#  ####   #XXXXX
-XXXX####XX#####XXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+9#|#7-#|#7-4#|##-4#-#--#|##-#@##4-#|#-3$-$--$$#|#--#-##-$--#|#--#-##--$-4#|4#--3$-$#--#|-#3-##3-4.#|-#-#3-#-#..-.#|-#3-#-#-##3.#|-5#-$--#3.#|5-##3-5#|6-5#
 
+6#5-4#|#4-7#--5#|#3-$#--#--$--#3-#|#--$--$--$-#-$-$--#|##$-$3-#-@#-$4-#|#--$-11#-##|#-#3-#7.#-$#|#-##--#-6.#--#|#-#3-$8.$-#|#-#-$-#4.-..#--#|#--$-$4#$4#-$#|#-$3-3#-$3-$--##|#-$5-$-$--$4-#|##-6#-$-5#-#|#9-#7-#|19#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX#########XXXXX
-XXXXXX#  ##   #XXXXX
-XXXXXX#   $   #XXXXX
-XXXXXX#$ ### $#XXXXX
-XXXXXX# #...# #XXXXX
-XXXXX## #...# ##XXXX
-XXXXX# $  $  $ #XXXX
-XXXXX#     # @ #XXXX
-XXXXX###########XXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+4-7#|4-#--#--4#|5#-$#$-#--##|#..-#--#--#3-4#|#..-#-$#$-#--$#--#|#.--#5-#$--#--#|#..3-$#--#-$4-#|#..@#--#$-#$--#--#|#..-#-$#5-$#--#|#..-#--#$$#$--#--##|#..-#-$#--#--$#$--#|#..-#--#--#3-#3-#|##.-4#--5#3-#|-4#--4#3-5#
 
+15#|#10.--.4#|#10.$$.#--#|11#$-#3-##|#6-$--$5-$-#|##-4#3-#--$-#--#|#6-#3-##--#-##|#--$#--#-##--3#-##|#-$-#$3#4-3#-##|3#--$-#--#--3#-##|-##4-$-##-#--#-##|-#-$--#--$--$-$3-#|-#--$--$#3$--#3-#|-#--#--$6-5#|-#-@##--#5-#|-14#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX#######XXXXX
-XXXXXX###     #XXXXX
-XXXXX##   # # #XXXXX
-XXXXX#  #.$$$ #XXXXX
-XXXXX# #.%# ###XXXXX
-XXXXX#  ..# #XXXXXXX
-XXXXX###..$ ##XXXXXX
-XXXXXXX#.# $ #XXXXXX
-XXXXXX## # #@#XXXXXX
-XXXXXX# $  $ #XXXXXX
-XXXXXX#    ###XXXXXX
-XXXXXX######XXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+4#|#--14#|#--#3-..#6.#|#--#-#-5#-3.#|##$#4-8.#|#3-##$6#--4#|#-$-#5-6#@-#|##$-#-$3-6#--#|#--$-#3$##7-#|#6-#4-#$#$3#|#-4#-#5$4-#|#-#4-$5-#3-#|#-#3-##-##5-3#|#-6#$6#-$-#|#8-#4-#3-#|10#4-5#
 
+-7#|-#--#--5#|##--#--#3.3#|#--$#--#3.--#|#-$-#$$-3.--#|#--$#--#3.-.#|#3-#-$8#|##$7-$-$-#|##--#--$$-#3-#|-6#--##$$@#|6-#6-##|6-8#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX##########XXXX
-XXXXX##        #XXXX
-XXXXX#@ $$$ $  #XXXX
-XXXXX## $  $ $ #XXXX
-XXXXXX## #### ##XXXX
-XXXXXXX#    $ ##XXXX
-XXXXX### ##$ $ #XXXX
-XXXXX#    #    #XXXX
-XXXXX#    ######XXXX
-XXXXX#    ##XXXXXXXX
-XXXXX#.....#XXXXXXXX
-XXXXX#.....#XXXXXXXX
-XXXXX#######XXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+-17#|-#3.3-#4-#3-##|##5.--$##-#-#$-#|#6.#--$--#4-#|#6.#--#--#-#--#|9#-$--$-$--#|--#5-#$##$-##$##|-##3-$4-#-$4-#|-#--##-3#-#--##$-#|-#-$-$$5-$--$--#|-#-$4-$##$-6#|-7#--@-##|7-6#
 
+9-5#|5-5#3-#|4-##-$--$--4#|5#-$--$-$-##.#|#7-$$--##..#|#--6#-3#..-#|##-#--#4-#3.-#|#-$3-#4-#3.-#|#@-#$-##-4#3.#|4#--$-$$--##..#|3-##--$-$--$3.#|4-#-$$--$-#--.#|4-#3-$-$--4#|4-6#3-#|9-5#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXX########XXXXXXX
-XXXXX#      #XXXXXXX
-XXXXX# @ $# #XXXXXXX
-XXXXX## #   #XXXXXXX
-XXXXX# $#.# #XXXXXXX
-XXXXX#  .%.$#XXXXXXX
-XXXXX## #.# #XXXXXXX
-XXXXXX# #.  ##XXXXXX
-XXXXX## $.#  #XXXXXX
-XXXXX#  # $  #XXXXXX
-XXXXX# $   ###XXXXXX
-XXXXX#  ####XXXXXXXX
-XXXXX####XXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+5#|#3-##|#-$--9#|##-#-#7-6#|##-#3-$#$#@--#3-#|#--#6-$-#3-$-#|#--3#-9#-##|#--##-..*5.-#-##|##-##-*.*..*.*-#-##|#-$10#-##$-#|#--$3-$--$4-$--#|#--#3-#3-#3-#--#|19#
 
+7-11#|7-#3-#5-#|5#--#5-$-$-#|#3-5#-$##-#-##|#-$-##3-#-##-$--#|#-$--@$$-#-##3$-#|##-3#3-#-##4-#|##-#3-3#-5#$#|##-#5-$--#4.#|#--3#-##-$-#4.##|#-$3-$-#3-#..$.-#|#--##-$-#--##4.-#|5#3-6#3.##|4-5#4-5#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXX####XXXXX
-XXXXXXXXXXX#@ #XXXXX
-XXXXXXX#####  #XXXXX
-XXXX####      #XXXXX
-XXXX#   .### ##XXXXX
-XXXX# # #    ##XXXXX
-XXXX# # $ $#. #XXXXX
-XXXX# #  %  # #XXXXX
-XXXX# .#$ $ # #XXXXX
-XXXX##    # # #XXXXX
-XXXXX# ###.   #XXXXX
-XXXXX#     ####XXXXX
-XXXXX#######XXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+--4#|--#--9#|-##--##--#3-#|-#--$#-$@$3-4#|-#$--$--#-$-$#--##|##--$##-#$-$5-#|#--#--#-#3-3$--#|#-$4-$--$##-4#|#-$-$-#$#--#--#|##--3#--3#$-#|-#--#4.5-#|-4#6.4#|3-#4.4#|3-#3.##|3-#3.#|3-5#
 
+6-4#|--5#--#|-##5-$#|##-$--##-3#|#@$-$-#-$--#|4#-##3-$#|-#4.#$-$-#|-#4.#3-$#|-#4.--$$-##|-#3.-#-$3-#|-6#$-$--#|6-#3-3#|6-#$-3#|6-#--#|6-4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXX#####XXXXXXXX
-XXXXXXX#   ##XXXXXXX
-XXXXXXX#  $ #XXXXXXX
-XXXXXXX# $ @#XXXXXXX
-XXXXXXX###. #XXXXXXX
-XXXXXXXXX#.##XXXXXXX
-XXXXXXXXX#. #XXXXXXX
-XXXXXXX###. #XXXXXXX
-XXXXXXX#  $ #XXXXXXX
-XXXXXXX# $  #XXXXXXX
-XXXXXXX##  ##XXXXXXX
-XXXXXXXX####XXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+12#|##5-##--#|##3-$3-$-#|4#-##-$$-#|#3-$-#4-#|#-3$-#-4#|#3-#-#-$-##|#--#--#--$-#|#-$#-$#4-#|#3-..#-4#|4#..-$-#@#|#5.#-$#-#|##4.#--$-#|3#..##4-#|12#
 
+-9#|-#4.3-##|-#.#.#--$-##|##4.#-#-@##|#-4.#--#--##|#5-#$-##$-#|##-3#--$4-#|-#$--$-$-$#--#|-#-#--$-$-##-#|-#--3#--##--#|-#4-##-##-##|-#--$-#--$--#|-3#$-$3-3#|3-#--5#|3-4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX####XXXXXXXXXX
-XXXXXX#  #####XXXXXX
-XXXXXX#  #   #XXXXXX
-XXXXXX# .  # #XXXXXX
-XXXXXX##$#  .#XXXXXX
-XXXXXXX# #$# #XXXXXX
-XXXXXX##.  . #XXXXXX
-XXXXXX#  ##  #XXXXXX
-XXXXXX#  #  %#XXXXXX
-XXXXXX# $  $ #XXXXXX
-XXXXXX# $#% @#XXXXXX
-XXXXXX#  #.###XXXXXX
-XXXXXX######XXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+12#-6#|#3-#4-#-3#4.#|#3-$$#3-@--5.#|#3-#-3#3-#-4.#|##-##-3#--#--4.#|-#-$-$5-#-#-4#|-#--$-$##--#6-#|4#-#--4#-#-##-#|#--#-#$3-##-#4-#|#-$--$--#-##-#3-##|#-#-$-$4-#-#3-#|#--$-##-##-#-5#|#-$$5-$$--#|##-##-3#-$--#|-#4-#-#4-#|-6#-6#
 
+12-5#|5#--6#3-#|#3-4#--$-$-$-#|#-$3-##-##-##--##|#3-$-$5-$--$-#|3#-$--##-##5-##|--#-5#-5#$$-#|-##$5#-@##5-#|-#-$--3#$3#-$--##|-#-$--#3-3#--3#|-#-$$-$-#3-$$-#|-#5-#3-##--#|-7#..-.4#|4-#9.#|4-#9.#|4-11#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX###XXXXXXXXX
-XXXXXXXX#.######XXXX
-XXXXXX###.$ #  #XXXX
-XXXXXX#...  #$ #XXXX
-XXXXXX#.## $   #XXXX
-XXXXX##.$ $## ##XXXX
-XXXXX#.$ # ## #XXXXX
-XXXXX#.#$     #XXXXX
-XXXXX#.$  #$ $#XXXXX
-XXXXX#. $## @ #XXXXX
-XXXXX#.$    $ #XXXXX
-XXXXX#. #######XXXXX
-XXXXX####XXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+11#|#6.3-9#|#6.3-#--##3-#|#..3#-$4-$5-#|#3.-$-$-#--3#3-#|#3.#$5#4-#--#|3#4-#3-#$--#$-#|--#--$$-$-$--$##--#|--#--$3-#$#$-##$-#|--3#-##-#4-##--#|3-#--$-$-##-6#|3-#4-$--$--#|3-##3-#-#3-#|4-5#@5#|8-3#
 
+6-4#|7#-@#|#5-$--#|#3-$##-$#|##$#3.#-#|-#-$3.--#|-#-#.-.#-##|-#3-#-#$-#|-#$--$4-#|-#--7#|-4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXX####XXXXXXX
-XXXXXXX###  ##XXXXXX
-XXXXXX##     ##XXXXX
-XXXXXX#   # ..#XXXXX
-XXXXX## $#%#$.#XXXXX
-XXXXX#  $ # $.#XXXXX
-XXXXX#  $ @ $.#XXXXX
-XXXXX#  $ # $.#XXXXX
-XXXXX##$$#%#$.#XXXXX
-XXXXXX#.  # ..#XXXXX
-XXXXXX##.    ##XXXXX
-XXXXXXX###  ##XXXXXX
-XXXXXXXXX####XXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+13-6#|-13#4.#|##3-##5-##4.#|#--$$##--$-@##4.#|#6-$$-$#--4.#|#--$-##-$$-#-#-3.#|#--$-##-$--#--4.#|##-5#-3#-##.3#|##3-$--$-##3-.--#|#-$3#--#-5#-3#|#3-$3-#7-#|#--$-#$-$-$3#--#|#-3$#-$3-#-4#|#4-#--$$-#|6#3-3#|5-5#
 
+4-12#|4-#10-##|4-#--#-#$$-$--#|4-#$-#$#--##-@#|3-##-##-#-$-#-##|3-#3-$-#$--#-#|3-#3-#-$3-#-#|3-##-$-$3-##-#|3-#--#--##--$-#|3-#4-##-$$#-#|6#$$3-#3-#|#4.#--8#|#.#3.-##|#4.3-#|#4.3-#|9#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX#########XXXXX
-XXXXXX#       #XXXXX
-XXXXXX# # ### #XXXXX
-XXXXXX# $$  # #XXXXX
-XXXXXX#@$   # #XXXXX
-XXXXXX## ## # #XXXXX
-XXXXXX#   $ $ #XXXXX
-XXXXXX# $## # #XXXXX
-XXXXXX#   #$# #XXXXX
-XXXXXX#...#   #XXXXX
-XXXXXX#.#.#$###XXXXX
-XXXXXX#...  #XXXXXXX
-XXXXXX#######XXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+11-5#|10-##3-##|9-##5-#|8-##--$$--#|7-##-$$--$-#|7-#-$4-$-#|4#3-#3-$$-5#|#--8#-##4-#|#.12-3$@#|#.#-7#-##3-##|#.#-7#.-#$-$##|#11.-#4-#|14#--$-#|13-##--##|14-4#
 
+5-8#|--4#6-6#|--#4-##-$-$3-@#|--#-##-##$#$-$-$##|3#-6.#--$$-##|#3-6.#--#3-#|#-#-6.#$--$--#|#-#-6.-$$#-$-#|#--$3#-3#$--$-##|3#--$--$--$--$-#|--#--$--$--$--$-#|--6#3-6#|7-5#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXX########XXXXXXX
-XXXXX#     .#XXXXXXX
-XXXXX# #$#..##XXXXXX
-XXXXX#   $...#XXXXXX
-XXXXX## ##.$.#XXXXXX
-XXXXXX# ##  ##XXXXXX
-XXXXXX#$##  #XXXXXXX
-XXXXX##   #$#XXXXXXX
-XXXXX#  #   #XXXXXXX
-XXXXX#   $ ####XXXXX
-XXXXX# $ $   @#XXXXX
-XXXXX#  ###   #XXXXX
-XXXXX####X#####XXXXX
-XXXXXXXXXXXXXXXXXXXX
+8-7#|4-5#--#--4#|4-#3-#3-$4-#|-4#-#$$-##-##--#|##6-#-#--##-3#|#--3#-$#$--$--$--#|#3.4-#-##--#3-#|#3.#4-@-#-3#-##|#3.#--3#--$--$--#|8#-##3-#3-#|10-9#
 
+-5#|-#3-#|-#-#-7#|-#6-$@6#|-#-$-##$-3#3-#|-#-4#-$4-$-#|-#-5#-#--#$-4#|##--4#-##$6-#|#--$#--$--#-##-##-#|#9-#-#3.#-#|6#--3#--3.--#|5-4#-#-#3.#-#|10-#-3#-#-#|10-#7-#|10-9#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX####XXXXXXXXXX
-XXXXXX#  ####XXXXXXX
-XXXXXX#  $  #XXXXXXX
-XXXXXX# #.# #XXXXXXX
-XXXXXX# # # #XXXXXXX
-XXXXXX#.$.$.#XXXXXXX
-XXXXXX# # # #XXXXXXX
-XXXXXX# #.# #XXXXXXX
-XXXXXX#  $$ #XXXXXXX
-XXXXXX## @  #XXXXXXX
-XXXXXXX#  ###XXXXXXX
-XXXXXXX####XXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+5#-4#|#3.#-#--4#|#3.3#--$--#|#4.##-$--$3#|##4.##3-$--#|3#3.-##-$-$-#|#-##4-#--$--#|#--##-#-3#-4#|#-$-#-#$--$4-#|#--$-@-$4-$--#|#3-#-$-$$-$-3#|#--6#--3#|#-##4-4#|3#
 
+10#|#8-4#|#-6#-#--##|#-#-$-$-$--$-#|#7-#$3-#|3#$--$$#--3#|--#--##-#-$##|--##$#3-$-@#|3-#--$-$-3#|3-#-#3-$--#|3-#-##3-#-#|--##--5#-#|--#9-#|--#7.3#|--#7.#|--9#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXX######X####XXXXX
-XXXX#    ###  #XXXXX
-XXXX# $$  ##  #XXXXX
-XXXX#  # $    #XXXXX
-XXXX## ## $#  #XXXXX
-XXXXX# #...  ##XXXXX
-XXXXX#  ...#$##XXXXX
-XXXXX# #...#  #XXXXX
-XXXX## # ###@ #XXXXX
-XXXX#  $ $  $ #XXXXX
-XXXX# #$####  #XXXXX
-XXXX#   #XX####XXXXX
-XXXX#####XXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+9-4#|-9#--##|##--$6-$-5#|#3-##-##3-##3.#|#-#$$-$-$$#$##3.#|#-#4-@--#3-3.#|#--$#-3#$$3-3.#|#-$--$$--$-##4.#|3#$7-7#|--#--7#|--4#
 
+--9#|--#*.*#*.*#|--#.*.*.*.#|--#*.*.*.*#|--#.*.*.*.#|--#*.*.*.*#|--3#3-3#|4-#3-#|6#-6#|#11-#|#-$-$-$-$-$-#|##-$-$-$-$-##|-#$-$-$-$-$#|-#3-$@$3-#|-#--5#--#|-4#3-4#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXX##########XXXXX
-XXXXX#..$ $ %.#XXXXX
-XXXXX#.% $ $..#XXXXX
-XXXXX##.$ $ %##XXXXX
-XXXXXX#% $ $.#XXXXXX
-XXXXXX#.$ $ .#XXXXXX
-XXXXXX#. $ $.#XXXXXX
-XXXXXX#.$@$ %#XXXXXX
-XXXXX##% $ $.##XXXXX
-XXXXX#..$ $ %.#XXXXX
-XXXXX#.% $ $..#XXXXX
-XXXXX##########XXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
+7-4#|7-#--##|7-#3-##|7-#-$$-##|5-3#$--$-##|--4#4-$3-#|3#--#-5#--#|#4-#-#4.$-#|#-#3-$-4.#-#|#--$-#-#.*..#-#|3#--4#-3#-#|--4#-@$--##$##|5-3#-$5-#|7-#--##3-#|7-9#
 
+6-12#|5-##..8-#|4-##..*-$4-$-#|3-##..*.#-#-#$-##|3-#..*.#-#-#-$--#|4#3.#--#4-#-#|#--##-#10-#|#-@$-$-3#--#-#-##|#-$3-$3-#-#3-#|3#$$3-#-#-#-#-#|--#3-$3-#-#-5#|--#-$#-5#6-#|--#$3-#3-#3-#--#|--#--3#3-##5-#|--#--#6-#4-##|--4#6-6#
 
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXX#####XXXXXXXXXXX
-XXXX#   #XXXXXXXXXXX
-XXXX#$  #XXXXXXXXXXX
-XX###  $##XXXXXXXXXX
-XX#  $ $ #XXXXXXXXXX
-### # ## #XXX######X
-#   # ## #####  ..#X
-# $  $          ..#X
-##### ### #@##  ..#X
-XXXX#     #########X
-XXXX#######XXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXX############XXXXX
-XXX#..  #     ###XXX
-XXX#..  # $  $  #XXX
-XXX#..  #$####  #XXX
-XXX#..    @ ##  #XXX
-XXX#..  #    $ ##XXX
-XXX###### ##$ $ #XXX
-XXXXX# $  $ $ $ #XXX
-XXXXX#    #     #XXX
-XXXXX############XXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXX########XXX
-XXXXXXXXX#     @#XXX
-XXXXXXXXX# $#$ ##XXX
-XXXXXXXXX# $  $#XXXX
-XXXXXXXXX##$ $ #XXXX
-X######### $ # ###XX
-X#....  ## $  $  #XX
-X##...    $  $   #XX
-X#....  ##########XX
-X########XXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXX########
-XXXXXXXXXXXX#  ....#
-X############  ....#
-X#    #  $ $   ....#
-X# $$$#$  $ #  ....#
-X#  $     $ #  ....#
-X# $$ #$ $ $########
-X#  $ #     #XXXXXXX
-X## #########XXXXXXX
-X#    #    ##XXXXXXX
-X#     $   ##XXXXXXX
-X#  $$#$$  @#XXXXXXX
-X#    #    ##XXXXXXX
-X###########XXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXX#####XXXXXX
-XXXXXXXXX#   #####XX
-XXXXXXXXX# #$##  #XX
-XXXXXXXXX#     $ #XX
-X######### ###   #XX
-X#....  ## $  $###XX
-X#....    $ $$ ##XXX
-X#....  ##$  $ @#XXX
-X#########  $  ##XXX
-XXXXXXXXX# $ $  #XXX
-XXXXXXXXX### ## #XXX
-XXXXXXXXXXX#    #XXX
-XXXXXXXXXXX######XXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXX######XX###XXXXX
-XXXX#..  #X##@##XXXX
-XXXX#..  ###   #XXXX
-XXXX#..     $$ #XXXX
-XXXX#..  # # $ #XXXX
-XXXX#..### # $ #XXXX
-XXXX#### $ #$  #XXXX
-XXXXXXX#  $# $ #XXXX
-XXXXXXX# $  $  #XXXX
-XXXXXXX#  ##   #XXXX
-XXXXXXX#########XXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXX#####XXXX
-XXXXX#######   ##XXX
-XXXX## # @## $$ #XXX
-XXXX#    $      #XXX
-XXXX#  $  ###   #XXX
-XXXX### #####$###XXX
-XXXX# $  ### ..#XXXX
-XXXX# $ $ $ ...#XXXX
-XXXX#    ###...#XXXX
-XXXX# $$ #X#...#XXXX
-XXXX#  ###X#####XXXX
-XXXX####XXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXX####XXXXXXXXXXXX
-XXXX#  ###########XX
-XXXX#    $   $ $ #XX
-XXXX# $# $ #  $  #XX
-XXXX#  $ $  #    #XX
-XX### $# #  #### #XX
-XX#@#$ $ $  ##   #XX
-XX#    $ #$#   # #XX
-XX#   $    $ $ $ #XX
-XX#####  #########XX
-XXXX#      #XXXXXXXX
-XXXX#......#XXXXXXXX
-XXXX#......#XXXXXXXX
-XXXX#......#XXXXXXXX
-XXXX########XXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXX#######XX
-XXXXXXXXXXX#  ...#XX
-XXXXXXX#####  ...#XX
-XXXXXXX#      . .#XX
-XXXXXXX#  ##  ...#XX
-XXXXXXX## ##  ...#XX
-XXXXXX### ########XX
-XXXXXX# $$$ ##XXXXXX
-XX#####  $ $ #####XX
-X##   #$ $   #   #XX
-X#@ $  $    $  $ #XX
-X###### $$ $ #####XX
-XXXXXX#      #XXXXXX
-XXXXXX########XXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-X###XX#############X
-##@####       #   #X
-# $$   $$  $ $ ...#X
-#  $$$#    $  #...#X
-# $   # $$ $$ #...#X
-###   #  $    #...#X
-#     # $ $ $ #...#X
-#    ###### ###...#X
-## #  #  $ $  #...#X
-#  ## # $$ $ $##..#X
-# ..# #  $      #.#X
-# ..# # $$$ $$$ #.#X
-##### #       # #.#X
-XXXX# ######### #.#X
-XXXX#           #.#X
-XXXX###############X
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXX####XXXXX
-XXXXXX####X#  #XXXXX
-XXXX###  ###$ #XXXXX
-XXX##   @  $  #XXXXX
-XX##  $ $$## ##XXXXX
-XX#  #$##     #XXXXX
-XX# # $ $$ # ###XXXX
-XX#   $ #  # $ #####
-X####    #  $$ #   #
-X#### ## $         #
-X#.    ###  ########
-X#.. ..#X####XXXXXXX
-X#...#.#XXXXXXXXXXXX
-X#.....#XXXXXXXXXXXX
-X#######XXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XX################XX
-XX#              #XX
-XX# # ######     #XX
-XX# #  $ $ $ $#  #XX
-XX# #   $@$   ## ##X
-XX# # #$ $ $###...#X
-XX# #   $ $  ##...#X
-XX# ###$$$ $ ##...#X
-XX#     # ## ##...#X
-XX#####   ## ##...#X
-XXXXXX#####     ###X
-XXXXXXXXXX#     #XXX
-XXXXXXXXXX#######XXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXX#########XXXXXXXX
-XX##   ##  ######XXX
-###     #  #    ###X
-#  $ #$ #  #  ... #X
-# # $#@$## # #.#. #X
-#  # #$  #    . . #X
-# $    $ # # #.#. #X
-#   ##  ##$ $ . . #X
-# $ #   #  #$#.#. #X
-## $  $   $  $... #X
-X#$ ######    ##  #X
-X#  #XXXX##########X
-X####XXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXX#######XXXXX
-XX#######     #XXXXX
-XX#     # $@$ #XXXXX
-XX#$$ #   #########X
-XX# ###......##   #X
-XX#   $......## # #X
-XX# ###......     #X
-X##   #### ### #$##X
-X#  #$   #  $  # #XX
-X#  $ $$$  # $## #XX
-X#   $ $ ###$$ # #XX
-X#####     $   # #XX
-XXXXX### ###   # #XX
-XXXXXXX#     #   #XX
-XXXXXXX########  #XX
-XXXXXXXXXXXXXX####XX
-
-
-XXXXX########XXXXXXX
-XXXXX#   #  #XXXXXXX
-XXXXX#  $   #XXXXXXX
-XXX### #$   ####XXXX
-XXX#  $  ##$   #XXXX
-XXX#  # @ $ # $#XXXX
-XXX#  #      $ ####X
-XXX## ####$##     #X
-XXX# $#.....# #   #X
-XXX#  $..%%. $# ###X
-XX##  #.....#   #XXX
-XX#   ### #######XXX
-XX# $$  #  #XXXXXXXX
-XX#  #     #XXXXXXXX
-XX######   #XXXXXXXX
-XXXXXXX#####XXXXXXXX
-
-
-XXX#####XXXXXXXXXXXX
-XXX#   ##XXXXXXXXXXX
-XXX#    #XX####XXXXX
-XXX# $  ####  #XXXXX
-XXX#  $$ $   $#XXXXX
-XXX###@ #$    ##XXXX
-XXXX#  ##  $ $ ##XXX
-XXXX# $  ## ## .#XXX
-XXXX#  #$##$  #.#XXX
-XXXX###   $..##.#XXX
-XXXXX#    #.%...#XXX
-XXXXX# $$ #.....#XXX
-XXXXX#  #########XXX
-XXXXX#  #XXXXXXXXXXX
-XXXXX####XXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXX##########XXXXX
-XXXXX#..  #   #XXXXX
-XXXXX#..      #XXXXX
-XXXXX#..  #  ####XXX
-XXXX#######  #  ##XX
-XXXX#            #XX
-XXXX#  #  ##  #  #XX
-XX#### ##  #### ##XX
-XX#  $  ##### #  #XX
-XX# # $  $  # $  #XX
-XX# @$  $   #   ##XX
-XX#### ## #######XXX
-XXXXX#    #XXXXXXXXX
-XXXXX######XXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXX###########XXXX
-XXXXX#  .  #   #XXXX
-XXXXX# #.    @ #XXXX
-X##### ##..# ####XXX
-##  # ..###     ###X
-# $ #...   $ #  $ #X
-#    .. ##  ## ## #X
-####$##$# $ #   # #X
-XX## #    #$ $$ # #X
-XX#  $ # #  # $## #X
-XX#               #X
-XX#  ###########  #X
-XX####XXXXXXXXX####X
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXX######XXXXXXXXXXX
-XXX#   @####XXXXXXXX
-X##### $   #XXXXXXXX
-X#   ##    ####XXXXX
-X# $ #  ##    #XXXXX
-X# $ #  ##### #XXXXX
-X## $  $    # #XXXXX
-X## $ $ ### # #XXXXX
-X## #  $  # # #XXXXX
-X## # #$#   # #XXXXX
-X## ###   # # ######
-X#  $  #### # #....#
-X#    $    $   ..#.#
-X####$  $# $   ....#
-X#       #  ## ....#
-X###################
-
-
-XXXXX##########XXXXX
-X#####        ####XX
-X#     #   $  #@ #XX
-X# #######$####  ###
-X# #    ## #  #$ ..#
-X# # $  $  #  #  #.#
-X# # $  #     #$ ..#
-X# #  ### ##     #.#
-X# ###  #  #  #$ ..#
-X# #    # $####  #.#
-X# #$   $  $  #% ..#
-X#    $ # $ $ #  #.#
-X#### $###    #% ..#
-XXXX#    $$ ###....#
-XXXX#      ##X######
-XXXX########XXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXX#########XXXXXXXX
-XXX#       #XXXXXXXX
-XXX#       ####XXXXX
-XXX## #### #  #XXXXX
-XXX## #@##    #XXXXX
-XXX# $$$ $  $$#XXXXX
-XXX#  # ## $  #XXXXX
-XXX#  # ##  $ ####XX
-XXX####  $$$ $#  #XX
-XXXX#   ##   ....#XX
-XXXX# #   # #.. .#XX
-XXXX#   # # ##...#XX
-XXXX##### $  #...#XX
-XXXXXXXX##   #####XX
-XXXXXXXXX#####XXXXXX
-
-
-X######XXXXX####XXXX
-X#    #######  #####
-X#   $#  #  $  #   #
-X#  $  $  $ # $ $  #
-X##$ $   # @# $    #
-X#  $ ########### ##
-X# #   #.......# $#X
-X# ##  # ......#  #X
-X# #   $........$ #X
-X# # $ #.... ..#  #X
-X#  $ $####$#### $#X
-X# $   ### $   $  ##
-X# $     $ $  $    #
-X## ###### $ ##### #
-X#         #       #
-X###################
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXX#######XXXXXXXX
-XXXXX#  #  ####XXXXX
-X##### $#$ #  ##XXXX
-X#.. #  #  #   ####X
-X#.. # $#$ #  $#  #X
-X#.  #     #$  #  #X
-X#..   $#  # $    #X
-X#..@#  #$ #$  #  #X
-X#.. # $#     $#  #X
-X#.. #  #$$#$  #  ##
-X#.. # $#  #  $#$  #
-X#.. #  #  #   #   #
-X##. ####  #####   #
-XX####XX####XXX#####
-XXXXXXXXXXXXXXXXXXXX
-
-
-X###############XXXX
-X#..........  .####X
-X#..........$$.#  #X
-X###########$ #   ##
-X#      $  $     $ #
-X## ####   #  $ #  #
-X#      #   ##  # ##
-X#  $#  # ##  ### ##
-X# $ #$###    ### ##
-X###  $ #  #  ### ##
-XX##    $ ## #  # ##
-XX# $  #  $  $ $   #
-XX#  $  $#$$$  #   #
-XX#  #  $      #####
-XX# @##  #     #XXXX
-XX##############XXXX
-
-
-X####XXXXXXXXXXXXXXX
-X#  ##############XX
-X#  #   ..#......#XX
-X#  # # ##### ...#XX
-X##$#    ........#XX
-X#   ##$######  ####
-X# $ #     ######@ #
-X##$ # $   ######  #
-X#  $ #$$$##       #
-X#      #    #$#$###
-X# #### #$$$$$    #X
-X# #    $     #   #X
-X# #   ## ##     ###
-X# ######$###### $ #
-X#        #XXXX#   #
-X##########XXXX#####
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXX#######XXXXXXXXXX
-XXX#  #  #####XXXXXX
-XX##  #  #...###XXXX
-XX#  $#  #...  #XXXX
-XX# $ #$$ ...  #XXXX
-XX#  $#  #... .#XXXX
-XX#   # $########XXX
-XX##$       $ $ #XXX
-XX##  #  $$ #   #XXX
-XXX######  ##$$@#XXX
-XXXXXXXX#      ##XXX
-XXXXXXXX########XXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-X#################XX
-X#...   #    #   ##X
-##.....  $## # #$ #X
-#......#  $  #    #X
-#......#  #  # #  #X
-######### $  $ $  #X
-XX#     #$##$ ##$##X
-X##   $    # $    #X
-X#  ## ### #  ##$ #X
-X# $ $$     $  $  #X
-X# $    $##$ ######X
-X#######  @ ##XXXXXX
-XXXXXXX######XXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXX#####XXXX
-XXXXXXX#####   #XXXX
-XXXXXX## $  $  ####X
-XX##### $  $ $ ##.#X
-XX#       $$  ##..#X
-XX#  ###### ###.. #X
-XX## #  #    #... #X
-XX# $   #    #... #X
-XX#@ #$ ## ####...#X
-XX####  $ $$  ##..#X
-XXXXX##  $ $  $...#X
-XXXXXX# $$  $ #  .#X
-XXXXXX#   $ $  ####X
-XXXXXX######   #XXXX
-XXXXXXXXXXX#####XXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-X#####XXXXXXXXXXXXXX
-X#   ##XXXXXXXXXXXXX
-X# $  #########XXXXX
-X## # #       ######
-X## #   $#$#@  #   #
-X#  #      $ #   $ #
-X#  ### ######### ##
-X#  ## ..%..... # ##
-X## ## %.%..%.% # ##
-X# $########## ##$ #
-X#  $   $  $    $  #
-X#  #   #   #   #  #
-X###################
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX###########X
-XXXXXXXX#   #     #X
-X#####XX#     $ $ #X
-X#   ##### $## # ##X
-X# $ ##   # ## $  #X
-X# $  @$$ # ##$$$ #X
-X## ###   # ##    #X
-X## #   ### #####$#X
-X## #     $  #....#X
-X#  ### ## $ #....##
-X# $   $ #   #..$. #
-X#  ## $ #  ##.... #
-X#####   ######...##
-XXXXX#####XXXX#####X
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXX####XXXXXXXXXXXXX
-XXX#  #########XXXXX
-XX##  ##  #   #XXXXX
-XX#  $# $@$   ####XX
-XX#$  $  # $ $#  ##X
-X##  $## #$ $     #X
-X#  #  # #   $$$  #X
-X# $    $  $## ####X
-X# $ $ #$#  #  #XXXX
-X##  ###  ###$ #XXXX
-XX#  #....     #XXXX
-XX####......####XXXX
-XXXX#....####XXXXXXX
-XXXX#...##XXXXXXXXXX
-XXXX#...#XXXXXXXXXXX
-XXXX#####XXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXX####XXXXXX
-XXXXXX#####  #XXXXXX
-XXXXX##     $#XXXXXX
-XXXX## $  ## ###XXXX
-XXXX#@$ $ # $  #XXXX
-XXXX#### ##   $#XXXX
-XXXXX#....#$ $ #XXXX
-XXXXX#....#   $#XXXX
-XXXXX#....  $$ ##XXX
-XXXXX#... # $   #XXX
-XXXXX######$ $  #XXX
-XXXXXXXXXX#   ###XXX
-XXXXXXXXXX#$ ###XXXX
-XXXXXXXXXX#  #XXXXXX
-XXXXXXXXXX####XXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXX############XXXX
-XXXX##     ##  #XXXX
-XXXX##   $   $ #XXXX
-XXXX#### ## $$ #XXXX
-XXXX#   $ #    #XXXX
-XXXX# $$$ # ####XXXX
-XXXX#   # # $ ##XXXX
-XXXX#  #  #  $ #XXXX
-XXXX# $# $#    #XXXX
-XXXX#   ..# ####XXXX
-XXXX####.. $ #@#XXXX
-XXXX#.....# $# #XXXX
-XXXX##....#  $ #XXXX
-XXXX###..##    #XXXX
-XXXX############XXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXX#########XXXXXXX
-XXXX#....   ##XXXXXX
-XXXX#.#.#  $ ##XXXXX
-XXX##....# # @##XXXX
-XXX# ....#  #  ##XXX
-XXX#     #$ ##$ #XXX
-XXX## ###  $    #XXX
-XXXX#$  $ $ $#  #XXX
-XXXX# #  $ $ ## #XXX
-XXXX#  ###  ##  #XXX
-XXXX#    ## ## ##XXX
-XXXX#  $ #  $  #XXXX
-XXXX###$ $   ###XXXX
-XXXXXX#  #####XXXXXX
-XXXXXX####XXXXXXXXXX
-
-
-############X######X
-#   #    # ###....#X
-#   $$#   @  .....#X
-#   # ###   # ....#X
-## ## ###  #  ....#X
-X# $ $     # # ####X
-X#  $ $##  #      #X
-#### #  #### # ## #X
-#  # #$   ## #    #X
-# $  $  # ## #   ##X
-# # $ $    # #   #XX
-#  $ ## ## # #####XX
-# $$     $$  #XXXXXX
-## ## ### $  #XXXXXX
-X#    #X#    #XXXXXX
-X######X######XXXXXX
-
-
-XXXXXXXXXXXXX#####XX
-X#####XX######   #XX
-X#   ####  $ $ $ #XX
-X# $   ## ## ##  ##X
-X#   $ $     $  $ #X
-X### $  ## ##     ##
-XXX# ##### #####$$ #
-XX##$##### @##     #
-XX# $  ###$### $  ##
-XX# $  #   ###  ###X
-XX# $$ $ #   $$ #XXX
-XX#     #   ##  #XXX
-XX#######.. .####XXX
-XXXXX#.........#XXXX
-XXXXX#.........#XXXX
-XXXXX###########XXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-###########XXXXXXXXX
-#......   #########X
-#......   #  ##   #X
-#..### $    $     #X
-#... $ $ #  ###   #X
-#...#$#####    #  #X
-###    #   #$  #$ #X
-XX#  $$ $ $  $##  #X
-XX#  $   #$#$ ##$ #X
-XX### ## #    ##  #X
-XXX#  $ $ ## ######X
-XXX#    $  $  #XXXXX
-XXX##   # #   #XXXXX
-XXXX#####@#####XXXXX
-XXXXXXXX###XXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXX####XXXXXX
-XXXX####### @#XXXXXX
-XXXX#     $  #XXXXXX
-XXXX#   $## $#XXXXXX
-XXXX##$#...# #XXXXXX
-XXXXX# $...  #XXXXXX
-XXXXX# #. .# ##XXXXX
-XXXXX#   # #$ #XXXXX
-XXXXX#$  $    #XXXXX
-XXXXX#  #######XXXXX
-XXXXX####XXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXX######
-XX#############....#
-X##   ##     ##....#
-X#  $$##  $ @##....#
-X#      $$ $#  ....#
-X#  $ ## $$ # # ...#
-X#  $ ## $  #  ....#
-X## ##### ### ##.###
-X##   $  $ ##   .  #
-X# $###  # ##### ###
-X#   $   #       #XX
-X#  $ #$ $ $###  #XX
-X# $$$# $   #X####XX
-X#    #  $$ #XXXXXXX
-X######   ###XXXXXXX
-XXXXXX#####XXXXXXXXX
-
-
-XXXXXX############XX
-XXXXXX#          ##X
-XXXXXX#  # #$$ $  #X
-XXXXXX#$ #$#  ## @#X
-XXXXX## ## # $ # ##X
-XXXXX#   $ #$  # #XX
-XXXXX#   # $   # #XX
-XXXXX## $ $   ## #XX
-XXXXX#  #  ##  $ #XX
-XXXXX#    ## $$# #XX
-XX######$$   #   #XX
-XX#....#  ########XX
-XX#.#... ##XXXXXXXXX
-XX#....   #XXXXXXXXX
-XX#....   #XXXXXXXXX
-XX#########XXXXXXXXX
-
-
-XXXXXXXXXXX#####XXXX
-XXXXXXXXXX##   ##XXX
-XXXXXXXXX##     #XXX
-XXXXXXXX##  $$  #XXX
-XXXXXXX## $$  $ #XXX
-XXXXXXX# $    $ #XXX
-####XXX#   $$ #####X
-#  ######## ##    #X
-#.            $$$@#X
-#.# ####### ##   ##X
-#.# #######. #$ $##X
-#........... #    #X
-##############  $ #X
-XXXXXXXXXXXXX##  ##X
-XXXXXXXXXXXXXX####XX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXX########XXXXXX
-XXX####      ######X
-XXX#    ## $ $   @#X
-XXX# ## ##$#$ $ $##X
-X### ......#  $$ ##X
-X#   ......#  #   #X
-X# # ......#$  $  #X
-X# # ...... $$# $ #X
-X#  $### ###$  $ ##X
-X###  $  $  $  $ #XX
-XXX#  $  $  $  $ #XX
-XXX######   ######XX
-XXXXXXXX#####XXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXX#######XXXXX
-XXXX#####  #  ####XX
-XXXX#   #   $    #XX
-X#### #$$ ## ##  #XX
-##      # #  ## ###X
-#  ### $#$  $  $  #X
-#...    # ##  #   #X
-#...#    @ # ### ##X
-#...#  ###  $  $  #X
-########X##   #   #X
-XXXXXXXXXX#########X
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-X#####XXXXXXXXXXXXXX
-X#   #XXXXXXXXXXXXXX
-X# # #######XXXXXXXX
-X#      $@######XXXX
-X# $ ##$ ###   #XXXX
-X# #### $    $ #XXXX
-X# ##### #  #$ ####X
-##  #### ##$      #X
-#  $#  $  # ## ## #X
-#         # #...# #X
-######  ###  ...  #X
-XXXXX####X# #...# #X
-XXXXXXXXXX# ### # #X
-XXXXXXXXXX#       #X
-XXXXXXXXXX#########X
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXX#####X####XXXXXXX
-XXX#...#X#  ####XXXX
-XXX#...###  $  #XXXX
-XXX#....## $  $###XX
-XXX##....##   $  #XX
-XXX###... ## $ $ #XX
-XXX# ##    #  $  #XX
-XXX#  ## # ### ####X
-XXX# $ # #$  $    #X
-XXX#  $ @ $    $  #X
-XXX#   # $ $$ $ ###X
-XXX#  ######  ###XXX
-XXX# ##XXXX####XXXXX
-XXX###XXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXX##########XXXXXXX
-XXX#        ####XXXX
-XXX# ###### #  ##XXX
-XXX# # $ $ $  $ #XXX
-XXX#       #$   #XXX
-XXX###$  $$#  ###XXX
-XXXXX#  ## # $##XXXX
-XXXXX##$#   $ @#XXXX
-XXXXXX#  $ $ ###XXXX
-XXXXXX# #   $  #XXXX
-XXXXXX# ##   # #XXXX
-XXXXX##  ##### #XXXX
-XXXXX#         #XXXX
-XXXXX#.......###XXXX
-XXXXX#.......#XXXXXX
-XXXXX#########XXXXXX
-
-
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXX####XXXXXX
-XX#########  ##XXXXX
-X##  $      $ #####X
-X#   ## ##   ##...#X
-X# #$$ $ $$#$##...#X
-X# #    @  #   ...#X
-X#  $# ###$$   ...#X
-X# $  $$  $ ##....#X
-X###$       #######X
-XXX#  #######XXXXXXX
-XXX####XXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXX#########XXXXXX
-XXXXX#%.%#%.%#XXXXXX
-XXXXX#.%.%.%.#XXXXXX
-XXXXX#%.%.%.%#XXXXXX
-XXXXX#.%.%.%.#XXXXXX
-XXXXX#%.%.%.%#XXXXXX
-XXXXX###   ###XXXXXX
-XXXXXXX#   #XXXXXXXX
-XXX###### ######XXXX
-XXX#           #XXXX
-XXX# $ $ $ $ $ #XXXX
-XXX## $ $ $ $ ##XXXX
-XXXX#$ $ $ $ $#XXXXX
-XXXX#   $@$   #XXXXX
-XXXX#  #####  #XXXXX
-XXXX####XXX####XXXXX
-
-
-XXXXXXXX####XXXXXXXX
-XXXXXXXX#  ##XXXXXXX
-XXXXXXXX#   ##XXXXXX
-XXXXXXXX# $$ ##XXXXX
-XXXXXX###$  $ ##XXXX
-XXX####    $   #XXXX
-X###  # #####  #XXXX
-X#    # #....$ #XXXX
-X# #   $ ....# #XXXX
-X#  $ # #.%..# #XXXX
-X###  #### ### #XXXX
-XXX#### @$  ##$##XXX
-XXXXXX### $     #XXX
-XXXXXXXX#  ##   #XXX
-XXXXXXXX#########XXX
-XXXXXXXXXXXXXXXXXXXX
-
-
-XXXXXX############XX
-XXXXX##..        #XX
-XXXX##..% $    $ #XX
-XXX##..%.# # #$ ##XX
-XXX#..%.# # # $  #XX
-####...#  #    # #XX
-#  ## #          #XX
-# @$ $ ###  # # ##XX
-# $   $   # #   #XXX
-###$$   # # # # #XXX
-XX#   $   # # #####X
-XX# $# #####      #X
-XX#$   #XXX#   #  #X
-XX#  ###XXX##     #X
-XX#  #XXXXXX#    ##X
-XX####XXXXXX######XX
-
-
-###################X
-#      ###    #   #X
-# ##$ $  # $$ # $ #X
-#.# . .$ # #..# #.#X
-#.####.# # # ## # #X
-#    # #   # #  # #X
-#  $ # # ### # ## #X
-#  # # # #.$ # #  #X
-# $$.# # ##  # ## #X
-#$ # # #  # ##  # #X
-# .# # ## # #  ## #X
-#    #  # # # ##  #X
-##   ## # # # # $.#X
-### ### $.# $.# $.#X
-#######   #   #  @#X
-XXXXXX#############X
+19#|#6-3#4-#3-#|#-##$-$--#-$$-#-$-#|#.#-.-.$-#-#..#-#.#|#.4#.#-#-#-##-#-#|#4-#-#3-#-#--#-#|#--$-#-#-3#-#-##-#|#--#-#-#-#.$-#-#--#|#-$$.#-#-##--#-##-#|#$-#-#-#--#-##--#-#|#-.#-#-##-#-#--##-#|#4-#--#-#-#-##--#|##3-##-#-#-#-#-$.#|3#-3#-$.#-$.#-$.#|7#3-#3-#--@#|6-13#
Index: apps/filetypes.c
===================================================================
--- apps/filetypes.c	(revision 12499)
+++ apps/filetypes.c	(working copy)
@@ -56,7 +56,7 @@
 #endif
 
 /* string buffer length */
-#define STRING_BUFFER_SIZE 548
+#define STRING_BUFFER_SIZE 563
 
 /* number of bytes for the binary icon */
 #define ICON_LENGTH 6
