splash_bmp.c revision 42623
142506Syokota/*-
242506Syokota * Copyright (c) 1999 Michael Smith <msmith@freebsd.org>
342506Syokota * Copyright (c) 1999 Kazutaka YOKOTA <yokota@freebsd.org>
442506Syokota * All rights reserved.
542506Syokota *
642506Syokota * Redistribution and use in source and binary forms, with or without
742506Syokota * modification, are permitted provided that the following conditions
842506Syokota * are met:
942506Syokota * 1. Redistributions of source code must retain the above copyright
1042506Syokota *    notice, this list of conditions and the following disclaimer.
1142506Syokota * 2. Redistributions in binary form must reproduce the above copyright
1242506Syokota *    notice, this list of conditions and the following disclaimer in the
1342506Syokota *    documentation and/or other materials provided with the distribution.
1442506Syokota *
1542506Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
1642506Syokota * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1742506Syokota * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1842506Syokota * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
1942506Syokota * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2042506Syokota * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2142506Syokota * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2242506Syokota * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2342506Syokota * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2442506Syokota * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2542506Syokota * SUCH DAMAGE.
2642506Syokota *
2742623Syokota * $Id: splash_bmp.c,v 1.2 1999/01/11 17:32:22 yokota Exp $
2842506Syokota */
2942506Syokota
3042506Syokota#include <sys/param.h>
3142506Syokota#include <sys/systm.h>
3242506Syokota#include <sys/kernel.h>
3342506Syokota#include <sys/linker.h>
3442506Syokota
3542506Syokota#include <machine/console.h>
3642506Syokota
3742506Syokota#include <dev/fb/fbreg.h>
3842506Syokota#include <dev/fb/splashreg.h>
3942506Syokota
4042506Syokota#define FADE_TIMEOUT	300	/* sec */
4142506Syokota
4242506Syokotastatic int splash_mode = -1;
4342506Syokotastatic int splash_on = FALSE;
4442506Syokota
4542506Syokotastatic int bmp_start(video_adapter_t *adp);
4642506Syokotastatic int bmp_end(video_adapter_t *adp);
4742506Syokotastatic int bmp_splash(video_adapter_t *adp, int on);
4842506Syokotastatic int bmp_Init(const char *data, int swidth, int sheight, int sdepth);
4942506Syokotastatic int bmp_Draw(video_adapter_t *adp);
5042506Syokota
5142506Syokotastatic splash_decoder_t bmp_decoder = {
5242506Syokota    "splash_bmp", bmp_start, bmp_end, bmp_splash, SPLASH_IMAGE,
5342506Syokota};
5442506Syokota
5542506SyokotaSPLASH_DECODER(splash_bmp, bmp_decoder);
5642506Syokota
5742506Syokotastatic int
5842506Syokotabmp_start(video_adapter_t *adp)
5942506Syokota{
6042506Syokota    static int		modes[] = {
6142506Syokota			M_VGA_CG320,
6242506Syokota			-1,
6342506Syokota    };
6442506Syokota    video_info_t 	info;
6542506Syokota    int			i;
6642506Syokota
6742506Syokota    if ((bmp_decoder.data == NULL) || (bmp_decoder.data_size <= 0))
6842506Syokota	return ENODEV;
6942506Syokota    for (i = 0; modes[i] >= 0; ++i) {
7042506Syokota	if (((*vidsw[adp->va_index]->get_info)(adp, modes[i], &info) == 0)
7142506Syokota	    && (bmp_Init((u_char *)bmp_decoder.data,
7242506Syokota			 info.vi_width, info.vi_height, info.vi_depth) == 0))
7342506Syokota	    break;
7442506Syokota    }
7542506Syokota    splash_mode = modes[i];
7642506Syokota    if (bootverbose)
7742506Syokota	printf("bmp_start(): splash_mode:%d\n", splash_mode);
7842506Syokota    return ((splash_mode < 0) ? ENODEV : 0);
7942506Syokota}
8042506Syokota
8142506Syokotastatic int
8242506Syokotabmp_end(video_adapter_t *adp)
8342506Syokota{
8442506Syokota    /* nothing to do */
8542506Syokota    return 0;
8642506Syokota}
8742506Syokota
8842506Syokotastatic int
8942506Syokotabmp_splash(video_adapter_t *adp, int on)
9042506Syokota{
9142506Syokota    static u_char	pal[256*3];
9242506Syokota    static long		time_stamp;
9342506Syokota    struct timeval	tv;
9442506Syokota    int			i;
9542506Syokota
9642506Syokota    if (on) {
9742506Syokota	if (!splash_on) {
9842506Syokota	    /* set up the video mode and draw something */
9942506Syokota	    if ((*vidsw[adp->va_index]->set_mode)(adp, splash_mode))
10042506Syokota		return 1;
10142506Syokota	    if (bmp_Draw(adp))
10242506Syokota		return 1;
10342506Syokota	    (*vidsw[adp->va_index]->save_palette)(adp, pal);
10442506Syokota	    time_stamp = 0;
10542506Syokota	    splash_on = TRUE;
10642506Syokota	}
10742506Syokota	/*
10842506Syokota	 * This is a kludge to fade the image away.  This section of the
10942506Syokota	 * code takes effect only after the system is completely up.
11042506Syokota	 */
11142506Syokota	if (!cold) {
11242506Syokota	    getmicrotime(&tv);
11342506Syokota	    if (time_stamp == 0)
11442506Syokota		time_stamp = tv.tv_sec;
11542506Syokota	    if (tv.tv_sec > time_stamp + FADE_TIMEOUT) {
11642506Syokota		for (i = 0; i < sizeof(pal); ++i) {
11742506Syokota		    if (pal[i] > 40)
11842506Syokota			pal[i] -= 4;
11942506Syokota		}
12042506Syokota		(*vidsw[adp->va_index]->load_palette)(adp, pal);
12142506Syokota	    }
12242506Syokota	}
12342506Syokota	return 0;
12442506Syokota    } else {
12542506Syokota	/* the video mode will be restored by the caller */
12642506Syokota	splash_on = FALSE;
12742506Syokota	return 0;
12842506Syokota    }
12942506Syokota}
13042506Syokota
13142506Syokota/*
13242506Syokota** Code to handle Microsoft DIB (".BMP") format images.
13342506Syokota**
13442506Syokota** Blame me (msmith@freebsd.org) if this is broken, not Soren.
13542506Syokota*/
13642506Syokota
13742506Syokotatypedef struct tagBITMAPFILEHEADER {    /* bmfh */
13842506Syokota    u_short	bfType		__attribute__ ((packed));
13942506Syokota    int		bfSize		__attribute__ ((packed));
14042506Syokota    u_short	bfReserved1	__attribute__ ((packed));
14142506Syokota    u_short	bfReserved2	__attribute__ ((packed));
14242506Syokota    int		bfOffBits	__attribute__ ((packed));
14342506Syokota} BITMAPFILEHEADER;
14442506Syokota
14542506Syokotatypedef struct tagBITMAPINFOHEADER {    /* bmih */
14642506Syokota    int		biSize		__attribute__ ((packed));
14742506Syokota    int		biWidth		__attribute__ ((packed));
14842506Syokota    int		biHeight	__attribute__ ((packed));
14942506Syokota    short	biPlanes	__attribute__ ((packed));
15042506Syokota    short	biBitCount	__attribute__ ((packed));
15142506Syokota    int		biCompression	__attribute__ ((packed));
15242506Syokota    int		biSizeImage	__attribute__ ((packed));
15342506Syokota    int		biXPelsPerMeter	__attribute__ ((packed));
15442506Syokota    int		biYPelsPerMeter	__attribute__ ((packed));
15542506Syokota    int		biClrUsed	__attribute__ ((packed));
15642506Syokota    int		biClrImportant	__attribute__ ((packed));
15742506Syokota} BITMAPINFOHEADER;
15842506Syokota
15942506Syokotatypedef struct tagRGBQUAD {     /* rgbq */
16042506Syokota    u_char	rgbBlue		__attribute__ ((packed));
16142506Syokota    u_char	rgbGreen	__attribute__ ((packed));
16242506Syokota    u_char	rgbRed		__attribute__ ((packed));
16342506Syokota    u_char	rgbReserved	__attribute__ ((packed));
16442506Syokota} RGBQUAD;
16542506Syokota
16642506Syokotatypedef struct tagBITMAPINFO {  /* bmi */
16742506Syokota    BITMAPINFOHEADER	bmiHeader	__attribute__ ((packed));
16842506Syokota    RGBQUAD		bmiColors[256]	__attribute__ ((packed));
16942506Syokota} BITMAPINFO;
17042506Syokota
17142506Syokotatypedef struct tagBITMAPF
17242506Syokota{
17342506Syokota    BITMAPFILEHEADER	bmfh	__attribute__ ((packed));
17442506Syokota    BITMAPINFO		bmfi	__attribute__ ((packed));
17542506Syokota} BITMAPF;
17642506Syokota
17742506Syokota#define BI_RGB		0
17842506Syokota#define BI_RLE8		1
17942506Syokota#define BI_RLE4		2
18042506Syokota
18142506Syokota/*
18242506Syokota** all we actually care about the image
18342506Syokota*/
18442506Syokotatypedef struct
18542506Syokota{
18642506Syokota    int		width,height;		/* image dimensions */
18742506Syokota    int		swidth,sheight;		/* screen dimensions for the current mode */
18842506Syokota    u_char	sdepth;			/* screen depth (1, 4, 8 bpp) */
18942506Syokota    int		ncols;			/* number of colours */
19042506Syokota    u_char	palette[256][3];	/* raw palette data */
19142506Syokota    u_char	format;			/* one of the BI_* constants above */
19242506Syokota    u_char	*data;			/* pointer to the raw data */
19342506Syokota    u_char	*index;			/* running pointer to the data while drawing */
19442506Syokota    u_char	*vidmem;		/* video memory allocated for drawing */
19542506Syokota} BMP_INFO;
19642506Syokota
19742506Syokotastatic BMP_INFO bmp_info;
19842506Syokota
19942506Syokota/*
20042506Syokota** bmp_SetPix
20142506Syokota**
20242506Syokota** Given (info), set the pixel at (x),(y) to (val)
20342506Syokota**
20442506Syokota*/
20542506Syokotastatic void
20642506Syokotabmp_SetPix(BMP_INFO *info, int x, int y, u_char val)
20742506Syokota{
20842506Syokota    int		sofs, bofs;
20942506Syokota    u_char	tpv, mask;
21042506Syokota
21142506Syokota    /*
21242506Syokota     * range check to avoid explosions
21342506Syokota     */
21442506Syokota    if ((x < 0) || (x >= info->swidth) || (y < 0) || (y >= info->sheight))
21542506Syokota	return;
21642506Syokota
21742506Syokota    /*
21842506Syokota     * calculate offset into video memory;
21942506Syokota     * because 0,0 is bottom-left for DIB, we have to convert.
22042506Syokota     */
22142506Syokota    sofs = ((info->height - (y+1) + (info->sheight - info->height) / 2)
22242506Syokota		* info->swidth) + x + (info->swidth - info->width) / 2;
22342506Syokota
22442506Syokota    switch(info->sdepth) {
22542506Syokota    case 1:
22642506Syokota	sofs = sofs >> 3;			/* correct for depth */
22742506Syokota	bofs = x & 0x7;				/* offset within byte */
22842506Syokota
22942506Syokota	val &= 1;				/* mask pixel value */
23042506Syokota	mask = ~(0x80 >> bofs);			/* calculate bit mask */
23142506Syokota	tpv = *(info->vidmem+sofs) & mask;	/* get screen contents, excluding masked bit */
23242506Syokota	*(info->vidmem+sofs) = tpv | (val << (8-bofs));	/* write new bit */
23342506Syokota	break;
23442506Syokota
23542506Syokota	/* XXX only correct for non-interleaved modes */
23642506Syokota    case 4:
23742506Syokota	sofs = sofs >> 1;			/* correct for depth */
23842506Syokota	bofs = x & 0x1;				/* offset within byte */
23942506Syokota
24042506Syokota	val &= 0xf;				/* mask pixel value */
24142506Syokota	mask = bofs ? 0x0f : 0xf0;		/* calculate bit mask */
24242506Syokota	tpv = *(info->vidmem+sofs) & mask;	/* get screen contents, excluding masked bits */
24342506Syokota	*(info->vidmem+sofs) = tpv | (val << (bofs ? 0 : 4));	/* write new bits */
24442506Syokota	break;
24542506Syokota
24642506Syokota    case 8:
24742506Syokota	*(info->vidmem+sofs) = val;
24842506Syokota	break;
24942506Syokota    }
25042506Syokota}
25142506Syokota
25242506Syokota/*
25342506Syokota** bmp_DecodeRLE4
25442506Syokota**
25542506Syokota** Given (data) pointing to a line of RLE4-format data and (line) being the starting
25642506Syokota** line onscreen, decode the line.
25742506Syokota*/
25842506Syokotastatic void
25942506Syokotabmp_DecodeRLE4(BMP_INFO *info, int line)
26042506Syokota{
26142506Syokota    int		count;		/* run count */
26242506Syokota    u_char	val;
26342506Syokota    int		x,y;		/* screen position */
26442506Syokota
26542506Syokota    x = 0;			/* starting position */
26642506Syokota    y = line;
26742506Syokota
26842506Syokota    /* loop reading data */
26942506Syokota    for (;;) {
27042506Syokota	/*
27142506Syokota	 * encoded mode starts with a run length, and then a byte with
27242506Syokota	 * two colour indexes to alternate between for the run
27342506Syokota	 */
27442506Syokota	if (*info->index) {
27542506Syokota	    for (count = 0; count < *info->index; count++, x++) {
27642506Syokota		if (count & 1) {		/* odd count, low nybble */
27742506Syokota		    bmp_SetPix(info, x, y, *(info->index+1) & 0x0f);
27842506Syokota		} else {			/* even count, high nybble */
27942506Syokota		    bmp_SetPix(info, x, y, (*(info->index+1) >>4) & 0x0f);
28042506Syokota		}
28142506Syokota	    }
28242506Syokota	    info->index += 2;
28342506Syokota        /*
28442506Syokota	 * A leading zero is an escape; it may signal the end of the
28542506Syokota	 * bitmap, a cursor move, or some absolute data.
28642506Syokota	 */
28742506Syokota	} else {	/* zero tag may be absolute mode or an escape */
28842506Syokota	    switch (*(info->index+1)) {
28942506Syokota	    case 0:				/* end of line */
29042506Syokota		info->index += 2;
29142506Syokota		return;
29242506Syokota	    case 1:				/* end of bitmap */
29342506Syokota		info->index = NULL;
29442506Syokota		return;
29542506Syokota	    case 2:				/* move */
29642506Syokota		x += *(info->index + 2);	/* new coords */
29742506Syokota		y += *(info->index + 3);
29842506Syokota		info->index += 4;
29942506Syokota		break;
30042506Syokota	    default:				/* literal bitmap data */
30142506Syokota		for (count = 0; count < *(info->index + 1); count++, x++) {
30242506Syokota		    val = *(info->index + 2 + (count / 2));	/* byte with nybbles */
30342506Syokota		    if (count & 1) {
30442506Syokota			val &= 0xf;		/* get low nybble */
30542506Syokota		    } else {
30642506Syokota			val = (val >> 4);	/* get high nybble */
30742506Syokota		    }
30842506Syokota		    bmp_SetPix(info, x, y, val);
30942506Syokota		}
31042506Syokota		/* warning, this depends on integer truncation, do not hand-optimise! */
31142506Syokota		info->index += 2 + ((count + 3) / 4) * 2;
31242506Syokota		break;
31342506Syokota	    }
31442506Syokota	}
31542506Syokota    }
31642506Syokota}
31742506Syokota
31842506Syokota/*
31942506Syokota** bmp_DecodeRLE8
32042506Syokota** Given (data) pointing to a line of RLE4-format data and (line) being the starting
32142506Syokota** line onscreen, decode the line.
32242506Syokota*/
32342506Syokotastatic void
32442506Syokotabmp_DecodeRLE8(BMP_INFO *info, int line)
32542506Syokota{
32642506Syokota    int		count;		/* run count */
32742506Syokota    int		x,y;		/* screen position */
32842506Syokota
32942506Syokota    x = 0;			/* starting position */
33042506Syokota    y = line;
33142506Syokota
33242506Syokota    /* loop reading data */
33342506Syokota    for(;;) {
33442506Syokota	/*
33542506Syokota	 * encoded mode starts with a run length, and then a byte with
33642506Syokota	 * two colour indexes to alternate between for the run
33742506Syokota	 */
33842506Syokota	if (*info->index) {
33942506Syokota	    for (count = 0; count < *info->index; count++, x++)
34042506Syokota		bmp_SetPix(info, x, y, *(info->index+1));
34142506Syokota	    info->index += 2;
34242506Syokota        /*
34342506Syokota	 * A leading zero is an escape; it may signal the end of the
34442506Syokota	 * bitmap, a cursor move, or some absolute data.
34542506Syokota	 */
34642506Syokota	} else {	/* zero tag may be absolute mode or an escape */
34742506Syokota	    switch(*(info->index+1)) {
34842506Syokota	    case 0:				/* end of line */
34942506Syokota		info->index += 2;
35042506Syokota		return;
35142506Syokota	    case 1:				/* end of bitmap */
35242506Syokota		info->index = NULL;
35342506Syokota		return;
35442506Syokota	    case 2:				/* move */
35542506Syokota		x += *(info->index + 2);	/* new coords */
35642506Syokota		y += *(info->index + 3);
35742506Syokota		info->index += 4;
35842506Syokota		break;
35942506Syokota	    default:				/* literal bitmap data */
36042506Syokota		for (count = 0; count < *(info->index + 1); count++, x++)
36142506Syokota		    bmp_SetPix(info, x, y, *(info->index + 2 + count));
36242506Syokota		/* must be an even count */
36342506Syokota		info->index += 2 + count + (count & 1);
36442506Syokota		break;
36542506Syokota	    }
36642506Syokota	}
36742506Syokota    }
36842506Syokota}
36942506Syokota
37042506Syokota/*
37142506Syokota** bmp_DecodeLine
37242506Syokota**
37342506Syokota** Given (info) pointing to an image being decoded, (line) being the line currently
37442506Syokota** being displayed, decode a line of data.
37542506Syokota*/
37642506Syokotastatic void
37742506Syokotabmp_DecodeLine(BMP_INFO *info, int line)
37842506Syokota{
37942506Syokota    int		x;
38042506Syokota
38142506Syokota    switch(info->format) {
38242506Syokota    case BI_RGB:
38342506Syokota	for (x = 0; x < info->width; x++, info->index++)
38442506Syokota	    bmp_SetPix(info, x, line, *info->index);
38542529Syokota	info->index += 3 - (--x % 4);
38642506Syokota	break;
38742506Syokota    case BI_RLE4:
38842506Syokota	bmp_DecodeRLE4(info, line);
38942506Syokota	break;
39042506Syokota    case BI_RLE8:
39142506Syokota	bmp_DecodeRLE8(info, line);
39242506Syokota	break;
39342506Syokota    }
39442506Syokota}
39542506Syokota
39642506Syokota/*
39742506Syokota** bmp_Init
39842506Syokota**
39942506Syokota** Given a pointer (data) to the image of a BMP file, fill in bmp_info with what
40042506Syokota** can be learnt from it.  Return nonzero if the file isn't usable.
40142506Syokota**
40242506Syokota** Take screen dimensions (swidth), (sheight) and (sdepth) and make sure we
40342506Syokota** can work with these.
40442506Syokota*/
40542506Syokotastatic int
40642506Syokotabmp_Init(const char *data, int swidth, int sheight, int sdepth)
40742506Syokota{
40842506Syokota    BITMAPF	*bmf = (BITMAPF *)data;
40942506Syokota    int		pind;
41042506Syokota
41142506Syokota    bmp_info.data = NULL;	/* assume setup failed */
41242506Syokota#if 0
41342506Syokota    bmp_info.vidmem = vidmem;	/* remember where */
41442506Syokota#endif
41542506Syokota
41642506Syokota    /* check file ID */
41742506Syokota    if (bmf->bmfh.bfType != 0x4d42) {
41842506Syokota	return(1);		/* XXX check word ordering for big-endian ports? */
41942506Syokota    }
42042506Syokota
42142506Syokota    /* save what we know about the screen */
42242506Syokota    bmp_info.swidth = swidth;
42342506Syokota    bmp_info.sheight = sheight;
42442506Syokota    bmp_info.sdepth = sdepth;
42542506Syokota
42642506Syokota    /* where's the data? */
42742506Syokota    bmp_info.data = (u_char *)data + bmf->bmfh.bfOffBits;
42842506Syokota
42942506Syokota    /* image parameters */
43042506Syokota    bmp_info.width = bmf->bmfi.bmiHeader.biWidth;
43142506Syokota    bmp_info.height = bmf->bmfi.bmiHeader.biHeight;
43242506Syokota    bmp_info.format = bmf->bmfi.bmiHeader.biCompression;
43342506Syokota
43442506Syokota    switch(bmp_info.format) {	/* check compression format */
43542506Syokota    case BI_RGB:
43642506Syokota    case BI_RLE4:
43742506Syokota    case BI_RLE8:
43842506Syokota	break;
43942506Syokota    default:
44042506Syokota	return(1);		/* unsupported compression format */
44142506Syokota    }
44242506Syokota
44342506Syokota    /* palette details */
44442506Syokota    bmp_info.ncols = (bmf->bmfi.bmiHeader.biClrUsed);
44542506Syokota    bzero(bmp_info.palette,sizeof(bmp_info.palette));
44642506Syokota    if (bmp_info.ncols == 0) {	/* uses all of them */
44742623Syokota	bmp_info.ncols = 1 << bmf->bmfi.bmiHeader.biBitCount;
44842506Syokota    }
44942506Syokota    if ((bmp_info.height > bmp_info.sheight) ||
45042506Syokota	(bmp_info.width > bmp_info.swidth) ||
45142506Syokota	(bmp_info.ncols > (1 << sdepth))) {
45242506Syokota	    return(1);		/* beyond screen capacity */
45342506Syokota    }
45442506Syokota
45542506Syokota    /* read palette */
45642506Syokota    for (pind = 0; pind < bmp_info.ncols; pind++) {
45742506Syokota	bmp_info.palette[pind][0] = bmf->bmfi.bmiColors[pind].rgbRed;
45842506Syokota	bmp_info.palette[pind][1] = bmf->bmfi.bmiColors[pind].rgbGreen;
45942506Syokota	bmp_info.palette[pind][2] = bmf->bmfi.bmiColors[pind].rgbBlue;
46042506Syokota    }
46142506Syokota    return(0);
46242506Syokota}
46342506Syokota
46442506Syokota/*
46542506Syokota** bmp_Draw
46642506Syokota**
46742506Syokota** Render the image.  Return nonzero if that's not possible.
46842506Syokota**
46942506Syokota*/
47042506Syokotastatic int
47142506Syokotabmp_Draw(video_adapter_t *adp)
47242506Syokota{
47342506Syokota    int		line;
47442506Syokota
47542506Syokota    if (bmp_info.data == NULL) {	/* init failed, do nothing */
47642506Syokota	return(1);
47742506Syokota    }
47842506Syokota
47942506Syokota    /* clear the screen */
48042506Syokota    bmp_info.vidmem = (u_char *)adp->va_window;
48142506Syokota    /* XXX; the following line is correct only for 8bpp modes */
48242506Syokota    bzero(bmp_info.vidmem, bmp_info.swidth * bmp_info.sheight);
48342506Syokota
48442506Syokota    /* initialise the info structure for drawing */
48542506Syokota    bmp_info.index = bmp_info.data;
48642506Syokota
48742506Syokota    /* set the palette for our image */
48842506Syokota    (*vidsw[adp->va_index]->load_palette)(adp, (u_char *)&bmp_info.palette);
48942506Syokota
49042506Syokota    for (line = 0; (line < bmp_info.height) && bmp_info.index; line++) {
49142506Syokota	bmp_DecodeLine(&bmp_info, line);
49242506Syokota    }
49342506Syokota    return(0);
49442506Syokota}
495