More work on VESA graphical console support
authorH. Peter Anvin <hpa@zytor.com>
Mon, 28 Aug 2006 07:28:31 +0000 (00:28 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Mon, 28 Aug 2006 07:28:31 +0000 (00:28 -0700)
com32/lib/Makefile
com32/lib/sys/vesa/background.c [new file with mode: 0644]
com32/lib/sys/vesa/drawtxt.c [new file with mode: 0644]
com32/lib/sys/vesa/initvesa.c
com32/lib/sys/vesa/video.h

index 0f65852..cfbeeb2 100644 (file)
@@ -33,6 +33,9 @@ LIBOBJS = \
        sys/null_read.o sys/null_write.o sys/serial_write.o             \
        sys/ansicon_write.o sys/ansiserial_write.o                      \
        \
+       sys/vesa/initvesa.o sys/vesa/alphatbl.o sys/vesa/drawtxt.o \
+       sys/vesa/background.o \
+       \
        pci/cfgtype.o                                                   \
        pci/readb.o pci/readw.o pci/readl.o pci/readbios.o              \
        pci/writeb.o pci/writew.o pci/writel.o pci/writebios.o          \
@@ -61,7 +64,7 @@ libcom32.a : $(LIBOBJS)
        $(RANLIB) $@
 
 tidy:
-       rm -f *.o .*.d */*.o */.*.d
+       rm -f *.o .*.d */*.o */.*.d lib/sys/vesa/alphatbl.c
 
 clean: tidy
        rm -f *.a
@@ -75,4 +78,9 @@ install: all
        -rm -rf $(INSTALLROOT)$(COM32DIR)/include
        cp -r ../include $(INSTALLROOT)$(COM32DIR)
 
+sys/vesa/alphatbl.o: sys/vesa/alphatbl.c
+
+sys/vesa/alphatbl.c: sys/vesa/alphatbl.pl
+       $(PERL) $< > $@ || ( rm -f $@ ; exit 1 )
+
 -include .*.d */.*.d
diff --git a/com32/lib/sys/vesa/background.c b/com32/lib/sys/vesa/background.c
new file mode 100644 (file)
index 0000000..7de2d5a
--- /dev/null
@@ -0,0 +1,171 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2006 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdio.h>
+#include <png.h>
+#include <com32.h>
+#include "vesa.h"
+#include "video.h"
+
+static void draw_background(void)
+{
+  uint32_t *outp = (uint32_t *)__vesa_info.mi.lfb_ptr;
+  uint32_t *inp = (uint32_t *)__vesacon_background;
+  size_t n = sizeof __vesacon_background;
+  uint32_t v;
+
+  while (n--) {
+    v = *inp++;
+    *outp++ = (__vesacon_alpha_tbl[(uint8_t)(v >> 16)][0] << 16)|
+      (__vesacon_alpha_tbl[(uint8_t)(v >> 8)][0] << 8)|
+      (__vesacon_alpha_tbl[(uint8_t)v][0]);
+  }
+}
+
+int vesacon_load_background(const char *filename)
+{
+  FILE *fp;
+  uint8_t header[8];
+  png_structp png_ptr = NULL;
+  png_infop info_ptr = NULL;
+  png_infop end_ptr = NULL;
+  png_color_16p image_background;
+  static const png_color_16 my_background = {0,0,0,0,0};
+  double gamma;
+  const double screen_gamma = 2.2;
+  png_bytep row_pointers[VIDEO_Y_SIZE];
+  int passes;
+  int i;
+  int rv = -1;
+
+  if (!filename) {
+    draw_background();
+    return 0;
+  }
+
+  fp = fopen(filename, "r");
+
+  if (!fp)
+    goto err;
+
+  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+                                  NULL, NULL, NULL);
+
+  info_ptr = png_create_info_struct(png_ptr);
+  end_ptr = png_create_info_struct(png_ptr);
+
+  if (fread(header, 1, 8, fp) != 8 || png_sig_cmp(header, 0, 8) ||
+      !png_ptr || !info_ptr || !end_ptr ||
+      setjmp(png_jmpbuf(png_ptr)))
+    goto err;
+
+  png_init_io(png_ptr, fp);
+  png_set_sig_bytes(png_ptr, 8);
+
+  png_set_user_limits(png_ptr, VIDEO_X_SIZE, VIDEO_Y_SIZE);
+
+  png_read_info(png_ptr, info_ptr);
+
+  /* Set the appropriate set of transformations.  We need to end up
+     with 32-bit BGRA format, no more, no less. */
+  
+  switch (info_ptr->color_type) {
+  case PNG_COLOR_TYPE_GRAY_ALPHA:
+    png_set_gray_to_rgb(png_ptr);
+    /* fall through */
+    
+  case PNG_COLOR_TYPE_RGB_ALPHA:
+    break;
+
+  case PNG_COLOR_TYPE_GRAY:
+    png_set_gray_to_rgb(png_ptr);
+    /* fall through */
+
+  case PNG_COLOR_TYPE_RGB:
+    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+      png_set_tRNS_to_alpha(png_ptr);
+    else
+      png_set_add_alpha(png_ptr, ~0, PNG_FILLER_AFTER);
+    break;
+    
+  case PNG_COLOR_TYPE_PALETTE:
+    png_set_palette_to_rgb(png_ptr);
+    break;
+
+  default:
+    /* Huh? */
+    break;
+  }
+
+  png_set_bgr(png_ptr);
+
+  if (png_get_bKGD(png_ptr, info_ptr, &image_background))
+    png_set_background(png_ptr, image_background,
+                      PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+  else
+    png_set_background(png_ptr, &my_background,
+                      PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+    
+
+  if (info_ptr->bit_depth == 16)
+    png_set_strip_16(png_ptr);
+  else if (info_ptr->bit_depth < 8)
+    png_set_packing(png_ptr);
+
+  if (png_get_gAMA(png_ptr, info_ptr, &gamma))
+    png_set_gamma(png_ptr, screen_gamma, gamma);
+  else
+    png_set_gamma(png_ptr, screen_gamma, 0.45455);
+
+  /* Whew!  Now we should get the stuff we want... */
+  for (i = 0; i < info_ptr->height; i++)
+    row_pointers[i] = (png_bytep *)__vesacon_background[i];
+    
+  passes = png_set_interlace_handling(png_ptr);
+
+  for (i = 0; i < passes; i++)
+    png_read_rows(png_ptr, row_pointers, NULL, info_ptr->height);
+
+  /* This actually displays the stuff */
+  draw_background();
+
+  rv = 0;
+
+ err:
+  if (png_ptr)
+    png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+  if (fp)
+    fclose(fp);
+  return rv;
+}
+
+int __vesacon_init_background(void)
+{
+  memset(__vesacon_background, 0, sizeof __vesacon_background);
+
+  /* The VESA BIOS has already cleared the screen */
+}
diff --git a/com32/lib/sys/vesa/drawtxt.c b/com32/lib/sys/vesa/drawtxt.c
new file mode 100644 (file)
index 0000000..6713063
--- /dev/null
@@ -0,0 +1,148 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2006 H. Peter Anvin - All Rights Reserved
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *   
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *   
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <inttypes.h>
+#include "vesa.h"
+#include "video.h"
+
+static void vesacon_update_characters(int row, int col, int nrows, int ncols)
+{
+  const int height = __vesacon_font_height;
+  const int width = FONT_WIDTH;
+  uint32_t *bgrowptr, *bgptr, *fbrowptr, *fbptr, bgval, bgxval;
+  int fr = 0, fg = 0, fb = 0;
+  int br = 0, bg = 0, bb = 0;
+  uint8_t r, g, b;
+  uint8_t chbits = 0, chxbits = 0, chsbits = 0;
+  int i, j, pixrow, pixsrow;
+  struct vesa_char *rowptr, *rowsptr, *cptr, *csptr;
+
+  bgrowptr  = &__vesacon_background[row*height+VIDEO_BORDER][col*width+VIDEO_BORDER];
+  fbrowptr = ((uint32_t *)__vesa_info.mi.lfb_ptr)+
+    ((row*height+VIDEO_BORDER)*VIDEO_X_SIZE)+(col*width+VIDEO_BORDER);
+
+  /* Note that we keep a 1-character guard area around the real text area... */
+  rowptr  = &__vesacon_text_display[(row+1)*(TEXT_PIXEL_COLS/FONT_WIDTH+2)+(col+1)];
+  rowsptr = rowptr - ((TEXT_PIXEL_COLS/FONT_WIDTH+2)+1);
+  pixrow = 0;
+  pixsrow = height-1;
+
+  for (i = height*nrows; i >= 0; i--) {
+    bgptr = bgrowptr;
+    fbptr = fbrowptr;
+
+    cptr = rowptr;
+    csptr = rowsptr;
+
+    chsbits = __vesacon_graphics_font[csptr->ch][pixsrow];
+    chsbits &= (csptr->sha & 0x02) ? 0xff : 0x00;
+    chsbits ^= (csptr->sha & 0x01) ? 0xff : 0x00;
+    chsbits <<= 7;
+    csptr++;
+    
+    for (j = width*ncols; j >= 0; j--) {
+      chbits <<= 1;
+      chsbits <<= 1;
+      chxbits <<= 1;
+
+      switch (j % FONT_WIDTH) {
+      case 0:
+       chbits = __vesacon_graphics_font[cptr->ch][pixrow];
+       chxbits = chbits;
+       chxbits &= (cptr->sha & 0x02) ? 0xff : 0x00;
+       chxbits ^= (cptr->sha & 0x01) ? 0xff : 0x00;
+       fr = ((cptr->attr & 4) >> 1) + ((cptr->attr & 8) >> 3);
+       fg = ((cptr->attr & 2)) + ((cptr->attr & 8) >> 3);
+       fb = ((cptr->attr & 1) << 1) + ((cptr->attr & 8) >> 3);
+       br = ((cptr->attr & 0x40) >> 5) + ((cptr->attr & 0x80) >> 7);
+       bg = ((cptr->attr & 0x20) >> 4) + ((cptr->attr & 0x80) >> 7);
+       bb = ((cptr->attr & 0x10) >> 3) + ((cptr->attr & 0x80) >> 7);
+       cptr++;
+       break;
+      case FONT_WIDTH-1:
+       chsbits = __vesacon_graphics_font[csptr->ch][pixsrow];
+       chsbits &= (csptr->sha & 0x02) ? 0xff : 0x00;
+       chsbits ^= (csptr->sha & 0x01) ? 0xff : 0x00;
+       csptr++;
+       break;
+      default:
+       break;
+      }
+
+      bgval = *bgptr;
+      bgxval = bgptr[VIDEO_X_SIZE+1];
+      bgptr++;
+      
+      if (chbits & 0x80) {
+       r = __vesacon_alpha_tbl[(uint8_t)(bgxval >> 16)][fr];
+       g = __vesacon_alpha_tbl[(uint8_t)(bgxval >> 8)][fg];
+       b = __vesacon_alpha_tbl[(uint8_t)bgxval][fb];
+      } else if ((chsbits & ~chxbits) & 0x80) {
+       r = __vesacon_alpha_tbl[(uint8_t)(bgval >> 16)][br] >> 2;
+       g = __vesacon_alpha_tbl[(uint8_t)(bgval >> 8)][bg] >> 2;
+       b = __vesacon_alpha_tbl[(uint8_t)bgval][bb] >> 2;
+      } else {
+       r = __vesacon_alpha_tbl[(uint8_t)(bgval >> 16)][br];
+       g = __vesacon_alpha_tbl[(uint8_t)(bgval >> 8)][bg];
+       b = __vesacon_alpha_tbl[(uint8_t)bgval][bb];
+      }
+      
+      *fbptr++ = (r << 16)|(g << 8)|b;
+    }
+
+    bgrowptr += VIDEO_X_SIZE;
+    fbrowptr += VIDEO_X_SIZE;
+
+    if (++pixrow == height) {
+      rowptr += TEXT_PIXEL_COLS/FONT_WIDTH+2;
+      pixrow = 0;
+    }
+    if (++pixsrow == height) {
+      rowsptr += TEXT_PIXEL_COLS/FONT_WIDTH+2;
+      pixsrow = 0;
+    }
+  }
+}
+
+void vesacon_write_at(int row, int col, const char *str, uint8_t attr, int rev)
+{
+  int n = 0;
+  struct vesa_char *ptr = &__vesacon_text_display[(row+1)*(TEXT_PIXEL_COLS/FONT_WIDTH+2)+(col+1)];
+
+  while (*str) {
+    ptr->ch   = *str;
+    ptr->attr = attr;
+    ptr->sha  = rev;
+
+    n++;
+    str++;
+    ptr++;
+  }
+
+  vesacon_update_characters(row, col, 1, n);
+}
+
index 43b3498..7d29427 100644 (file)
 #include <inttypes.h>
 #include <com32.h>
 #include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
 #include "vesa.h"
 #include "video.h"
 
-struct vesa_general_info __vesa_general_info;
-struct vesa_mode_info    __vesa_mode_info;
+struct vesa_info __vesa_info;
 
+struct vesa_char *__vesacon_text_display;
+
+int __vesacon_font_height;
 uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT];
+
 uint32_t __vesacon_background[VIDEO_Y_SIZE][VIDEO_X_SIZE];
-uint32_t __vesacon_shadowfb[VIDEO_Y_SIZE][VIDEO_X_SIZE];
+
+ssize_t __serial_write(void *fp, const void *buf, size_t count);
+
+static void debug(const char *str, ...)
+{
+  va_list va;
+  char buf[65536];
+  size_t len;
+
+  va_start(va, str);
+  len = vsnprintf(buf, sizeof buf, str, va);
+  va_end(va);
+
+  if (len >= sizeof buf)
+    len = sizeof buf - 1;
+
+  __serial_write(NULL, buf, len);
+}
 
 static void unpack_font(uint8_t *dst, uint8_t *src, int height)
 {
@@ -51,9 +74,9 @@ static void unpack_font(uint8_t *dst, uint8_t *src, int height)
 
   for (i = 0; i < FONT_MAX_CHARS; i++) {
     memcpy(dst, src, height);
-    memset(dst+height, 0, 32-height);
+    memset(dst+height, 0, FONT_MAX_HEIGHT-height);
 
-    dst += 32;
+    dst += FONT_MAX_HEIGHT;
     src += height;
   }
 }
@@ -70,6 +93,8 @@ static int vesacon_set_mode(void)
   gi = &((struct vesa_info *)__com32.cs_bounce)->gi;
   mi = &((struct vesa_info *)__com32.cs_bounce)->mi;
 
+  debug("Hello, World!\r\n");
+
   memset(&rm, 0, sizeof rm);
 
   gi->signature = VBE2_MAGIC;  /* Get VBE2 extended data */
@@ -87,12 +112,14 @@ static int vesacon_set_mode(void)
   }
 
   /* Search for a 640x480 32-bit linear frame buffer mode */
-  mode_ptr = CVT_PTR(gi->video_mode_ptr);
+  mode_ptr = GET_PTR(gi->video_mode_ptr);
 
   for(;;) {
     if ((mode = *mode_ptr++) == 0xFFFF)
       return 4;                        /* No mode found */
 
+    debug("Found mode: 0x%04x\r\n", mode);
+
     rm.eax.w[0] = 0x4F01;      /* Get SVGA mode information */
     rm.ecx.w[0] = mode;
     rm.edi.w[0] = OFFS(mi);
@@ -102,6 +129,11 @@ static int vesacon_set_mode(void)
     /* Must be a supported mode */
     if ( rm.eax.w[0] != 0x004f )
       continue;
+
+    debug("mode_attr 0x%04x, h_res = %4d, v_res = %4d, bpp = %2d, layout = %d (%d,%d,%d)\r\n",
+         mi->mode_attr, mi->h_res, mi->v_res, mi->bpp, mi->memory_layout,
+         mi->rpos, mi->gpos, mi->bpos);
+
     /* Must be an LFB color graphics mode supported by the hardware */
     if ( (mi->mode_attr & 0x0099) != 0x0099 )
       continue;
@@ -112,8 +144,8 @@ static int vesacon_set_mode(void)
     /* Must either be a packed-pixel mode or a direct color mode
        (depending on VESA version ) */
     if ( mi->memory_layout != 4 && /* Packed pixel */
-        (mi->memory_layout != 6 || mi->rpos != 24 ||
-         mi->gpos != 16 || mi->bpos != 0) )
+        (mi->memory_layout != 6 || mi->rpos != 16 ||
+         mi->gpos != 8 || mi->bpos != 0) )
       continue;
 
     /* Hey, looks like we found something we can live with */
@@ -125,7 +157,8 @@ static int vesacon_set_mode(void)
   rm.ebx.w[0] = 0x0600;                /* Get 8x16 ROM font */
   __intcall(0x10, &rm, &rm);
   rom_font = MK_PTR(rm.es, rm.ebp.w[0]);
-  unpack_font(graphics_font, rom_font, 16);
+  __vesacon_font_height = 16;
+  unpack_font((uint8_t *)__vesacon_graphics_font, rom_font, 16);
 
   /* Now set video mode */
   rm.eax.w[0] = 0x4F02;                /* Set SVGA video mode */
@@ -143,7 +176,110 @@ static int vesacon_set_mode(void)
   return 0;
 }
 
+
+static int init_text_display(void)
+{
+  size_t nchars;
+  struct vesa_char *ptr;
+
+  nchars = (TEXT_PIXEL_ROWS/__vesacon_font_height+2)*
+    (TEXT_PIXEL_COLS/FONT_WIDTH+2);
+
+  __vesacon_text_display = ptr = malloc(nchars*sizeof(struct vesa_char));
+
+  if (!ptr)
+    return -1;
+
+  /* I really which C had a memset() for larger-than-bytes objects... */
+  asm volatile("cld; rep; stosl"
+              : "+D" (ptr), "+c" (nchars)
+              : "a" (' '+(0x07 << 8)+(SHADOW_NORMAL << 16))
+              : "memory");
+
+  return 0;
+}
+
 int __vesacon_init(void)
 {
-  return vesacon_set_mode();
+  int i, j, r, g, b, n;
+  const int step = 8;
+
+  /* Fill the background image with a test pattern */
+  for (i = 0; i < VIDEO_Y_SIZE; i++) {
+    r = g = b = n = 0;
+
+    for (j = 0; j < VIDEO_X_SIZE; j++) {
+      switch (n) {
+      case 0:
+       r += step;
+       if (r >= 255) {
+         r = 255;
+         n++;
+       }
+       break;
+      case 1:
+       g += step;
+       if (g >= 255) {
+         g = 255;
+         n++;
+       }
+       break;
+      case 2:
+       r -= step;
+       if (r <= 0) {
+         r = 0;
+         n++;
+       }
+       break;
+      case 3:
+       b += step;
+       if (b >= 255) {
+         b = 255;
+         n++;
+       }
+       break;
+      case 4:
+       g -= step;
+       if (g <= 0) {
+         g = 0;
+         n++;
+       }
+       break;
+      case 5:
+       r += step;
+       if (r >= 255) {
+         r = 255;
+         n++;
+       }
+       break;
+      case 6:
+       g += step;
+       if (g >= 255) {
+         g = 255;
+         n++;
+       }
+       break;
+      case 7:
+       r -= step;
+       if (r < 0) {
+         r = 0;
+         n = 0;
+       }
+       g = b = r;
+       break;
+      }
+      __vesacon_background[i][j] = (r << 16) + (g << 8) + b;
+    }
+  }
+
+  vesacon_set_mode();
+
+  init_text_display();
+
+  debug("Mode set, now drawing at %#p\n", __vesa_info.mi.lfb_ptr);
+
+  __vesacon_init_background();
+
+  debug("Ready!\r\n");
+  return 0;
 }
index acbbc10..9237a85 100644 (file)
 
 #define FONT_MAX_CHARS 256
 #define FONT_MAX_HEIGHT         32
+#define FONT_WIDTH       8
 
 #define VIDEO_X_SIZE   640
 #define VIDEO_Y_SIZE   480
 
-extern uint8_t graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT];
+#define VIDEO_BORDER   8
+#define TEXT_PIXEL_ROWS (VIDEO_Y_SIZE-2*VIDEO_BORDER)
+#define TEXT_PIXEL_COLS (VIDEO_X_SIZE-2*VIDEO_BORDER)
+
+#define SHADOW_NONE    0
+#define SHADOW_ALL     1
+#define SHADOW_NORMAL  2
+#define SHADOW_REVERSE 3
+
+struct vesa_char {
+  uint8_t ch;                  /* Character */
+  uint8_t attr;                        /* PC-style graphics attribute */
+  uint8_t sha;                 /* Shadow attributes */
+  uint8_t pad;                 /* Currently unused */
+};
+
+extern struct vesa_char *__vesacon_text_display;
+
+extern int __vesacon_font_height;
+extern uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT];
+extern uint32_t __vesacon_background[VIDEO_Y_SIZE][VIDEO_X_SIZE];
+extern uint32_t __vesacon_shadowfb[VIDEO_Y_SIZE][VIDEO_X_SIZE];
+
+extern unsigned char __vesacon_alpha_tbl[256][4];
+
+extern int __vesacon_init_background(void);
+int vesacon_load_background(const char *);
 
 #endif /* LIB_SYS_VESA_VIDEO_H */