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 *
2750477Speter * $FreeBSD$
2842506Syokota */
2942506Syokota
3042506Syokota#include <sys/param.h>
3142506Syokota#include <sys/systm.h>
3242506Syokota#include <sys/kernel.h>
33129880Sphk#include <sys/module.h>
3442506Syokota#include <sys/linker.h>
3548104Syokota#include <sys/fbio.h>
3642506Syokota
3742506Syokota#include <dev/fb/fbreg.h>
3842506Syokota#include <dev/fb/splashreg.h>
3959690Snyan#ifndef PC98
4059583Syokota#include <dev/fb/vgareg.h>
4142506Syokota
4259583Syokota#include <isa/isareg.h>
4359690Snyan#endif
4459583Syokota
4545119Syokota#define FADE_TIMEOUT	15	/* sec */
4645119Syokota#define FADE_LEVELS	10
4742506Syokota
4842506Syokotastatic int splash_mode = -1;
4942506Syokotastatic int splash_on = FALSE;
5042506Syokota
5142506Syokotastatic int bmp_start(video_adapter_t *adp);
5242506Syokotastatic int bmp_end(video_adapter_t *adp);
5342506Syokotastatic int bmp_splash(video_adapter_t *adp, int on);
54106765Smuxstatic int bmp_Init(char *data, int swidth, int sheight, int sdepth);
5542506Syokotastatic int bmp_Draw(video_adapter_t *adp);
5642506Syokota
5742506Syokotastatic splash_decoder_t bmp_decoder = {
5842506Syokota    "splash_bmp", bmp_start, bmp_end, bmp_splash, SPLASH_IMAGE,
5942506Syokota};
6042506Syokota
6142506SyokotaSPLASH_DECODER(splash_bmp, bmp_decoder);
6242506Syokota
6342506Syokotastatic int
6442506Syokotabmp_start(video_adapter_t *adp)
6542506Syokota{
6642998Syokota    /* currently only 256-color modes are supported XXX */
6742506Syokota    static int		modes[] = {
6859690Snyan#ifdef PC98
6959690Snyan    			/*
7059690Snyan			 * As 640x400 doesn't generally look great,
7159690Snyan			 * it's least preferred here.
7259690Snyan			 */
7359690Snyan			M_PC98_PEGC640x400,
7459690Snyan			M_PC98_PEGC640x480,
7559690Snyan			M_PC98_EGC640x400,
7659690Snyan#else
7742998Syokota			M_VESA_CG640x480,
7842998Syokota			M_VESA_CG800x600,
7942998Syokota			M_VESA_CG1024x768,
8059583Syokota			M_CG640x480,
8142998Syokota    			/*
8242998Syokota			 * As 320x200 doesn't generally look great,
8342998Syokota			 * it's least preferred here.
8442998Syokota			 */
8542506Syokota			M_VGA_CG320,
8659690Snyan#endif
8742506Syokota			-1,
8842506Syokota    };
8942506Syokota    video_info_t 	info;
9042506Syokota    int			i;
9142506Syokota
9247945Syokota    if ((bmp_decoder.data == NULL) || (bmp_decoder.data_size <= 0)) {
9347945Syokota	printf("splash_bmp: No bitmap file found\n");
9442506Syokota	return ENODEV;
9547945Syokota    }
9642506Syokota    for (i = 0; modes[i] >= 0; ++i) {
97174985Swkoszek	if ((vidd_get_info(adp, modes[i], &info) == 0) &&
98174985Swkoszek	    (bmp_Init((u_char *)bmp_decoder.data, info.vi_width,
99174985Swkoszek		      info.vi_height, info.vi_depth) == 0))
10042506Syokota	    break;
10142506Syokota    }
10242506Syokota    splash_mode = modes[i];
10347945Syokota    if (splash_mode < 0)
10447945Syokota	printf("splash_bmp: No appropriate video mode found\n");
10542506Syokota    if (bootverbose)
10642506Syokota	printf("bmp_start(): splash_mode:%d\n", splash_mode);
10742506Syokota    return ((splash_mode < 0) ? ENODEV : 0);
10842506Syokota}
10942506Syokota
11042506Syokotastatic int
11142506Syokotabmp_end(video_adapter_t *adp)
11242506Syokota{
11342506Syokota    /* nothing to do */
11442506Syokota    return 0;
11542506Syokota}
11642506Syokota
11742506Syokotastatic int
11842506Syokotabmp_splash(video_adapter_t *adp, int on)
11942506Syokota{
12042506Syokota    static u_char	pal[256*3];
12142506Syokota    static long		time_stamp;
12245119Syokota    u_char		tpal[256*3];
12345119Syokota    static int		fading = TRUE, brightness = FADE_LEVELS;
12442506Syokota    struct timeval	tv;
12542506Syokota    int			i;
12642506Syokota
12742506Syokota    if (on) {
12842506Syokota	if (!splash_on) {
12942506Syokota	    /* set up the video mode and draw something */
130174985Swkoszek	    if (vidd_set_mode(adp, splash_mode))
13142506Syokota		return 1;
13242506Syokota	    if (bmp_Draw(adp))
13342506Syokota		return 1;
134174985Swkoszek	    vidd_save_palette(adp, pal);
13542506Syokota	    time_stamp = 0;
13642506Syokota	    splash_on = TRUE;
13742506Syokota	}
13842506Syokota	/*
13942506Syokota	 * This is a kludge to fade the image away.  This section of the
14042506Syokota	 * code takes effect only after the system is completely up.
14142998Syokota	 * FADE_TIMEOUT should be configurable.
14242506Syokota	 */
14342506Syokota	if (!cold) {
14442506Syokota	    getmicrotime(&tv);
14542506Syokota	    if (time_stamp == 0)
14642506Syokota		time_stamp = tv.tv_sec;
14742506Syokota	    if (tv.tv_sec > time_stamp + FADE_TIMEOUT) {
14845119Syokota		if (fading)
14945119Syokota		    if (brightness == 0) {
15045119Syokota			fading = FALSE;
15145119Syokota			brightness++;
15245119Syokota		    }
15345119Syokota		    else brightness--;
15445119Syokota		else
15545119Syokota		    if (brightness == FADE_LEVELS) {
15645119Syokota			fading = TRUE;
15745119Syokota			brightness--;
15845119Syokota		    }
15945119Syokota		    else brightness++;
16042506Syokota		for (i = 0; i < sizeof(pal); ++i) {
16145119Syokota		    tpal[i] = pal[i] * brightness / FADE_LEVELS;
16242506Syokota		}
163174985Swkoszek		vidd_load_palette(adp, tpal);
16445119Syokota		time_stamp = tv.tv_sec;
16542506Syokota	    }
16642506Syokota	}
16742506Syokota	return 0;
16842506Syokota    } else {
16942506Syokota	/* the video mode will be restored by the caller */
17042506Syokota	splash_on = FALSE;
17142506Syokota	return 0;
17242506Syokota    }
17342506Syokota}
17442506Syokota
17542506Syokota/*
17642506Syokota** Code to handle Microsoft DIB (".BMP") format images.
17742506Syokota**
17842506Syokota** Blame me (msmith@freebsd.org) if this is broken, not Soren.
17942506Syokota*/
18042506Syokota
18142506Syokotatypedef struct tagBITMAPFILEHEADER {    /* bmfh */
182171382Smjacob    u_short	bfType;
183171382Smjacob    int		bfSize;
184171382Smjacob    u_short	bfReserved1;
185171382Smjacob    u_short	bfReserved2;
186171382Smjacob    int		bfOffBits;
187171382Smjacob} __packed BITMAPFILEHEADER;
18842506Syokota
18942506Syokotatypedef struct tagBITMAPINFOHEADER {    /* bmih */
190171382Smjacob    int		biSize;
191171382Smjacob    int		biWidth;
192171382Smjacob    int		biHeight;
193171382Smjacob    short	biPlanes;
194171382Smjacob    short	biBitCount;
195171382Smjacob    int		biCompression;
196171382Smjacob    int		biSizeImage;
197171382Smjacob    int		biXPelsPerMeter;
198171382Smjacob    int		biYPelsPerMeter;
199171382Smjacob    int		biClrUsed;
200171382Smjacob    int		biClrImportant;
201171382Smjacob} __packed BITMAPINFOHEADER;
20242506Syokota
20342506Syokotatypedef struct tagRGBQUAD {     /* rgbq */
204171382Smjacob    u_char	rgbBlue;
205171382Smjacob    u_char	rgbGreen;
206171382Smjacob    u_char	rgbRed;
207171382Smjacob    u_char	rgbReserved;
208171382Smjacob} __packed RGBQUAD;
20942506Syokota
21042506Syokotatypedef struct tagBITMAPINFO {  /* bmi */
211171382Smjacob    BITMAPINFOHEADER	bmiHeader;
212171382Smjacob    RGBQUAD		bmiColors[256];
213171382Smjacob} __packed BITMAPINFO;
21442506Syokota
21542506Syokotatypedef struct tagBITMAPF
21642506Syokota{
217171382Smjacob    BITMAPFILEHEADER	bmfh;
218171382Smjacob    BITMAPINFO		bmfi;
219171382Smjacob} __packed BITMAPF;
22042506Syokota
22142506Syokota#define BI_RGB		0
22242506Syokota#define BI_RLE8		1
22342506Syokota#define BI_RLE4		2
22442506Syokota
22542506Syokota/*
22642506Syokota** all we actually care about the image
22742506Syokota*/
22842506Syokotatypedef struct
22942506Syokota{
23042506Syokota    int		width,height;		/* image dimensions */
23142506Syokota    int		swidth,sheight;		/* screen dimensions for the current mode */
23259583Syokota    u_char	depth;			/* image depth (1, 4, 8, 24 bits) */
23342506Syokota    u_char	sdepth;			/* screen depth (1, 4, 8 bpp) */
23442506Syokota    int		ncols;			/* number of colours */
23542506Syokota    u_char	palette[256][3];	/* raw palette data */
23642506Syokota    u_char	format;			/* one of the BI_* constants above */
23742506Syokota    u_char	*data;			/* pointer to the raw data */
23842506Syokota    u_char	*index;			/* running pointer to the data while drawing */
23942506Syokota    u_char	*vidmem;		/* video memory allocated for drawing */
24042998Syokota    video_adapter_t *adp;
24142998Syokota    int		bank;
24259690Snyan#ifdef PC98
24359690Snyan    u_char	prev_val;
24459690Snyan#endif
24542506Syokota} BMP_INFO;
24642506Syokota
24742506Syokotastatic BMP_INFO bmp_info;
24842506Syokota
24942506Syokota/*
25042506Syokota** bmp_SetPix
25142506Syokota**
25242506Syokota** Given (info), set the pixel at (x),(y) to (val)
25342506Syokota**
25442506Syokota*/
25542506Syokotastatic void
25642506Syokotabmp_SetPix(BMP_INFO *info, int x, int y, u_char val)
25742506Syokota{
25842506Syokota    int		sofs, bofs;
25942998Syokota    int		newbank;
26042506Syokota
26142506Syokota    /*
26242506Syokota     * range check to avoid explosions
26342506Syokota     */
26442506Syokota    if ((x < 0) || (x >= info->swidth) || (y < 0) || (y >= info->sheight))
26542506Syokota	return;
26642506Syokota
26742506Syokota    /*
26842506Syokota     * calculate offset into video memory;
26942506Syokota     * because 0,0 is bottom-left for DIB, we have to convert.
27042506Syokota     */
27142506Syokota    sofs = ((info->height - (y+1) + (info->sheight - info->height) / 2)
27243664Syokota		* info->adp->va_line_width);
27359583Syokota    x += (info->swidth - info->width) / 2;
27442506Syokota
27542506Syokota    switch(info->sdepth) {
27659690Snyan#ifdef PC98
27759583Syokota    case 4:
27859690Snyan	sofs += (x >> 3);
27959690Snyan	bofs = x & 0x7;				/* offset within byte */
28059690Snyan
28159690Snyan	outb(0x7c, 0x80 | 0x40);	/* GRCG on & RMW mode */
28259690Snyan	if (val != info->prev_val) {
28359690Snyan	    outb(0x7e, (val & 1) ? 0xff : 0);	/* tile B */
28459690Snyan	    outb(0x7e, (val & 2) ? 0xff : 0);	/* tile R */
28559690Snyan	    outb(0x7e, (val & 4) ? 0xff : 0);	/* tile G */
28659690Snyan	    outb(0x7e, (val & 8) ? 0xff : 0);	/* tile I */
28759690Snyan
28859690Snyan	    info->prev_val = val;
28959690Snyan	}
29059690Snyan
29159690Snyan	*(info->vidmem+sofs) = (0x80 >> bofs);	/* write new bit */
29259690Snyan	outb(0x7c, 0);		/* GRCG off */
29359690Snyan	break;
29459690Snyan#else
29559690Snyan    case 4:
29642506Syokota    case 1:
29759583Syokota	/* EGA/VGA planar modes */
29859583Syokota	sofs += (x >> 3);
29959583Syokota	newbank = sofs/info->adp->va_window_size;
30059583Syokota	if (info->bank != newbank) {
301174985Swkoszek	    vidd_set_win_org(info->adp, newbank*info->adp->va_window_size);
30259583Syokota	    info->bank = newbank;
30359583Syokota	}
30459583Syokota	sofs %= info->adp->va_window_size;
30542506Syokota	bofs = x & 0x7;				/* offset within byte */
30659583Syokota	outw(GDCIDX, (0x8000 >> bofs) | 0x08);	/* bit mask */
30759583Syokota	outw(GDCIDX, (val << 8) | 0x00);	/* set/reset */
30859583Syokota	*(info->vidmem + sofs) ^= 0xff;		/* read-modify-write */
30942506Syokota	break;
31059690Snyan#endif
31142506Syokota
31242506Syokota    case 8:
31359583Syokota	sofs += x;
31442998Syokota	newbank = sofs/info->adp->va_window_size;
31542998Syokota	if (info->bank != newbank) {
316174985Swkoszek	    vidd_set_win_org(info->adp, newbank*info->adp->va_window_size);
31742998Syokota	    info->bank = newbank;
31842998Syokota	}
31942998Syokota	sofs %= info->adp->va_window_size;
32042506Syokota	*(info->vidmem+sofs) = val;
32142506Syokota	break;
32242506Syokota    }
32342506Syokota}
32442506Syokota
32542506Syokota/*
32642506Syokota** bmp_DecodeRLE4
32742506Syokota**
32842506Syokota** Given (data) pointing to a line of RLE4-format data and (line) being the starting
32942506Syokota** line onscreen, decode the line.
33042506Syokota*/
33142506Syokotastatic void
33242506Syokotabmp_DecodeRLE4(BMP_INFO *info, int line)
33342506Syokota{
33442506Syokota    int		count;		/* run count */
33542506Syokota    u_char	val;
33642506Syokota    int		x,y;		/* screen position */
33742506Syokota
33842506Syokota    x = 0;			/* starting position */
33942506Syokota    y = line;
34042506Syokota
34142506Syokota    /* loop reading data */
34242506Syokota    for (;;) {
34342506Syokota	/*
34442506Syokota	 * encoded mode starts with a run length, and then a byte with
34542506Syokota	 * two colour indexes to alternate between for the run
34642506Syokota	 */
34742506Syokota	if (*info->index) {
34842506Syokota	    for (count = 0; count < *info->index; count++, x++) {
34942506Syokota		if (count & 1) {		/* odd count, low nybble */
35042506Syokota		    bmp_SetPix(info, x, y, *(info->index+1) & 0x0f);
35142506Syokota		} else {			/* even count, high nybble */
35242506Syokota		    bmp_SetPix(info, x, y, (*(info->index+1) >>4) & 0x0f);
35342506Syokota		}
35442506Syokota	    }
35542506Syokota	    info->index += 2;
35642506Syokota        /*
35742506Syokota	 * A leading zero is an escape; it may signal the end of the
35842506Syokota	 * bitmap, a cursor move, or some absolute data.
35942506Syokota	 */
36042506Syokota	} else {	/* zero tag may be absolute mode or an escape */
36142506Syokota	    switch (*(info->index+1)) {
36242506Syokota	    case 0:				/* end of line */
36342506Syokota		info->index += 2;
36442506Syokota		return;
36542506Syokota	    case 1:				/* end of bitmap */
36642506Syokota		info->index = NULL;
36742506Syokota		return;
36842506Syokota	    case 2:				/* move */
36942506Syokota		x += *(info->index + 2);	/* new coords */
37042506Syokota		y += *(info->index + 3);
37142506Syokota		info->index += 4;
37242506Syokota		break;
37342506Syokota	    default:				/* literal bitmap data */
37442506Syokota		for (count = 0; count < *(info->index + 1); count++, x++) {
37542506Syokota		    val = *(info->index + 2 + (count / 2));	/* byte with nybbles */
37642506Syokota		    if (count & 1) {
37742506Syokota			val &= 0xf;		/* get low nybble */
37842506Syokota		    } else {
37942506Syokota			val = (val >> 4);	/* get high nybble */
38042506Syokota		    }
38142506Syokota		    bmp_SetPix(info, x, y, val);
38242506Syokota		}
38342506Syokota		/* warning, this depends on integer truncation, do not hand-optimise! */
38442506Syokota		info->index += 2 + ((count + 3) / 4) * 2;
38542506Syokota		break;
38642506Syokota	    }
38742506Syokota	}
38842506Syokota    }
38942506Syokota}
39042506Syokota
39142506Syokota/*
39242506Syokota** bmp_DecodeRLE8
39359583Syokota** Given (data) pointing to a line of RLE8-format data and (line) being the starting
39442506Syokota** line onscreen, decode the line.
39542506Syokota*/
39642506Syokotastatic void
39742506Syokotabmp_DecodeRLE8(BMP_INFO *info, int line)
39842506Syokota{
39942506Syokota    int		count;		/* run count */
40042506Syokota    int		x,y;		/* screen position */
40142506Syokota
40242506Syokota    x = 0;			/* starting position */
40342506Syokota    y = line;
40442506Syokota
40542506Syokota    /* loop reading data */
40642506Syokota    for(;;) {
40742506Syokota	/*
40842506Syokota	 * encoded mode starts with a run length, and then a byte with
40942506Syokota	 * two colour indexes to alternate between for the run
41042506Syokota	 */
41142506Syokota	if (*info->index) {
41242506Syokota	    for (count = 0; count < *info->index; count++, x++)
41342506Syokota		bmp_SetPix(info, x, y, *(info->index+1));
41442506Syokota	    info->index += 2;
41542506Syokota        /*
41642506Syokota	 * A leading zero is an escape; it may signal the end of the
41742506Syokota	 * bitmap, a cursor move, or some absolute data.
41842506Syokota	 */
41942506Syokota	} else {	/* zero tag may be absolute mode or an escape */
42042506Syokota	    switch(*(info->index+1)) {
42142506Syokota	    case 0:				/* end of line */
42242506Syokota		info->index += 2;
42342506Syokota		return;
42442506Syokota	    case 1:				/* end of bitmap */
42542506Syokota		info->index = NULL;
42642506Syokota		return;
42742506Syokota	    case 2:				/* move */
42842506Syokota		x += *(info->index + 2);	/* new coords */
42942506Syokota		y += *(info->index + 3);
43042506Syokota		info->index += 4;
43142506Syokota		break;
43242506Syokota	    default:				/* literal bitmap data */
43342506Syokota		for (count = 0; count < *(info->index + 1); count++, x++)
43442506Syokota		    bmp_SetPix(info, x, y, *(info->index + 2 + count));
43542506Syokota		/* must be an even count */
43642506Syokota		info->index += 2 + count + (count & 1);
43742506Syokota		break;
43842506Syokota	    }
43942506Syokota	}
44042506Syokota    }
44142506Syokota}
44242506Syokota
44342506Syokota/*
44442506Syokota** bmp_DecodeLine
44542506Syokota**
44642506Syokota** Given (info) pointing to an image being decoded, (line) being the line currently
44742506Syokota** being displayed, decode a line of data.
44842506Syokota*/
44942506Syokotastatic void
45042506Syokotabmp_DecodeLine(BMP_INFO *info, int line)
45142506Syokota{
45242506Syokota    int		x;
45359583Syokota    u_char	val, mask, *p;
45442506Syokota
45542506Syokota    switch(info->format) {
45642506Syokota    case BI_RGB:
45759583Syokota    	switch(info->depth) {
45859583Syokota	case 8:
45959583Syokota	    for (x = 0; x < info->width; x++, info->index++)
46059583Syokota		bmp_SetPix(info, x, line, *info->index);
46159583Syokota	    info->index += 3 - (--x % 4);
46259583Syokota	    break;
46359583Syokota	case 4:
46459583Syokota	    p = info->index;
46559583Syokota	    for (x = 0; x < info->width; x++) {
46659583Syokota		if (x & 1) {
46759583Syokota		    val = *p & 0xf;	/* get low nybble */
46859583Syokota		    p++;
46959583Syokota		} else {
47059583Syokota		    val = *p >> 4;	/* get high nybble */
47159583Syokota		}
47259583Syokota		bmp_SetPix(info, x, line, val);
47359583Syokota	    }
47459583Syokota	    /* warning, this depends on integer truncation, do not hand-optimise! */
47559583Syokota	    info->index += ((x + 7) / 8) * 4;
47659583Syokota	    break;
47759583Syokota	case 1:
47859583Syokota	    p = info->index;
47959583Syokota	    mask = 0x80;
48059583Syokota	    for (x = 0; x < info->width; x++) {
48159583Syokota		val = (*p & mask) ? 1 : 0;
48259583Syokota		mask >>= 1;
48359583Syokota		if (mask == 0) {
48459583Syokota		    mask = 0x80;
48559583Syokota		    p++;
48659583Syokota		}
48759583Syokota		bmp_SetPix(info, x, line, val);
48859583Syokota	    }
48959583Syokota	    /* warning, this depends on integer truncation, do not hand-optimise! */
49059583Syokota	    info->index += ((x + 31) / 32) * 4;
49159583Syokota	    break;
49259583Syokota	}
49342506Syokota	break;
49442506Syokota    case BI_RLE4:
49542506Syokota	bmp_DecodeRLE4(info, line);
49642506Syokota	break;
49742506Syokota    case BI_RLE8:
49842506Syokota	bmp_DecodeRLE8(info, line);
49942506Syokota	break;
50042506Syokota    }
50142506Syokota}
50242506Syokota
50342506Syokota/*
50442506Syokota** bmp_Init
50542506Syokota**
50642506Syokota** Given a pointer (data) to the image of a BMP file, fill in bmp_info with what
50742506Syokota** can be learnt from it.  Return nonzero if the file isn't usable.
50842506Syokota**
50942506Syokota** Take screen dimensions (swidth), (sheight) and (sdepth) and make sure we
51042506Syokota** can work with these.
51142506Syokota*/
51242506Syokotastatic int
513106765Smuxbmp_Init(char *data, int swidth, int sheight, int sdepth)
51442506Syokota{
51542506Syokota    BITMAPF	*bmf = (BITMAPF *)data;
51642506Syokota    int		pind;
51742506Syokota
51842506Syokota    bmp_info.data = NULL;	/* assume setup failed */
51942506Syokota
52042506Syokota    /* check file ID */
52142506Syokota    if (bmf->bmfh.bfType != 0x4d42) {
52247945Syokota	printf("splash_bmp: not a BMP file\n");
52342506Syokota	return(1);		/* XXX check word ordering for big-endian ports? */
52442506Syokota    }
52542506Syokota
52647945Syokota    /* do we understand this bitmap format? */
52747945Syokota    if (bmf->bmfi.bmiHeader.biSize > sizeof(bmf->bmfi.bmiHeader)) {
52847945Syokota	printf("splash_bmp: unsupported BMP format (size=%d)\n",
52947945Syokota		bmf->bmfi.bmiHeader.biSize);
53047945Syokota	return(1);
53147945Syokota    }
53247945Syokota
53342506Syokota    /* save what we know about the screen */
53442506Syokota    bmp_info.swidth = swidth;
53542506Syokota    bmp_info.sheight = sheight;
53642506Syokota    bmp_info.sdepth = sdepth;
53742506Syokota
53842506Syokota    /* where's the data? */
53942506Syokota    bmp_info.data = (u_char *)data + bmf->bmfh.bfOffBits;
54042506Syokota
54142506Syokota    /* image parameters */
54242506Syokota    bmp_info.width = bmf->bmfi.bmiHeader.biWidth;
54342506Syokota    bmp_info.height = bmf->bmfi.bmiHeader.biHeight;
54459583Syokota    bmp_info.depth = bmf->bmfi.bmiHeader.biBitCount;
54542506Syokota    bmp_info.format = bmf->bmfi.bmiHeader.biCompression;
54642506Syokota
54742506Syokota    switch(bmp_info.format) {	/* check compression format */
54842506Syokota    case BI_RGB:
54942506Syokota    case BI_RLE4:
55042506Syokota    case BI_RLE8:
55142506Syokota	break;
55242506Syokota    default:
55347945Syokota	printf("splash_bmp: unsupported compression format\n");
55442506Syokota	return(1);		/* unsupported compression format */
55542506Syokota    }
55642506Syokota
55742506Syokota    /* palette details */
55842506Syokota    bmp_info.ncols = (bmf->bmfi.bmiHeader.biClrUsed);
55942506Syokota    bzero(bmp_info.palette,sizeof(bmp_info.palette));
56042506Syokota    if (bmp_info.ncols == 0) {	/* uses all of them */
56142623Syokota	bmp_info.ncols = 1 << bmf->bmfi.bmiHeader.biBitCount;
56242506Syokota    }
56342506Syokota    if ((bmp_info.height > bmp_info.sheight) ||
56442506Syokota	(bmp_info.width > bmp_info.swidth) ||
56542506Syokota	(bmp_info.ncols > (1 << sdepth))) {
56659583Syokota	if (bootverbose)
56759583Syokota	    printf("splash_bmp: beyond screen capacity (%dx%d, %d colors)\n",
56859583Syokota		   bmp_info.width, bmp_info.height, bmp_info.ncols);
56959583Syokota	return(1);
57042506Syokota    }
57142506Syokota
57242506Syokota    /* read palette */
57342506Syokota    for (pind = 0; pind < bmp_info.ncols; pind++) {
57442506Syokota	bmp_info.palette[pind][0] = bmf->bmfi.bmiColors[pind].rgbRed;
57542506Syokota	bmp_info.palette[pind][1] = bmf->bmfi.bmiColors[pind].rgbGreen;
57642506Syokota	bmp_info.palette[pind][2] = bmf->bmfi.bmiColors[pind].rgbBlue;
57742506Syokota    }
57842506Syokota    return(0);
57942506Syokota}
58042506Syokota
58142506Syokota/*
58242506Syokota** bmp_Draw
58342506Syokota**
58442506Syokota** Render the image.  Return nonzero if that's not possible.
58542506Syokota**
58642506Syokota*/
58742506Syokotastatic int
58842506Syokotabmp_Draw(video_adapter_t *adp)
58942506Syokota{
59042506Syokota    int		line;
59173857Sjhb#if 0
59273857Sjhb#ifndef PC98
59359583Syokota    int		i;
59473857Sjhb#endif
59573857Sjhb#endif
59642506Syokota
59742506Syokota    if (bmp_info.data == NULL) {	/* init failed, do nothing */
59842506Syokota	return(1);
59942506Syokota    }
60042506Syokota
60142506Syokota    /* clear the screen */
60242506Syokota    bmp_info.vidmem = (u_char *)adp->va_window;
60342998Syokota    bmp_info.adp = adp;
604174985Swkoszek    vidd_clear(adp);
605174985Swkoszek    vidd_set_win_org(adp, 0);
60642998Syokota    bmp_info.bank = 0;
60742506Syokota
60842506Syokota    /* initialise the info structure for drawing */
60942506Syokota    bmp_info.index = bmp_info.data;
61059690Snyan#ifdef PC98
61159690Snyan    bmp_info.prev_val = 255;
61259690Snyan#endif
61342506Syokota
61442506Syokota    /* set the palette for our image */
615174985Swkoszek    vidd_load_palette(adp, (u_char *)&bmp_info.palette);
61642506Syokota
61768050Snyan#if 0
61859690Snyan#ifndef PC98
61959583Syokota    /* XXX: this is ugly, but necessary for EGA/VGA 1bpp/4bpp modes */
62059583Syokota    if ((adp->va_type == KD_EGA) || (adp->va_type == KD_VGA)) {
62159583Syokota	inb(adp->va_crtc_addr + 6);		/* reset flip-flop */
62259583Syokota	outb(ATC, 0x14);
62359583Syokota	outb(ATC, 0);
62459583Syokota	for (i = 0; i < 16; ++i) {
62559583Syokota	    outb(ATC, i);
62659583Syokota	    outb(ATC, i);
62759583Syokota	}
62859583Syokota	inb(adp->va_crtc_addr + 6);		/* reset flip-flop */
62959583Syokota	outb(ATC, 0x20);			/* enable palette */
63059583Syokota
63159583Syokota	outw(GDCIDX, 0x0f01);			/* set/reset enable */
63259583Syokota
63359583Syokota	if (bmp_info.sdepth == 1)
63459583Syokota	    outw(TSIDX, 0x0102);		/* unmask plane #0 */
63559583Syokota    }
63659690Snyan#endif
63768050Snyan#endif
63859583Syokota
63942506Syokota    for (line = 0; (line < bmp_info.height) && bmp_info.index; line++) {
64042506Syokota	bmp_DecodeLine(&bmp_info, line);
64142506Syokota    }
64242506Syokota    return(0);
64342506Syokota}
644