First version of loadable fonts patch by Alex Gitelman


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@1666 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/Makefile b/apps/Makefile
index 3629813..0347c03 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -25,7 +25,7 @@
 # store output files in this directory:
 OBJDIR = .
 
-CFLAGS = -O -W -Wall -m1 -nostdlib -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(TARGET) $(DEFINES) -DAPPSVERSION=\"$(VERSION)\"
+CFLAGS = -O -W -Wall -m1 -nostdlib -Wstrict-prototypes -fomit-frame-pointer -fschedule-insns $(INCLUDES) $(TARGET) $(DEFINES) -DAPPSVERSION=\"$(VERSION)\" $(EXTRA_DEFINES)
 AFLAGS += -small -relax
 
 ifdef DEBUG
diff --git a/apps/main.c b/apps/main.c
index 895f79af..887c85b 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -44,10 +44,11 @@
 #include "backlight.h"
 #include "status.h"
 #include "debug_menu.h"
-
 #include "version.h"
-
 #include "sprintf.h"
+#ifdef LOADABLE_FONTS
+#include "unicode.h"
+#endif
 
 char appsversion[]=APPSVERSION;
 
@@ -64,6 +65,9 @@
 void init(void)
 {
     init_threads();
+#ifdef LOADABLE_FONTS
+    unicode_init();
+#endif
     lcd_init();
     show_logo();
     settings_reset();
@@ -153,8 +157,11 @@
 
     status_init();
     usb_start_monitoring();
-    
     power_init();
+#ifdef LOADABLE_FONTS
+    unicode_init();
+    lcd_init_fonts();
+#endif
 }
 
 int main(void)
diff --git a/apps/menu.c b/apps/menu.c
index c8a5d0e..7267afe 100644
--- a/apps/menu.c
+++ b/apps/menu.c
@@ -22,11 +22,14 @@
 #include "button.h"
 #include "kernel.h"
 #include "debug.h"
+#include "panic.h"
 
 #ifdef HAVE_LCD_BITMAP
 #include "icons.h"
 #endif
-
+#ifdef LOADABLE_FONTS
+#include "ajf.h"
+#endif
 struct menu {
     int top;
     int cursor;
@@ -54,11 +57,19 @@
 /* count in letter posistions, NOT pixels */
 void put_cursorxy(int x, int y, bool on)
 {
+#ifdef LOADABLE_FONTS
+    int fh;
+    unsigned char* font = lcd_getcurrentldfont();
+    fh = ajf_get_fontheight(font);
+#else 
+    int fh = 8;
+#endif
+
     /* place the cursor */
     if(on) {
 #ifdef HAVE_LCD_BITMAP
         lcd_bitmap ( bitmap_icons_6x8[Cursor], 
-                     x*6, y*8, 4, 8, true);
+                     x*6, y*fh, 4, 8, true);
 #elif defined(SIMULATOR)
         /* player simulator */
         unsigned char cursor[] = { 0x7f, 0x3e, 0x1c, 0x08 };
@@ -70,7 +81,7 @@
     else {
 #if defined(HAVE_LCD_BITMAP)
         /* I use xy here since it needs to disregard the margins */
-        lcd_clearrect (x*6, y*8, 4, 8);
+        lcd_clearrect (x*6, y*fh, 4, 8);
 #elif defined(SIMULATOR)
         /* player simulator in action */
         lcd_clearrect (x*6, 12+y*16, 4, 8);
@@ -83,6 +94,15 @@
 static void menu_draw(int m)
 {
     int i = 0;
+#ifdef LOADABLE_FONTS
+    int menu_lines;
+    int fh;
+    unsigned char* font = lcd_getcurrentldfont();
+    fh = ajf_get_fontheight(font);
+    menu_lines = LCD_HEIGHT/fh;
+#else
+    int menu_lines = MENU_LINES;
+#endif
 
     lcd_clear_display(); 
     lcd_stop_scroll();
@@ -91,7 +111,7 @@
     lcd_setfont(0);
 #endif
     for (i = menus[m].top; 
-         (i < menus[m].itemcount) && (i<menus[m].top+MENU_LINES);
+         (i < menus[m].itemcount) && (i<menus[m].top+menu_lines);
          i++) {
         if((menus[m].cursor - menus[m].top)==(i-menus[m].top))
             lcd_puts_scroll(1, i-menus[m].top, menus[m].items[i].desc);
@@ -111,7 +131,15 @@
 static void put_cursor(int m, int target)
 {
     bool do_update = true;
-
+#ifdef LOADABLE_FONTS
+    int menu_lines;
+    int fh;
+    unsigned char* font = lcd_getcurrentldfont();
+    fh = ajf_get_fontheight(font);
+    menu_lines = LCD_HEIGHT/fh;
+#else
+    int menu_lines = MENU_LINES;
+#endif
     put_cursorxy(0, menus[m].cursor - menus[m].top, false);
     menus[m].cursor = target;
     menu_draw(m);
@@ -121,7 +149,7 @@
         menu_draw(m);
         do_update = false;
     }
-    else if ( target-menus[m].top > MENU_LINES-1 ) {
+    else if ( target-menus[m].top > menu_lines-1 ) {
         menus[m].top++;
         menu_draw(m);
         do_update = false;
diff --git a/apps/tree.c b/apps/tree.c
index cbb19fc..80af6e0 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -43,6 +43,10 @@
 #include "icons.h"
 #endif
 
+#ifdef LOADABLE_FONTS
+#include "ajf.h"
+#endif
+
 #define MAX_FILES_IN_DIR 200
 #define TREE_MAX_FILENAMELEN MAX_PATH
 #define MAX_DIR_LEVELS 10
@@ -152,8 +156,20 @@
 {
 #ifdef HAVE_LCD_BITMAP
     int icon_type = 0;
+    int line_height = LINE_HEIGTH;
 #endif
     int i;
+    int tree_max_on_screen;
+#ifdef LOADABLE_FONTS
+    int fh;
+    unsigned char *font = lcd_getcurrentldfont();
+    fh  = ajf_get_fontheight(font);
+    tree_max_on_screen =  ((LCD_HEIGHT-MARGIN_Y)/fh)-LINE_Y;
+    line_height = fh;
+#else
+    tree_max_on_screen = TREE_MAX_ON_SCREEN;
+#endif
+
 
     /* new dir? cache it */
     if (strncmp(path,lastdir,sizeof(lastdir))) {
@@ -217,7 +233,7 @@
     lcd_setfont(0);
 #endif
 
-    for ( i=start; i < start+TREE_MAX_ON_SCREEN; i++ ) {
+    for ( i=start; i < start+tree_max_on_screen; i++ ) {
         int len;
 
         if ( i >= filesindir )
@@ -235,9 +251,10 @@
                 icon_type = File;
         }
         lcd_bitmap(bitmap_icons_6x8[icon_type], 
-                   6, MARGIN_Y+(LINE_Y+i-start)*LINE_HEIGTH, 6, 8, true);
+                   6, MARGIN_Y+(LINE_Y+i-start)*line_height, 6, 8, true);
 #endif
 
+
         /* if MP3 filter is on, cut off the extension */
         if (global_settings.mp3filter && 
             (dircacheptr[i]->attr & (TREE_ATTR_M3U|TREE_ATTR_MP3)))
@@ -270,6 +287,15 @@
     int rc;
     int button;
     int start_index;
+    int tree_max_on_screen;
+#ifdef LOADABLE_FONTS
+    int fh;
+    unsigned char *font = lcd_getcurrentldfont();
+    fh  = ajf_get_fontheight(font);
+    tree_max_on_screen =  ((LCD_HEIGHT-MARGIN_Y)/fh)-LINE_Y;
+#else
+    tree_max_on_screen = TREE_MAX_ON_SCREEN;
+#endif
 
     memcpy(currdir,root,sizeof(currdir));
     numentries = showdir(root, start);
@@ -379,7 +405,7 @@
                             put_cursorxy(0, CURSOR_Y + LINE_Y+dircursor, true);
                         }
                         else {
-                            if (numentries < TREE_MAX_ON_SCREEN) {
+                            if (numentries < tree_max_on_screen) {
                                 put_cursorxy(0, CURSOR_Y + LINE_Y+dircursor,
                                              false);
                                 dircursor = numentries - 1;
@@ -387,11 +413,11 @@
                                              true);
                             }
                             else {
-                                start = numentries - TREE_MAX_ON_SCREEN;
-                                dircursor = TREE_MAX_ON_SCREEN - 1;
+                                start = numentries - tree_max_on_screen;
+                                dircursor = tree_max_on_screen - 1;
                                 numentries = showdir(currdir, start);
                                 put_cursorxy(0, CURSOR_Y + LINE_Y +
-                                             TREE_MAX_ON_SCREEN - 1, true);
+                                             tree_max_on_screen - 1, true);
                             }
                         }
                     }
@@ -404,7 +430,7 @@
                 if(filesindir)
                 {
                     if (dircursor + start + 1 < numentries ) {
-                        if(dircursor+1 < TREE_MAX_ON_SCREEN) {
+                        if(dircursor+1 < tree_max_on_screen) {
                             put_cursorxy(0, CURSOR_Y + LINE_Y+dircursor,
                                          false);
                             dircursor++;
@@ -417,7 +443,7 @@
                         }
                     }
                     else {
-                        if(numentries < TREE_MAX_ON_SCREEN) {
+                        if(numentries < tree_max_on_screen) {
                             put_cursorxy(0, CURSOR_Y + LINE_Y+dircursor,
                                          false);
                             start = dircursor = 0;
@@ -512,7 +538,7 @@
             /* restore display */
             /* We need to adjust if the number of lines on screen have
                changed because of a status bar change */
-            if(CURSOR_Y+LINE_Y+dircursor>TREE_MAX_ON_SCREEN) {
+            if(CURSOR_Y+LINE_Y+dircursor>tree_max_on_screen) {
                 start++;
                 dircursor--;
             }
diff --git a/apps/wps.c b/apps/wps.c
index 53458ca..2bf384b 100644
--- a/apps/wps.c
+++ b/apps/wps.c
@@ -39,6 +39,10 @@
 #include "widgets.h"
 #endif
 
+#ifdef LOADABLE_FONTS
+#include "ajf.h"
+#endif
+
 #ifdef HAVE_LCD_BITMAP
 #define LINE_Y      (global_settings.statusbar&&statusbar_enabled?1:0) /* Y position the entry-list starts at */
 #else /* HAVE_LCD_BITMAP */
@@ -59,6 +63,15 @@
 
 static void draw_screen(struct mp3entry* id3)
 {
+    int font_height;
+#ifdef LOADABLE_FONTS
+    unsigned char *font = lcd_getcurrentldfont();
+    font_height  = ajf_get_fontheight(font);
+#else
+    font_height = 8;
+#endif
+
+
     lcd_clear_display();
     if(!id3)
     {
@@ -125,7 +138,7 @@
                 lcd_puts(0, l++, id3->album?id3->album:"");
                 lcd_puts(0, l++, id3->artist?id3->artist:"");
 
-                if(LINE_Y==0) {
+                if(LINE_Y==0&&font_height<=8) {
                     if(id3->vbr)
                         snprintf(buffer, sizeof(buffer), "%d kbit (avg)",
                                  id3->bitrate);
@@ -133,7 +146,6 @@
                         snprintf(buffer, sizeof(buffer), "%d kbit", id3->bitrate);
 
                     lcd_puts(0, l++, buffer);
-
                     snprintf(buffer,sizeof(buffer), "%d Hz", id3->frequency);
                     lcd_puts(0, l++, buffer);
                 }
@@ -148,7 +160,6 @@
                     lcd_puts(0, l++, buffer);
                 }
 #else
-
                 lcd_puts(0, l++, id3->artist?id3->artist:"<no artist>");
                 lcd_puts_scroll(0, l++, id3->title?id3->title:"<no title>");
 #endif
@@ -444,13 +455,13 @@
                 if(!keys_locked && !dont_go_to_menu && menu_button_is_down)
                 {
 #ifdef HAVE_LCD_BITMAP
-                        bool laststate=statusbar(false);
+                    bool laststate=statusbar(false);
 #endif
                     lcd_stop_scroll();
                     button_set_release(old_release_mask);
                     main_menu();
 #ifdef HAVE_LCD_BITMAP
-                        statusbar(laststate);
+                    statusbar(laststate);
 #endif
                     old_release_mask = button_set_release(RELEASE_MASK);
                     id3 = mpeg_current_track();
@@ -464,14 +475,14 @@
                 break;
 
 #ifdef HAVE_RECORDER_KEYPAD
-                case BUTTON_F3:
+            case BUTTON_F3:
 #ifdef HAVE_LCD_BITMAP
-                    if(global_settings.statusbar) {
-                        statusbar_toggle();
-                        draw_screen(id3);
-                    }
+                if(global_settings.statusbar) {
+                    statusbar_toggle();
+                    draw_screen(id3);
+                }
 #endif
-                    break;
+                break;
 #endif
 
 #ifdef HAVE_RECORDER_KEYPAD
@@ -504,19 +515,19 @@
                 usb_wait_for_disconnect(&button_queue);
 
 #ifdef HAVE_LCD_BITMAP
-                        statusbar(laststate);
+                statusbar(laststate);
 #endif
                 /* Signal to our caller that we have been in USB mode */
                 return SYS_USB_CONNECTED;
                 break;
-                }
+            }
 #endif
             case BUTTON_NONE: /* Timeout */
                 if (mpeg_is_playing() && id3)
                 {
 #ifdef HAVE_LCD_BITMAP
                     snprintf(buffer,sizeof(buffer),
-                                     "Time:%3d:%02d/%d:%02d",
+                             "Time:%3d:%02d/%d:%02d",
                              id3->elapsed / 60000,
                              id3->elapsed % 60000 / 1000,
                              id3->length / 60000,
@@ -524,9 +535,9 @@
                         
                     lcd_puts(0, 6, buffer);
                         
-                            slidebar(0, LCD_HEIGHT-6, LCD_WIDTH, 6,
-                                 id3->elapsed*100/id3->length,
-                                     Grow_Right);
+                    slidebar(0, LCD_HEIGHT-6, LCD_WIDTH, 6,
+                             id3->elapsed*100/id3->length,
+                             Grow_Right);
                         
                     lcd_update();
 #else
@@ -535,7 +546,7 @@
                     if (global_settings.wps_display ==
                         PLAY_DISPLAY_FILENAME_SCROLL)
                     { 
-                                snprintf(buffer,sizeof(buffer), "%d:%02d/%d:%02d  ",
+                        snprintf(buffer,sizeof(buffer), "%d:%02d/%d:%02d  ",
                                  id3->elapsed / 60000,
                                  id3->elapsed % 60000 / 1000,
                                  id3->length / 60000,
diff --git a/firmware/Makefile b/firmware/Makefile
index 69a27a1..eb17384 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -15,6 +15,8 @@
 
 INCLUDES=-Iinclude -I. -Icommon -Idrivers
 
+SYSTEM_FONT = fonts/alt6x10.bdf
+
 # Pick a target to build for
 TARGET = -DARCHOS_PLAYER=1
 #TARGET = -DARCHOS_PLAYER_OLD=1
@@ -23,7 +25,7 @@
 # store output files in this directory:
 OBJDIR = .
 
-CFLAGS = -W -Wall -O -m1 -nostdlib -Wstrict-prototypes $(INCLUDES) $(TARGET)
+CFLAGS = -W -Wall -O -m1 -nostdlib -Wstrict-prototypes $(INCLUDES) $(TARGET) $(EXTRA_DEFINES)
 
 ifdef DEBUG
 CFLAGS += -g -DDEBUG
@@ -39,7 +41,11 @@
 
 OUTPUT = $(OBJDIR)/librockbox.a
 
-$(OUTPUT): $(OBJS)
+ifdef LOADABLE_FONTS
+	EXTRA_TARGETS = $(OBJDIR)/system.ajf
+endif
+
+$(OUTPUT): $(OBJS) $(EXTRA_TARGETS)
 	$(AR) ruv $@ $+
 
 $(OBJDIR)/%.o: %.c
@@ -50,6 +56,9 @@
 	@mkdir -p `dirname $@`
 	$(CC) $(CFLAGS) -c $< -o $@
 
+$(OBJDIR)/system.ajf: ../tools/bdf2ajf $(SYSTEM_FONT)
+	../tools/bdf2ajf -f $(SYSTEM_FONT) -o $(OBJDIR)/system.ajf
+
 clean:
 	rm -f $(OBJS) $(OUTPUT)
 	rm -rf $(OBJDIR)/$(DEPS)
diff --git a/firmware/common/dir.c b/firmware/common/dir.c
index 473997b..809e1a2 100644
--- a/firmware/common/dir.c
+++ b/firmware/common/dir.c
@@ -107,6 +107,7 @@
 
     if ( !entry.name[0] )
         return NULL;
+	
 
     strncpy(theent->d_name, entry.name, sizeof( theent->d_name ) );
     theent->attribute = entry.attr;
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index 75915bd..7fe011c 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -27,6 +27,7 @@
 #include <sys/timeb.h>
 #endif
 #include <stdbool.h>
+#include <unicode.h>
 #include "fat.h"
 #include "ata.h"
 #include "debug.h"
@@ -1029,12 +1030,14 @@
                     /* replace shortname with longname? */
                     if ( longs ) {
                         int j,k,l=0;
-
                         /* iterate backwards through the dir entries */
                         for (j=longs-1; j>=0; j--) {
                             unsigned char* ptr = dir->cached_buf;
                             int index = longarray[j];
-                            
+#ifdef LOADABLE_FONTS
+                            int offset_idx = 0;
+                            unsigned char uni_char[2];
+#endif
                             /* current or cached sector? */
                             if ( sectoridx >= SECTOR_SIZE ) {
                                 if ( sectoridx >= SECTOR_SIZE*2 ) {
@@ -1052,16 +1055,39 @@
                                 index &= SECTOR_SIZE-1;
                             }
 
-                            /* piece together the name subcomponents.
-                               names are stored in unicode, but we
-                               only grab the low byte (iso8859-1).
-			     */
+                            /* piece together the name subcomponents. */
+#ifdef LOADABLE_FONTS
+                            for (k=0; k<5; k++)
+                            {
+                                offset_idx = index + k*2 + 1;
+                                uni_char[0] = ptr[offset_idx+1];
+                                uni_char[1] = ptr[offset_idx];
+                                entry->name[l++] = from_unicode(uni_char);
+                            }
+                            for (k=0; k<6; k++)
+                            {
+                                offset_idx = index + k*2 + 14;
+                                uni_char[0] = ptr[offset_idx+1];
+                                uni_char[1] = ptr[offset_idx];
+                                entry->name[l++] = from_unicode(uni_char);
+                            }
+                            for (k=0; k<2; k++)
+                            {
+                                offset_idx = index + k*2 + 28;
+                                uni_char[0] = ptr[offset_idx+1];
+                                uni_char[1] = ptr[offset_idx];
+                                entry->name[l++] = from_unicode(uni_char);
+                            }
+#else
+                            /* names are stored in unicode, but we
+                               only grab the low byte (iso8859-1). */
                             for (k=0; k<5; k++)
                                 entry->name[l++] = ptr[index + k*2 + 1];
                             for (k=0; k<6; k++)
                                 entry->name[l++] = ptr[index + k*2 + 14];
                             for (k=0; k<2; k++)
                                 entry->name[l++] = ptr[index + k*2 + 28];
+#endif
                         }
                         entry->name[l]=0;
                     }
diff --git a/firmware/drivers/lcd.c b/firmware/drivers/lcd.c
index a9cd8c6..806b812 100644
--- a/firmware/drivers/lcd.c
+++ b/firmware/drivers/lcd.c
@@ -27,6 +27,13 @@
 #include "debug.h"
 #include "system.h"
 
+#ifdef LOADABLE_FONTS
+#include "ajf.h"
+#include "panic.h"
+#endif
+
+
+
 /*** definitions ***/
 
 #define LCDR (PBDR_ADDR+1)
@@ -296,21 +303,21 @@
     PBDR &= ~LCD_CS; /* enable lcd chip select */
 
     if ( command ) {
-	on=~(LCD_SD|LCD_SC|LCD_DS);
-	off=LCD_SC;
+    on=~(LCD_SD|LCD_SC|LCD_DS);
+    off=LCD_SC;
     }
     else {
-	on=~(LCD_SD|LCD_SC);
-	off=LCD_SC|LCD_DS;
+    on=~(LCD_SD|LCD_SC);
+    off=LCD_SC|LCD_DS;
     }
 
     /* clock out each bit, MSB first */
     for (i=0x80;i;i>>=1)
     {
-	PBDR &= on;
-	if (i & byte)
-	    PBDR |= LCD_SD;
-	PBDR |= off;
+    PBDR &= on;
+    if (i & byte)
+        PBDR |= LCD_SD;
+    PBDR |= off;
     }
 
     PBDR |= LCD_CS; /* disable lcd chip select */
@@ -322,9 +329,9 @@
 void lcd_backlight(bool on)
 {
     if ( on )
-	PAIOR |= LCD_BL;
+    PAIOR |= LCD_BL;
     else
-	PAIOR &= ~LCD_BL;
+    PAIOR &= ~LCD_BL;
 }
 
 #endif /* SIMULATOR */
@@ -431,7 +438,7 @@
     int i;
     lcd_write(true,LCD_PRAM|which);
     for (i=0;i<length;i++)
-	lcd_write(false,pattern[i]);
+    lcd_write(false,pattern[i]);
 }
 
 void lcd_double_height(bool on)
@@ -510,7 +517,9 @@
 {
     create_thread(scroll_thread, scroll_stack,
                   sizeof(scroll_stack), scroll_name);
-    
+#if  defined(LOADABLE_FONTS) && defined(SIMULATOR)
+    lcd_init_fonts();
+#endif
     memset(icon_mirror, sizeof(icon_mirror), 0);
 }
 #endif
@@ -541,8 +550,8 @@
  * This contains only the printable characters (0x20-0x7f).
  * Each element in this table is a character pattern bitmap.
  */
-#define	ASCII_MIN			0x20	/* First char in table */
-#define	ASCII_MAX			0x7f	/* Last char in table */
+#define    ASCII_MIN            0x20    /* First char in table */
+#define    ASCII_MAX            0x7f    /* Last char in table */
 
 extern unsigned char char_gen_6x8[][5];
 extern unsigned char char_gen_8x12[][14];
@@ -550,9 +559,9 @@
 
 /* All zeros and ones bitmaps for area filling */
 static unsigned char zeros[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				 0x00, 0x00 };
+                 0x00, 0x00 };
 static unsigned char ones[]  = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-				 0xff, 0xff };
+                 0xff, 0xff };
 static char fonts[] = { 6,8,12 };
 static char fontheight[] = { 8,12,16 };
 
@@ -654,6 +663,101 @@
     ymargin = y;
 }
 
+
+
+#ifdef LOADABLE_FONTS
+
+static unsigned char* _font = NULL;
+
+int lcd_init_fonts(void)
+{
+    if (!_font)
+        _font = ajf_read_font("/system.ajf");
+
+    if (!_font)
+    {
+        lcd_putsxy(0,0,"No font", 0);
+        return -1;
+    }
+
+    return 0;
+}
+
+void lcd_setldfont(unsigned char* f)
+{
+    _font = f;
+}
+
+unsigned char* lcd_getcurrentldfont()
+{
+    if (!_font)
+        panicf("No font loaded!");
+    return _font;
+}
+
+/*
+ * Return width and height of a string with a given font.
+ */
+int lcd_getstringsize(unsigned char *str, unsigned char* font, int *w, int *h)
+{
+    int width=0;
+    int height=0;
+    unsigned char ch;
+
+    if (!font)
+        panicf("No font specified");
+
+    while((ch = *str++)) 
+    {
+        int dw,dh;
+        ajf_get_charsize(ch, font, &dw, &dh);
+        if (dh>height)
+            height = dh;
+        width+=dw;
+    }
+    *w = width;
+    *h = height;
+
+    return width;
+}
+
+/*
+ * Put a string at specified bit position
+ */
+
+void lcd_putsldfxy(int x, int y, unsigned char *str)
+{
+    unsigned char ch;
+    int nx;
+    int ny=8;
+    int lcd_x = x;
+    int lcd_y = y;
+    if (!_font)
+    {
+        lcd_putsxy(0,0,"No font", 0);
+        return;
+    }
+    ny = (int)_font[2];
+    while (((ch = *str++) != '\0'))
+    {
+        unsigned char *char_buf = ajf_get_charbuf(ch, _font, &nx, &ny);
+        if (!char_buf)
+        {
+            char_buf = ajf_get_charbuf('?', _font, &nx, &ny);
+            if (!char_buf)
+                panicf("Bad font");
+        }
+        if(lcd_x + nx > LCD_WIDTH)
+            break;
+
+        lcd_clearrect (lcd_x, lcd_y, 1, ny);
+        lcd_bitmap (&char_buf[0], lcd_x, lcd_y, nx, ny, true);
+        lcd_x += nx+1;
+    }
+}
+#endif
+
+
 #ifdef LCD_PROPFONTS
 
 extern unsigned char char_dw_8x8_prop[][9];
@@ -746,10 +850,19 @@
     ymargin = 8;
 #endif
 
+    if(!str || !str[0])
+        return;
+
 #ifdef LCD_PROPFONTS
     lcd_putspropxy( xmargin + x*fonts[font],
                     ymargin + y*fontheight[font],
                     str, font );
+#elif LOADABLE_FONTS
+    {
+        int w,h;
+        lcd_getstringsize(str,_font,&w,&h);
+        lcd_putsldfxy( xmargin + x*w/strlen(str), ymargin + y*h, str );
+    }
 #else
     lcd_putsxy( xmargin + x*fonts[font],
                 ymargin + y*fontheight[font],
@@ -1105,25 +1218,31 @@
     s->space = 11 - x;
 #else
 
-#ifdef LCD_PROPFONTS
+#if defined(LCD_PROPFONTS) || defined(LOADABLE_FONTS)
     unsigned char ch[2];
     int w, h;
 #endif
     int width, height;
     lcd_getfontsize(font, &width, &height);
-#ifndef LCD_PROPFONTS
-    s->space = (LCD_WIDTH - xmargin - x*width) / width;
-#else
+#if defined(LCD_PROPFONTS) || defined(LOADABLE_FONTS)
     ch[1] = 0; /* zero terminate */
     ch[0] = string[0];
     width = 0;
-    for (s->space = 0;
-         ch[0] &&
-             (width + lcd_getstringsize(ch, 0, &w, &h) < (LCD_WIDTH - x*8));
-         ) {
+    s->space = 0;
+    while ( ch[0] &&
+#ifdef LCD_PROPFONTS
+            (width + lcd_getstringsize(ch, 0, &w, &h) <
+             (LCD_WIDTH - x*8))) {
+#else
+            (width + lcd_getstringsize(ch, _font, &w, &h) <
+             (LCD_WIDTH - x*8))) {
+#endif
         width += w;
-        ch[0]=string[(int)++s->space];
+        s->space++;
+        ch[0]=string[s->space];
     }
+#else
+    s->space = (LCD_WIDTH - xmargin - x*width) / width;
 #endif
 #endif
 
@@ -1148,11 +1267,25 @@
         scroll_count = 0;
         
 #ifdef LCD_PROPFONTS
+
         lcd_clearrect(xmargin + s->startx*fonts[font],
-                        ymargin + s->starty*fontheight[font],
-                        LCD_WIDTH - xmargin,
-                        fontheight[font]);
+                      ymargin + s->starty*fontheight[font],
+                      LCD_WIDTH - xmargin,
+                      fontheight[font]);
+
+#elif defined(LOADABLE_FONTS)
+        {
+            int w,h;
+            lcd_getstringsize( s->text, _font, &w, &h);
+            lcd_clearrect(xmargin + s->startx*w/s->textlen,
+                          ymargin + s->starty*h,
+                          LCD_WIDTH - xmargin,
+                          h);
+
+        }
 #endif
+
+
         /* restore scrolled row */
         lcd_puts(s->startx,s->starty,s->text);
         lcd_update();
@@ -1208,6 +1341,15 @@
                           ymargin + s->starty*fontheight[font],
                           LCD_WIDTH - xmargin,
                           fontheight[font]);
+#elif defined(LOADABLE_FONTS)
+            {
+                int w,h;
+                lcd_getstringsize( s->text, _font, &w, &h);
+                lcd_clearrect(xmargin + s->startx*w/s->textlen,
+                              ymargin + s->starty*h,
+                              LCD_WIDTH - xmargin,
+                              h);
+            }
 #endif
             lcd_puts(s->startx,s->starty,s->line);
             lcd_update();
diff --git a/firmware/drivers/lcd.h b/firmware/drivers/lcd.h
index bc971dc..ed2fe7e 100644
--- a/firmware/drivers/lcd.h
+++ b/firmware/drivers/lcd.h
@@ -105,4 +105,15 @@
 
 #endif /* CHARCELLS / BITMAP */
 
+#ifdef LOADABLE_FONTS
+extern int lcd_init_fonts(void);
+extern void lcd_putsldfxy(int x, int y, unsigned char *str);
+extern int lcd_getstringsize(unsigned char *str,
+                             unsigned char* font,
+                             int *w, int *h);
+extern void lcd_setldfont(unsigned char* f);
+
+extern unsigned char* lcd_getcurrentldfont(void);
+#endif
+
 #endif /* __LCD_H__ */
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index efe7570..a85545e 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -967,6 +967,7 @@
                 
             case SYS_USB_CONNECTED:
                 stop_playing();
+#ifndef SIMULATOR
                 
                 /* Tell the USB thread that we are safe */
                 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
@@ -974,6 +975,7 @@
 
                 /* Wait until the USB cable is extracted again */
                 usb_wait_for_disconnect(&mpeg_queue);
+#endif
                 break;
         }
     }
diff --git a/firmware/panic.c b/firmware/panic.c
index f9023fe..b130482 100644
--- a/firmware/panic.c
+++ b/firmware/panic.c
@@ -8,7 +8,7 @@
  * $Id$
  *
  * Copyright (C) 2002 by wavey@wavey.org
- *
+ *nn
  * 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.
  *
@@ -48,8 +48,9 @@
     lcd_puts(0,0,panic_buf);
 #elif defined(HAVE_LCD_BITMAP)
     lcd_clear_display();
-    lcd_puts(0,0,panic_buf);
+    lcd_putsxy(0,0,panic_buf,0);
     lcd_update();
+
 #else
     /* no LCD */
 #endif
diff --git a/tools/Makefile b/tools/Makefile
index 92f621f..9d47a1c 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -8,7 +8,7 @@
 #
 CFLAGS := -O -s -ansi
 
-TARGETS := scramble descramble sh2d
+TARGETS := scramble descramble sh2d bdf2ajf
 
 all: $(TARGETS)
 
@@ -18,5 +18,9 @@
 
 sh2d: sh2d.c
 
+bdf2ajf: bdf2ajf.c
+	gcc -O -ansi $+ -o $@
+
 clean:
-	rm -f $(TARGETS) *~
+	rm -f $(TARGETS) $(shell for f in $(TARGETS) ; do echo $$f.exe $$f.o $$f.obj ; done) *.ajf *~
+
diff --git a/tools/configure b/tools/configure
index 2ddfb72..bf89d88 100755
--- a/tools/configure
+++ b/tools/configure
@@ -11,6 +11,8 @@
 target=$1
 debug=$2
 
+extra_defines="-"
+
 input() {
     read response
     echo $response
@@ -66,8 +68,9 @@
  -e "s,@KEYPAD@,${keypad},g" \
  -e "s,@PWD@,${pwd},g" \
  -e "s,@SIMVER@,${simver},g" \
+ -e "s,@EXTRA_DEFINES@,${extra_defines},g" \
 <<EOF 
-## Automaticly generated. http://bjorn.haxx.se/rockbox/
+## Automaticly generated. http://rockbox.haxx.se
 
 SIMDIR=@SIMDIR@
 DEBUG=@DEBUG@
@@ -77,13 +80,14 @@
 THISDIR="@PWD@"
 SIMVER=@SIMVER@
 VERSION=\$(shell date +%y%m%d-%H%M)
+EXTRA_DEFINES=@EXTRA_DEFINES@
 
 .PHONY: 
 
 all: sim
 
 sim:
-	\$(MAKE) -C \$(SIMDIR) DISPLAY=\$(DISPLAY) KEYPAD=\$(KEYPAD) OBJDIR=\$(THISDIR) VERSION=\$(VERSION)
+	\$(MAKE) -C \$(SIMDIR) DISPLAY=\$(DISPLAY) KEYPAD=\$(KEYPAD) OBJDIR=\$(THISDIR) VERSION=\$(VERSION) EXTRA_DEFINES=\$(EXTRA_DEFINES)
 
 clean-sim:
 	\$(MAKE) -C \$(SIMDIR) DISPLAY=\$(DISPLAY) KEYPAD=\$(KEYPAD) OBJDIR=\$(THISDIR) clean
@@ -121,6 +125,7 @@
       echo "Existing generated Makefile found. Getting defaults from it."
       target=`grep "^TARGET=" Makefile | cut -d= -f2-`
       debug=`grep "^DEBUG=" Makefile | cut -d= -f2-`
+      extra_defines=`grep "^EXTRA_DEFINES=" Makefile | cut -d= -f2-`
 
       if [ "$debug" = "SIMULATOR=1" ]; then
         simulator="yes"
@@ -133,7 +138,7 @@
 else
 
 echo "Setup your Rockbox build environment."
-echo "http://bjorn.haxx.se/rockbox/"
+echo "http://rockbox.haxx.se/"
 echo ""
 
 fi
@@ -175,6 +180,25 @@
   esac
 fi
 
+if [ "-" == "$extra_defines" ]; then
+ if [  "-DARCHOS_RECORDER" = "$target" ] ; then
+  
+  echo "Loadable fonts support? (N)"
+  getit=`input`;
+  if [ "y" = "$getit" ] ; then
+     extra_defines="-DLOADABLE_FONTS"
+  else
+     echo "Proportional font support? (N)"
+     getit=`input`;
+     if [ "y" = "$getit" ] ; then
+        extra_defines="-DLCD_PROPFONTS"
+     else
+        extra_defines=""
+     fi
+  fi
+ fi
+fi
+
 if [ -z "$debug" ]; then
   ##################################################################
   # Figure out debug on/off
@@ -250,9 +274,10 @@
  -e "s,@APPSDIR@,${appsdir},g" \
  -e "s,@DEBUG@,${debug},g" \
  -e "s,@TARGET@,${target},g" \
+ -e "s,@EXTRA_DEFINES@,${extra_defines},g" \
  -e "s,@PWD@,${pwd},g" \
 <<EOF 
-## Automaticly generated. http://bjorn.haxx.se/rockbox/
+## Automaticly generated. http://rockbox.haxx.se
 
 FIRMDIR=@FIRMDIR@
 APPSDIR=@APPSDIR@
@@ -261,15 +286,16 @@
 THISDIR="@PWD@"
 VERSION=\$(shell date +%y%m%d-%H%M)
 
+EXTRA_DEFINES=@EXTRA_DEFINES@
 .PHONY: firmware apps
 
 all: firmware apps
 
 firmware:
-	\$(MAKE) -C \$(FIRMDIR) TARGET=\$(TARGET) \$(DEBUG) OBJDIR=\$(THISDIR)
+	\$(MAKE) -C \$(FIRMDIR) TARGET=\$(TARGET) \$(DEBUG) OBJDIR=\$(THISDIR) EXTRA_DEFINES=\$(EXTRA_DEFINES)
 
 apps:
-	\$(MAKE) -C \$(APPSDIR) TARGET=\$(TARGET) \$(DEBUG) OBJDIR=\$(THISDIR) VERSION=\$(VERSION)
+	\$(MAKE) -C \$(APPSDIR) TARGET=\$(TARGET) \$(DEBUG) OBJDIR=\$(THISDIR) VERSION=\$(VERSION) EXTRA_DEFINES=\$(EXTRA_DEFINES)
 
 clean-firmware:
 	\$(MAKE) -C \$(FIRMDIR) TARGET=\$(TARGET) OBJDIR=\$(THISDIR) clean
diff --git a/uisimulator/x11/Makefile b/uisimulator/x11/Makefile
index e64ae6f..b34bb48 100644
--- a/uisimulator/x11/Makefile
+++ b/uisimulator/x11/Makefile
@@ -25,6 +25,7 @@
 DRIVERS = $(FIRMWAREDIR)/drivers
 COMMON = $(FIRMWAREDIR)/common
 LIBMADDIR = $(PREVAPPDIR)/common/libmad
+TOOLSDIR = ../../tools
 
 CC = gcc
 RM = rm -f
@@ -42,7 +43,7 @@
 KEYPAD = -DHAVE_RECORDER_KEYPAD
 
 DEFINES = -DHAVE_CONFIG_H -DGETTIMEOFDAY_TWO_ARGS -DSIMULATOR	\
-$(KEYPAD) $(DISPLAY) #-DLCD_PROPFONTS
+$(KEYPAD) $(DISPLAY) $(EXTRA_DEFINES)
 
 LDFLAGS = -lX11 -lm -lXt -lXmu -lnsl
 
@@ -69,11 +70,17 @@
   INCLUDES += -I$(PREVAPPDIR)/common
 endif
 
-CFLAGS = $(DEBUG) $(DEFINES) $(INCLUDES) -W -Wall 
+CFLAGS = $(DEBUG) $(DEFINES) $(INCLUDES) -W -Wall
 
 APPCFLAGS = $(DEBUG) $(DEFINES) -DAPPSVERSION=\"$(VERSION)\" $(APPINCLUDES) -W -Wall
 
-FIRMSRCS = chartables.c lcd.c sprintf.c id3.c debug.c usb.c mpeg.c power.c powermgmt.c
+FIRMSRCS = chartables.c lcd.c sprintf.c id3.c debug.c usb.c mpeg.c power.c powermgmt.c 
+
+ifeq (LOADABLE_FONTS,$(findstring LOADABLE_FONTS, $(DEFINES)))
+	FIRMSRCS += unicode.c ajf.c panic.c
+	EXTRA_TARGETS = $(OBJDIR)/archos/system.ajf
+	SYSTEM_FONT = $(FIRMWAREDIR)/fonts/alt6x10.bdf
+endif
 
 APPS = main.c tree.c menu.c credits.c main_menu.c\
 	playlist.c showtext.c wps.c settings.c status.c
@@ -95,12 +102,15 @@
 
 OBJS := $(SRCS:%.c=$(OBJDIR)/%.o)
 
-all: $(TARGET)
+all: $(TARGET) $(EXTRA_TARGETS)
 
 clean:
 	$(RM) $(OBJS) *~ core $(TARGET) $(CLIENTS)
 	$(RM) -r $(DEPS)
 
+$(OBJDIR)/archos/system.ajf: $(TOOLSDIR)/bdf2ajf $(SYSTEM_FONT)
+	$(TOOLSDIR)/bdf2ajf -f $(SYSTEM_FONT) -o $(OBJDIR)/archos/system.ajf
+
 distclean: clean
 	$(RM) config.cache
 
@@ -218,6 +228,9 @@
 $(OBJDIR)/debug.o: $(FIRMWAREDIR)/debug.c
 	$(CC) $(CFLAGS) -c $< -o $@
 
+$(OBJDIR)/panic.o: $(FIRMWAREDIR)/panic.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
 $(OBJDIR)/mpeg.o: $(FIRMWAREDIR)/mpeg.c
 	$(CC) $(CFLAGS) -c $< -o $@
 
@@ -230,6 +243,12 @@
 $(OBJDIR)/powermgmt.o: $(FIRMWAREDIR)/powermgmt.c
 	$(CC) $(CFLAGS) -c $< -o $@
 
+$(OBJDIR)/unicode.o: $(FIRMWAREDIR)/unicode.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+$(OBJDIR)/ajf.o: $(FIRMWAREDIR)/ajf.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
 $(OBJDIR)/stubs.o: ../common/stubs.c
 	$(CC) $(CFLAGS) -c $< -o $@