splash_bmp.c revision 48104
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 * 2748104Syokota * $Id: splash_bmp.c,v 1.8 1999/06/16 14:04:45 yokota Exp $ 2842506Syokota */ 2942506Syokota 3042506Syokota#include <sys/param.h> 3142506Syokota#include <sys/systm.h> 3242506Syokota#include <sys/kernel.h> 3342506Syokota#include <sys/linker.h> 3448104Syokota#include <sys/fbio.h> 3542506Syokota 3642506Syokota#include <dev/fb/fbreg.h> 3742506Syokota#include <dev/fb/splashreg.h> 3842506Syokota 3945119Syokota#define FADE_TIMEOUT 15 /* sec */ 4045119Syokota#define FADE_LEVELS 10 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{ 6042998Syokota /* currently only 256-color modes are supported XXX */ 6142506Syokota static int modes[] = { 6242998Syokota M_VESA_CG640x480, 6342998Syokota M_VESA_CG800x600, 6442998Syokota M_VESA_CG1024x768, 6542998Syokota /* 6642998Syokota * As 320x200 doesn't generally look great, 6742998Syokota * it's least preferred here. 6842998Syokota */ 6942506Syokota M_VGA_CG320, 7042506Syokota -1, 7142506Syokota }; 7242506Syokota video_info_t info; 7342506Syokota int i; 7442506Syokota 7547945Syokota if ((bmp_decoder.data == NULL) || (bmp_decoder.data_size <= 0)) { 7647945Syokota printf("splash_bmp: No bitmap file found\n"); 7742506Syokota return ENODEV; 7847945Syokota } 7942506Syokota for (i = 0; modes[i] >= 0; ++i) { 8042506Syokota if (((*vidsw[adp->va_index]->get_info)(adp, modes[i], &info) == 0) 8142506Syokota && (bmp_Init((u_char *)bmp_decoder.data, 8242506Syokota info.vi_width, info.vi_height, info.vi_depth) == 0)) 8342506Syokota break; 8442506Syokota } 8542506Syokota splash_mode = modes[i]; 8647945Syokota if (splash_mode < 0) 8747945Syokota printf("splash_bmp: No appropriate video mode found\n"); 8842506Syokota if (bootverbose) 8942506Syokota printf("bmp_start(): splash_mode:%d\n", splash_mode); 9042506Syokota return ((splash_mode < 0) ? ENODEV : 0); 9142506Syokota} 9242506Syokota 9342506Syokotastatic int 9442506Syokotabmp_end(video_adapter_t *adp) 9542506Syokota{ 9642506Syokota /* nothing to do */ 9742506Syokota return 0; 9842506Syokota} 9942506Syokota 10042506Syokotastatic int 10142506Syokotabmp_splash(video_adapter_t *adp, int on) 10242506Syokota{ 10342506Syokota static u_char pal[256*3]; 10442506Syokota static long time_stamp; 10545119Syokota u_char tpal[256*3]; 10645119Syokota static int fading = TRUE, brightness = FADE_LEVELS; 10742506Syokota struct timeval tv; 10842506Syokota int i; 10942506Syokota 11042506Syokota if (on) { 11142506Syokota if (!splash_on) { 11242506Syokota /* set up the video mode and draw something */ 11342506Syokota if ((*vidsw[adp->va_index]->set_mode)(adp, splash_mode)) 11442506Syokota return 1; 11542506Syokota if (bmp_Draw(adp)) 11642506Syokota return 1; 11742506Syokota (*vidsw[adp->va_index]->save_palette)(adp, pal); 11842506Syokota time_stamp = 0; 11942506Syokota splash_on = TRUE; 12042506Syokota } 12142506Syokota /* 12242506Syokota * This is a kludge to fade the image away. This section of the 12342506Syokota * code takes effect only after the system is completely up. 12442998Syokota * FADE_TIMEOUT should be configurable. 12542506Syokota */ 12642506Syokota if (!cold) { 12742506Syokota getmicrotime(&tv); 12842506Syokota if (time_stamp == 0) 12942506Syokota time_stamp = tv.tv_sec; 13042506Syokota if (tv.tv_sec > time_stamp + FADE_TIMEOUT) { 13145119Syokota if (fading) 13245119Syokota if (brightness == 0) { 13345119Syokota fading = FALSE; 13445119Syokota brightness++; 13545119Syokota } 13645119Syokota else brightness--; 13745119Syokota else 13845119Syokota if (brightness == FADE_LEVELS) { 13945119Syokota fading = TRUE; 14045119Syokota brightness--; 14145119Syokota } 14245119Syokota else brightness++; 14342506Syokota for (i = 0; i < sizeof(pal); ++i) { 14445119Syokota tpal[i] = pal[i] * brightness / FADE_LEVELS; 14542506Syokota } 14645119Syokota (*vidsw[adp->va_index]->load_palette)(adp, tpal); 14745119Syokota time_stamp = tv.tv_sec; 14842506Syokota } 14942506Syokota } 15042506Syokota return 0; 15142506Syokota } else { 15242506Syokota /* the video mode will be restored by the caller */ 15342506Syokota splash_on = FALSE; 15442506Syokota return 0; 15542506Syokota } 15642506Syokota} 15742506Syokota 15842506Syokota/* 15942506Syokota** Code to handle Microsoft DIB (".BMP") format images. 16042506Syokota** 16142506Syokota** Blame me (msmith@freebsd.org) if this is broken, not Soren. 16242506Syokota*/ 16342506Syokota 16442506Syokotatypedef struct tagBITMAPFILEHEADER { /* bmfh */ 16542506Syokota u_short bfType __attribute__ ((packed)); 16642506Syokota int bfSize __attribute__ ((packed)); 16742506Syokota u_short bfReserved1 __attribute__ ((packed)); 16842506Syokota u_short bfReserved2 __attribute__ ((packed)); 16942506Syokota int bfOffBits __attribute__ ((packed)); 17042506Syokota} BITMAPFILEHEADER; 17142506Syokota 17242506Syokotatypedef struct tagBITMAPINFOHEADER { /* bmih */ 17342506Syokota int biSize __attribute__ ((packed)); 17442506Syokota int biWidth __attribute__ ((packed)); 17542506Syokota int biHeight __attribute__ ((packed)); 17642506Syokota short biPlanes __attribute__ ((packed)); 17742506Syokota short biBitCount __attribute__ ((packed)); 17842506Syokota int biCompression __attribute__ ((packed)); 17942506Syokota int biSizeImage __attribute__ ((packed)); 18042506Syokota int biXPelsPerMeter __attribute__ ((packed)); 18142506Syokota int biYPelsPerMeter __attribute__ ((packed)); 18242506Syokota int biClrUsed __attribute__ ((packed)); 18342506Syokota int biClrImportant __attribute__ ((packed)); 18442506Syokota} BITMAPINFOHEADER; 18542506Syokota 18642506Syokotatypedef struct tagRGBQUAD { /* rgbq */ 18742506Syokota u_char rgbBlue __attribute__ ((packed)); 18842506Syokota u_char rgbGreen __attribute__ ((packed)); 18942506Syokota u_char rgbRed __attribute__ ((packed)); 19042506Syokota u_char rgbReserved __attribute__ ((packed)); 19142506Syokota} RGBQUAD; 19242506Syokota 19342506Syokotatypedef struct tagBITMAPINFO { /* bmi */ 19442506Syokota BITMAPINFOHEADER bmiHeader __attribute__ ((packed)); 19542506Syokota RGBQUAD bmiColors[256] __attribute__ ((packed)); 19642506Syokota} BITMAPINFO; 19742506Syokota 19842506Syokotatypedef struct tagBITMAPF 19942506Syokota{ 20042506Syokota BITMAPFILEHEADER bmfh __attribute__ ((packed)); 20142506Syokota BITMAPINFO bmfi __attribute__ ((packed)); 20242506Syokota} BITMAPF; 20342506Syokota 20442506Syokota#define BI_RGB 0 20542506Syokota#define BI_RLE8 1 20642506Syokota#define BI_RLE4 2 20742506Syokota 20842506Syokota/* 20942506Syokota** all we actually care about the image 21042506Syokota*/ 21142506Syokotatypedef struct 21242506Syokota{ 21342506Syokota int width,height; /* image dimensions */ 21442506Syokota int swidth,sheight; /* screen dimensions for the current mode */ 21542506Syokota u_char sdepth; /* screen depth (1, 4, 8 bpp) */ 21642506Syokota int ncols; /* number of colours */ 21742506Syokota u_char palette[256][3]; /* raw palette data */ 21842506Syokota u_char format; /* one of the BI_* constants above */ 21942506Syokota u_char *data; /* pointer to the raw data */ 22042506Syokota u_char *index; /* running pointer to the data while drawing */ 22142506Syokota u_char *vidmem; /* video memory allocated for drawing */ 22242998Syokota video_adapter_t *adp; 22342998Syokota int bank; 22442506Syokota} BMP_INFO; 22542506Syokota 22642506Syokotastatic BMP_INFO bmp_info; 22742506Syokota 22842998Syokotastatic void 22942998Syokotafill(BMP_INFO *info, int x, int y, int xsize, int ysize) 23042998Syokota{ 23142998Syokota u_char *window; 23242998Syokota int banksize; 23342998Syokota int bank; 23442998Syokota int p; 23542998Syokota 23642998Syokota banksize = info->adp->va_window_size; 23743664Syokota bank = (info->adp->va_line_width*y + x)/banksize; 23842998Syokota window = (u_char *)info->adp->va_window; 23942998Syokota (*vidsw[info->adp->va_index]->set_win_org)(info->adp, bank*banksize); 24042998Syokota while (ysize > 0) { 24143664Syokota p = (info->adp->va_line_width*y + x)%banksize; 24242998Syokota for (; (p + xsize <= banksize) && ysize > 0; --ysize, ++y) { 24342998Syokota generic_bzero(window + p, xsize); 24443664Syokota p += info->adp->va_line_width; 24542998Syokota } 24642998Syokota if (ysize <= 0) 24742998Syokota break; 24842998Syokota if (p < banksize) { 24942998Syokota /* the last line crosses the window boundary */ 25042998Syokota generic_bzero(window + p, banksize - p); 25142998Syokota } 25242998Syokota ++bank; /* next bank */ 25342998Syokota (*vidsw[info->adp->va_index]->set_win_org)(info->adp, bank*banksize); 25442998Syokota if (p < banksize) { 25542998Syokota /* the remaining part of the last line */ 25642998Syokota generic_bzero(window, p + xsize - banksize); 25742998Syokota ++y; 25842998Syokota --ysize; 25942998Syokota } 26042998Syokota } 26142998Syokota info->bank = bank; 26242998Syokota} 26342998Syokota 26442506Syokota/* 26542506Syokota** bmp_SetPix 26642506Syokota** 26742506Syokota** Given (info), set the pixel at (x),(y) to (val) 26842506Syokota** 26942506Syokota*/ 27042506Syokotastatic void 27142506Syokotabmp_SetPix(BMP_INFO *info, int x, int y, u_char val) 27242506Syokota{ 27342506Syokota int sofs, bofs; 27442506Syokota u_char tpv, mask; 27542998Syokota int newbank; 27642506Syokota 27742506Syokota /* 27842506Syokota * range check to avoid explosions 27942506Syokota */ 28042506Syokota if ((x < 0) || (x >= info->swidth) || (y < 0) || (y >= info->sheight)) 28142506Syokota return; 28242506Syokota 28342506Syokota /* 28442506Syokota * calculate offset into video memory; 28542506Syokota * because 0,0 is bottom-left for DIB, we have to convert. 28642506Syokota */ 28742506Syokota sofs = ((info->height - (y+1) + (info->sheight - info->height) / 2) 28843664Syokota * info->adp->va_line_width); 28942506Syokota 29042506Syokota switch(info->sdepth) { 29142506Syokota case 1: 29243664Syokota sofs += ((x + (info->swidth - info->width) / 2) >> 3); 29342506Syokota bofs = x & 0x7; /* offset within byte */ 29442506Syokota 29542506Syokota val &= 1; /* mask pixel value */ 29642506Syokota mask = ~(0x80 >> bofs); /* calculate bit mask */ 29742506Syokota tpv = *(info->vidmem+sofs) & mask; /* get screen contents, excluding masked bit */ 29842506Syokota *(info->vidmem+sofs) = tpv | (val << (8-bofs)); /* write new bit */ 29942506Syokota break; 30042506Syokota 30142506Syokota /* XXX only correct for non-interleaved modes */ 30242506Syokota case 4: 30343664Syokota sofs += ((x + (info->swidth - info->width) / 2) >> 1); 30442506Syokota bofs = x & 0x1; /* offset within byte */ 30542506Syokota 30642506Syokota val &= 0xf; /* mask pixel value */ 30742506Syokota mask = bofs ? 0x0f : 0xf0; /* calculate bit mask */ 30842506Syokota tpv = *(info->vidmem+sofs) & mask; /* get screen contents, excluding masked bits */ 30942506Syokota *(info->vidmem+sofs) = tpv | (val << (bofs ? 0 : 4)); /* write new bits */ 31042506Syokota break; 31142506Syokota 31242506Syokota case 8: 31343664Syokota sofs += x + (info->swidth - info->width) / 2; 31442998Syokota newbank = sofs/info->adp->va_window_size; 31542998Syokota if (info->bank != newbank) { 31642998Syokota (*vidsw[info->adp->va_index]->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 39342506Syokota** Given (data) pointing to a line of RLE4-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; 45342506Syokota 45442506Syokota switch(info->format) { 45542506Syokota case BI_RGB: 45642506Syokota for (x = 0; x < info->width; x++, info->index++) 45742506Syokota bmp_SetPix(info, x, line, *info->index); 45842529Syokota info->index += 3 - (--x % 4); 45942506Syokota break; 46042506Syokota case BI_RLE4: 46142506Syokota bmp_DecodeRLE4(info, line); 46242506Syokota break; 46342506Syokota case BI_RLE8: 46442506Syokota bmp_DecodeRLE8(info, line); 46542506Syokota break; 46642506Syokota } 46742506Syokota} 46842506Syokota 46942506Syokota/* 47042506Syokota** bmp_Init 47142506Syokota** 47242506Syokota** Given a pointer (data) to the image of a BMP file, fill in bmp_info with what 47342506Syokota** can be learnt from it. Return nonzero if the file isn't usable. 47442506Syokota** 47542506Syokota** Take screen dimensions (swidth), (sheight) and (sdepth) and make sure we 47642506Syokota** can work with these. 47742506Syokota*/ 47842506Syokotastatic int 47942506Syokotabmp_Init(const char *data, int swidth, int sheight, int sdepth) 48042506Syokota{ 48142506Syokota BITMAPF *bmf = (BITMAPF *)data; 48242506Syokota int pind; 48342506Syokota 48442506Syokota bmp_info.data = NULL; /* assume setup failed */ 48542506Syokota 48642506Syokota /* check file ID */ 48742506Syokota if (bmf->bmfh.bfType != 0x4d42) { 48847945Syokota printf("splash_bmp: not a BMP file\n"); 48942506Syokota return(1); /* XXX check word ordering for big-endian ports? */ 49042506Syokota } 49142506Syokota 49247945Syokota /* do we understand this bitmap format? */ 49347945Syokota if (bmf->bmfi.bmiHeader.biSize > sizeof(bmf->bmfi.bmiHeader)) { 49447945Syokota printf("splash_bmp: unsupported BMP format (size=%d)\n", 49547945Syokota bmf->bmfi.bmiHeader.biSize); 49647945Syokota return(1); 49747945Syokota } 49847945Syokota 49942506Syokota /* save what we know about the screen */ 50042506Syokota bmp_info.swidth = swidth; 50142506Syokota bmp_info.sheight = sheight; 50242506Syokota bmp_info.sdepth = sdepth; 50342506Syokota 50442506Syokota /* where's the data? */ 50542506Syokota bmp_info.data = (u_char *)data + bmf->bmfh.bfOffBits; 50642506Syokota 50742506Syokota /* image parameters */ 50842506Syokota bmp_info.width = bmf->bmfi.bmiHeader.biWidth; 50942506Syokota bmp_info.height = bmf->bmfi.bmiHeader.biHeight; 51042506Syokota bmp_info.format = bmf->bmfi.bmiHeader.biCompression; 51142506Syokota 51242506Syokota switch(bmp_info.format) { /* check compression format */ 51342506Syokota case BI_RGB: 51442506Syokota case BI_RLE4: 51542506Syokota case BI_RLE8: 51642506Syokota break; 51742506Syokota default: 51847945Syokota printf("splash_bmp: unsupported compression format\n"); 51942506Syokota return(1); /* unsupported compression format */ 52042506Syokota } 52142506Syokota 52242506Syokota /* palette details */ 52342506Syokota bmp_info.ncols = (bmf->bmfi.bmiHeader.biClrUsed); 52442506Syokota bzero(bmp_info.palette,sizeof(bmp_info.palette)); 52542506Syokota if (bmp_info.ncols == 0) { /* uses all of them */ 52642623Syokota bmp_info.ncols = 1 << bmf->bmfi.bmiHeader.biBitCount; 52742506Syokota } 52847945Syokota if ((bmf->bmfi.bmiHeader.biBitCount != sdepth) 52947945Syokota || (bmp_info.ncols > (1 << sdepth))) { 53047945Syokota printf("splash_bmp: unsupported color depth (%d bits, %d colors)\n", 53147945Syokota bmf->bmfi.bmiHeader.biBitCount, bmp_info.ncols); 53247945Syokota return(1); 53347945Syokota } 53442506Syokota if ((bmp_info.height > bmp_info.sheight) || 53542506Syokota (bmp_info.width > bmp_info.swidth) || 53642506Syokota (bmp_info.ncols > (1 << sdepth))) { 53742506Syokota return(1); /* beyond screen capacity */ 53842506Syokota } 53942506Syokota 54042506Syokota /* read palette */ 54142506Syokota for (pind = 0; pind < bmp_info.ncols; pind++) { 54242506Syokota bmp_info.palette[pind][0] = bmf->bmfi.bmiColors[pind].rgbRed; 54342506Syokota bmp_info.palette[pind][1] = bmf->bmfi.bmiColors[pind].rgbGreen; 54442506Syokota bmp_info.palette[pind][2] = bmf->bmfi.bmiColors[pind].rgbBlue; 54542506Syokota } 54642506Syokota return(0); 54742506Syokota} 54842506Syokota 54942506Syokota/* 55042506Syokota** bmp_Draw 55142506Syokota** 55242506Syokota** Render the image. Return nonzero if that's not possible. 55342506Syokota** 55442506Syokota*/ 55542506Syokotastatic int 55642506Syokotabmp_Draw(video_adapter_t *adp) 55742506Syokota{ 55842506Syokota int line; 55942506Syokota 56042506Syokota if (bmp_info.data == NULL) { /* init failed, do nothing */ 56142506Syokota return(1); 56242506Syokota } 56342506Syokota 56442506Syokota /* clear the screen */ 56542506Syokota bmp_info.vidmem = (u_char *)adp->va_window; 56642998Syokota bmp_info.adp = adp; 56742506Syokota /* XXX; the following line is correct only for 8bpp modes */ 56842998Syokota fill(&bmp_info, 0, 0, bmp_info.swidth, bmp_info.sheight); 56942998Syokota (*vidsw[adp->va_index]->set_win_org)(adp, 0); 57042998Syokota bmp_info.bank = 0; 57142506Syokota 57242506Syokota /* initialise the info structure for drawing */ 57342506Syokota bmp_info.index = bmp_info.data; 57442506Syokota 57542506Syokota /* set the palette for our image */ 57642506Syokota (*vidsw[adp->va_index]->load_palette)(adp, (u_char *)&bmp_info.palette); 57742506Syokota 57842506Syokota for (line = 0; (line < bmp_info.height) && bmp_info.index; line++) { 57942506Syokota bmp_DecodeLine(&bmp_info, line); 58042506Syokota } 58142506Syokota return(0); 58242506Syokota} 583