aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Alcantara <pcacjr@zytor.com>2015-12-27 11:42:00 -0200
committerPaulo Alcantara <pcacjr@zytor.com>2016-01-17 19:06:10 -0200
commit9ef1011ffdad8c76e61285382cfc1eb2a3d11e85 (patch)
tree9f012db69e37b0801d561acc3f3c64b37140fa83
parent54dc5933e22e5d60e7c2a664bc7edb02c613c108 (diff)
downloadsyslinux-lss16-fixes-v2.tar.gz
syslinux-lss16-fixes-v2.tar.xz
syslinux-lss16-fixes-v2.zip
core/graphics: Fix drawing of lss16 images (WIP)lss16-fixes-v2
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
-rw-r--r--com32/elflink/ldlinux/msg.c12
-rw-r--r--com32/lib/Makefile3
-rw-r--r--com32/lib/sys/vesa/background.c124
-rw-r--r--com32/lib/sys/vesa/dummy.c39
-rw-r--r--com32/lib/sys/vesa/foreground.c232
-rw-r--r--com32/lib/sys/vesa/initvesa.c12
-rw-r--r--com32/lib/sys/vesa/lss16.c190
-rw-r--r--com32/lib/sys/vesa/screencpy.c4
-rw-r--r--com32/lib/sys/vesa/video.h12
-rw-r--r--core/graphics.c13
-rw-r--r--core/include/graphics.h2
-rw-r--r--mk/lib.mk13
12 files changed, 519 insertions, 137 deletions
diff --git a/com32/elflink/ldlinux/msg.c b/com32/elflink/ldlinux/msg.c
index 794003ba..b750cdc3 100644
--- a/com32/elflink/ldlinux/msg.c
+++ b/com32/elflink/ldlinux/msg.c
@@ -126,20 +126,10 @@ static void msg_novga(void)
static void msg_viewimage(void)
{
- FILE *f;
-
*VGAFilePtr = '\0'; /* Zero-terminate filename */
mangle_name(VGAFileMBuf, VGAFileBuf);
- f = fopen(VGAFileMBuf, "r");
- if (!f) {
- /* Not there */
- NextCharJump = msg_putchar;
- return;
- }
-
- vgadisplayfile(f);
- fclose(f);
+ vgadisplayfile(VGAFileMBuf);
msg_initvars();
}
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 1624ae78..ea6013cb 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -30,7 +30,8 @@ endif
LIBVESA_OBJS = \
sys/vesacon_write.o sys/vesaserial_write.o \
- sys/vesa/initvesa.o sys/vesa/drawtxt.o sys/vesa/background.o \
+ sys/vesa/initvesa.o sys/vesa/drawtxt.o sys/vesa/lss16.o \
+ sys/vesa/background.o sys/vesa/foreground.o \
sys/vesa/alphatbl.o sys/vesa/screencpy.o sys/vesa/fmtpixel.o \
$(I915VESA_OBJ)
diff --git a/com32/lib/sys/vesa/background.c b/com32/lib/sys/vesa/background.c
index 15e90895..7e77850e 100644
--- a/com32/lib/sys/vesa/background.c
+++ b/com32/lib/sys/vesa/background.c
@@ -291,126 +291,6 @@ int vesacon_set_background(unsigned int rgb)
return 0;
}
-struct lss16_header {
- uint32_t magic;
- uint16_t xsize;
- uint16_t ysize;
-};
-
-#define LSS16_MAGIC 0x1413f33d
-
-static inline int lss16_sig_cmp(const void *header, int len)
-{
- const struct lss16_header *h = header;
-
- if (len != 8)
- return 1;
-
- return !(h->magic == LSS16_MAGIC &&
- h->xsize <= __vesa_info.mi.h_res &&
- h->ysize <= __vesa_info.mi.v_res);
-}
-
-static int read_lss16_file(FILE * fp, const void *header, int header_len)
-{
- const struct lss16_header *h = header;
- uint32_t colors[16], color;
- bool has_nybble;
- uint8_t byte;
- int count;
- int nybble, prev;
- enum state {
- st_start,
- st_c0,
- st_c1,
- st_c2,
- } state;
- int i, x, y;
- uint32_t *bgptr = __vesacon_background;
-
- /* Assume the header, 8 bytes, has already been loaded. */
- if (header_len != 8)
- return -1;
-
- for (i = 0; i < 16; i++) {
- uint8_t rgb[3];
- if (fread(rgb, 1, 3, fp) != 3)
- return -1;
-
- colors[i] = (((rgb[0] & 63) * 255 / 63) << 16) +
- (((rgb[1] & 63) * 255 / 63) << 8) +
- ((rgb[2] & 63) * 255 / 63);
- }
-
- /* By spec, the state machine is per row */
- for (y = 0; y < h->ysize; y++) {
- state = st_start;
- has_nybble = false;
- color = colors[prev = 0]; /* By specification */
- count = 0;
-
- x = 0;
- while (x < h->xsize) {
- if (!has_nybble) {
- if (fread(&byte, 1, 1, fp) != 1)
- return -1;
- nybble = byte & 0xf;
- has_nybble = true;
- } else {
- nybble = byte >> 4;
- has_nybble = false;
- }
-
- switch (state) {
- case st_start:
- if (nybble != prev) {
- *bgptr++ = color = colors[prev = nybble];
- x++;
- } else {
- state = st_c0;
- }
- break;
-
- case st_c0:
- if (nybble == 0) {
- state = st_c1;
- } else {
- count = nybble;
- goto do_run;
- }
- break;
-
- case st_c1:
- count = nybble + 16;
- state = st_c2;
- break;
-
- case st_c2:
- count += nybble << 4;
- goto do_run;
-
-do_run:
- count = min(count, h->xsize - x);
- x += count;
- asm volatile ("rep; stosl":"+D" (bgptr),
- "+c"(count):"a"(color));
- state = st_start;
- break;
- }
- }
-
- /* Zero-fill rest of row */
- i = __vesa_info.mi.h_res - x;
- asm volatile ("rep; stosl":"+D" (bgptr), "+c"(i):"a"(0):"memory");
- }
-
- /* Zero-fill rest of screen */
- i = (__vesa_info.mi.v_res - y) * __vesa_info.mi.h_res;
- asm volatile ("rep; stosl":"+D" (bgptr), "+c"(i):"a"(0):"memory");
-
- return 0;
-}
-
int vesacon_load_background(const char *filename)
{
FILE *fp = NULL;
@@ -433,7 +313,9 @@ int vesacon_load_background(const char *filename)
} else if (!jpeg_sig_cmp(header, 8)) {
rv = read_jpeg_file(fp, header, 8);
} else if (!lss16_sig_cmp(header, 8)) {
- rv = read_lss16_file(fp, header, 8);
+ fclose(fp);
+ fp = NULL;
+ rv = vesacon_load_lss16_image(filename, VESACON_AREA_BACKGROUND);
}
/* This actually displays the stuff */
diff --git a/com32/lib/sys/vesa/dummy.c b/com32/lib/sys/vesa/dummy.c
new file mode 100644
index 00000000..34d3ccdf
--- /dev/null
+++ b/com32/lib/sys/vesa/dummy.c
@@ -0,0 +1,39 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2015 Paulo Alcantara <pcacjr@zytor.com>
+ *
+ * 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 "video.h"
+
+int __vesacon_i915resolution(int x __attribute__((unused)),
+ int y __attribute__((unused)))
+{
+ return 0;
+}
+
+int __vesacon_init_background(void)
+{
+ return 0;
+}
diff --git a/com32/lib/sys/vesa/foreground.c b/com32/lib/sys/vesa/foreground.c
new file mode 100644
index 00000000..712344c7
--- /dev/null
+++ b/com32/lib/sys/vesa/foreground.c
@@ -0,0 +1,232 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2006-2008 H. Peter Anvin - All Rights Reserved
+ * Copyright 2015 Paulo Alcantara <pcacjr@zytor.com>
+ *
+ * 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 <com32.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <minmax.h>
+#include <stdbool.h>
+#include <ilog2.h>
+#include <syslinux/loadfile.h>
+#include "vesa.h"
+#include "video.h"
+
+/*
+ * Visible cursor information
+ */
+static uint8_t cursor_pattern[FONT_MAX_HEIGHT];
+static struct vesa_char *cursor_pointer = NULL;
+static int cursor_x, cursor_y;
+
+static inline void *copy_dword(void *dst, void *src, size_t dword_count)
+{
+ asm volatile ("rep; movsl":"+D" (dst), "+S"(src), "+c"(dword_count));
+ return dst; /* Updated destination pointer */
+}
+
+static inline __attribute__ ((always_inline))
+uint8_t alpha_val(uint8_t fg, uint8_t bg, uint8_t alpha)
+{
+ unsigned int tmp;
+
+ tmp = __vesacon_srgb_to_linear[fg] * alpha;
+ tmp += __vesacon_srgb_to_linear[bg] * (255 - alpha);
+
+ return __vesacon_linear_to_srgb[tmp >> 12];
+}
+
+static uint32_t alpha_pixel(uint32_t fg, uint32_t bg)
+{
+ uint8_t alpha = fg >> 24;
+ uint8_t fg_r = fg >> 16;
+ uint8_t fg_g = fg >> 8;
+ uint8_t fg_b = fg;
+ uint8_t bg_r = bg >> 16;
+ uint8_t bg_g = bg >> 8;
+ uint8_t bg_b = bg;
+
+ return
+ (alpha_val(fg_r, bg_r, alpha) << 16) |
+ (alpha_val(fg_g, bg_g, alpha) << 8) | (alpha_val(fg_b, bg_b, alpha));
+}
+
+static void update_characters(int row, int col, int nrows, int ncols)
+{
+ const int height = __vesacon_font_height;
+ const int width = FONT_WIDTH;
+ uint32_t *fgrowptr, *fgptr, bgval, fgval;
+ uint32_t fgcolor = 0, bgcolor = 0, color;
+ uint8_t chbits = 0, chxbits = 0, chsbits = 0;
+ int i, j, jx, pixrow, pixsrow;
+ struct vesa_char *rowptr, *rowsptr, *cptr, *csptr;
+ unsigned int bytes_per_pixel = __vesacon_bytes_per_pixel;
+ unsigned long pixel_offset;
+ uint32_t row_buffer[__vesa_info.mi.h_res], *rowbufptr;
+ size_t fbrowptr;
+ uint8_t sha;
+
+ pixel_offset = ((row * height + VIDEO_BORDER) * __vesa_info.mi.h_res) +
+ (col * width + VIDEO_BORDER);
+
+ fgrowptr = &__vesacon_foreground[pixel_offset];
+ fbrowptr = (row * height + VIDEO_BORDER) * __vesa_info.mi.logical_scan +
+ (col * width + VIDEO_BORDER) * bytes_per_pixel;
+
+ /* Note that we keep a 1-character guard area around the real text area... */
+ rowptr = &__vesacon_text_display[(row+1)*(__vesacon_text_cols+2)+(col+1)];
+ rowsptr = rowptr - ((__vesacon_text_cols+2)+1);
+ pixrow = 0;
+ pixsrow = height - 1;
+
+ for (i = height * nrows; i >= 0; i--) {
+ fgptr = fgrowptr;
+ rowbufptr = row_buffer;
+
+ cptr = rowptr;
+ csptr = rowsptr;
+
+ chsbits = __vesacon_graphics_font[csptr->ch][pixsrow];
+ if (__unlikely(csptr == cursor_pointer))
+ chsbits |= cursor_pattern[pixsrow];
+ sha = console_color_table[csptr->attr].shadow;
+ chsbits &= (sha & 0x02) ? 0xff : 0x00;
+ chsbits ^= (sha & 0x01) ? 0xff : 0x00;
+ chsbits <<= (width - 2);
+ csptr++;
+
+ /* Draw two pixels beyond the end of the line. One for the shadow,
+ and one to make sure we have a whole dword of data for the copy
+ operation at the end. Note that this code depends on the fact that
+ all characters begin on dword boundaries in the frame buffer. */
+
+ for (jx = 1, j = width * ncols + 1; j >= 0; j--) {
+ chbits <<= 1;
+ chsbits <<= 1;
+ chxbits <<= 1;
+
+ switch (jx) {
+ case 1:
+ chbits = __vesacon_graphics_font[cptr->ch][pixrow];
+ if (__unlikely(cptr == cursor_pointer))
+ chbits |= cursor_pattern[pixrow];
+ sha = console_color_table[cptr->attr].shadow;
+ chxbits = chbits;
+ chxbits &= (sha & 0x02) ? 0xff : 0x00;
+ chxbits ^= (sha & 0x01) ? 0xff : 0x00;
+ fgcolor = console_color_table[cptr->attr].argb_fg;
+ bgcolor = console_color_table[cptr->attr].argb_bg;
+ cptr++;
+ jx--;
+ break;
+ case 0:
+ chsbits = __vesacon_graphics_font[csptr->ch][pixsrow];
+ if (__unlikely(csptr == cursor_pointer))
+ chsbits |= cursor_pattern[pixsrow];
+ sha = console_color_table[csptr->attr].shadow;
+ chsbits &= (sha & 0x02) ? 0xff : 0x00;
+ chsbits ^= (sha & 0x01) ? 0xff : 0x00;
+ csptr++;
+ jx = width - 1;
+ break;
+ default:
+ jx--;
+ break;
+ }
+
+ /* If this pixel is raised, use the offsetted value */
+ bgval = (chxbits & 0x80)
+ ? fgptr[__vesa_info.mi.h_res + 1] : *fgptr;
+ fgptr++;
+
+ /* If this pixel is set, use the fg color, else the bg color */
+ fgval = (chbits & 0x80) ? fgcolor : bgcolor;
+
+ /* Produce the combined color pixel value */
+ color = alpha_pixel(fgval, bgval);
+
+ /* Apply the shadow (75% shadow) */
+ if ((chsbits & ~chxbits) & 0x80) {
+ color >>= 2;
+ color &= 0x3f3f3f;
+ }
+
+ *rowbufptr++ = color;
+ }
+
+ /* Copy to frame buffer */
+ __vesacon_copy_to_screen(fbrowptr, row_buffer, rowbufptr - row_buffer);
+
+ fgrowptr += __vesa_info.mi.h_res;
+ fbrowptr += __vesa_info.mi.logical_scan;
+
+ if (++pixrow == height) {
+ rowptr += __vesacon_text_cols + 2;
+ pixrow = 0;
+ }
+ if (++pixsrow == height) {
+ rowsptr += __vesacon_text_cols + 2;
+ pixsrow = 0;
+ }
+ }
+}
+
+/* For best performance, "start" should be a multiple of 4, to assure
+ aligned dwords. */
+static void draw_foreground_line(int line, int start, int npixels)
+{
+ uint32_t *bgptr = &__vesacon_foreground[line*__vesa_info.mi.h_res+start];
+ unsigned int bytes_per_pixel = __vesacon_bytes_per_pixel;
+ size_t fbptr = line * __vesa_info.mi.logical_scan + start*bytes_per_pixel;
+
+ __vesacon_copy_to_screen(fbptr, bgptr, npixels);
+}
+
+int vesacon_draw_foreground(void)
+{
+ int i;
+ const int bottom_border = VIDEO_BORDER +
+ (TEXT_PIXEL_ROWS % __vesacon_font_height);
+ const int right_border = VIDEO_BORDER + (TEXT_PIXEL_COLS % FONT_WIDTH);
+
+ for (i = 0; i < VIDEO_BORDER; i++)
+ draw_foreground_line(i, 0, __vesa_info.mi.h_res);
+
+ for (i = VIDEO_BORDER; i < __vesa_info.mi.v_res - bottom_border; i++) {
+ draw_foreground_line(i, 0, VIDEO_BORDER);
+ draw_foreground_line(i, __vesa_info.mi.h_res - right_border,
+ right_border);
+ }
+
+ for (i = __vesa_info.mi.v_res - bottom_border;
+ i < __vesa_info.mi.v_res; i++)
+ draw_foreground_line(i, 0, __vesa_info.mi.h_res);
+
+ update_characters(0, 0, __vesacon_text_rows, __vesacon_text_cols);
+}
diff --git a/com32/lib/sys/vesa/initvesa.c b/com32/lib/sys/vesa/initvesa.c
index c2721b8d..f13557e3 100644
--- a/com32/lib/sys/vesa/initvesa.c
+++ b/com32/lib/sys/vesa/initvesa.c
@@ -32,6 +32,7 @@
* support, if one exists.
*/
+#include <dprintf.h>
#include <inttypes.h>
#include <com32.h>
#include <stdlib.h>
@@ -54,7 +55,7 @@ enum vesa_pixel_format __vesacon_pixel_format = PXF_NONE;
unsigned int __vesacon_bytes_per_pixel;
uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT];
-uint32_t *__vesacon_background, *__vesacon_shadowfb;
+uint32_t *__vesacon_background, *__vesacon_foreground, *__vesacon_shadowfb;
static void unpack_font(uint8_t * dst, uint8_t * src, int height)
{
@@ -83,6 +84,10 @@ static int vesacon_set_mode(int *x, int *y)
free(__vesacon_background);
__vesacon_background = NULL;
}
+ if (__vesacon_foreground) {
+ free(__vesacon_foreground);
+ __vesacon_foreground = NULL;
+ }
if (__vesacon_shadowfb) {
free(__vesacon_shadowfb);
__vesacon_shadowfb = NULL;
@@ -92,8 +97,12 @@ static int vesacon_set_mode(int *x, int *y)
if (rv)
return rv;
+ dprintf("%s: %d,%d bestpxf %d\n", __func__, *x, *y, bestpxf);
+
mi = &__vesa_info.mi;
+ dprintf("%s: h_res %d v_res %d\n", __func__, mi->h_res, mi->v_res);
__vesacon_bytes_per_pixel = (mi->bpp + 7) >> 3;
+ dprintf("%s: bytes per pixel %d\n", __func__, __vesacon_bytes_per_pixel);
__vesacon_format_pixels = __vesacon_format_pixels_list[bestpxf];
/* Download the SYSLINUX- or firmware-provided font */
@@ -105,6 +114,7 @@ static int vesacon_set_mode(int *x, int *y)
__vesacon_font_height);
__vesacon_background = calloc(mi->h_res*mi->v_res, 4);
+ __vesacon_foreground = calloc(mi->h_res*mi->v_res, 4);
__vesacon_shadowfb = calloc(mi->h_res*mi->v_res, 4);
__vesacon_init_copy_to_screen();
diff --git a/com32/lib/sys/vesa/lss16.c b/com32/lib/sys/vesa/lss16.c
new file mode 100644
index 00000000..f428dbef
--- /dev/null
+++ b/com32/lib/sys/vesa/lss16.c
@@ -0,0 +1,190 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2006-2008 H. Peter Anvin - All Rights Reserved
+ * Copyright 2015 Paulo Alcantara <pcacjr@zytor.com>
+ *
+ * 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 <dprintf.h>
+#include <com32.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <minmax.h>
+#include <stdbool.h>
+#include <ilog2.h>
+#include <syslinux/loadfile.h>
+#include "vesa.h"
+#include "video.h"
+
+struct lss16_header {
+ uint32_t magic;
+ uint16_t xsize;
+ uint16_t ysize;
+};
+
+#define LSS16_MAGIC 0x1413f33d
+
+int lss16_sig_cmp(const void *header, int len)
+{
+ const struct lss16_header *h = header;
+
+ if (len != 8)
+ return 1;
+
+ return !(h->magic == LSS16_MAGIC &&
+ h->xsize <= __vesa_info.mi.h_res &&
+ h->ysize <= __vesa_info.mi.v_res);
+}
+
+static int read_lss16_file(FILE *fp, const struct lss16_header *const h,
+ uint32_t *screen)
+{
+ uint32_t colors[16], color;
+ bool has_nybble;
+ uint8_t byte;
+ int count;
+ int nybble, prev;
+ enum state {
+ st_start,
+ st_c0,
+ st_c1,
+ st_c2,
+ } state;
+ int i, x, y;
+ uint32_t *sptr = screen;
+
+ for (i = 0; i < 16; i++) {
+ uint8_t rgb[3];
+ if (fread(rgb, 1, 3, fp) != 3)
+ return -1;
+
+ colors[i] = (((rgb[0] & 63) * 255 / 63) << 16) +
+ (((rgb[1] & 63) * 255 / 63) << 8) +
+ ((rgb[2] & 63) * 255 / 63);
+ }
+
+ /* By spec, the state machine is per row */
+ for (y = 0; y < h->ysize; y++) {
+ state = st_start;
+ has_nybble = false;
+ color = colors[prev = 0]; /* By specification */
+ count = 0;
+
+ x = 0;
+ while (x < h->xsize) {
+ if (!has_nybble) {
+ if (fread(&byte, 1, 1, fp) != 1)
+ return -1;
+ nybble = byte & 0xf;
+ has_nybble = true;
+ } else {
+ nybble = byte >> 4;
+ has_nybble = false;
+ }
+
+ switch (state) {
+ case st_start:
+ if (nybble != prev) {
+ *sptr++ = color = colors[prev = nybble];
+ x++;
+ } else {
+ state = st_c0;
+ }
+ break;
+
+ case st_c0:
+ if (nybble == 0) {
+ state = st_c1;
+ } else {
+ count = nybble;
+ goto do_run;
+ }
+ break;
+
+ case st_c1:
+ count = nybble + 16;
+ state = st_c2;
+ break;
+
+ case st_c2:
+ count += nybble << 4;
+ goto do_run;
+
+do_run:
+ count = min(count, h->xsize - x);
+ x += count;
+ asm volatile ("rep; stosl":"+D" (sptr),
+ "+c"(count):"a"(color));
+ state = st_start;
+ break;
+ }
+ }
+
+ /* Zero-fill rest of row */
+ i = __vesa_info.mi.h_res - x;
+ asm volatile ("rep; stosl":"+D" (sptr), "+c"(i):"a"(0):"memory");
+ }
+
+ /* Zero-fill rest of screen */
+ i = (__vesa_info.mi.v_res - y) * __vesa_info.mi.h_res;
+ asm volatile ("rep; stosl":"+D" (sptr), "+c"(i):"a"(0):"memory");
+
+ return 0;
+}
+
+int vesacon_load_lss16_image(const char *filename,
+ enum vesacon_screen_area sc_area)
+{
+ FILE *fp;
+ int ret = 1;
+ struct lss16_header h;
+ uint32_t *sptr;
+
+ if (__vesacon_pixel_format == PXF_NONE) {
+ dprintf("%s: not in graphics mode\n", __func__);
+ return 0;
+ }
+
+ fp = fopen(filename, "r");
+ if (!fp)
+ goto err;
+
+ if (fread(&h, 1, sizeof(h), fp) != sizeof(h))
+ goto err;
+
+ if (sc_area == VESACON_AREA_BACKGROUND)
+ sptr = __vesacon_background;
+ else if (sc_area == VESACON_AREA_FOREGROUND)
+ sptr = __vesacon_foreground;
+
+ ret = read_lss16_file(fp, &h, sptr);
+
+err:
+ if (fp)
+ fclose(fp);
+
+ return ret;
+}
diff --git a/com32/lib/sys/vesa/screencpy.c b/com32/lib/sys/vesa/screencpy.c
index d78109bc..6aec4b1a 100644
--- a/com32/lib/sys/vesa/screencpy.c
+++ b/com32/lib/sys/vesa/screencpy.c
@@ -33,7 +33,7 @@
#include <ilog2.h>
#include "vesa.h"
#include "video.h"
-
+#include <dprintf.h>
static struct win_info wi;
@@ -45,6 +45,8 @@ void __vesacon_init_copy_to_screen(void)
if (mi->mode_attr & 0x0080) {
/* Linear frame buffer */
+ dprintf("%s: linear frame buffer setup\n", __func__);
+
wi.win_base = (char *)mi->lfb_ptr;
wi.win_size = 1 << 31; /* 2 GB, i.e. one huge window */
wi.win_pos = 0; /* Already positioned (only one position...) */
diff --git a/com32/lib/sys/vesa/video.h b/com32/lib/sys/vesa/video.h
index f57e34f9..6907a652 100644
--- a/com32/lib/sys/vesa/video.h
+++ b/com32/lib/sys/vesa/video.h
@@ -82,11 +82,17 @@ extern int __vesacon_text_rows;
extern int __vesacon_text_cols;
extern uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT];
extern uint32_t *__vesacon_background;
+extern uint32_t *__vesacon_foreground;
extern uint32_t *__vesacon_shadowfb;
extern const uint16_t __vesacon_srgb_to_linear[256];
extern const uint8_t __vesacon_linear_to_srgb[4080];
+enum vesacon_screen_area {
+ VESACON_AREA_BACKGROUND,
+ VESACON_AREA_FOREGROUND,
+};
+
int __vesacon_init_background(void);
int vesacon_load_background(const char *);
int __vesacon_init(int *, int *);
@@ -102,4 +108,10 @@ void __vesacon_init_copy_to_screen(void);
int __vesacon_i915resolution(int x, int y);
+int vesacon_draw_foreground(void);
+
+int lss16_sig_cmp(const void *header, int len);
+int vesacon_load_lss16_image(const char *filename,
+ enum vesacon_screen_area sc_area);
+
#endif /* LIB_SYS_VESA_VIDEO_H */
diff --git a/core/graphics.c b/core/graphics.c
index 1d756380..400310a4 100644
--- a/core/graphics.c
+++ b/core/graphics.c
@@ -26,6 +26,10 @@
#include "graphics.h"
#include <syslinux/video.h>
+#include <console.h>
+#include "../com32/lib/sys/vesa/vesa.h"
+#include "../com32/lib/sys/vesa/video.h"
+
__export uint8_t UsingVGA = 0;
uint16_t VGAPos; /* Pointer into VGA memory */
__export char *VGAFilePtr; /* Pointer into VGAFileBuf */
@@ -233,6 +237,7 @@ static void outputvga(const void *in, void *out)
/*
* Display a graphical splash screen.
*/
+#if 0
__export void vgadisplayfile(FILE *_fd)
{
char *p;
@@ -304,6 +309,14 @@ __export void vgadisplayfile(FILE *_fd)
}
}
}
+#else
+__export void vgadisplayfile(const char *filename)
+{
+ openconsole(&dev_rawcon_r, &dev_vesaserial_w);
+ vesacon_load_lss16_image(filename, VESACON_AREA_FOREGROUND);
+ vesacon_draw_foreground();
+}
+#endif
/*
* Disable VGA graphics.
diff --git a/core/include/graphics.h b/core/include/graphics.h
index 10433df3..f7c3f1d6 100644
--- a/core/include/graphics.h
+++ b/core/include/graphics.h
@@ -50,7 +50,7 @@ extern uint8_t UserFont;
extern char fontbuf[8192];
-extern void vgadisplayfile(FILE *_fd);
+extern void vgadisplayfile(const char *filename);
extern void using_vga(uint8_t vga, uint16_t pix_cols, uint16_t pix_rows);
static inline void graphics_using_vga(uint8_t vga, uint16_t pix_cols,
diff --git a/mk/lib.mk b/mk/lib.mk
index 7a48756c..713edc0c 100644
--- a/mk/lib.mk
+++ b/mk/lib.mk
@@ -150,6 +150,15 @@ LIBCONSOLE_OBJS = \
\
syslinux/serial.o
+LIBGRAPHICS_OBJS = \
+ calloc.o \
+ sys/x86_init_fpu.o \
+ syslinux/video/fontquery.o syslinux/video/reportmode.o \
+ sys/vesacon_write.o sys/vesaserial_write.o sys/vesa/dummy.o \
+ sys/vesa/initvesa.o sys/vesa/drawtxt.o \
+ sys/vesa/alphatbl.o sys/vesa/screencpy.o sys/vesa/fmtpixel.o \
+ sys/vesa/lss16.o sys/vesa/foreground.o
+
LIBLOAD_OBJS = \
syslinux/addlist.o syslinux/freelist.o syslinux/memmap.o \
syslinux/movebits.o syslinux/shuffle.o syslinux/shuffle_pm.o \
@@ -203,7 +212,9 @@ CORELIBOBJS = \
libgcc/__divdi3.o libgcc/__moddi3.o \
syslinux/debug.o \
$(LIBENTRY_OBJS) \
- $(LIBMODULE_OBJS)
+ $(LIBMODULE_OBJS) \
+ $(LIBGRAPHICS_OBJS) \
+ $(LIBCONSOLE_OBJS)
LDFLAGS = -m elf_$(ARCH) --hash-style=gnu -T $(com32)/lib/$(ARCH)/elf.ld