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