diff --git a/apps/bitmaps/native/SOURCES b/apps/bitmaps/native/SOURCES
index b3bd2c4..99424db 100644
--- a/apps/bitmaps/native/SOURCES
+++ b/apps/bitmaps/native/SOURCES
@@ -1,5 +1,13 @@
 #ifdef HAVE_LCD_BITMAP
 
+#ifdef DYNAMIC_LCD_SIZE
+/* This is a hack to prevent buildtime errors popping up */
+#undef LCD_WIDTH
+#undef LCD_HEIGHT
+#define LCD_WIDTH 0
+#define LCD_HEIGHT 0
+#endif
+
 /* Rockbox logo */
 #if (LCD_DEPTH == 1)
 #if (LCD_WIDTH == 160)
@@ -9,6 +17,12 @@ rockboxlogo.128x42x1.bmp
 #else
 rockboxlogo.112x30x1.bmp
 #endif
+#elif defined(DYNAMIC_LCD_SIZE)
+/* Currently only one screen size is supported.
+ * Ideally, we should compile in multiple logos and choose the correct one
+ * at runtime (and optionally discard the others using INIT_ATTR).
+ */
+rockboxlogo.320x98x16.bmp
 #elif (LCD_WIDTH == 128) && (LCD_DEPTH == 2)
 rockboxlogo.128x42x2.bmp
 #elif (LCD_WIDTH == 128) && (LCD_DEPTH == 16)
@@ -41,7 +55,9 @@ rockboxlogo.640x198x16.bmp
 
 /* USB logo */
 #ifdef HAVE_LCD_COLOR
-#if LCD_WIDTH > 176
+#if defined(DYNAMIC_LCD_SIZE)
+usblogo.176x48x16.bmp
+#elif LCD_WIDTH > 176
 usblogo.176x48x16.bmp
 #elif LCD_WIDTH >= 128
 usblogo.128x37x16.bmp
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index c0a476d..5a8d154 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -337,8 +337,13 @@ static bool dbg_buffering_thread(void)
             screens[i].putsf(0, line++, "alloc: %6ld/%ld", audio_filebufused(),
                             (long) filebuflen);
 
-#if LCD_HEIGHT > 80 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_HEIGHT > 80)
-            if (screens[i].lcdheight > 80)
+            if ((LCD_HEIGHT > 80 ||
+#ifdef HAVE_REMOTE_LCD
+                LCD_REMOTE_HEIGHT > 80
+#else
+                0
+#endif
+                ) && screens[i].lcdheight > 80)
             {
                 gui_scrollbar_draw(&screens[i],0, line*8, screens[i].lcdwidth, 6,
                                    filebuflen, 0, audio_filebufused(), HORIZONTAL);
@@ -351,19 +356,22 @@ static bool dbg_buffering_thread(void)
                                    filebuflen, 0, (long)d.buffered_data, HORIZONTAL);
                 line++;
             }
-#endif
 
             screens[i].putsf(0, line++, "usefl: %6ld/%ld", (long)(d.useful_data),
                                                        (long)filebuflen);
 
-#if LCD_HEIGHT > 80 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_HEIGHT > 80)
-            if (screens[i].lcdheight > 80)
+            if ((LCD_HEIGHT > 80 ||
+#ifdef HAVE_REMOTE_LCD
+                LCD_REMOTE_HEIGHT > 80
+#else
+                0
+#endif
+                ) && screens[i].lcdheight > 80)
             {
                 gui_scrollbar_draw(&screens[i],0, line*8, screens[i].lcdwidth, 6,
                                    filebuflen, 0, d.useful_data, HORIZONTAL);
                 line++;
             }
-#endif
 
             screens[i].putsf(0, line++, "data_rem: %ld", (long)d.data_rem);
 
diff --git a/apps/gui/skin_engine/skin_fonts.h b/apps/gui/skin_engine/skin_fonts.h
index 698ed4f..48bef2c 100644
--- a/apps/gui/skin_engine/skin_fonts.h
+++ b/apps/gui/skin_engine/skin_fonts.h
@@ -31,11 +31,7 @@
 #ifndef _SKINFONTS_H_
 #define _SKINFONTS_H_
 
-#if LCD_HEIGHT > 160
-#define SKIN_FONT_SIZE (1024*10)
-#else
-#define SKIN_FONT_SIZE (1024*3)
-#endif
+#define SKIN_FONT_SIZE  (LCD_HEIGHT > 160 ? 1024*10 : 1024*3)
 #define GLYPHS_TO_CACHE 256
 
 void skin_font_init(void);
diff --git a/apps/main.c b/apps/main.c
index 5f2c9e5..3780af4 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -344,6 +344,7 @@ static void init(void)
     lcd_remote_init();
 #endif
     font_init();
+    screen_init();
     show_logo();
     button_init();
     backlight_init();
diff --git a/apps/plugin.c b/apps/plugin.c
index 9e08951..c253cae 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -99,7 +99,7 @@ static int close_wrapper(int fd);
 static int creat_wrapper(const char *pathname, mode_t mode);
 #endif
 
-static const struct plugin_api rockbox_api = {
+static struct plugin_api rockbox_api = {
 
     /* lcd */
 #ifdef HAVE_LCD_CONTRAST
@@ -124,7 +124,7 @@ static const struct plugin_api rockbox_api = {
     lcd_icon,
     lcd_double_height,
 #else
-    &lcd_framebuffer[0][0],
+    NULL, /* will get filled in later */
     lcd_update_rect,
     lcd_set_drawmode,
     lcd_get_drawmode,
@@ -782,6 +782,8 @@ int plugin_load(const char* plugin, const void* parameter)
     plugin_size = 0;
 #endif
 
+    rockbox_api.lcd_framebuffer = lcd_framebuffer;
+
     *(hdr->api) = &rockbox_api;
 
 #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1
diff --git a/apps/recorder/bmp.c b/apps/recorder/bmp.c
index 81ed8bc..17058da 100644
--- a/apps/recorder/bmp.c
+++ b/apps/recorder/bmp.c
@@ -64,6 +64,7 @@
 #undef DEBUGF
 #define DEBUGF(...)
 #endif
+#include "buffer.h"
 
 #ifdef __GNUC__
 #define STRUCT_PACKED __attribute__((packed))
@@ -181,7 +182,7 @@ struct bmp_args {
     short read_width;
     short width;
     short depth;
-    unsigned char buf[BM_MAX_WIDTH * 4];
+    unsigned char *buf;
     struct uint8_rgb *palette;
 #if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
     defined(HAVE_BMP_SCALING) || defined(PLUGIN)
@@ -191,6 +192,8 @@ struct bmp_args {
 #endif
 };
 
+static unsigned char *ba_buf;
+
 static unsigned int read_part_line(struct bmp_args *ba)
 {
     const int padded_width = ba->padded_width;
@@ -708,9 +711,13 @@ int read_bmp_fd(int fd,
 
     memset(bitmap, 0, totalsize);
 
+    if (!ba_buf)
+        ba_buf = buffer_alloc(BM_MAX_WIDTH*4);
+
     struct bmp_args ba = {
         .fd = fd, .padded_width = padded_width, .read_width = read_width,
         .width = src_dim.width, .depth = depth, .palette = palette,
+        .buf = ba_buf,
 #if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
     defined(HAVE_BMP_SCALING) || defined(PLUGIN)
         .cur_row = 0, .cur_col = 0, .part = {0,0}
diff --git a/apps/recorder/keyboard.c b/apps/recorder/keyboard.c
index c48eced..fea4323 100644
--- a/apps/recorder/keyboard.c
+++ b/apps/recorder/keyboard.c
@@ -370,10 +370,8 @@ int kbd_input(char* text, int buflen)
             const unsigned char *p;
             int len = 0;
 
-#if LCD_WIDTH >= 160 && LCD_HEIGHT >= 96
-            struct screen *sc = &screens[l];
-
-            if (sc->getwidth() >= 160 && sc->getheight() >= 96)
+            if (LCD_WIDTH >= 160 && LCD_HEIGHT >= 96 &&
+                screens[l].getwidth() >= 160 && screens[l].getheight() >= 96)
             {
                 p = "ABCDEFG abcdefg !?\" @#$%+'\n"
                     "HIJKLMN hijklmn 789 &_()-`\n"
@@ -388,7 +386,6 @@ int kbd_input(char* text, int buflen)
                 pm->max_line_len = 26;
             }
             else
-#endif /* LCD_WIDTH >= 160 && LCD_HEIGHT >= 96 */
             {
                 p = "ABCDEFG !?\" @#$%+'\n"
                     "HIJKLMN 789 &_()-`\n"
diff --git a/apps/screen_access.c b/apps/screen_access.c
index 7b64c40..4968486 100644
--- a/apps/screen_access.c
+++ b/apps/screen_access.c
@@ -105,8 +105,6 @@ struct screen screens[NB_SCREENS] =
 {
     {
         .screen_type=SCREEN_MAIN,
-        .lcdwidth=LCD_WIDTH,
-        .lcdheight=LCD_HEIGHT,
         .depth=LCD_DEPTH,
         .getnblines=&screen_helper_getnblines,
 #if defined(HAVE_LCD_COLOR)
@@ -308,3 +306,9 @@ void screen_clear_area(struct screen * display, int xstart, int ystart,
     display->set_drawmode(DRMODE_SOLID);
 }
 #endif
+
+void screen_init(void)
+{
+    screens[SCREEN_MAIN].lcdwidth = LCD_WIDTH;
+    screens[SCREEN_MAIN].lcdheight = LCD_HEIGHT;
+}
diff --git a/apps/screen_access.h b/apps/screen_access.h
index 463ca3f..ce62066 100644
--- a/apps/screen_access.h
+++ b/apps/screen_access.h
@@ -171,4 +171,6 @@ void screen_clear_area(struct screen * display, int xstart, int ystart,
  */
 extern struct screen screens[NB_SCREENS];
 
+void screen_init(void) INIT_ATTR;
+
 #endif /*_SCREEN_ACCESS_H_*/
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 0745066..fa1618d 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -205,7 +205,7 @@ static const char graphic_numeric[] = "graphic,numeric";
 #define DEFAULT_SBSNAME  "-"
 #define DEFAULT_FMS_NAME DEFAULT_WPSNAME
 
-#ifdef HAVE_LCD_BITMAP
+#if defined(HAVE_LCD_BITMAP) && !defined(DYNAMIC_LCD_SIZE)
 
 #if LCD_HEIGHT <= 64
   #define DEFAULT_FONTNAME "08-Rockfont"
@@ -720,7 +720,7 @@ const struct settings_list settings[] = {
                   LANG_SCROLL_BAR, SCROLLBAR_LEFT, "scrollbar","off,left,right",
                   NULL, 3, ID2P(LANG_OFF), ID2P(LANG_LEFT), ID2P(LANG_RIGHT)),
     INT_SETTING(F_THEMESETTING, scrollbar_width, LANG_SCROLLBAR_WIDTH, 6,
-                "scrollbar width",UNIT_INT, 3, MAX(LCD_WIDTH/10,25), 1,
+                "scrollbar width",UNIT_INT, 3, 25, 1,
                 NULL, NULL, NULL),
 #if CONFIG_KEYPAD == RECORDER_PAD
     OFFON_SETTING(F_THEMESETTING,buttonbar, LANG_BUTTON_BAR ,true,"buttonbar", NULL),
@@ -907,9 +907,9 @@ const struct settings_list settings[] = {
                   false, "Screen Scrolls Out Of View",
                   gui_list_screen_scroll_out_of_view),
     INT_SETTING(F_PADTITLE, scroll_step, LANG_SCROLL_STEP, 6, "scroll step",
-                UNIT_PIXEL, 1, LCD_WIDTH, 1, NULL, NULL, lcd_scroll_step),
+                UNIT_PIXEL, 1, 400/*LCD_WIDTH*/, 1, NULL, NULL, lcd_scroll_step),
     INT_SETTING(F_PADTITLE, screen_scroll_step, LANG_SCREEN_SCROLL_STEP, 16,
-                "screen scroll step", UNIT_PIXEL, 1, LCD_WIDTH, 1, NULL, NULL,
+                "screen scroll step", UNIT_PIXEL, 1, 400/*LCD_WIDTH*/, 1, NULL, NULL,
                 gui_list_screen_scroll_step),
 #endif /* HAVE_LCD_BITMAP */
     OFFON_SETTING(0,scroll_paginated,LANG_SCROLL_PAGINATED,
diff --git a/firmware/bidi.c b/firmware/bidi.c
index 2f4e137..ffd18c6 100644
--- a/firmware/bidi.c
+++ b/firmware/bidi.c
@@ -137,10 +137,10 @@ static void arabjoin(unsigned short * stringprt, int length)
 
 unsigned short *bidi_l2v(const unsigned char *str, int orientation)
 {
-    static unsigned short  utf16_buf[SCROLL_LINE_SIZE];
+    unsigned short  utf16_buf[SCROLL_LINE_SIZE];
     unsigned short *target, *tmp;
 #ifndef BOOTLOADER
-    static unsigned short  bidi_buf[SCROLL_LINE_SIZE];
+    unsigned short  bidi_buf[SCROLL_LINE_SIZE];
     unsigned short *heb_str; /* *broken_str */
     int block_start, block_end, block_type, block_length, i;
     int length = utf8length(str);
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c
index be4f21f..7979b54 100644
--- a/firmware/drivers/lcd-16bit.c
+++ b/firmware/drivers/lcd-16bit.c
@@ -43,8 +43,12 @@ enum fill_opt {
 };
 
 /*** globals ***/
-fb_data lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]
+fb_data *lcd_framebuffer;
+
+#ifndef DYNAMIC_LCD_SIZE
+fb_data _lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH]
     IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16);
+#endif
 
 
 static fb_data* lcd_backdrop = NULL;
@@ -54,8 +58,6 @@ static struct viewport default_vp =
 {
     .x        = 0,
     .y        = 0,
-    .width    = LCD_WIDTH,
-    .height   = LCD_HEIGHT,
     .font     = FONT_SYSFIXED,
     .drawmode = DRMODE_SOLID,
     .fg_pattern = LCD_DEFAULT_FG,
@@ -75,6 +77,12 @@ void lcd_init(void)
     /* Call device specific init */
     lcd_init_device();
     scroll_init();
+
+    default_vp.width = LCD_WIDTH;
+    default_vp.height = LCD_HEIGHT;
+#ifndef DYNAMIC_LCD_SIZE
+    lcd_framebuffer = &_lcd_framebuffer[0][0];
+#endif
 }
 /*** Viewports ***/
 
@@ -200,7 +208,7 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h)
 
 /*** low-level drawing functions ***/
 
-#define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)])
+#define LCDADDR(x, y) (lcd_framebuffer + y * LCD_WIDTH + x)
 
 static void ICODE_ATTR setpixel(fb_data *address)
 {
@@ -244,7 +252,7 @@ void lcd_set_backdrop(fb_data* backdrop)
     lcd_backdrop = backdrop;
     if (backdrop)
     {
-        lcd_backdrop_offset = (long)backdrop - (long)&lcd_framebuffer[0][0];
+        lcd_backdrop_offset = (long)backdrop - (long)lcd_framebuffer;
         lcd_fastpixelfuncs = lcd_fastpixelfuncs_backdrop;
     }
     else
diff --git a/firmware/export/config.h b/firmware/export/config.h
index b81c684..c103b54 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -579,6 +579,14 @@ Lyre prototype 1 */
 #endif
 #endif /* HAVE_REMOTE_LCD */
 
+#ifdef DYNAMIC_LCD_SIZE
+#undef LCD_WIDTH
+#undef LCD_HEIGHT
+
+#define LCD_WIDTH ({extern int lcd_width; lcd_width;})
+#define LCD_HEIGHT ({extern int lcd_height; lcd_height;})
+#endif
+
 /* define this in the target config.h to use a different size */
 #ifndef CONFIG_DEFAULT_ICON_HEIGHT
 #define CONFIG_DEFAULT_ICON_HEIGHT 8
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 1cbb286..330a271 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -405,7 +405,7 @@ static inline unsigned lcd_color_to_native(unsigned color)
 #define LCD_FBHEIGHT LCD_HEIGHT
 #endif
 /* The actual framebuffer */
-extern fb_data lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH];
+extern fb_data *lcd_framebuffer;
 
 /** Port-specific functions. Enable in port config file. **/
 #ifdef HAVE_REMOTE_LCD_AS_MAIN
diff --git a/firmware/export/scroll_engine.h b/firmware/export/scroll_engine.h
index ca94828..4711cc3 100644
--- a/firmware/export/scroll_engine.h
+++ b/firmware/export/scroll_engine.h
@@ -49,7 +49,7 @@ void lcd_remote_scroll_stop_line(const struct viewport* vp, int y);
 struct scrollinfo
 {
     struct viewport* vp;
-    char line[SCROLL_LINE_SIZE];
+    char *line;
 #ifdef HAVE_LCD_CHARCELLS
     int len;    /* length of line in chars */
 #endif
@@ -67,7 +67,7 @@ struct scrollinfo
 
 struct scroll_screen_info
 {
-    struct scrollinfo * const scroll;
+    struct scrollinfo * scroll;
     const int num_scroll; /* number of scrollable lines (also number of scroll structs) */
     int lines;  /* Number of currently scrolling lines */
     long ticks; /* # of ticks between updates*/
diff --git a/firmware/font.c b/firmware/font.c
index e973108..68f92b5 100644
--- a/firmware/font.c
+++ b/firmware/font.c
@@ -38,20 +38,13 @@
 #include "rbunicode.h"
 #include "diacritic.h"
 #include "rbpaths.h"
+#include "buffer.h"
 
 #define MAX_FONTSIZE_FOR_16_BIT_OFFSETS 0xFFDB
 
 /* max static loadable font buffer size */
 #ifndef MAX_FONT_SIZE
-#if LCD_HEIGHT > 64
-#if MEM > 2
-#define MAX_FONT_SIZE   60000
-#else
-#define MAX_FONT_SIZE   10000
-#endif
-#else
-#define MAX_FONT_SIZE   4000
-#endif
+#define MAX_FONT_SIZE (LCD_HEIGHT > 64 ? (MEM > 2 ? 60000 : 10000) : 4000)
 #endif
 
 #ifndef FONT_HEADER_SIZE
@@ -76,11 +69,11 @@ extern struct font sysfont;
 /* structure filled in by font_load */
 static struct font font_ui;
 /* static buffer allocation structures */
-static unsigned char main_buf[MAX_FONT_SIZE];
+static unsigned char *main_buf;
 #ifdef HAVE_REMOTE_LCD
 #define REMOTE_FONT_SIZE 10000
 static struct font remote_font_ui;
-static unsigned char remote_buf[REMOTE_FONT_SIZE];
+static unsigned char *remote_buf;
 #endif
 
 /* system font table, in order of FONT_xxx definition */
@@ -97,8 +90,10 @@ void font_init(void)
     int i = SYSTEMFONTCOUNT;
     while (i<MAXFONTS)
         sysfonts[i++] = NULL;
+    main_buf = buffer_alloc(MAX_FONT_SIZE);
     font_reset(NULL);
 #ifdef HAVE_REMOTE_LCD
+    remote_buf = buffer_alloc(REMOTE_FONT_SIZE);
     font_reset(&remote_font_ui);
 #endif
 }
diff --git a/firmware/screendump.c b/firmware/screendump.c
index 1876df8..ed3f24d 100644
--- a/firmware/screendump.c
+++ b/firmware/screendump.c
@@ -67,25 +67,44 @@
 #define BMP_DATASIZE   (BMP_LINESIZE * (LCD_HEIGHT+LCD_SPLIT_LINES))
 #define BMP_TOTALSIZE  (BMP_HEADERSIZE + BMP_DATASIZE)
 
-static const unsigned char bmpheader[] =
-{
-    0x42, 0x4d,                 /* 'BM' */
-    LE32_CONST(BMP_TOTALSIZE),  /* Total file size */
-    0x00, 0x00, 0x00, 0x00,     /* Reserved */
-    LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */
-
-    0x28, 0x00, 0x00, 0x00,     /* Size of (2nd) header */
-    LE32_CONST(LCD_WIDTH),      /* Width in pixels */
-    LE32_CONST(LCD_HEIGHT+LCD_SPLIT_LINES),  /* Height in pixels */
-    0x01, 0x00,                 /* Number of planes (always 1) */
-    LE16_CONST(BMP_BPP),        /* Bits per pixel 1/4/8/16/24 */
-    LE32_CONST(BMP_COMPRESSION),/* Compression mode */
-    LE32_CONST(BMP_DATASIZE),   /* Size of bitmap data */
-    0xc4, 0x0e, 0x00, 0x00,     /* Horizontal resolution (pixels/meter) */
-    0xc4, 0x0e, 0x00, 0x00,     /* Vertical resolution (pixels/meter) */
-    LE32_CONST(BMP_NUMCOLORS),  /* Number of used colours */
-    LE32_CONST(BMP_NUMCOLORS),  /* Number of important colours */
+#define ASSIGN_LE32(dst, x) memcpy((dst), (unsigned char[4]){LE32_CONST(x)}, 4);
+
+static struct {
+    const unsigned char header[2];
+    unsigned char       file_size[4];
+    const unsigned char reserved[4];
+    unsigned char       header_size[4];
+    const unsigned char second_header_size[4];
+    unsigned char       lcd_width[4];
+    unsigned char       lcd_height[4];
+    const unsigned char nr_planes[2];
+    const unsigned char bpp[2];
+    const unsigned char compression[4];
+    unsigned char       data_size[4];
+    const unsigned char horizontal_resolution[4];
+    const unsigned char vertical_resolution[4];
+    const unsigned char nr_used_colors[4];
+    const unsigned char nr_important_colors[4];
+    const unsigned char colors[BMP_NUMCOLORS*4];
+} __attribute__((__packed__)) bmpheader = {
+    {0x42, 0x4d},                 /* 'BM' */
+    {},                           /* Total file size */
+    {0x00, 0x00, 0x00, 0x00},     /* Reserved */
+    {},                           /* Offset to start of pixel data */
+
+    {0x28, 0x00, 0x00, 0x00},     /* Size of (2nd) header */
+    {},                           /* Width in pixels */
+    {},                           /* Height in pixels */
+    {0x01, 0x00},                 /* Number of planes (always 1) */
+    {LE16_CONST(BMP_BPP)},        /* Bits per pixel 1/4/8/16/24 */
+    {LE32_CONST(BMP_COMPRESSION)},/* Compression mode */
+    {},                           /* Size of bitmap data */
+    {0xc4, 0x0e, 0x00, 0x00},     /* Horizontal resolution (pixels/meter) */
+    {0xc4, 0x0e, 0x00, 0x00},     /* Vertical resolution (pixels/meter) */
+    {LE32_CONST(BMP_NUMCOLORS)},  /* Number of used colours */
+    {LE32_CONST(BMP_NUMCOLORS)},  /* Number of important colours */
 
+    {
 #if LCD_DEPTH == 1
 #ifdef HAVE_NEGATIVE_LCD
     BMP_COLOR(LCD_BL_DARKCOLOR),
@@ -108,6 +127,7 @@ static const unsigned char bmpheader[] =
     0xe0, 0x07, 0x00, 0x00,     /* green bitfield mask */
     0x1f, 0x00, 0x00, 0x00,     /* blue bitfield mask */
 #endif
+    }
 };
 
 static void (*screen_dump_hook)(int fh) = NULL;
@@ -150,7 +170,12 @@ void screen_dump(void)
     }
     else
     {
-        write(fd, bmpheader, sizeof(bmpheader));
+        ASSIGN_LE32(bmpheader.file_size, BMP_TOTALSIZE);
+        ASSIGN_LE32(bmpheader.header_size, BMP_HEADERSIZE);
+        ASSIGN_LE32(bmpheader.lcd_width, LCD_WIDTH);
+        ASSIGN_LE32(bmpheader.lcd_height, LCD_HEIGHT+LCD_SPLIT_LINES);
+        ASSIGN_LE32(bmpheader.data_size, BMP_DATASIZE);
+        write(fd, &bmpheader, sizeof(bmpheader));
 
         /* BMP image goes bottom up */
         for (y = LCD_HEIGHT - 1; y >= 0; y--)
@@ -228,7 +253,7 @@ void screen_dump(void)
 #endif
 #elif LCD_DEPTH == 16
             dst_end = dst + LCD_WIDTH;
-            src = lcd_framebuffer[y];
+            src = &lcd_framebuffer[y];
             
             do
             {
diff --git a/firmware/scroll_engine.c b/firmware/scroll_engine.c
index 70bbcbe..6823171 100644
--- a/firmware/scroll_engine.c
+++ b/firmware/scroll_engine.c
@@ -33,6 +33,7 @@
 #ifdef HAVE_REMOTE_LCD
 #include "lcd-remote.h"
 #endif
+#include "buffer.h"
 #include "scroll_engine.h"
 
 static const char scroll_tick_table[16] = {
@@ -45,16 +46,12 @@ static void scroll_thread(void);
 static char scroll_stack[DEFAULT_STACK_SIZE*3];
 static const char scroll_name[] = "scroll";
 
-static struct scrollinfo lcd_scroll[LCD_SCROLLABLE_LINES];
-
 #ifdef HAVE_REMOTE_LCD
-static struct scrollinfo lcd_remote_scroll[LCD_REMOTE_SCROLLABLE_LINES];
 static struct event_queue scroll_queue;
 #endif
 
 struct scroll_screen_info lcd_scroll_info =
 {
-    .scroll       = lcd_scroll,
     .lines        = 0,
     .ticks        = 12,
     .delay        = HZ/2,
@@ -71,7 +68,6 @@ struct scroll_screen_info lcd_scroll_info =
 #ifdef HAVE_REMOTE_LCD
 struct scroll_screen_info lcd_remote_scroll_info =
 {
-    .scroll       = lcd_remote_scroll,
     .lines        = 0,
     .ticks        = 12,
     .delay        = HZ/2,
@@ -348,5 +344,21 @@ void scroll_init(void)
                   sizeof(scroll_stack), 0, scroll_name
                   IF_PRIO(, PRIORITY_USER_INTERFACE)
                   IF_COP(, CPU));
+
+    struct scrollinfo *lcd_scroll = buffer_alloc(sizeof(struct scrollinfo) *
+                                                 LCD_SCROLLABLE_LINES);
+    lcd_scroll_info.scroll = lcd_scroll;
+
+    for (int i = 0; i < LCD_SCROLLABLE_LINES; i++)
+        lcd_scroll[i].line = buffer_alloc(SCROLL_LINE_SIZE);
+#ifdef HAVE_REMOTE_LCD
+    struct scrollinfo *lcd_remote_scroll;
+    lcd_remote_scroll = buffer_alloc(sizeof(struct scrollinfo) *
+                                     LCD_REMOTE_SCROLLABLE_LINES);
+    lcd_remote_scroll_info.scroll = lcd_remote_scroll;
+
+    for (int i = 0; i < LCD_REMOTE_SCROLLABLE_LINES; i++)
+        lcd_remote_scroll[i].line = buffer_alloc(SCROLL_LINE_SIZE);
+#endif
 }
 
diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c
index 1043dfa..224ae0a 100644
--- a/firmware/target/hosted/android/lcd-android.c
+++ b/firmware/target/hosted/android/lcd-android.c
@@ -35,6 +35,8 @@ static jmethodID java_lcd_update_rect;
 
 static bool display_on;
 
+int lcd_width = 320, lcd_height = 480;
+
 void lcd_init_device(void)
 {
     /* get the RockboxFramebuffer instance allocated by the activity */
@@ -71,7 +73,8 @@ void lcd_init_device(void)
      * be directly feched from the framebuffer */
     jobject buf = (*env_ptr)->NewDirectByteBuffer(env_ptr,
                                                   lcd_framebuffer,
-                                                  sizeof(lcd_framebuffer));
+                                                  sizeof(fb_data) *
+                                                  LCD_WIDTH * LCD_HEIGHT);
     
     (*env_ptr)->CallVoidMethod(env_ptr,
                                Framebuffer_instance,
@@ -152,6 +155,8 @@ void lcd_yuv_set_options(unsigned options)
     (void)options;
 }
 
+#define LCD_PIXEL(x, y) (lcd_framebuffer + y * lcd_width + x)
+
 /* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
    in the core */
 void lcd_blit_yuv(unsigned char * const src[3],
@@ -167,13 +172,16 @@ void lcd_blit_yuv(unsigned char * const src[3],
     width &= ~1;
     linecounter = height >> 1;
 
-#if LCD_WIDTH >= LCD_HEIGHT
-    dst     = &lcd_framebuffer[y][x];
-    row_end = dst + width;
-#else
-    dst     = &lcd_framebuffer[x][LCD_WIDTH - y - 1];
-    row_end = dst + LCD_WIDTH * width;
-#endif
+    if (LCD_WIDTH >= LCD_HEIGHT)
+    {
+        dst     = LCD_PIXEL(x, y);
+        row_end = dst + width;
+    }
+    else
+    {
+        dst     = LCD_PIXEL(x, LCD_WIDTH - y - 1);
+        row_end = dst + LCD_WIDTH * width;
+    }
 
     z    = stride * src_y;
     ysrc = src[0] + z + src_x;
@@ -212,11 +220,10 @@ void lcd_blit_yuv(unsigned char * const src[3],
 
             *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
 
-#if LCD_WIDTH >= LCD_HEIGHT
-            dst++;
-#else
-            dst += LCD_WIDTH;
-#endif
+            if (LCD_WIDTH >= LCD_HEIGHT)
+                dst++;
+            else
+                dst += LCD_WIDTH;
 
             y = YFAC*(*ysrc++ - 16);
             r = y + rv;
@@ -232,11 +239,10 @@ void lcd_blit_yuv(unsigned char * const src[3],
 
             *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
 
-#if LCD_WIDTH >= LCD_HEIGHT
-            dst++;
-#else
-            dst += LCD_WIDTH;
-#endif
+            if (LCD_WIDTH >= LCD_HEIGHT)
+                dst++;
+            else
+                dst += LCD_WIDTH;
         }
         while (dst < row_end);
 
@@ -244,13 +250,16 @@ void lcd_blit_yuv(unsigned char * const src[3],
         usrc    -= width >> 1;
         vsrc    -= width >> 1;
 
-#if LCD_WIDTH >= LCD_HEIGHT
-        row_end += LCD_WIDTH;
-        dst     += LCD_WIDTH - width;
-#else
-        row_end -= 1;
-        dst     -= LCD_WIDTH*width + 1;
-#endif
+        if (LCD_WIDTH >= LCD_HEIGHT)
+        {
+            row_end += LCD_WIDTH;
+            dst     += LCD_WIDTH - width;
+        }
+        else
+        {
+            row_end -= 1;
+            dst     -= LCD_WIDTH*width + 1;
+        }
 
         do
         {
@@ -277,11 +286,10 @@ void lcd_blit_yuv(unsigned char * const src[3],
 
             *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
 
-#if LCD_WIDTH >= LCD_HEIGHT
-            dst++;
-#else
-            dst += LCD_WIDTH;
-#endif
+            if (LCD_WIDTH >= LCD_HEIGHT)
+                dst++;
+            else
+                dst += LCD_WIDTH;
 
             y = YFAC*(*ysrc++ - 16);
             r = y + rv;
@@ -297,11 +305,10 @@ void lcd_blit_yuv(unsigned char * const src[3],
 
             *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
 
-#if LCD_WIDTH >= LCD_HEIGHT
-            dst++;
-#else
-            dst += LCD_WIDTH;
-#endif
+            if (LCD_WIDTH >= LCD_HEIGHT)
+                dst++;
+            else
+                dst += LCD_WIDTH;
         }
         while (dst < row_end);
 
@@ -309,19 +316,21 @@ void lcd_blit_yuv(unsigned char * const src[3],
         usrc    += stride >> 1;
         vsrc    += stride >> 1;
 
-#if LCD_WIDTH >= LCD_HEIGHT
-        row_end += LCD_WIDTH;
-        dst     += LCD_WIDTH - width;
-#else
-        row_end -= 1;
-        dst     -= LCD_WIDTH*width + 1;
-#endif
+        if (LCD_WIDTH >= LCD_HEIGHT)
+        {
+            row_end += LCD_WIDTH;
+            dst     += LCD_WIDTH - width;
+        }
+        else
+        {
+            row_end -= 1;
+            dst     -= LCD_WIDTH*width + 1;
+        }
     }
     while (--linecounter > 0);
 
-#if LCD_WIDTH >= LCD_HEIGHT
-    lcd_update_rect(x, y, width, height);
-#else
-    lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
-#endif
+    if (LCD_WIDTH >= LCD_HEIGHT)
+        lcd_update_rect(x, y, width, height);
+    else
+        lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
 }
diff --git a/firmware/target/hosted/sdl/lcd-bitmap.c b/firmware/target/hosted/sdl/lcd-bitmap.c
index 7058b26..af328eb 100644
--- a/firmware/target/hosted/sdl/lcd-bitmap.c
+++ b/firmware/target/hosted/sdl/lcd-bitmap.c
@@ -27,6 +27,8 @@
 
 SDL_Surface* lcd_surface;
 
+int lcd_width = 320, lcd_height = 480; /* TODO: set me at runtime */
+
 #if LCD_DEPTH <= 8
 #ifdef HAVE_BACKLIGHT
 SDL_Color lcd_bl_color_dark    = {RED_CMP(LCD_BL_DARKCOLOR),
@@ -84,6 +86,8 @@ unsigned long (*lcd_ex_getpixel)(int, int) = NULL;
 static const unsigned char colorindex[4] = {128, 85, 43, 0};
 #endif
 
+#define LCD_PIXEL(x, y) (lcd_framebuffer + y * lcd_width + x)
+
 static unsigned long get_lcd_pixel(int x, int y)
 {
 #if LCD_DEPTH == 1
@@ -109,7 +113,7 @@ static unsigned long get_lcd_pixel(int x, int y)
 #if   defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
     return *(&lcd_framebuffer[0][0]+LCD_HEIGHT*x+y);
 #else
-    return lcd_framebuffer[y][x];
+    return *LCD_PIXEL(x, y);
 #endif
 #endif
 #endif
@@ -162,6 +166,10 @@ void sim_backlight(int value)
 /* initialise simulator lcd driver */
 void lcd_init_device(void)
 {
+#ifdef DYNAMIC_LCD_SIZE
+    lcd_framebuffer = malloc(lcd_width * lcd_height * sizeof(fb_data));
+#endif
+
 #if LCD_DEPTH == 16
     lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
                                        SIM_LCD_WIDTH * display_zoom,
@@ -255,13 +263,16 @@ void lcd_blit_yuv(unsigned char * const src[3],
     width &= ~1;
     linecounter = height >> 1;
 
-#if LCD_WIDTH >= LCD_HEIGHT
-    dst     = &lcd_framebuffer[y][x];
-    row_end = dst + width;
-#else
-    dst     = &lcd_framebuffer[x][LCD_WIDTH - y - 1];
-    row_end = dst + LCD_WIDTH * width;
-#endif
+    if (LCD_WIDTH >= LCD_HEIGHT)
+    {
+        dst     = LCD_PIXEL(x, y);
+        row_end = dst + width;
+    }
+    else
+    {
+        dst     = LCD_PIXEL(x, LCD_WIDTH - y - 1);
+        row_end = dst + LCD_WIDTH * width;
+    }
 
     z    = stride * src_y;
     ysrc = src[0] + z + src_x;
@@ -300,11 +311,10 @@ void lcd_blit_yuv(unsigned char * const src[3],
 
             *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
 
-#if LCD_WIDTH >= LCD_HEIGHT
-            dst++;
-#else
-            dst += LCD_WIDTH;
-#endif
+            if (LCD_WIDTH >= LCD_HEIGHT)
+                dst++;
+            else
+                dst += LCD_WIDTH;
 
             y = YFAC*(*ysrc++ - 16);
             r = y + rv;
@@ -320,11 +330,10 @@ void lcd_blit_yuv(unsigned char * const src[3],
 
             *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
 
-#if LCD_WIDTH >= LCD_HEIGHT
-            dst++;
-#else
-            dst += LCD_WIDTH;
-#endif
+            if (LCD_WIDTH >= LCD_HEIGHT)
+                dst++;
+            else
+                dst += LCD_WIDTH;
         }
         while (dst < row_end);
 
@@ -332,13 +341,16 @@ void lcd_blit_yuv(unsigned char * const src[3],
         usrc    -= width >> 1;
         vsrc    -= width >> 1;
 
-#if LCD_WIDTH >= LCD_HEIGHT
-        row_end += LCD_WIDTH;
-        dst     += LCD_WIDTH - width;
-#else
-        row_end -= 1;
-        dst     -= LCD_WIDTH*width + 1;
-#endif
+        if (LCD_WIDTH >= LCD_HEIGHT)
+        {
+            row_end += LCD_WIDTH;
+            dst     += LCD_WIDTH - width;
+        }
+        else
+        {
+            row_end -= 1;
+            dst     -= LCD_WIDTH*width + 1;
+        }
 
         do
         {
@@ -365,11 +377,10 @@ void lcd_blit_yuv(unsigned char * const src[3],
 
             *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
 
-#if LCD_WIDTH >= LCD_HEIGHT
-            dst++;
-#else
-            dst += LCD_WIDTH;
-#endif
+            if (LCD_WIDTH >= LCD_HEIGHT)
+                dst++;
+            else
+                dst += LCD_WIDTH;
 
             y = YFAC*(*ysrc++ - 16);
             r = y + rv;
@@ -385,11 +396,10 @@ void lcd_blit_yuv(unsigned char * const src[3],
 
             *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
 
-#if LCD_WIDTH >= LCD_HEIGHT
-            dst++;
-#else
-            dst += LCD_WIDTH;
-#endif
+            if (LCD_WIDTH >= LCD_HEIGHT)
+                dst++;
+            else
+                dst += LCD_WIDTH;
         }
         while (dst < row_end);
 
@@ -397,20 +407,22 @@ void lcd_blit_yuv(unsigned char * const src[3],
         usrc    += stride >> 1;
         vsrc    += stride >> 1;
 
-#if LCD_WIDTH >= LCD_HEIGHT
-        row_end += LCD_WIDTH;
-        dst     += LCD_WIDTH - width;
-#else
-        row_end -= 1;
-        dst     -= LCD_WIDTH*width + 1;
-#endif
+        if (LCD_WIDTH >= LCD_HEIGHT)
+        {
+            row_end += LCD_WIDTH;
+            dst     += LCD_WIDTH - width;
+        }
+        else
+        {
+            row_end -= 1;
+            dst     -= LCD_WIDTH*width + 1;
+        }
     }
     while (--linecounter > 0);
 
-#if LCD_WIDTH >= LCD_HEIGHT
-    lcd_update_rect(x, y, width, height);
-#else
-    lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
-#endif
+    if (LCD_WIDTH >= LCD_HEIGHT)
+        lcd_update_rect(x, y, width, height);
+    else
+        lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
 }
 #endif /* HAVE_LCD_COLOR */
