splash_bmp.c revision 47945
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 *
2747945Syokota * $Id: splash_bmp.c,v 1.7 1999/03/29 15:13:53 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
4045119Syokota#define FADE_TIMEOUT	15	/* sec */
4145119Syokota#define FADE_LEVELS	10
4242506Syokota
4342506Syokotastatic int splash_mode = -1;
4442506Syokotastatic int splash_on = FALSE;
4542506Syokota
4642506Syokotastatic int bmp_start(video_adapter_t *adp);
4742506Syokotastatic int bmp_end(video_adapter_t *adp);
4842506Syokotastatic int bmp_splash(video_adapter_t *adp, int on);
4942506Syokotastatic int bmp_Init(const char *data, int swidth, int sheight, int sdepth);
5042506Syokotastatic int bmp_Draw(video_adapter_t *adp);
5142506Syokota
5242506Syokotastatic splash_decoder_t bmp_decoder = {
5342506Syokota    "splash_bmp", bmp_start, bmp_end, bmp_splash, SPLASH_IMAGE,
5442506Syokota};
5542506Syokota
5642506SyokotaSPLASH_DECODER(splash_bmp, bmp_decoder);
5742506Syokota
5842506Syokotastatic int
5942506Syokotabmp_start(video_adapter_t *adp)
6042506Syokota{
6142998Syokota    /* currently only 256-color modes are supported XXX */
6242506Syokota    static int		modes[] = {
6342998Syokota			M_VESA_CG640x480,
6442998Syokota			M_VESA_CG800x600,
6542998Syokota			M_VESA_CG1024x768,
6642998Syokota    			/*
6742998Syokota			 * As 320x200 doesn't generally look great,
6842998Syokota			 * it's least preferred here.
6942998Syokota			 */
7042506Syokota			M_VGA_CG320,
7142506Syokota			-1,
7242506Syokota    };
7342506Syokota    video_info_t 	info;
7442506Syokota    int			i;
7542506Syokota
7647945Syokota    if ((bmp_decoder.data == NULL) || (bmp_decoder.data_size <= 0)) {
7747945Syokota	printf("splash_bmp: No bitmap file found\n");
7842506Syokota	return ENODEV;
7947945Syokota    }
8042506Syokota    for (i = 0; modes[i] >= 0; ++i) {
8142506Syokota	if (((*vidsw[adp->va_index]->get_info)(adp, modes[i], &info) == 0)
8242506Syokota	    && (bmp_Init((u_char *)bmp_decoder.data,
8342506Syokota			 info.vi_width, info.vi_height, info.vi_depth) == 0))
8442506Syokota	    break;
8542506Syokota    }
8642506Syokota    splash_mode = modes[i];
8747945Syokota    if (splash_mode < 0)
8847945Syokota	printf("splash_bmp: No appropriate video mode found\n");
8942506Syokota    if (bootverbose)
9042506Syokota	printf("bmp_start(): splash_mode:%d\n", splash_mode);
9142506Syokota    return ((splash_mode < 0) ? ENODEV : 0);
9242506Syokota}
9342506Syokota
9442506Syokotastatic int
9542506Syokotabmp_end(video_adapter_t *adp)
9642506Syokota{
9742506Syokota    /* nothing to do */
9842506Syokota    return 0;
9942506Syokota}
10042506Syokota
10142506Syokotastatic int
10242506Syokotabmp_splash(video_adapter_t *adp, int on)
10342506Syokota{
10442506Syokota    static u_char	pal[256*3];
10542506Syokota    static long		time_stamp;
10645119Syokota    u_char		tpal[256*3];
10745119Syokota    static int		fading = TRUE, brightness = FADE_LEVELS;
10842506Syokota    struct timeval	tv;
10942506Syokota    int			i;
11042506Syokota
11142506Syokota    if (on) {
11242506Syokota	if (!splash_on) {
11342506Syokota	    /* set up the video mode and draw something */
11442506Syokota	    if ((*vidsw[adp->va_index]->set_mode)(adp, splash_mode))
11542506Syokota		return 1;
11642506Syokota	    if (bmp_Draw(adp))
11742506Syokota		return 1;
11842506Syokota	    (*vidsw[adp->va_index]->save_palette)(adp, pal);
11942506Syokota	    time_stamp = 0;
12042506Syokota	    splash_on = TRUE;
12142506Syokota	}
12242506Syokota	/*
12342506Syokota	 * This is a kludge to fade the image away.  This section of the
12442506Syokota	 * code takes effect only after the system is completely up.
12542998Syokota	 * FADE_TIMEOUT should be configurable.
12642506Syokota	 */
12742506Syokota	if (!cold) {
12842506Syokota	    getmicrotime(&tv);
12942506Syokota	    if (time_stamp == 0)
13042506Syokota		time_stamp = tv.tv_sec;
13142506Syokota	    if (tv.tv_sec > time_stamp + FADE_TIMEOUT) {
13245119Syokota		if (fading)
13345119Syokota		    if (brightness == 0) {
13445119Syokota			fading = FALSE;
13545119Syokota			brightness++;
13645119Syokota		    }
13745119Syokota		    else brightness--;
13845119Syokota		else
13945119Syokota		    if (brightness == FADE_LEVELS) {
14045119Syokota			fading = TRUE;
14145119Syokota			brightness--;
14245119Syokota		    }
14345119Syokota		    else brightness++;
14442506Syokota		for (i = 0; i < sizeof(pal); ++i) {
14545119Syokota		    tpal[i] = pal[i] * brightness / FADE_LEVELS;
14642506Syokota		}
14745119Syokota		(*vidsw[adp->va_index]->load_palette)(adp, tpal);
14845119Syokota		time_stamp = tv.tv_sec;
14942506Syokota	    }
15042506Syokota	}
15142506Syokota	return 0;
15242506Syokota    } else {
15342506Syokota	/* the video mode will be restored by the caller */
15442506Syokota	splash_on = FALSE;
15542506Syokota	return 0;
15642506Syokota    }
15742506Syokota}
15842506Syokota
15942506Syokota/*
16042506Syokota** Code to handle Microsoft DIB (".BMP") format images.
16142506Syokota**
16242506Syokota** Blame me (msmith@freebsd.org) if this is broken, not Soren.
16342506Syokota*/
16442506Syokota
16542506Syokotatypedef struct tagBITMAPFILEHEADER {    /* bmfh */
16642506Syokota    u_short	bfType		__attribute__ ((packed));
16742506Syokota    int		bfSize		__attribute__ ((packed));
16842506Syokota    u_short	bfReserved1	__attribute__ ((packed));
16942506Syokota    u_short	bfReserved2	__attribute__ ((packed));
17042506Syokota    int		bfOffBits	__attribute__ ((packed));
17142506Syokota} BITMAPFILEHEADER;
17242506Syokota
17342506Syokotatypedef struct tagBITMAPINFOHEADER {    /* bmih */
17442506Syokota    int		biSize		__attribute__ ((packed));
17542506Syokota    int		biWidth		__attribute__ ((packed));
17642506Syokota    int		biHeight	__attribute__ ((packed));
17742506Syokota    short	biPlanes	__attribute__ ((packed));
17842506Syokota    short	biBitCount	__attribute__ ((packed));
17942506Syokota    int		biCompression	__attribute__ ((packed));
18042506Syokota    int		biSizeImage	__attribute__ ((packed));
18142506Syokota    int		biXPelsPerMeter	__attribute__ ((packed));
18242506Syokota    int		biYPelsPerMeter	__attribute__ ((packed));
18342506Syokota    int		biClrUsed	__attribute__ ((packed));
18442506Syokota    int		biClrImportant	__attribute__ ((packed));
18542506Syokota} BITMAPINFOHEADER;
18642506Syokota
18742506Syokotatypedef struct tagRGBQUAD {     /* rgbq */
18842506Syokota    u_char	rgbBlue		__attribute__ ((packed));
18942506Syokota    u_char	rgbGreen	__attribute__ ((packed));
19042506Syokota    u_char	rgbRed		__attribute__ ((packed));
19142506Syokota    u_char	rgbReserved	__attribute__ ((packed));
19242506Syokota} RGBQUAD;
19342506Syokota
19442506Syokotatypedef struct tagBITMAPINFO {  /* bmi */
19542506Syokota    BITMAPINFOHEADER	bmiHeader	__attribute__ ((packed));
19642506Syokota    RGBQUAD		bmiColors[256]	__attribute__ ((packed));
19742506Syokota} BITMAPINFO;
19842506Syokota
19942506Syokotatypedef struct tagBITMAPF
20042506Syokota{
20142506Syokota    BITMAPFILEHEADER	bmfh	__attribute__ ((packed));
20242506Syokota    BITMAPINFO		bmfi	__attribute__ ((packed));
20342506Syokota} BITMAPF;
20442506Syokota
20542506Syokota#define BI_RGB		0
20642506Syokota#define BI_RLE8		1
20742506Syokota#define BI_RLE4		2
20842506Syokota
20942506Syokota/*
21042506Syokota** all we actually care about the image
21142506Syokota*/
21242506Syokotatypedef struct
21342506Syokota{
21442506Syokota    int		width,height;		/* image dimensions */
21542506Syokota    int		swidth,sheight;		/* screen dimensions for the current mode */
21642506Syokota    u_char	sdepth;			/* screen depth (1, 4, 8 bpp) */
21742506Syokota    int		ncols;			/* number of colours */
21842506Syokota    u_char	palette[256][3];	/* raw palette data */
21942506Syokota    u_char	format;			/* one of the BI_* constants above */
22042506Syokota    u_char	*data;			/* pointer to the raw data */
22142506Syokota    u_char	*index;			/* running pointer to the data while drawing */
22242506Syokota    u_char	*vidmem;		/* video memory allocated for drawing */
22342998Syokota    video_adapter_t *adp;
22442998Syokota    int		bank;
22542506Syokota} BMP_INFO;
22642506Syokota
22742506Syokotastatic BMP_INFO bmp_info;
22842506Syokota
22942998Syokotastatic void
23042998Syokotafill(BMP_INFO *info, int x, int y, int xsize, int ysize)
23142998Syokota{
23242998Syokota    u_char	*window;
23342998Syokota    int		banksize;
23442998Syokota    int		bank;
23542998Syokota    int		p;
23642998Syokota
23742998Syokota    banksize = info->adp->va_window_size;
23843664Syokota    bank = (info->adp->va_line_width*y + x)/banksize;
23942998Syokota    window = (u_char *)info->adp->va_window;
24042998Syokota    (*vidsw[info->adp->va_index]->set_win_org)(info->adp, bank*banksize);
24142998Syokota    while (ysize > 0) {
24243664Syokota	p = (info->adp->va_line_width*y + x)%banksize;
24342998Syokota	for (; (p + xsize <= banksize) && ysize > 0; --ysize, ++y) {
24442998Syokota	    generic_bzero(window + p, xsize);
24543664Syokota	    p += info->adp->va_line_width;
24642998Syokota	}
24742998Syokota	if (ysize <= 0)
24842998Syokota	    break;
24942998Syokota	if (p < banksize) {
25042998Syokota	    /* the last line crosses the window boundary */
25142998Syokota	    generic_bzero(window + p, banksize - p);
25242998Syokota	}
25342998Syokota	++bank;				/* next bank */
25442998Syokota	(*vidsw[info->adp->va_index]->set_win_org)(info->adp, bank*banksize);
25542998Syokota	if (p < banksize) {
25642998Syokota	    /* the remaining part of the last line */
25742998Syokota	    generic_bzero(window, p + xsize - banksize);
25842998Syokota	    ++y;
25942998Syokota	    --ysize;
26042998Syokota	}
26142998Syokota    }
26242998Syokota    info->bank = bank;
26342998Syokota}
26442998Syokota
26542506Syokota/*
26642506Syokota** bmp_SetPix
26742506Syokota**
26842506Syokota** Given (info), set the pixel at (x),(y) to (val)
26942506Syokota**
27042506Syokota*/
27142506Syokotastatic void
27242506Syokotabmp_SetPix(BMP_INFO *info, int x, int y, u_char val)
27342506Syokota{
27442506Syokota    int		sofs, bofs;
27542506Syokota    u_char	tpv, mask;
27642998Syokota    int		newbank;
27742506Syokota
27842506Syokota    /*
27942506Syokota     * range check to avoid explosions
28042506Syokota     */
28142506Syokota    if ((x < 0) || (x >= info->swidth) || (y < 0) || (y >= info->sheight))
28242506Syokota	return;
28342506Syokota
28442506Syokota    /*
28542506Syokota     * calculate offset into video memory;
28642506Syokota     * because 0,0 is bottom-left for DIB, we have to convert.
28742506Syokota     */
28842506Syokota    sofs = ((info->height - (y+1) + (info->sheight - info->height) / 2)
28943664Syokota		* info->adp->va_line_width);
29042506Syokota
29142506Syokota    switch(info->sdepth) {
29242506Syokota    case 1:
29343664Syokota	sofs += ((x + (info->swidth - info->width) / 2) >> 3);
29442506Syokota	bofs = x & 0x7;				/* offset within byte */
29542506Syokota
29642506Syokota	val &= 1;				/* mask pixel value */
29742506Syokota	mask = ~(0x80 >> bofs);			/* calculate bit mask */
29842506Syokota	tpv = *(info->vidmem+sofs) & mask;	/* get screen contents, excluding masked bit */
29942506Syokota	*(info->vidmem+sofs) = tpv | (val << (8-bofs));	/* write new bit */
30042506Syokota	break;
30142506Syokota
30242506Syokota	/* XXX only correct for non-interleaved modes */
30342506Syokota    case 4:
30443664Syokota	sofs += ((x + (info->swidth - info->width) / 2) >> 1);
30542506Syokota	bofs = x & 0x1;				/* offset within byte */
30642506Syokota
30742506Syokota	val &= 0xf;				/* mask pixel value */
30842506Syokota	mask = bofs ? 0x0f : 0xf0;		/* calculate bit mask */
30942506Syokota	tpv = *(info->vidmem+sofs) & mask;	/* get screen contents, excluding masked bits */
31042506Syokota	*(info->vidmem+sofs) = tpv | (val << (bofs ? 0 : 4));	/* write new bits */
31142506Syokota	break;
31242506Syokota
31342506Syokota    case 8:
31443664Syokota	sofs += x + (info->swidth - info->width) / 2;
31542998Syokota	newbank = sofs/info->adp->va_window_size;
31642998Syokota	if (info->bank != newbank) {
31742998Syokota	    (*vidsw[info->adp->va_index]->set_win_org)(info->adp, newbank*info->adp->va_window_size);
31842998Syokota	    info->bank = newbank;
31942998Syokota	}
32042998Syokota	sofs %= info->adp->va_window_size;
32142506Syokota	*(info->vidmem+sofs) = val;
32242506Syokota	break;
32342506Syokota    }
32442506Syokota}
32542506Syokota
32642506Syokota/*
32742506Syokota** bmp_DecodeRLE4
32842506Syokota**
32942506Syokota** Given (data) pointing to a line of RLE4-format data and (line) being the starting
33042506Syokota** line onscreen, decode the line.
33142506Syokota*/
33242506Syokotastatic void
33342506Syokotabmp_DecodeRLE4(BMP_INFO *info, int line)
33442506Syokota{
33542506Syokota    int		count;		/* run count */
33642506Syokota    u_char	val;
33742506Syokota    int		x,y;		/* screen position */
33842506Syokota
33942506Syokota    x = 0;			/* starting position */
34042506Syokota    y = line;
34142506Syokota
34242506Syokota    /* loop reading data */
34342506Syokota    for (;;) {
34442506Syokota	/*
34542506Syokota	 * encoded mode starts with a run length, and then a byte with
34642506Syokota	 * two colour indexes to alternate between for the run
34742506Syokota	 */
34842506Syokota	if (*info->index) {
34942506Syokota	    for (count = 0; count < *info->index; count++, x++) {
35042506Syokota		if (count & 1) {		/* odd count, low nybble */
35142506Syokota		    bmp_SetPix(info, x, y, *(info->index+1) & 0x0f);
35242506Syokota		} else {			/* even count, high nybble */
35342506Syokota		    bmp_SetPix(info, x, y, (*(info->index+1) >>4) & 0x0f);
35442506Syokota		}
35542506Syokota	    }
35642506Syokota	    info->index += 2;
35742506Syokota        /*
35842506Syokota	 * A leading zero is an escape; it may signal the end of the
35942506Syokota	 * bitmap, a cursor move, or some absolute data.
36042506Syokota	 */
36142506Syokota	} else {	/* zero tag may be absolute mode or an escape */
36242506Syokota	    switch (*(info->index+1)) {
36342506Syokota	    case 0:				/* end of line */
36442506Syokota		info->index += 2;
36542506Syokota		return;
36642506Syokota	    case 1:				/* end of bitmap */
36742506Syokota		info->index = NULL;
36842506Syokota		return;
36942506Syokota	    case 2:				/* move */
37042506Syokota		x += *(info->index + 2);	/* new coords */
37142506Syokota		y += *(info->index + 3);
37242506Syokota		info->index += 4;
37342506Syokota		break;
37442506Syokota	    default:				/* literal bitmap data */
37542506Syokota		for (count = 0; count < *(info->index + 1); count++, x++) {
37642506Syokota		    val = *(info->index + 2 + (count / 2));	/* byte with nybbles */
37742506Syokota		    if (count & 1) {
37842506Syokota			val &= 0xf;		/* get low nybble */
37942506Syokota		    } else {
38042506Syokota			val = (val >> 4);	/* get high nybble */
38142506Syokota		    }
38242506Syokota		    bmp_SetPix(info, x, y, val);
38342506Syokota		}
38442506Syokota		/* warning, this depends on integer truncation, do not hand-optimise! */
38542506Syokota		info->index += 2 + ((count + 3) / 4) * 2;
38642506Syokota		break;
38742506Syokota	    }
38842506Syokota	}
38942506Syokota    }
39042506Syokota}
39142506Syokota
39242506Syokota/*
39342506Syokota** bmp_DecodeRLE8
39442506Syokota** Given (data) pointing to a line of RLE4-format data and (line) being the starting
39542506Syokota** line onscreen, decode the line.
39642506Syokota*/
39742506Syokotastatic void
39842506Syokotabmp_DecodeRLE8(BMP_INFO *info, int line)
39942506Syokota{
40042506Syokota    int		count;		/* run count */
40142506Syokota    int		x,y;		/* screen position */
40242506Syokota
40342506Syokota    x = 0;			/* starting position */
40442506Syokota    y = line;
40542506Syokota
40642506Syokota    /* loop reading data */
40742506Syokota    for(;;) {
40842506Syokota	/*
40942506Syokota	 * encoded mode starts with a run length, and then a byte with
41042506Syokota	 * two colour indexes to alternate between for the run
41142506Syokota	 */
41242506Syokota	if (*info->index) {
41342506Syokota	    for (count = 0; count < *info->index; count++, x++)
41442506Syokota		bmp_SetPix(info, x, y, *(info->index+1));
41542506Syokota	    info->index += 2;
41642506Syokota        /*
41742506Syokota	 * A leading zero is an escape; it may signal the end of the
41842506Syokota	 * bitmap, a cursor move, or some absolute data.
41942506Syokota	 */
42042506Syokota	} else {	/* zero tag may be absolute mode or an escape */
42142506Syokota	    switch(*(info->index+1)) {
42242506Syokota	    case 0:				/* end of line */
42342506Syokota		info->index += 2;
42442506Syokota		return;
42542506Syokota	    case 1:				/* end of bitmap */
42642506Syokota		info->index = NULL;
42742506Syokota		return;
42842506Syokota	    case 2:				/* move */
42942506Syokota		x += *(info->index + 2);	/* new coords */
43042506Syokota		y += *(info->index + 3);
43142506Syokota		info->index += 4;
43242506Syokota		break;
43342506Syokota	    default:				/* literal bitmap data */
43442506Syokota		for (count = 0; count < *(info->index + 1); count++, x++)
43542506Syokota		    bmp_SetPix(info, x, y, *(info->index + 2 + count));
43642506Syokota		/* must be an even count */
43742506Syokota		info->index += 2 + count + (count & 1);
43842506Syokota		break;
43942506Syokota	    }
44042506Syokota	}
44142506Syokota    }
44242506Syokota}
44342506Syokota
44442506Syokota/*
44542506Syokota** bmp_DecodeLine
44642506Syokota**
44742506Syokota** Given (info) pointing to an image being decoded, (line) being the line currently
44842506Syokota** being displayed, decode a line of data.
44942506Syokota*/
45042506Syokotastatic void
45142506Syokotabmp_DecodeLine(BMP_INFO *info, int line)
45242506Syokota{
45342506Syokota    int		x;
45442506Syokota
45542506Syokota    switch(info->format) {
45642506Syokota    case BI_RGB:
45742506Syokota	for (x = 0; x < info->width; x++, info->index++)
45842506Syokota	    bmp_SetPix(info, x, line, *info->index);
45942529Syokota	info->index += 3 - (--x % 4);
46042506Syokota	break;
46142506Syokota    case BI_RLE4:
46242506Syokota	bmp_DecodeRLE4(info, line);
46342506Syokota	break;
46442506Syokota    case BI_RLE8:
46542506Syokota	bmp_DecodeRLE8(info, line);
46642506Syokota	break;
46742506Syokota    }
46842506Syokota}
46942506Syokota
47042506Syokota/*
47142506Syokota** bmp_Init
47242506Syokota**
47342506Syokota** Given a pointer (data) to the image of a BMP file, fill in bmp_info with what
47442506Syokota** can be learnt from it.  Return nonzero if the file isn't usable.
47542506Syokota**
47642506Syokota** Take screen dimensions (swidth), (sheight) and (sdepth) and make sure we
47742506Syokota** can work with these.
47842506Syokota*/
47942506Syokotastatic int
48042506Syokotabmp_Init(const char *data, int swidth, int sheight, int sdepth)
48142506Syokota{
48242506Syokota    BITMAPF	*bmf = (BITMAPF *)data;
48342506Syokota    int		pind;
48442506Syokota
48542506Syokota    bmp_info.data = NULL;	/* assume setup failed */
48642506Syokota
48742506Syokota    /* check file ID */
48842506Syokota    if (bmf->bmfh.bfType != 0x4d42) {
48947945Syokota	printf("splash_bmp: not a BMP file\n");
49042506Syokota	return(1);		/* XXX check word ordering for big-endian ports? */
49142506Syokota    }
49242506Syokota
49347945Syokota    /* do we understand this bitmap format? */
49447945Syokota    if (bmf->bmfi.bmiHeader.biSize > sizeof(bmf->bmfi.bmiHeader)) {
49547945Syokota	printf("splash_bmp: unsupported BMP format (size=%d)\n",
49647945Syokota		bmf->bmfi.bmiHeader.biSize);
49747945Syokota	return(1);
49847945Syokota    }
49947945Syokota
50042506Syokota    /* save what we know about the screen */
50142506Syokota    bmp_info.swidth = swidth;
50242506Syokota    bmp_info.sheight = sheight;
50342506Syokota    bmp_info.sdepth = sdepth;
50442506Syokota
50542506Syokota    /* where's the data? */
50642506Syokota    bmp_info.data = (u_char *)data + bmf->bmfh.bfOffBits;
50742506Syokota
50842506Syokota    /* image parameters */
50942506Syokota    bmp_info.width = bmf->bmfi.bmiHeader.biWidth;
51042506Syokota    bmp_info.height = bmf->bmfi.bmiHeader.biHeight;
51142506Syokota    bmp_info.format = bmf->bmfi.bmiHeader.biCompression;
51242506Syokota
51342506Syokota    switch(bmp_info.format) {	/* check compression format */
51442506Syokota    case BI_RGB:
51542506Syokota    case BI_RLE4:
51642506Syokota    case BI_RLE8:
51742506Syokota	break;
51842506Syokota    default:
51947945Syokota	printf("splash_bmp: unsupported compression format\n");
52042506Syokota	return(1);		/* unsupported compression format */
52142506Syokota    }
52242506Syokota
52342506Syokota    /* palette details */
52442506Syokota    bmp_info.ncols = (bmf->bmfi.bmiHeader.biClrUsed);
52542506Syokota    bzero(bmp_info.palette,sizeof(bmp_info.palette));
52642506Syokota    if (bmp_info.ncols == 0) {	/* uses all of them */
52742623Syokota	bmp_info.ncols = 1 << bmf->bmfi.bmiHeader.biBitCount;
52842506Syokota    }
52947945Syokota    if ((bmf->bmfi.bmiHeader.biBitCount != sdepth)
53047945Syokota	|| (bmp_info.ncols > (1 << sdepth))) {
53147945Syokota	printf("splash_bmp: unsupported color depth (%d bits, %d colors)\n",
53247945Syokota		bmf->bmfi.bmiHeader.biBitCount, bmp_info.ncols);
53347945Syokota	return(1);
53447945Syokota    }
53542506Syokota    if ((bmp_info.height > bmp_info.sheight) ||
53642506Syokota	(bmp_info.width > bmp_info.swidth) ||
53742506Syokota	(bmp_info.ncols > (1 << sdepth))) {
53842506Syokota	    return(1);		/* beyond screen capacity */
53942506Syokota    }
54042506Syokota
54142506Syokota    /* read palette */
54242506Syokota    for (pind = 0; pind < bmp_info.ncols; pind++) {
54342506Syokota	bmp_info.palette[pind][0] = bmf->bmfi.bmiColors[pind].rgbRed;
54442506Syokota	bmp_info.palette[pind][1] = bmf->bmfi.bmiColors[pind].rgbGreen;
54542506Syokota	bmp_info.palette[pind][2] = bmf->bmfi.bmiColors[pind].rgbBlue;
54642506Syokota    }
54742506Syokota    return(0);
54842506Syokota}
54942506Syokota
55042506Syokota/*
55142506Syokota** bmp_Draw
55242506Syokota**
55342506Syokota** Render the image.  Return nonzero if that's not possible.
55442506Syokota**
55542506Syokota*/
55642506Syokotastatic int
55742506Syokotabmp_Draw(video_adapter_t *adp)
55842506Syokota{
55942506Syokota    int		line;
56042506Syokota
56142506Syokota    if (bmp_info.data == NULL) {	/* init failed, do nothing */
56242506Syokota	return(1);
56342506Syokota    }
56442506Syokota
56542506Syokota    /* clear the screen */
56642506Syokota    bmp_info.vidmem = (u_char *)adp->va_window;
56742998Syokota    bmp_info.adp = adp;
56842506Syokota    /* XXX; the following line is correct only for 8bpp modes */
56942998Syokota    fill(&bmp_info, 0, 0, bmp_info.swidth, bmp_info.sheight);
57042998Syokota    (*vidsw[adp->va_index]->set_win_org)(adp, 0);
57142998Syokota    bmp_info.bank = 0;
57242506Syokota
57342506Syokota    /* initialise the info structure for drawing */
57442506Syokota    bmp_info.index = bmp_info.data;
57542506Syokota
57642506Syokota    /* set the palette for our image */
57742506Syokota    (*vidsw[adp->va_index]->load_palette)(adp, (u_char *)&bmp_info.palette);
57842506Syokota
57942506Syokota    for (line = 0; (line < bmp_info.height) && bmp_info.index; line++) {
58042506Syokota	bmp_DecodeLine(&bmp_info, line);
58142506Syokota    }
58242506Syokota    return(0);
58342506Syokota}
584