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