splash_bmp.c revision 45119
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 * 2745119Syokota * $Id: splash_bmp.c,v 1.6 1999/02/05 11:52:13 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 7642506Syokota if ((bmp_decoder.data == NULL) || (bmp_decoder.data_size <= 0)) 7742506Syokota return ENODEV; 7842506Syokota for (i = 0; modes[i] >= 0; ++i) { 7942506Syokota if (((*vidsw[adp->va_index]->get_info)(adp, modes[i], &info) == 0) 8042506Syokota && (bmp_Init((u_char *)bmp_decoder.data, 8142506Syokota info.vi_width, info.vi_height, info.vi_depth) == 0)) 8242506Syokota break; 8342506Syokota } 8442506Syokota splash_mode = modes[i]; 8542506Syokota if (bootverbose) 8642506Syokota printf("bmp_start(): splash_mode:%d\n", splash_mode); 8742506Syokota return ((splash_mode < 0) ? ENODEV : 0); 8842506Syokota} 8942506Syokota 9042506Syokotastatic int 9142506Syokotabmp_end(video_adapter_t *adp) 9242506Syokota{ 9342506Syokota /* nothing to do */ 9442506Syokota return 0; 9542506Syokota} 9642506Syokota 9742506Syokotastatic int 9842506Syokotabmp_splash(video_adapter_t *adp, int on) 9942506Syokota{ 10042506Syokota static u_char pal[256*3]; 10142506Syokota static long time_stamp; 10245119Syokota u_char tpal[256*3]; 10345119Syokota static int fading = TRUE, brightness = FADE_LEVELS; 10442506Syokota struct timeval tv; 10542506Syokota int i; 10642506Syokota 10742506Syokota if (on) { 10842506Syokota if (!splash_on) { 10942506Syokota /* set up the video mode and draw something */ 11042506Syokota if ((*vidsw[adp->va_index]->set_mode)(adp, splash_mode)) 11142506Syokota return 1; 11242506Syokota if (bmp_Draw(adp)) 11342506Syokota return 1; 11442506Syokota (*vidsw[adp->va_index]->save_palette)(adp, pal); 11542506Syokota time_stamp = 0; 11642506Syokota splash_on = TRUE; 11742506Syokota } 11842506Syokota /* 11942506Syokota * This is a kludge to fade the image away. This section of the 12042506Syokota * code takes effect only after the system is completely up. 12142998Syokota * FADE_TIMEOUT should be configurable. 12242506Syokota */ 12342506Syokota if (!cold) { 12442506Syokota getmicrotime(&tv); 12542506Syokota if (time_stamp == 0) 12642506Syokota time_stamp = tv.tv_sec; 12742506Syokota if (tv.tv_sec > time_stamp + FADE_TIMEOUT) { 12845119Syokota if (fading) 12945119Syokota if (brightness == 0) { 13045119Syokota fading = FALSE; 13145119Syokota brightness++; 13245119Syokota } 13345119Syokota else brightness--; 13445119Syokota else 13545119Syokota if (brightness == FADE_LEVELS) { 13645119Syokota fading = TRUE; 13745119Syokota brightness--; 13845119Syokota } 13945119Syokota else brightness++; 14042506Syokota for (i = 0; i < sizeof(pal); ++i) { 14145119Syokota tpal[i] = pal[i] * brightness / FADE_LEVELS; 14242506Syokota } 14345119Syokota (*vidsw[adp->va_index]->load_palette)(adp, tpal); 14445119Syokota time_stamp = tv.tv_sec; 14542506Syokota } 14642506Syokota } 14742506Syokota return 0; 14842506Syokota } else { 14942506Syokota /* the video mode will be restored by the caller */ 15042506Syokota splash_on = FALSE; 15142506Syokota return 0; 15242506Syokota } 15342506Syokota} 15442506Syokota 15542506Syokota/* 15642506Syokota** Code to handle Microsoft DIB (".BMP") format images. 15742506Syokota** 15842506Syokota** Blame me (msmith@freebsd.org) if this is broken, not Soren. 15942506Syokota*/ 16042506Syokota 16142506Syokotatypedef struct tagBITMAPFILEHEADER { /* bmfh */ 16242506Syokota u_short bfType __attribute__ ((packed)); 16342506Syokota int bfSize __attribute__ ((packed)); 16442506Syokota u_short bfReserved1 __attribute__ ((packed)); 16542506Syokota u_short bfReserved2 __attribute__ ((packed)); 16642506Syokota int bfOffBits __attribute__ ((packed)); 16742506Syokota} BITMAPFILEHEADER; 16842506Syokota 16942506Syokotatypedef struct tagBITMAPINFOHEADER { /* bmih */ 17042506Syokota int biSize __attribute__ ((packed)); 17142506Syokota int biWidth __attribute__ ((packed)); 17242506Syokota int biHeight __attribute__ ((packed)); 17342506Syokota short biPlanes __attribute__ ((packed)); 17442506Syokota short biBitCount __attribute__ ((packed)); 17542506Syokota int biCompression __attribute__ ((packed)); 17642506Syokota int biSizeImage __attribute__ ((packed)); 17742506Syokota int biXPelsPerMeter __attribute__ ((packed)); 17842506Syokota int biYPelsPerMeter __attribute__ ((packed)); 17942506Syokota int biClrUsed __attribute__ ((packed)); 18042506Syokota int biClrImportant __attribute__ ((packed)); 18142506Syokota} BITMAPINFOHEADER; 18242506Syokota 18342506Syokotatypedef struct tagRGBQUAD { /* rgbq */ 18442506Syokota u_char rgbBlue __attribute__ ((packed)); 18542506Syokota u_char rgbGreen __attribute__ ((packed)); 18642506Syokota u_char rgbRed __attribute__ ((packed)); 18742506Syokota u_char rgbReserved __attribute__ ((packed)); 18842506Syokota} RGBQUAD; 18942506Syokota 19042506Syokotatypedef struct tagBITMAPINFO { /* bmi */ 19142506Syokota BITMAPINFOHEADER bmiHeader __attribute__ ((packed)); 19242506Syokota RGBQUAD bmiColors[256] __attribute__ ((packed)); 19342506Syokota} BITMAPINFO; 19442506Syokota 19542506Syokotatypedef struct tagBITMAPF 19642506Syokota{ 19742506Syokota BITMAPFILEHEADER bmfh __attribute__ ((packed)); 19842506Syokota BITMAPINFO bmfi __attribute__ ((packed)); 19942506Syokota} BITMAPF; 20042506Syokota 20142506Syokota#define BI_RGB 0 20242506Syokota#define BI_RLE8 1 20342506Syokota#define BI_RLE4 2 20442506Syokota 20542506Syokota/* 20642506Syokota** all we actually care about the image 20742506Syokota*/ 20842506Syokotatypedef struct 20942506Syokota{ 21042506Syokota int width,height; /* image dimensions */ 21142506Syokota int swidth,sheight; /* screen dimensions for the current mode */ 21242506Syokota u_char sdepth; /* screen depth (1, 4, 8 bpp) */ 21342506Syokota int ncols; /* number of colours */ 21442506Syokota u_char palette[256][3]; /* raw palette data */ 21542506Syokota u_char format; /* one of the BI_* constants above */ 21642506Syokota u_char *data; /* pointer to the raw data */ 21742506Syokota u_char *index; /* running pointer to the data while drawing */ 21842506Syokota u_char *vidmem; /* video memory allocated for drawing */ 21942998Syokota video_adapter_t *adp; 22042998Syokota int bank; 22142506Syokota} BMP_INFO; 22242506Syokota 22342506Syokotastatic BMP_INFO bmp_info; 22442506Syokota 22542998Syokotastatic void 22642998Syokotafill(BMP_INFO *info, int x, int y, int xsize, int ysize) 22742998Syokota{ 22842998Syokota u_char *window; 22942998Syokota int banksize; 23042998Syokota int bank; 23142998Syokota int p; 23242998Syokota 23342998Syokota banksize = info->adp->va_window_size; 23443664Syokota bank = (info->adp->va_line_width*y + x)/banksize; 23542998Syokota window = (u_char *)info->adp->va_window; 23642998Syokota (*vidsw[info->adp->va_index]->set_win_org)(info->adp, bank*banksize); 23742998Syokota while (ysize > 0) { 23843664Syokota p = (info->adp->va_line_width*y + x)%banksize; 23942998Syokota for (; (p + xsize <= banksize) && ysize > 0; --ysize, ++y) { 24042998Syokota generic_bzero(window + p, xsize); 24143664Syokota p += info->adp->va_line_width; 24242998Syokota } 24342998Syokota if (ysize <= 0) 24442998Syokota break; 24542998Syokota if (p < banksize) { 24642998Syokota /* the last line crosses the window boundary */ 24742998Syokota generic_bzero(window + p, banksize - p); 24842998Syokota } 24942998Syokota ++bank; /* next bank */ 25042998Syokota (*vidsw[info->adp->va_index]->set_win_org)(info->adp, bank*banksize); 25142998Syokota if (p < banksize) { 25242998Syokota /* the remaining part of the last line */ 25342998Syokota generic_bzero(window, p + xsize - banksize); 25442998Syokota ++y; 25542998Syokota --ysize; 25642998Syokota } 25742998Syokota } 25842998Syokota info->bank = bank; 25942998Syokota} 26042998Syokota 26142506Syokota/* 26242506Syokota** bmp_SetPix 26342506Syokota** 26442506Syokota** Given (info), set the pixel at (x),(y) to (val) 26542506Syokota** 26642506Syokota*/ 26742506Syokotastatic void 26842506Syokotabmp_SetPix(BMP_INFO *info, int x, int y, u_char val) 26942506Syokota{ 27042506Syokota int sofs, bofs; 27142506Syokota u_char tpv, mask; 27242998Syokota int newbank; 27342506Syokota 27442506Syokota /* 27542506Syokota * range check to avoid explosions 27642506Syokota */ 27742506Syokota if ((x < 0) || (x >= info->swidth) || (y < 0) || (y >= info->sheight)) 27842506Syokota return; 27942506Syokota 28042506Syokota /* 28142506Syokota * calculate offset into video memory; 28242506Syokota * because 0,0 is bottom-left for DIB, we have to convert. 28342506Syokota */ 28442506Syokota sofs = ((info->height - (y+1) + (info->sheight - info->height) / 2) 28543664Syokota * info->adp->va_line_width); 28642506Syokota 28742506Syokota switch(info->sdepth) { 28842506Syokota case 1: 28943664Syokota sofs += ((x + (info->swidth - info->width) / 2) >> 3); 29042506Syokota bofs = x & 0x7; /* offset within byte */ 29142506Syokota 29242506Syokota val &= 1; /* mask pixel value */ 29342506Syokota mask = ~(0x80 >> bofs); /* calculate bit mask */ 29442506Syokota tpv = *(info->vidmem+sofs) & mask; /* get screen contents, excluding masked bit */ 29542506Syokota *(info->vidmem+sofs) = tpv | (val << (8-bofs)); /* write new bit */ 29642506Syokota break; 29742506Syokota 29842506Syokota /* XXX only correct for non-interleaved modes */ 29942506Syokota case 4: 30043664Syokota sofs += ((x + (info->swidth - info->width) / 2) >> 1); 30142506Syokota bofs = x & 0x1; /* offset within byte */ 30242506Syokota 30342506Syokota val &= 0xf; /* mask pixel value */ 30442506Syokota mask = bofs ? 0x0f : 0xf0; /* calculate bit mask */ 30542506Syokota tpv = *(info->vidmem+sofs) & mask; /* get screen contents, excluding masked bits */ 30642506Syokota *(info->vidmem+sofs) = tpv | (val << (bofs ? 0 : 4)); /* write new bits */ 30742506Syokota break; 30842506Syokota 30942506Syokota case 8: 31043664Syokota sofs += x + (info->swidth - info->width) / 2; 31142998Syokota newbank = sofs/info->adp->va_window_size; 31242998Syokota if (info->bank != newbank) { 31342998Syokota (*vidsw[info->adp->va_index]->set_win_org)(info->adp, newbank*info->adp->va_window_size); 31442998Syokota info->bank = newbank; 31542998Syokota } 31642998Syokota sofs %= info->adp->va_window_size; 31742506Syokota *(info->vidmem+sofs) = val; 31842506Syokota break; 31942506Syokota } 32042506Syokota} 32142506Syokota 32242506Syokota/* 32342506Syokota** bmp_DecodeRLE4 32442506Syokota** 32542506Syokota** Given (data) pointing to a line of RLE4-format data and (line) being the starting 32642506Syokota** line onscreen, decode the line. 32742506Syokota*/ 32842506Syokotastatic void 32942506Syokotabmp_DecodeRLE4(BMP_INFO *info, int line) 33042506Syokota{ 33142506Syokota int count; /* run count */ 33242506Syokota u_char val; 33342506Syokota int x,y; /* screen position */ 33442506Syokota 33542506Syokota x = 0; /* starting position */ 33642506Syokota y = line; 33742506Syokota 33842506Syokota /* loop reading data */ 33942506Syokota for (;;) { 34042506Syokota /* 34142506Syokota * encoded mode starts with a run length, and then a byte with 34242506Syokota * two colour indexes to alternate between for the run 34342506Syokota */ 34442506Syokota if (*info->index) { 34542506Syokota for (count = 0; count < *info->index; count++, x++) { 34642506Syokota if (count & 1) { /* odd count, low nybble */ 34742506Syokota bmp_SetPix(info, x, y, *(info->index+1) & 0x0f); 34842506Syokota } else { /* even count, high nybble */ 34942506Syokota bmp_SetPix(info, x, y, (*(info->index+1) >>4) & 0x0f); 35042506Syokota } 35142506Syokota } 35242506Syokota info->index += 2; 35342506Syokota /* 35442506Syokota * A leading zero is an escape; it may signal the end of the 35542506Syokota * bitmap, a cursor move, or some absolute data. 35642506Syokota */ 35742506Syokota } else { /* zero tag may be absolute mode or an escape */ 35842506Syokota switch (*(info->index+1)) { 35942506Syokota case 0: /* end of line */ 36042506Syokota info->index += 2; 36142506Syokota return; 36242506Syokota case 1: /* end of bitmap */ 36342506Syokota info->index = NULL; 36442506Syokota return; 36542506Syokota case 2: /* move */ 36642506Syokota x += *(info->index + 2); /* new coords */ 36742506Syokota y += *(info->index + 3); 36842506Syokota info->index += 4; 36942506Syokota break; 37042506Syokota default: /* literal bitmap data */ 37142506Syokota for (count = 0; count < *(info->index + 1); count++, x++) { 37242506Syokota val = *(info->index + 2 + (count / 2)); /* byte with nybbles */ 37342506Syokota if (count & 1) { 37442506Syokota val &= 0xf; /* get low nybble */ 37542506Syokota } else { 37642506Syokota val = (val >> 4); /* get high nybble */ 37742506Syokota } 37842506Syokota bmp_SetPix(info, x, y, val); 37942506Syokota } 38042506Syokota /* warning, this depends on integer truncation, do not hand-optimise! */ 38142506Syokota info->index += 2 + ((count + 3) / 4) * 2; 38242506Syokota break; 38342506Syokota } 38442506Syokota } 38542506Syokota } 38642506Syokota} 38742506Syokota 38842506Syokota/* 38942506Syokota** bmp_DecodeRLE8 39042506Syokota** Given (data) pointing to a line of RLE4-format data and (line) being the starting 39142506Syokota** line onscreen, decode the line. 39242506Syokota*/ 39342506Syokotastatic void 39442506Syokotabmp_DecodeRLE8(BMP_INFO *info, int line) 39542506Syokota{ 39642506Syokota int count; /* run count */ 39742506Syokota int x,y; /* screen position */ 39842506Syokota 39942506Syokota x = 0; /* starting position */ 40042506Syokota y = line; 40142506Syokota 40242506Syokota /* loop reading data */ 40342506Syokota for(;;) { 40442506Syokota /* 40542506Syokota * encoded mode starts with a run length, and then a byte with 40642506Syokota * two colour indexes to alternate between for the run 40742506Syokota */ 40842506Syokota if (*info->index) { 40942506Syokota for (count = 0; count < *info->index; count++, x++) 41042506Syokota bmp_SetPix(info, x, y, *(info->index+1)); 41142506Syokota info->index += 2; 41242506Syokota /* 41342506Syokota * A leading zero is an escape; it may signal the end of the 41442506Syokota * bitmap, a cursor move, or some absolute data. 41542506Syokota */ 41642506Syokota } else { /* zero tag may be absolute mode or an escape */ 41742506Syokota switch(*(info->index+1)) { 41842506Syokota case 0: /* end of line */ 41942506Syokota info->index += 2; 42042506Syokota return; 42142506Syokota case 1: /* end of bitmap */ 42242506Syokota info->index = NULL; 42342506Syokota return; 42442506Syokota case 2: /* move */ 42542506Syokota x += *(info->index + 2); /* new coords */ 42642506Syokota y += *(info->index + 3); 42742506Syokota info->index += 4; 42842506Syokota break; 42942506Syokota default: /* literal bitmap data */ 43042506Syokota for (count = 0; count < *(info->index + 1); count++, x++) 43142506Syokota bmp_SetPix(info, x, y, *(info->index + 2 + count)); 43242506Syokota /* must be an even count */ 43342506Syokota info->index += 2 + count + (count & 1); 43442506Syokota break; 43542506Syokota } 43642506Syokota } 43742506Syokota } 43842506Syokota} 43942506Syokota 44042506Syokota/* 44142506Syokota** bmp_DecodeLine 44242506Syokota** 44342506Syokota** Given (info) pointing to an image being decoded, (line) being the line currently 44442506Syokota** being displayed, decode a line of data. 44542506Syokota*/ 44642506Syokotastatic void 44742506Syokotabmp_DecodeLine(BMP_INFO *info, int line) 44842506Syokota{ 44942506Syokota int x; 45042506Syokota 45142506Syokota switch(info->format) { 45242506Syokota case BI_RGB: 45342506Syokota for (x = 0; x < info->width; x++, info->index++) 45442506Syokota bmp_SetPix(info, x, line, *info->index); 45542529Syokota info->index += 3 - (--x % 4); 45642506Syokota break; 45742506Syokota case BI_RLE4: 45842506Syokota bmp_DecodeRLE4(info, line); 45942506Syokota break; 46042506Syokota case BI_RLE8: 46142506Syokota bmp_DecodeRLE8(info, line); 46242506Syokota break; 46342506Syokota } 46442506Syokota} 46542506Syokota 46642506Syokota/* 46742506Syokota** bmp_Init 46842506Syokota** 46942506Syokota** Given a pointer (data) to the image of a BMP file, fill in bmp_info with what 47042506Syokota** can be learnt from it. Return nonzero if the file isn't usable. 47142506Syokota** 47242506Syokota** Take screen dimensions (swidth), (sheight) and (sdepth) and make sure we 47342506Syokota** can work with these. 47442506Syokota*/ 47542506Syokotastatic int 47642506Syokotabmp_Init(const char *data, int swidth, int sheight, int sdepth) 47742506Syokota{ 47842506Syokota BITMAPF *bmf = (BITMAPF *)data; 47942506Syokota int pind; 48042506Syokota 48142506Syokota bmp_info.data = NULL; /* assume setup failed */ 48242506Syokota 48342506Syokota /* check file ID */ 48442506Syokota if (bmf->bmfh.bfType != 0x4d42) { 48542506Syokota return(1); /* XXX check word ordering for big-endian ports? */ 48642506Syokota } 48742506Syokota 48842506Syokota /* save what we know about the screen */ 48942506Syokota bmp_info.swidth = swidth; 49042506Syokota bmp_info.sheight = sheight; 49142506Syokota bmp_info.sdepth = sdepth; 49242506Syokota 49342506Syokota /* where's the data? */ 49442506Syokota bmp_info.data = (u_char *)data + bmf->bmfh.bfOffBits; 49542506Syokota 49642506Syokota /* image parameters */ 49742506Syokota bmp_info.width = bmf->bmfi.bmiHeader.biWidth; 49842506Syokota bmp_info.height = bmf->bmfi.bmiHeader.biHeight; 49942506Syokota bmp_info.format = bmf->bmfi.bmiHeader.biCompression; 50042506Syokota 50142506Syokota switch(bmp_info.format) { /* check compression format */ 50242506Syokota case BI_RGB: 50342506Syokota case BI_RLE4: 50442506Syokota case BI_RLE8: 50542506Syokota break; 50642506Syokota default: 50742506Syokota return(1); /* unsupported compression format */ 50842506Syokota } 50942506Syokota 51042506Syokota /* palette details */ 51142506Syokota bmp_info.ncols = (bmf->bmfi.bmiHeader.biClrUsed); 51242506Syokota bzero(bmp_info.palette,sizeof(bmp_info.palette)); 51342506Syokota if (bmp_info.ncols == 0) { /* uses all of them */ 51442623Syokota bmp_info.ncols = 1 << bmf->bmfi.bmiHeader.biBitCount; 51542506Syokota } 51642506Syokota if ((bmp_info.height > bmp_info.sheight) || 51742506Syokota (bmp_info.width > bmp_info.swidth) || 51842506Syokota (bmp_info.ncols > (1 << sdepth))) { 51942506Syokota return(1); /* beyond screen capacity */ 52042506Syokota } 52142506Syokota 52242506Syokota /* read palette */ 52342506Syokota for (pind = 0; pind < bmp_info.ncols; pind++) { 52442506Syokota bmp_info.palette[pind][0] = bmf->bmfi.bmiColors[pind].rgbRed; 52542506Syokota bmp_info.palette[pind][1] = bmf->bmfi.bmiColors[pind].rgbGreen; 52642506Syokota bmp_info.palette[pind][2] = bmf->bmfi.bmiColors[pind].rgbBlue; 52742506Syokota } 52842506Syokota return(0); 52942506Syokota} 53042506Syokota 53142506Syokota/* 53242506Syokota** bmp_Draw 53342506Syokota** 53442506Syokota** Render the image. Return nonzero if that's not possible. 53542506Syokota** 53642506Syokota*/ 53742506Syokotastatic int 53842506Syokotabmp_Draw(video_adapter_t *adp) 53942506Syokota{ 54042506Syokota int line; 54142506Syokota 54242506Syokota if (bmp_info.data == NULL) { /* init failed, do nothing */ 54342506Syokota return(1); 54442506Syokota } 54542506Syokota 54642506Syokota /* clear the screen */ 54742506Syokota bmp_info.vidmem = (u_char *)adp->va_window; 54842998Syokota bmp_info.adp = adp; 54942506Syokota /* XXX; the following line is correct only for 8bpp modes */ 55042998Syokota fill(&bmp_info, 0, 0, bmp_info.swidth, bmp_info.sheight); 55142998Syokota (*vidsw[adp->va_index]->set_win_org)(adp, 0); 55242998Syokota bmp_info.bank = 0; 55342506Syokota 55442506Syokota /* initialise the info structure for drawing */ 55542506Syokota bmp_info.index = bmp_info.data; 55642506Syokota 55742506Syokota /* set the palette for our image */ 55842506Syokota (*vidsw[adp->va_index]->load_palette)(adp, (u_char *)&bmp_info.palette); 55942506Syokota 56042506Syokota for (line = 0; (line < bmp_info.height) && bmp_info.index; line++) { 56142506Syokota bmp_DecodeLine(&bmp_info, line); 56242506Syokota } 56342506Syokota return(0); 56442506Syokota} 565