moved from the simulator dir


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@614 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/app.c b/apps/app.c
new file mode 100644
index 0000000..c5149d8
--- /dev/null
+++ b/apps/app.c
@@ -0,0 +1,104 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2002 Daniel Stenberg
+ *
+ * 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.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "lcd.h"
+#include "button.h"
+#include "kernel.h"
+#include "menu.h"
+
+/* Apps to include */
+#include "tree.h"
+
+#ifdef HAVE_LCD_BITMAP
+
+/*#include "screensaver.h"*/
+
+/*extern void tetris(void);*/
+
+void app_main(void)
+{
+    int key;
+    
+    menu_init();
+    menu_draw();
+    put_cursor_menu_top();
+    
+    while(1) {
+        key = button_get();
+        
+        if(!key) {
+            sleep(1);
+            continue;
+        }
+        
+        switch(key) {
+        case BUTTON_UP:
+            if(is_cursor_menu_top()){
+                /* wrap around to menu bottom */
+                put_cursor_menu_bottom();
+            } else {
+                /* move up */
+                move_cursor_up();
+            }
+            break;
+        case BUTTON_DOWN:
+            if(is_cursor_menu_bottom() ){
+                /* wrap around to menu top */
+                put_cursor_menu_top();
+            } else {
+                /* move down */
+                move_cursor_down();
+            }
+            break;
+        case BUTTON_RIGHT:      
+        case BUTTON_PLAY:      
+            /* Erase current display state */
+            lcd_clear_display();
+            
+            execute_menu_item();
+            
+            /* Return to previous display state */
+            lcd_clear_display();
+            menu_draw();
+            break;
+        case BUTTON_OFF:
+            return;
+        default:
+            break;
+        }
+        
+        lcd_update();
+    }
+}
+
+#else
+
+void app_main(void)
+{
+    int key;
+    int cursor = 0;
+
+    lcd_puts(0,0, "Mooo!");
+    lcd_puts(1,1, " Rockbox!");
+
+    browse_root();
+    
+}
+
+#endif
diff --git a/apps/bmp.c b/apps/bmp.c
new file mode 100644
index 0000000..828f855
--- /dev/null
+++ b/apps/bmp.c
@@ -0,0 +1,584 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Linus Nielsen Feltzing
+ *
+ * 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.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+/*********************************************************************
+ *
+ * Converts BMP files to Rockbox bitmap format
+ *
+ * 1999-05-03 Linus Nielsen Feltzing
+ *
+ **********************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "file.h"
+
+#ifdef __GNUC__
+#define STRUCT_PACKED __attribute__((packed))
+#endif
+
+struct Fileheader
+{
+  unsigned short Type;          /* signature - 'BM' */
+  unsigned  long Size;          /* file size in bytes */
+  unsigned short Reserved1;     /* 0 */
+  unsigned short Reserved2;     /* 0 */
+  unsigned long  OffBits;       /* offset to bitmap */
+  unsigned long  StructSize;    /* size of this struct (40) */
+  unsigned long  Width;         /* bmap width in pixels */
+  unsigned long  Height;        /* bmap height in pixels */
+  unsigned short Planes;        /* num planes - always 1 */
+  unsigned short BitCount;      /* bits per pixel */
+  unsigned long  Compression;   /* compression flag */
+  unsigned long  SizeImage;     /* image size in bytes */
+  long           XPelsPerMeter; /* horz resolution */
+  long           YPelsPerMeter; /* vert resolution */
+  unsigned long  ClrUsed;       /* 0 -> color table size */
+  unsigned long  ClrImportant;  /* important color count */
+} STRUCT_PACKED;
+
+struct RGBQUAD
+{
+  unsigned char rgbBlue;
+  unsigned char rgbGreen;
+  unsigned char rgbRed;
+  unsigned char rgbReserved;
+} STRUCT_PACKED;
+
+static struct Fileheader fh;
+static unsigned char* bmp;
+static struct RGBQUAD palette[2]; /* two colors only */
+
+static unsigned int bitmap_width, bitmap_height;
+static unsigned char *bitmap;
+
+#ifdef STANDALONE
+static id_str[256];
+static bool compress = false;
+static bool assembly = false;
+static unsigned char* converted_bmp;
+static unsigned char* compressed_bmp;
+static unsigned int width;
+static unsigned int converted_size;
+static unsigned int compressed_size;
+static unsigned int rounded_width;
+#endif
+
+#ifdef LITTLE_ENDIAN
+#define readshort(x) x
+#define readlong(x) x
+#else
+
+#define readshort(x) (((x&0xff00)>>8)|((x&0x00ff)<<8))
+#define readlong(x) (((x&0xff000000)>>24)| \
+                     ((x&0x00ff0000)>>8) | \
+                     ((x&0x0000ff00)<<8) | \
+                     ((x&0x000000ff)<<24))
+#endif
+
+/*********************************************************************
+ * read_bmp_file()
+ *
+ * Reads a monochrome BMP file and puts the data in a 1-pixel-per-byte
+ * array. Returns 0 on success.
+ *
+ **********************************************/
+int read_bmp_file(char* filename,
+                  int *get_width,  /* in pixels */
+                  int *get_height, /* in pixels */
+                  char *bitmap)
+{
+   long PaddedWidth;
+   int background;
+   int fd = open(filename, O_RDONLY);
+   long size;
+   unsigned int row, col, byte, bit;
+   int l;
+   unsigned char *bmp;
+   int width;
+   int height;
+
+   if(fd == -1)
+   {
+      debugf("error - can't open '%s'\n", filename);
+      return 1;
+   }
+   else
+   {
+     if(read(fd, &fh, sizeof(struct Fileheader)) !=
+        sizeof(struct Fileheader))
+      {
+	debugf("error - can't Read Fileheader Stucture\n");
+        close(fd);
+        return 2;
+      }
+
+      /* Exit if not monochrome */
+      if(readshort(fh.BitCount) > 8)
+      {
+	debugf("error - Bitmap must be less than 8, got %d\n",
+               readshort(fh.BitCount));
+        close(fd);
+        return 2;
+      }
+
+      /* Exit if too wide */
+      if(readlong(fh.Width) > 112)
+      {
+	debugf("error - Bitmap is too wide (%d pixels, max is 112)\n",
+               readlong(fh.Width));
+        close(fd);
+        return 3;
+      }
+      debugf("Bitmap is %d pixels wide\n", readlong(fh.Width));
+
+      /* Exit if too high */
+      if(readlong(fh.Height) > 64)
+      {
+	debugf("error - Bitmap is too high (%d pixels, max is 64)\n",
+               readlong(fh.Height));
+        close(fd);
+	return 4;
+      }
+      debugf("Bitmap is %d pixels heigh\n", readlong(fh.Height));
+
+      for(l=0;l < 2;l++)
+      {
+	if(read(fd, &palette[l],sizeof(struct RGBQUAD)) !=
+           sizeof(struct RGBQUAD))
+	{
+          debugf("error - Can't read bitmap's color palette\n");
+          close(fd);
+          return 5;
+	}
+      }
+      /* pass the other palettes */
+      lseek(fd, 254*sizeof(struct RGBQUAD), SEEK_CUR);
+
+      /* Try to guess the foreground and background colors.
+         We assume that the foreground color is the darkest. */
+      if(((int)palette[0].rgbRed +
+          (int)palette[0].rgbGreen +
+          (int)palette[0].rgbBlue) >
+          ((int)palette[1].rgbRed +
+          (int)palette[1].rgbGreen +
+          (int)palette[1].rgbBlue))
+      {
+         background = 0;
+      }
+      else
+      {
+         background = 1;
+      }
+
+      /*  width = readlong(fh.Width)*readshort(fh.BitCount); */
+
+      width = readlong(fh.Width);
+
+      /* PaddedWidth = ((width+31)&(~0x1f))/8; */
+      PaddedWidth = ((width+7)&(~0x7));
+      size = PaddedWidth*readlong(fh.Height);
+
+      bmp = (unsigned char *)malloc(size);
+
+      if(bmp == NULL)
+      {
+          debugf("error - Out of memory\n");
+          close(fd);
+          return 6;
+      }
+      else
+      {
+          if(read(fd, (unsigned char*)bmp,(long)size) != size) {
+              debugf("error - Can't read image\n");
+              close(fd);
+              return 7;
+          }
+      }
+
+      bitmap_height = readlong(fh.Height);
+      bitmap_width = readlong(fh.Width);
+
+      *get_width = bitmap_width;
+      *get_height = bitmap_height;
+
+#if 0
+      /* Now convert the bitmap into an array with 1 byte per pixel,
+	exactly the size of the image */
+      for(row = 0;row < bitmap_height;row++) {
+	bit = 7;
+	byte = 0;
+	for(col = 0;col < bitmap_width;col++) {
+          if((bmp[(bitmap_height - row - 1) * PaddedWidth + byte] &
+              (1 << bit))) {
+
+            bitmap[ (row/8) * bitmap_width + col ] |= 1<<(row&7);
+          }
+          else {
+            bitmap[ (row/8) * bitmap_width + col ] &= ~ 1<<(row&7);
+          }
+          if(bit) {
+            bit--;
+          }
+          else {
+            bit = 7;
+            byte++;
+          }
+	}
+      }
+#else
+      /* Now convert the bitmap into an array with 1 byte per pixel,
+         exactly the size of the image */
+
+      for(row = 0;row < bitmap_height;row++) {
+	for(col = 0;col < bitmap_width;col++) {
+          if(bmp[(bitmap_height-1 -row) * PaddedWidth + col]) {
+            bitmap[ (row/8) * bitmap_width + col ] &= ~ (1<<(row&7));
+          }
+          else {
+            bitmap[ (row/8) * bitmap_width + col ] |= 1<<(row&7);
+          }
+	}
+      }
+
+#endif
+   }
+   close(fd);
+   return 0; /* success */
+}
+
+#ifdef STANDALONE
+
+/*********************************************************************
+** read_next_converted_byte()
+**
+** Reads the next 6-pixel chunk from the 1-byte-per-pixel array,
+** padding the last byte with zeros if the size is not divisible by 6.
+**********************************************/
+unsigned char read_next_converted_byte(void)
+{
+   unsigned char dest;
+   unsigned int i;
+   static unsigned int row = 0, col = 0;
+
+   dest = 0;
+   for(i = 0;i < 6 && col < bitmap_width;i++,col++)
+   {
+      if(bitmap[row * bitmap_width + col])
+      {
+	dest |= (unsigned char)(1 << (5-i));
+      }
+   }
+
+   if(col >= bitmap_width)
+   {
+      col = 0;
+      row++;
+   }
+
+   return dest;
+}
+
+/*********************************************************************
+** convert_image()
+**
+** Converts the 1-byte-per-pixel array into a 6-pixel-per-byte array,
+** i.e the BMP_FORMAT_VANILLA format.
+**********************************************/
+void convert_image(void)
+{
+   int newsize;
+   unsigned int row, col;
+
+   rounded_width = fh.Width/6 + ((fh.Width%6)?1:0);
+   newsize = rounded_width * fh.Height;
+
+   converted_bmp = (unsigned char *)malloc(newsize);
+
+   for(row = 0;row < fh.Height;row++)
+   {
+      for(col = 0;col < rounded_width;col++)
+      {
+	converted_bmp[row * rounded_width + col] = read_next_converted_byte();
+      }
+   }
+   converted_size = rounded_width * fh.Height;
+}
+
+#define COMPRESSED_ZEROS_AHEAD 0x40
+#define COMPRESSED_ONES_AHEAD 0x80
+
+/*********************************************************************
+** compress_image()
+**
+** Compresses the BMP_FORMAT_VANILLA format with a simple RLE
+** algorithm. The output is in the BMP_FORMAT_RLE format.
+**********************************************/
+void compress_image(void)
+{
+   unsigned int i, j, count;
+   unsigned int index = 0;
+   unsigned char val;
+
+   compressed_bmp = (unsigned char *)malloc(converted_size);
+
+   for(i = 0;i < converted_size;i++)
+   {
+      val = converted_bmp[i];
+
+      if(val == 0|| val == 0x3f)
+      {
+	count = 0;
+	while(count < 0x4000 && (i + count) < converted_size &&
+	      converted_bmp[i+count] == val)
+	{
+	   count++;
+	}
+	if(count > 2)
+	{
+	   compressed_bmp[index++] = (unsigned char)
+	      (((val == 0)?COMPRESSED_ZEROS_AHEAD:COMPRESSED_ONES_AHEAD) |
+	      (count >> 8));
+	   compressed_bmp[index++] = (unsigned char)(count & 0xff);
+	}
+	else
+	{
+	   for(j = 0;j < count;j++)
+	   {
+	      compressed_bmp[index++] = val;
+	   }
+	}
+	i += count - 1;
+      }
+      else
+      {
+	compressed_bmp[index++] = val;
+      }
+   }
+
+   compressed_size = index;
+}
+
+/*********************************************************************
+** generate_c_source()
+**
+** Outputs a C source code with the converted/compressed bitmap in
+** an array, accompanied by some #define's
+**********************************************/
+void generate_c_source(char *id, BOOL compressed)
+{
+   FILE *f;
+   unsigned int i;
+   unsigned int size;
+   unsigned char *bmp;
+
+   size = compressed?compressed_size:converted_size;
+   bmp = compressed?compressed_bmp:converted_bmp;
+
+   f = stdout;
+
+   fprintf(f, "#define %s_WIDTH %d\n", id, rounded_width * 6);
+   fprintf(f, "#define %s_HEIGHT %d\n", id, fh.Height);
+   fprintf(f, "#define %s_SIZE %d\n", id, size + 6);
+   if(compressed)
+   {
+      fprintf(f, "#define %s_ORIGINAL_SIZE %d\n", id, converted_size);
+   }
+   fprintf(f, "#define %s_FORMAT %s\n", id,
+	      compressed?"BMP_FORMAT_RLE":"BMP_FORMAT_VANILLA");
+   fprintf(f, "\nconst unsigned char bmpdata_%s[] = {", id);
+
+   /* Header */
+   fprintf(f, "\n    %s, 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,",
+	compressed?"BMP_FORMAT_RLE":"BMP_FORMAT_VANILLA",
+	size >> 8, size & 0xff, 2, fh.Height, rounded_width * 6);
+
+   for(i = 0;i < size;i++)
+   {
+      if(i % 10 == 0)
+      {
+	fprintf(f, "\n    ");
+      }
+      fprintf(f, "0x%02x,", bmp[i]);
+   }
+   fprintf(f, "\n};");
+}
+
+/*********************************************************************
+** generate_asm_source()
+**
+** Outputs an ASM source code with the converted/compressed bitmap in
+** an array, the first 2 bytes describing the X and Y size
+**********************************************/
+void generate_asm_source(char *id, BOOL compressed)
+{
+   FILE *f;
+   unsigned int i;
+   unsigned int size;
+   unsigned char *bmp;
+
+   size = compressed?compressed_size:converted_size;
+   bmp = compressed?compressed_bmp:converted_bmp;
+
+   f = stdout;
+
+   fprintf(f, "bmpdata_%s:\n", id);
+   /* Header */
+   fprintf(f, "\n    db %s, %.2xh,%.2xh,%.2xh,%.2xh,%.2xh,",
+	compressed?"1":"0",
+	size >> 8, size & 0xff, 2, fh.Height, rounded_width * 6);
+
+   for(i = 0;i < size;i++)
+   {
+      if(i % 10 == 0)
+      {
+	fprintf(f, "\n   db ");
+      }
+      fprintf(f, "%.2xh,", bmp[i]);
+   }
+   fprintf(f, "\n");
+}
+
+void print_usage(void)
+{
+   printf("bmp2mt - Converts BMP files to MT Pro source code format\n");
+   printf("build date: " __DATE__ "\n\n");
+   printf("Usage: %s [-i <id>] [-c] [-a] <bitmap file>\n"
+   "-i <id>     Bitmap ID (default is filename without extension)\n"
+   "-c          Compress (BMP_FORMAT_RLE)\n"
+   "-f          Frexx Format!!!\n"
+   "-a          Assembly format source code\n", APPLICATION_NAME);
+}
+
+#pragma argsused
+int main(int argc, char **argv)
+{
+   char *bmp_filename = NULL;
+   char *id = NULL;
+   char errstr[80];
+   int i;
+
+   for(i = 1;i < argc;i++)
+   {
+      if(argv[i][0] == '-')
+      {
+	switch(argv[i][1])
+	{
+	case 'i':   /* ID */
+	   if(argv[i][2])
+	   {
+	      id = &argv[i][2];
+	   }
+	   else if(argc > i+1)
+	   {
+	      id = argv[i+1];
+	      i++;
+	   }
+	   else
+	   {
+	      print_usage();
+	      exit(1);
+	   }
+	   break;
+
+	case 'c':   /* Compressed */
+	   compress = true;
+	   break;
+
+	case 'a':   /* Assembly */
+	   assembly = true;
+	   break;
+
+	default:
+	   print_usage();
+	   exit(1);
+	   break;
+	}
+      }
+      else
+      {
+	if(!bmp_filename)
+	{
+	   bmp_filename = argv[i];
+	}
+	else
+	{
+	   print_usage();
+	   exit(1);
+	}
+      }
+   }
+
+   if(!bmp_filename)
+   {
+      print_usage();
+      exit(1);
+   }
+
+   if(!id)
+   {
+      id = strdup(bmp_filename);
+
+      for(i = 0;id[i];i++)
+      {
+	if(id[i] == ' ')
+	{
+	   id[i] = '_';
+	}
+	else if(id[i] == '.')
+	{
+	   id[i] = '\0';
+	   break;
+	}
+	else
+	{
+	   id[i] = (char)toupper(id[i]);
+	}
+      }
+   }
+
+   read_bmp_file(bmp_filename);
+   convert_image();
+   if(fh.Width % 6)
+   {
+
+      sprintf(errstr, "warning - width is not divisible by 6 (%d), "
+		"padding with zeros to %d\n", fh.Width, rounded_width*6);
+      print_error(errstr, 0);
+   }
+
+   if(compress)
+   {
+      compress_image();
+   }
+
+   if(assembly)
+   {
+      generate_asm_source(id, compress);
+   }
+   else
+   {
+      generate_c_source(id, compress);
+   }
+   return 0;
+}
+
+#endif
diff --git a/apps/icons.c b/apps/icons.c
new file mode 100644
index 0000000..6627c7d
--- /dev/null
+++ b/apps/icons.c
@@ -0,0 +1,50 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2002 Robert E. Hak
+ *
+ * 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.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include <lcd.h>
+
+#include "icons.h"
+
+#ifdef HAVE_LCD_BITMAP
+
+unsigned char bitmap_icons_6x8[LastIcon][6] =
+{
+    /* Box_Filled */
+    { 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f }, 
+    /* Box_Empty */
+    { 0x00, 0x7f, 0x41, 0x41, 0x41, 0x7f }, 
+    /* Slider_Horizontal */
+    { 0x00, 0x3e, 0x7f, 0x63, 0x7f, 0x3e }, 
+    /* File */
+    { 0x60, 0x7f, 0x03, 0x63, 0x7f, 0x00 },
+    /* Folder */
+    { 0x00, 0x7e, 0x41, 0x41, 0x42, 0x7e },
+    /* Directory */
+    { 0x3e, 0x26, 0x26, 0x24, 0x3c, 0x00 },
+    /* Playlist */
+    { 0x55, 0x00, 0x55, 0x55, 0x55, 0x00 }, 
+    /* Repeat */
+    { 0x39, 0x43, 0x47, 0x71, 0x61, 0x4e }, 
+    /* Selected */
+	{ 0x00, 0x1c, 0x3e, 0x3e, 0x3e, 0x1c },
+    /* Selector */
+    { 0x00, 0x7f, 0x3e, 0x1c, 0x08, 0x00 }, 
+};
+
+
+#endif
diff --git a/apps/icons.h b/apps/icons.h
new file mode 100644
index 0000000..08e4a7e
--- /dev/null
+++ b/apps/icons.h
@@ -0,0 +1,37 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2002 Robert E. Hak
+ *
+ * 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.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include <lcd.h>
+
+/* 
+ * Icons of size 6x8 pixels 
+ */
+
+#ifdef HAVE_LCD_BITMAP
+
+enum icons_6x8 {
+    Box_Filled, Box_Empty, Slider_Horizontal, File, 
+    Folder,     Directory, Playlist,          Repeat,
+    Selected,   Selector,  LastIcon
+};
+
+extern unsigned char bitmap_icons_6x8[LastIcon][6];
+extern icons_6x8;
+
+#endif /* End HAVE_LCD_BITMAP */
+
diff --git a/apps/menu.c b/apps/menu.c
new file mode 100644
index 0000000..5c8356c
--- /dev/null
+++ b/apps/menu.c
@@ -0,0 +1,187 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2002 Robert E. Hak
+ *
+ * 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.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "lcd.h"
+#include "menu.h"
+
+#include "tree.h"
+
+#ifdef HAVE_LCD_BITMAP
+
+#include "screensaver.h"
+extern void tetris(void);
+
+
+#define MENU_ITEM_FONT    0
+#define MENU_ITEM_Y_LOC   6
+#define MENU_LINE_HEIGHT  8
+
+enum Main_Menu_Ids {
+    Tetris, Screen_Saver, Browse, Last_Id
+};
+
+struct main_menu_items items[] = {
+    { Tetris,       "Tetris",       tetris      },
+    { Screen_Saver, "Screen Saver", screensaver },
+    { Browse,       "Browse",       browse_root },
+};
+
+/* Global values for menuing */
+int menu_top;
+int menu_bottom;
+int menu_line_height;
+int cursor;
+
+int get_line_height(void)
+{
+    return menu_line_height;
+}
+
+int is_cursor_menu_top(void)
+{
+    return ((cursor == menu_top) ? 1 : 0);
+}
+
+int is_cursor_menu_bottom(void)
+{
+    return ((cursor == menu_bottom) ? 1 : 0);
+}
+
+void put_cursor_menu_top(void)
+{
+    put_cursor(menu_top);
+}
+
+void put_cursor_menu_bottom(void)
+{
+    put_cursor(menu_bottom);
+}
+
+void move_cursor_up(void)
+{
+    put_cursor(cursor-1);
+}
+
+void move_cursor_down(void)
+{
+    put_cursor(cursor+1);
+}
+
+void redraw_cursor(void)
+{
+    lcd_putsxy(0, cursor*menu_line_height, "-", 0);
+}
+
+/* 
+ * Move the cursor to a particular id, 
+ *   current: where it is now 
+ *   target: where you want it to be 
+ */
+void put_cursor(int target)
+{
+    lcd_putsxy(0, cursor*menu_line_height, " ",0);
+    cursor = target;
+    lcd_putsxy(0, cursor*menu_line_height, "-",0);
+}
+
+/* We call the function pointer related to the current cursor position */
+void execute_menu_item(void)
+{
+    /* call the proper function for this line */
+    items[cursor].function();
+}
+
+void add_menu_item(int location, char *string)
+{
+    lcd_putsxy(MENU_ITEM_Y_LOC, MENU_LINE_HEIGHT*location, string,
+               MENU_ITEM_FONT);
+    if (location < menu_top)
+        menu_top = location;
+    if (location > menu_bottom)
+        menu_bottom = location;
+}
+
+void show_logo(void)
+{
+  unsigned char buffer[112 * 8];
+
+  int failure;
+  int width=0;
+  int height=0;
+
+  failure = read_bmp_file("/rockbox112.bmp", &width, &height, buffer);
+
+  debugf("read_bmp_file() returned %d, width %d height %d\n",
+         failure, width, height);
+
+  if(!failure) {
+    int i;
+    int eline;
+    for(i=0, eline=0; i< height; i+=8, eline++) {
+      int x,y;
+      
+      /* the bitmap function doesn't work with full-height bitmaps
+         so we "stripe" the logo output */
+
+      lcd_bitmap(&buffer[eline*width], 0, 24+i, width,
+                 (height-i)>8?8:height-i, false);
+      
+#if 0
+      /* for screen output debugging */
+      for(y=0; y<8 && (i+y < height); y++) {
+        for(x=0; x < width; x++) {
+
+          if(buffer[eline*width + x] & (1<<y)) {
+            printf("*");
+          }
+          else
+            printf(" ");
+        }
+        printf("\n");
+      }
+#endif
+    }
+
+    lcd_update();
+  }
+
+}
+
+void menu_init(void)
+{
+    menu_top = Tetris;
+    menu_bottom = Last_Id-1;
+    menu_line_height = MENU_LINE_HEIGHT;
+    cursor = menu_top;
+}
+
+void menu_draw(void)
+{
+    int i = 0;
+
+    for (i = i; i < Last_Id; i++)
+        add_menu_item(items[i].menu_id, (char *) items[i].menu_desc);
+
+    show_logo();
+    redraw_cursor();
+}
+
+#endif /* end HAVE_LCD_BITMAP */
+
+
diff --git a/apps/menu.h b/apps/menu.h
new file mode 100644
index 0000000..1e3075f
--- /dev/null
+++ b/apps/menu.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2002 Robert E. Hak
+ *
+ * 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.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __MENU_H__
+#define __MENU_H__
+
+struct main_menu_items {
+    int menu_id;
+    const char *menu_desc;
+    void (*function) (void);
+};
+
+int get_line_height(void);
+
+/* Cursor calls */
+void put_cursor(int target);
+void put_cursor_menu_top(void);
+void put_cursor_menu_bottom(void);
+void move_cursor_up(void);
+void move_cursor_down(void);
+int is_cursor_menu_top(void);
+int is_cursor_menu_bottom(void);
+
+/* Menu calls */
+void add_menu_item(int location, char *string);
+void menu_init(void);
+void menu_draw(void);
+void execute_menu_item(void);
+
+#endif /* End __MENU_H__ */
+
+
+
+
+
diff --git a/apps/screensaver.c b/apps/screensaver.c
new file mode 100644
index 0000000..b814447
--- /dev/null
+++ b/apps/screensaver.c
@@ -0,0 +1,129 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2002 Robert E. Hak (rhak at ramapo.edu)
+ *
+ * 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.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_LCD_BITMAP
+
+#include "screensaver.h"
+#include "lcd.h"
+#include "button.h"
+#include "kernel.h"
+
+#ifdef SIMULATOR
+#include <stdio.h>
+#include <string.h>
+#endif
+
+#define SS_TITLE       "Boxes"
+#define SS_TITLE_FONT  2
+
+void ss_loop(void)
+{
+    int b;
+    int x2 = LCD_WIDTH/2;
+    int y2 = LCD_HEIGHT/2;
+    int x = LCD_WIDTH/2;
+    int y = LCD_HEIGHT/2;
+    int i = 0;
+    int center = 0;
+    int factor = 0;
+    int offset = 0;
+
+    if (LCD_HEIGHT < LCD_WIDTH)
+        center = LCD_HEIGHT/2;
+    else
+        center = LCD_WIDTH/2;
+
+    i = center+1;
+    while(1)
+    {
+        /* Grow */
+        if ( i < 0 ) {
+            factor = 1;
+            i = 1;
+        }
+
+        /* Shrink */
+        if (i >= center) {
+            factor = -1;
+            i = center;
+        }
+
+        offset=i*factor;
+
+        b = button_get();
+        if ( b & BUTTON_OFF )
+            return;
+
+        lcd_clear_display();
+        lcd_drawrect(x-offset, y-offset, x2+offset, y2+offset);
+        lcd_update();
+
+        i+=factor;
+
+        sleep(10);
+    }
+}
+
+
+void screensaver(void)
+{
+    int w, h;
+    char *off = "[Off] to stop";
+    int len = strlen(SS_TITLE);
+
+    lcd_getfontsize(SS_TITLE_FONT, &w, &h);
+
+    /* Get horizontel centering for text */
+    len *= w;
+    if (len%2 != 0)
+        len = ((len+1)/2)+(w/2);
+    else
+        len /= 2;
+
+    if (h%2 != 0)
+        h = (h/2)+1;
+    else
+        h /= 2;
+
+    lcd_clear_display();
+    lcd_putsxy(LCD_WIDTH/2-len, (LCD_HEIGHT/2)-h, SS_TITLE, SS_TITLE_FONT);
+
+    len = strlen(off);
+    lcd_getfontsize(0, &w, &h);
+
+    /* Get horizontel centering for text */
+    len *= w;
+    if (len%2 != 0)
+        len = ((len+1)/2)+(w/2);
+    else
+        len /= 2;
+
+    if (h%2 != 0)
+        h = (h/2)+1;
+    else
+        h /= 2;
+
+    lcd_putsxy(LCD_WIDTH/2-len, LCD_HEIGHT-(2*h), off,0);
+
+    lcd_update();
+    sleep(150);
+    ss_loop();
+}
+
+#endif
diff --git a/apps/screensaver.h b/apps/screensaver.h
new file mode 100644
index 0000000..5c67b83
--- /dev/null
+++ b/apps/screensaver.h
@@ -0,0 +1,27 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2002 Robert E. Hak
+ *
+ * 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.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __SCREEN_SAVER_H__
+#define __SCREEN_SAVER_H__
+
+void ss_loop(void);
+void screensaver(void);
+
+#endif /*__SCREEN_SAVER_H__ */
+
diff --git a/apps/tetris.c b/apps/tetris.c
new file mode 100644
index 0000000..24090eb
--- /dev/null
+++ b/apps/tetris.c
@@ -0,0 +1,362 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 1999 Mattis Wadman (nappe@sudac.org)
+ *
+ * Heavily modified for embedded use by Björn Stenberg (bjorn@haxx.se)
+ *
+ * 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.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_LCD_BITMAP
+#include <stdbool.h>
+#include "lcd.h"
+#include "button.h"
+#include "kernel.h"
+
+#ifdef SIMULATOR
+#include <stdio.h>
+#endif
+
+#define TETRIS_TITLE       "Tetris!"
+#define TETRIS_TITLE_FONT  2
+#define TETRIS_TITLE_XLOC  10
+#define TETRIS_TITLE_YLOC  32
+
+int start_x = 1;
+int start_y = 1;
+int max_x = 14;
+int max_y = 24;
+int current_x = 0;
+int current_y = 0;
+int current_f = 0;
+int current_b = 0;
+int level = 0;
+short lines = 0;
+int score = 0;
+int next_b = 0;
+int next_f = 0;
+char virtual[LCD_WIDTH*LCD_HEIGHT];
+short level_speeds[10] = {1000,900,800,700,600,500,400,300,250,200};
+int blocks = 7;
+int block_frames[7] = {1,2,2,2,4,4,4};
+
+/*
+ block_data is built up the following way
+
+ first array index specifies the block number
+ second array index specifies the rotation of the block
+ third array index specifies:
+     0: x-coordinates of pixels
+     1: y-coordinates of pixels
+ fourth array index specifies the coordinate of a pixel
+
+ each block consists of four pixels whose relative coordinates are given
+ with block_data
+*/
+
+int block_data[7][4][2][4] =
+{
+    {
+        {{0,1,0,1},{0,0,1,1}}
+    },
+    {
+        {{0,1,1,2},{1,1,0,0}},
+        {{0,0,1,1},{0,1,1,2}}
+    },
+    {
+        {{0,1,1,2},{0,0,1,1}},
+        {{1,1,0,0},{0,1,1,2}}
+    },
+    {
+        {{1,1,1,1},{0,1,2,3}},
+        {{0,1,2,3},{2,2,2,2}}
+    },
+    {
+        {{1,1,1,2},{2,1,0,0}},
+        {{0,1,2,2},{1,1,1,2}},
+        {{0,1,1,1},{2,2,1,0}},
+        {{0,0,1,2},{0,1,1,1}}
+    },
+    {
+        {{0,1,1,1},{0,0,1,2}},
+        {{0,1,2,2},{1,1,1,0}},
+        {{1,1,1,2},{0,1,2,2}},
+        {{0,0,1,2},{2,1,1,1}}
+    },
+    {
+        {{1,0,1,2},{0,1,1,1}},
+        {{2,1,1,1},{1,0,1,2}},
+        {{1,0,1,2},{2,1,1,1}},
+        {{0,1,1,1},{1,0,1,2}}
+    }
+};
+
+/* not even pseudo random :) */
+int t_rand(int range)
+{
+    static int count;
+    count++;
+    return count % range;
+}
+
+void draw_frame(int fstart_x,int fstop_x,int fstart_y,int fstop_y)
+{
+    lcd_drawline(fstart_x, fstart_y, fstop_x, fstart_y);
+    lcd_drawline(fstart_x, fstop_y, fstop_x, fstop_y);
+
+    lcd_drawline(fstart_x, fstart_y, fstart_x, fstop_y);
+    lcd_drawline(fstop_x, fstart_y, fstop_x, fstop_y);
+}
+
+void draw_block(int x,int y,int block,int frame,bool clear)
+{
+    int i;
+    for(i=0;i < 4;i++) {
+        if (clear) 
+            lcd_clearpixel(start_x+x+block_data[block][frame][0][i],
+                           start_y+y+block_data[block][frame][1][i]);
+        else
+            lcd_drawpixel(start_x+x+block_data[block][frame][0][i],
+                          start_y+y+block_data[block][frame][1][i]);
+    }
+}
+
+void to_virtual()
+{
+    int i;
+    for(i=0;i < 4;i++)
+        *(virtual+
+          ((current_y+block_data[current_b][current_f][1][i])*max_x)+
+          (current_x+block_data[current_b][current_f][0][i])) = current_b+1;
+}
+
+bool gameover()
+{
+    int i;
+    int frame, block, y, x;
+
+    x = current_x;
+    y = current_y;
+    block = current_b;
+    frame = current_f;
+
+    for(i=0;i < 4; i++){
+        /* Do we have blocks touching? */
+        if(*(virtual+((y+block_data[block][frame][1][i])*max_x)+x+
+             block_data[block][frame][0][i]) != 0) 
+        {
+            /* Are we at the top of the frame? */
+            if(y+block_data[block][frame][1][i] < start_y)
+            {
+                /* Game over ;) */
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool valid_position(int x,int y,int block,int frame)
+{
+    int i;
+    for(i=0;i < 4;i++)
+        if( (*(virtual+((y+block_data[block][frame][1][i])*max_x)+x+
+               block_data[block][frame][0][i]) != 0) || 
+            (x+block_data[block][frame][0][i] < 0) || 
+            (x+block_data[block][frame][0][i] > max_x-1) ||
+            (y+block_data[block][frame][1][i] < 0) || 
+            (y+block_data[block][frame][1][i] > max_y-1))
+            return false;
+    return true;
+}
+
+void from_virtual()
+{
+    int x,y;
+    for(y=0;y < max_y;y++)
+        for(x=0;x < max_x;x++)
+            if(*(virtual+(y*max_x)+x))
+                lcd_drawpixel(start_x+x,start_y+y);
+            else
+                lcd_clearpixel(start_x+x,start_y+y);
+}
+
+void move_block(int x,int y,int f)
+{
+    int last_frame = current_f;
+    if(f != 0)
+    {
+        current_f += f;
+        if(current_f > block_frames[current_b]-1)
+            current_f = 0;
+        if(current_f < 0)
+            current_f = block_frames[current_b]-1;
+    }        
+    if(valid_position(current_x+x,current_y+y,current_b,current_f))
+    {
+        draw_block(current_x,current_y,current_b,last_frame,true);
+        current_x += x;
+        current_y += y;
+        draw_block(current_x,current_y,current_b,current_f,false);
+        lcd_update();
+    }
+    else
+        current_f = last_frame;
+}
+
+void new_block()
+{
+    current_b = next_b;
+    current_f = next_f;
+    current_x = (int)((max_x)/2)-1;
+    current_y = 0;
+    next_b = t_rand(blocks);
+    next_f = t_rand(block_frames[next_b]);
+    draw_block(max_x+2,start_y-1,current_b,current_f,true);
+    draw_block(max_x+2,start_y-1,next_b,next_f,false);
+    if(!valid_position(current_x,current_y,current_b,current_f))
+    {
+        draw_block(current_x,current_y,current_b,current_f,false);
+        lcd_update();
+    }
+    else
+        draw_block(current_x,current_y,current_b,current_f,false);
+}
+
+int check_lines()
+{
+    int x,y,i;
+    bool line;
+    int lines = 0;
+    for(y=0;y < max_y;y++)
+    {
+        line = true;
+        for(x=0;x < max_x;x++)
+            if(virtual[y*max_x+x] == 0)
+                line = false;
+        if(line)
+        {
+            lines++;
+            for(i=y;i > 1;i--)
+		for (x=0;x<max_x;x++)
+		    virtual[i*max_x] = virtual[((i-1)*max_x)];
+	    for (x=0;x<max_x;x++)
+		virtual[max_x] = 0;
+        }
+    }
+    return lines;
+}
+
+void move_down()
+{
+    int l;
+    if(!valid_position(current_x,current_y+1,current_b,current_f))
+    {
+        to_virtual();
+	l = check_lines();
+        if(l)
+        {
+            lines += l;
+            level = (int)lines/10;
+            if(level > 9)
+                level = 9;
+            from_virtual();
+            score += l*l;
+        }
+        new_block();
+        move_block(0,0,0);
+    }
+    else
+        move_block(0,1,0);
+} 
+
+void game_loop(void)
+{
+    while(1)
+    {
+	int b=0;
+	int count = 0;
+	/*  while(count*20 < level_speeds[level]) */
+	{
+	    b = button_get();
+	    if ( b & BUTTON_OFF )
+              return; /* get out of here */
+
+	    if ( b & BUTTON_LEFT ) {
+		move_block(-1,0,0);
+	    }
+	    if ( b & BUTTON_RIGHT ) {
+		move_block(1,0,0);
+	    }
+	    if ( b & BUTTON_UP ) {
+		move_block(0,0,1);
+	    }
+	    if ( b & BUTTON_DOWN ) {
+		move_down();
+	    }
+	    count++;
+	    sleep(10);
+	}
+    if(gameover()) {
+        int w, h;
+
+        lcd_getfontsize(TETRIS_TITLE_FONT, &w, &h);
+        lcd_clearrect(TETRIS_TITLE_XLOC, TETRIS_TITLE_YLOC, 
+                      TETRIS_TITLE_XLOC+(w*sizeof(TETRIS_TITLE)), 
+                      TETRIS_TITLE_YLOC-h);
+        lcd_putsxy(TETRIS_TITLE_XLOC, TETRIS_TITLE_YLOC, "You lose!",
+                   TETRIS_TITLE_FONT);
+        lcd_update();
+        sleep(2);
+        return;
+    }
+	move_down();
+    }
+}
+
+void init_tetris()
+{
+    memset(&virtual, 0, sizeof(virtual));
+    start_x = 1;
+    start_y = 1;
+    max_x = 14;
+    max_y = 24;
+    current_x = 0;
+    current_y = 0;
+    current_f = 0;
+    current_b = 0;
+    level = 0;
+    lines = 0;
+    score = 0;
+    next_b = 0;
+    next_f = 0;
+}
+
+void tetris(void)
+{
+    init_tetris();
+
+    draw_frame(start_x-1,start_x+max_x,start_y-1,start_y+max_y);
+    lcd_putsxy(TETRIS_TITLE_XLOC, TETRIS_TITLE_YLOC, TETRIS_TITLE,
+               TETRIS_TITLE_FONT);
+    lcd_update();
+
+    next_b = t_rand(blocks);
+    next_f = t_rand(block_frames[next_b]);
+    new_block();
+    game_loop();
+}
+
+#endif