Date: Wed, 07 Jan 1998 19:20:24 +1030 From: Mike Smith <mike@smith.net.au> To: hackers@FreeBSD.ORG Subject: Splashscreen stuff Message-ID: <199801070850.TAA01382@word.smith.net.au>
next in thread | raw e-mail | index | archive | help
This is a multipart MIME message. --==_Exmh_15534752400 Content-Type: text/plain; charset=us-ascii I have been veritably deluged with requests for this (at least by one respondent 8), so here are the gruesome details: - The 2.2 splashkit (now 11 months old) is available at ftp://ftp.gsoft.com.au/misc/2.2_splashkit.tar.gz It may also be on 2.2.x CDROMs in the 'experimental' area. YMMV with this code; I haven't tried it in a long time, and it is moderately ugly. - The 3.0 splashkit patches are attached. These are against a kernel of around 971209, but should apply to today's current fairly cleanly. If you have a moment to look these over, please do, as there are a few things of a moderately sensitive nature in here that could do with commentary (bootblock changes, locore changes, a new kernel internal interface, etc.) You will have to: - Build and install new bootblocks. Make sure that BOOT_SPLASH is defined. - Copy your 320x200x256 .BMP file to /splash - Build a new kernel with SC_SPLASH_SCREEN defined. The splash will be displayed by default when booting. It will not be displayed if the -v boot flag is supplied (although still loaded). Pressing PrtSc (next console) will discard the splash. There is a keymap entry which will toggle the splash back on, although it is not currently assigned to any key. The splash should also automagically disappear if you force a vty change, eg. by starting X. Note that while the kernel is loading, keypresses are *only* checked during text output; there is no way to detect a keypress while a device probe is in progress. --==_Exmh_15534752400 Content-Type: text/plain ; name="splashdiff"; charset=us-ascii Content-Description: splashdiff Content-Disposition: attachment; filename="splashdiff" ? boot/biosboot/.depend ? boot/biosboot/boot ? boot/biosboot/boot.strip ? boot/biosboot/boot.nohdr ? boot/biosboot/boot1 ? boot/biosboot/boot2 ? boot/biosboot/sizetest ? conf/WORD Index: boot/biosboot/Makefile =================================================================== RCS file: /local3/ncvs/src/sys/i386/boot/biosboot/Makefile,v retrieving revision 1.60 diff -u -r1.60 Makefile --- Makefile 1997/08/31 06:11:25 1.60 +++ Makefile 1998/01/07 08:44:26 @@ -12,8 +12,9 @@ -mno-486 \ -DBOOTWAIT=${BOOTWAIT} -DTIMEOUT=${TIMEOUT} CFLAGS+= -DBOOTSEG=${BOOTSEG} -DBOOTSTACK=${BOOTSTACK} -CFLAGS+= -DDO_BAD144 +#CFLAGS+= -DDO_BAD144 CFLAGS+= -DVESA_SUPPORT +CFLAGS+= -DBOOT_SPLASH CFLAGS+= -I${.CURDIR}/../../.. CFLAGS+= ${CWARNFLAGS} @@ -27,8 +28,8 @@ # Enable code to take the default boot string from a fixed location on the # disk. See nextboot(8) and README.386BSD for more info. -#CFLAGS+= -DNAMEBLOCK -#CFLAGS+= -DNAMEBLOCK_WRITEBACK +CFLAGS+= -DNAMEBLOCK +CFLAGS+= -DNAMEBLOCK_WRITEBACK # Bias the conversion from the BIOS drive number to the FreeBSD unit number # for hard disks. This may be useful for people booting in a mixed IDE/SCSI Index: boot/biosboot/boot.c =================================================================== RCS file: /local3/ncvs/src/sys/i386/boot/biosboot/boot.c,v retrieving revision 1.69 diff -u -r1.69 boot.c --- boot.c 1997/08/31 06:11:26 1.69 +++ boot.c 1998/01/07 08:44:27 @@ -55,7 +55,8 @@ #include "boot.h" #include <a.out.h> #include <sys/reboot.h> -#include <machine/bootinfo.h> +/*#include <machine/bootinfo.h>*/ +#include "../../include/bootinfo.h" /* XXX */ #define ouraddr (BOOTSEG << 4) /* XXX */ @@ -66,6 +67,11 @@ static char boot_config[BOOT_CONFIG_SIZE]; static char boot_help[BOOT_HELP_SIZE]; +#ifdef BOOT_SPLASH +#define BOOT_SPLASH_HEADER_SIZE 512 +static char boot_splash_header[BOOT_SPLASH_HEADER_SIZE]; +#endif +extern void *end; #ifdef NAMEBLOCK char *dflt_name; #endif @@ -80,6 +86,7 @@ static void getbootdev(char *ptr, int *howto); static void loadprog(void); static void readfile(char *path, char *buf, size_t nbytes); +static long int putextra(long int base, long int code, long int length); /* NORETURN */ void @@ -126,6 +133,9 @@ } readfile("boot.config", boot_config, BOOT_CONFIG_SIZE); readfile("boot.help", boot_help, BOOT_HELP_SIZE); +#ifdef BOOT_SPLASH + readfile("splash", boot_splash_header, BOOT_SPLASH_HEADER_SIZE); +#endif #ifdef NAMEBLOCK /* * XXX @@ -200,7 +210,12 @@ int i; unsigned pad; char *s, *t; - + long int extras_base; + struct bootinfo_extra be; +#ifdef BOOT_SPLASH + char *splash_base = 0; + long int splash_size; +#endif #ifdef VESA_SUPPORT if (bootinfo.bi_vesa) @@ -272,6 +287,25 @@ /* kzip & kernel will zero their own bss */ addr += head.a_bss; + bootinfo.bi_extras = addr; + +#ifdef BOOT_SPLASH + /********************************************************/ + /* If the splash is valid, reserve space for it. */ + /* For now, we are working with DIB (.BMP) images only. */ + /********************************************************/ + splash_size = *(long int *)(boot_splash_header + 2); + if ((*(short *)boot_splash_header == 0x4d42) && (splash_size < 65536)) { + splash_base = (char *)(addr + sizeof(struct bootinfo_extra)); + addr = putextra(addr, BI_EXTRA_SPLASH, splash_size); + } +#endif + + /* Terminate the extras area */ + addr = putextra(addr, BI_EXTRA_END, 0); + bootinfo.bi_extralen = addr - bootinfo.bi_extras; + printf("extra=0x%x ", bootinfo.bi_extralen); + /* Pad to a page boundary. */ pad = (unsigned)addr & PAGE_MASK; if (pad != 0) { @@ -305,7 +339,7 @@ /********************************************************/ /* Load the string table */ /********************************************************/ - printf("+0x%x+0x%x]\n", sizeof(int), i); + printf("+0x%x+0x%x]\n", sizeof(int), i); xread((void *)addr, i); addr += i; @@ -344,6 +378,16 @@ pcpy(kernel_config, (char *)&disklabel + ouraddr, KERNEL_CONFIG_SIZE); printf("total=0x%x entry point=0x%x\n", (int)addr, (int)startaddr); + +#ifdef BOOT_SPLASH + /* Now we can suck in the splash image */ + name = "splash"; + if (splash_base && !openrd()) { + printf("Reading %d bytes of splash image...", splash_size); + xread(splash_base, splash_size); + } +#endif + startprog((int)startaddr, loadflags | RB_BOOTINFO, bootdev, (int)&bootinfo + ouraddr); } @@ -364,6 +408,17 @@ read(buf, nbytes); } buf[nbytes - 1] = '\0'; +} + +static long int +putextra(long int base, long int code, long int length) +{ + struct bootinfo_extra be; + + be.extra_code = code; + be.extra_length = length; + pcpy(&be, (void *)base, sizeof(struct bootinfo_extra)); + return(base + length + sizeof(struct bootinfo_extra)); } static void Index: conf/options.i386 =================================================================== RCS file: /local3/ncvs/src/sys/i386/conf/options.i386,v retrieving revision 1.66 diff -u -r1.66 options.i386 --- options.i386 1997/12/28 13:36:00 1.66 +++ options.i386 1998/01/07 08:44:27 @@ -71,6 +71,7 @@ I686_CPU opt_global.h SC_SPLASH_SCREEN opt_syscons.h +SC_SPLASH_PATH opt_syscons.h MAXCONS opt_syscons.h SLOW_VGA opt_syscons.h STD8X16FONT opt_syscons.h Index: i386/genassym.c =================================================================== RCS file: /local3/ncvs/src/sys/i386/i386/genassym.c,v retrieving revision 1.50 diff -u -r1.50 genassym.c --- genassym.c 1997/10/10 12:38:27 1.50 +++ genassym.c 1998/01/07 08:44:27 @@ -188,6 +188,8 @@ printf("#define\tBI_SIZE %p\n", &bootinfo->bi_size); printf("#define\tBI_SYMTAB %p\n", &bootinfo->bi_symtab); printf("#define\tBI_ESYMTAB %p\n", &bootinfo->bi_esymtab); + printf("#define\tBI_EXTRAS %p\n", &bootinfo->bi_extras); + printf("#define\tBI_EXTRALEN %p\n", &bootinfo->bi_extralen); return (0); } Index: i386/locore.s =================================================================== RCS file: /local3/ncvs/src/sys/i386/i386/locore.s,v retrieving revision 1.102 diff -u -r1.102 locore.s --- locore.s 1997/11/07 19:58:32 1.102 +++ locore.s 1998/01/07 08:44:27 @@ -795,6 +795,12 @@ /* Find end of kernel image (rounded up to a page boundary). */ movl $R(_end),%esi +/* Account for after-kernel extras, if present. */ + movl R(_bootinfo+BI_EXTRALEN),%edi + addl %edi,%esi + movl $KERNBASE,%edi + addl %edi,R(_bootinfo+BI_EXTRAS) + /* include symbols in "kernel image" if they are loaded and useful */ #ifdef DDB movl R(_bootinfo+BI_ESYMTAB),%edi Index: i386/machdep.c =================================================================== RCS file: /local3/ncvs/src/sys/i386/i386/machdep.c,v retrieving revision 1.280 diff -u -r1.280 machdep.c --- machdep.c 1997/12/27 02:28:27 1.280 +++ machdep.c 1998/01/07 08:44:28 @@ -1805,3 +1805,28 @@ } #endif /* DDB */ + +/* + * Hunt through the extras region loaded by the bootstrap code for + * the nominated region type. + */ +void * +biextra_lookup(int code) +{ + struct bootinfo_extra *be; + char *exp; + + /* Are there any extras? */ + if ((bootinfo.bi_extras > 0) && (bootinfo.bi_extralen > 0)) { + + be = (struct bootinfo_extra *)bootinfo.bi_extras; + while (be->extra_code != BI_EXTRA_END) { + exp = (char *)be; + if (be->extra_code == code) { + return(exp + sizeof(struct bootinfo_extra)); + } + be = (struct bootinfo_extra*)(exp + be->extra_length + sizeof(struct bootinfo_extra)); + } + } + return(NULL); +} Index: include/bootinfo.h =================================================================== RCS file: /local3/ncvs/src/sys/i386/include/bootinfo.h,v retrieving revision 1.8 diff -u -r1.8 bootinfo.h --- bootinfo.h 1997/07/31 08:07:36 1.8 +++ bootinfo.h 1998/01/07 08:44:28 @@ -61,10 +61,22 @@ unsigned long bi_extmem; unsigned long bi_symtab; unsigned long bi_esymtab; + unsigned long bi_extras; + unsigned long bi_extralen; +}; + +struct bootinfo_extra +{ + long int extra_code; +#define BI_EXTRA_END 0 +#define BI_EXTRA_SPLASH 1 +#define BI_EXTRA_CONFIG 2 + long int extra_length; }; #ifdef KERNEL extern struct bootinfo bootinfo; +extern void *biextra_lookup(int code); #endif #endif /* !_MACHINE_BOOTINFO_H_ */ Index: isa/syscons.c =================================================================== RCS file: /local3/ncvs/src/sys/i386/isa/syscons.c,v retrieving revision 1.242 diff -u -r1.242 syscons.c --- syscons.c 1997/12/07 08:09:19 1.242 +++ syscons.c 1998/01/07 08:44:28 @@ -46,6 +46,7 @@ #include <sys/devfsext.h> #endif +#include <machine/bootinfo.h> #include <machine/clock.h> #include <machine/cons.h> #include <machine/console.h> @@ -270,6 +271,8 @@ static timeout_t blink_screen; #ifdef SC_SPLASH_SCREEN static void toggle_splash_screen(scr_stat *scp); +static int splash_show(scr_stat *scp); +static int splash_hide(scr_stat *scp); #endif struct isa_driver scdriver = { @@ -744,6 +747,10 @@ apm_hook_establish(APM_HOOK_RESUME , &scp->r_hook); #endif +#ifdef SC_SPLASH_SCREEN + scp->splash_up = 0; +#endif + cdevsw_add(&cdev, &scdevsw, NULL); #ifdef DEVFS @@ -2034,6 +2041,11 @@ scr_stat *scp = console[0]; term_stat save = scp->term; +#ifdef SC_SPLASH_SCREEN + /* Check for input in case the user is trying to toggle the splash */ + (void)sccncheckc(dev); +#endif + scp->term = kernel_console; current_default = &kernel_default; if (scp == cur_console && !(scp->status & UNKNOWN_MODE)) @@ -2280,6 +2292,11 @@ if (switch_in_progress && (cur_console->proc != pfind(cur_console->pid))) switch_in_progress = FALSE; +#ifdef SC_SPLASH_SCREEN + /* Take the splash down so we can switch away */ + splash_hide(scp); +#endif + if (next_scr >= MAXCONS || switch_in_progress || (cur_console->smode.mode == VT_AUTO && cur_console->status & UNKNOWN_MODE)) { @@ -3140,10 +3157,10 @@ #ifdef SC_SPLASH_SCREEN /* - * Now put up a graphics image, and maybe cycle a - * couble of palette entries for simple animation. + * If not booting verbosely, put up the splash. */ - toggle_splash_screen(cur_console); + if (!bootverbose) + splash_show(cur_console); #endif } @@ -3219,6 +3236,9 @@ */ clear_screen(scp); scp->cursor_saveunder = *scp->cursor_pos; +#ifdef SC_SPLASH_SCREEN + scp->splash_up = 0; +#endif return scp; } @@ -3625,9 +3645,6 @@ switch (action) { /* LOCKING KEYS */ case NLK: -#ifdef SC_SPLASH_SCREEN - toggle_splash_screen(cur_console); /* SOS XXX */ -#endif if (!nlkcnt) { nlkcnt++; if (cur_console->status & NLKED) @@ -3709,6 +3726,10 @@ case DBG: #ifdef DDB /* try to switch to console 0 */ +#ifdef SC_SPLASH_SCREEN + (void)splash_hide(cur_console); + (void)splash_hide(console[0]); +#endif if (cur_console->smode.mode == VT_AUTO && console[0]->smode.mode == VT_AUTO) switch_scr(cur_console, 0); @@ -3742,6 +3763,11 @@ metas = 1; break; case NEXT: +#ifdef SC_SPLASH_SCREEN + /* "next" cycles us off the splash */ + if (splash_hide(cur_console)) + break; +#endif { int next, this = get_scr_num(); for (next = this+1; next != this; next = (next+1)%MAXCONS) { @@ -4754,33 +4780,447 @@ } #ifdef SC_SPLASH_SCREEN + +static int bmp_Init(const char *data, int swidth, int sheight, int sdepth, u_char *vidmem); +static int bmp_Draw(void); +static int splash_up = 0; +static u_char splash_save_mode; + +#ifdef SC_SPLASH_PATH +# include SC_SPLASH_PATH +#endif + +static int +splash_show(scr_stat *scp) +{ + static int initted = 0, failed = 0; + int s = splhigh(); + u_char *splash_bitmap; + void *eptr; + struct bootinfo_extra *be; + + /* something has gone wrong before, don't try again */ + if (failed) + return(0); + +#ifdef SC_SPLASH_PATH + splash_bitmap = bmp; +#else + if ((splash_bitmap = biextra_lookup(BI_EXTRA_SPLASH)) == NULL) + return(0); +#endif + + if (!initted) { /* look at the image first time 'round */ + initted = 1; + if (bmp_Init(splash_bitmap, 320, 200, 8, (u_char *)pa_to_va(VIDEOMEM))) { + failed = 1; /* init failed */ + return(0); + } + } + + save_palette(); /* try to draw the image */ + scp->splash_save_mode = scp->mode; + scp->mode = M_VGA_CG320; /* XXX should detect image format */ + scp->status |= UNKNOWN_MODE; + scp->splash_up = 1; + set_mode(scp); + failed = bmp_Draw(); + splx(s); + + if (failed) { /* restore original screen */ + splash_hide(scp); + printf("Splash screen load failed!\n"); + return(0); + } + return(1); +} + +static int +splash_hide(scr_stat *scp) +{ + int s; + + if (scp->splash_up) { /* only do anything if splash is up */ + s = splhigh(); + load_palette(palette); + scp->mode = scp->splash_save_mode; + scp->status &= ~UNKNOWN_MODE; + scp->splash_up = 0; + set_mode(scp); + splx(s); + return(1); + } else { + return(0); + } +} + + static void toggle_splash_screen(scr_stat *scp) { - static int toggle = 0; - static u_char save_mode; - int s; + if (splash_up) { + (void)splash_hide(scp); + } else { + (void)splash_show(scp); + } +} + + +/* +** Code to handle Microsoft DIB (".BMP") format images. +** +** Blame me (msmith@freebsd.org) if this is broken, not Soren. +*/ + +typedef struct tagBITMAPFILEHEADER { /* bmfh */ + u_short bfType __attribute__ ((packed)); + int bfSize __attribute__ ((packed)); + u_short bfReserved1 __attribute__ ((packed)); + u_short bfReserved2 __attribute__ ((packed)); + int bfOffBits __attribute__ ((packed)); +} BITMAPFILEHEADER; + +typedef struct tagBITMAPINFOHEADER { /* bmih */ + int biSize __attribute__ ((packed)); + int biWidth __attribute__ ((packed)); + int biHeight __attribute__ ((packed)); + short biPlanes __attribute__ ((packed)); + short biBitCount __attribute__ ((packed)); + int biCompression __attribute__ ((packed)); + int biSizeImage __attribute__ ((packed)); + int biXPelsPerMeter __attribute__ ((packed)); + int biYPelsPerMeter __attribute__ ((packed)); + int biClrUsed __attribute__ ((packed)); + int biClrImportant __attribute__ ((packed)); +} BITMAPINFOHEADER; + +typedef struct tagRGBQUAD { /* rgbq */ + u_char rgbBlue __attribute__ ((packed)); + u_char rgbGreen __attribute__ ((packed)); + u_char rgbRed __attribute__ ((packed)); + u_char rgbReserved __attribute__ ((packed)); +} RGBQUAD; + +typedef struct tagBITMAPINFO { /* bmi */ + BITMAPINFOHEADER bmiHeader __attribute__ ((packed)); + RGBQUAD bmiColors[256] __attribute__ ((packed)); +} BITMAPINFO; + +typedef struct tagBITMAPF +{ + BITMAPFILEHEADER bmfh __attribute__ ((packed)); + BITMAPINFO bmfi __attribute__ ((packed)); +} BITMAPF; + +#define BI_RGB 0 +#define BI_RLE8 1 +#define BI_RLE4 2 + +/* +** all we actually care about the image +*/ +typedef struct +{ + int width,height; /* image dimensions */ + int swidth,sheight; /* screen dimensions for the current mode */ + u_char sdepth; /* screen depth (1, 4, 8 bpp) */ + int ncols; /* number of colours */ + u_char palette[256][3]; /* raw palette data */ + u_char format; /* one of the BI_* constants above */ + u_char *data; /* pointer to the raw data */ + u_char *index; /* running pointer to the data while drawing */ + u_char *vidmem; /* video memory allocated for drawing */ +} BMP_INFO; + +static BMP_INFO bmp_info; - if (video_mode_ptr == NULL) +/* +** bmp_SetPix +** +** Given (info), set the pixel at (x),(y) to (val) +** +*/ +static void +bmp_SetPix(BMP_INFO *info, int x, int y, u_char val) +{ + int sofs, bofs; + u_char tpv, mask; + int ppb = (8 / info->sdepth); /* pixels per byte */ + + /* + * range check to avoid explosions + */ + if ((x < 0) || (x >= info->swidth) || (y < 0) || (y >= info->sheight)) return; + + /* + * calculate offset into video memory; + * because 0,0 is bottom-left for DIB, we have to convert. + */ + sofs = ((info->height - (y+1)) * info->swidth) + x; - s = splhigh(); - if (toggle) { - scp->mode = save_mode; - scp->status &= ~UNKNOWN_MODE; - set_mode(scp); - load_palette(palette); - toggle = 0; + switch(info->sdepth) { + case 1: + sofs = sofs >> 3; /* correct for depth */ + bofs = x & 0x7; /* offset within byte */ + + val &= 1; /* mask pixel value */ + mask = ~(0x80 >> bofs); /* calculate bit mask */ + tpv = *(info->vidmem+sofs) & mask; /* get screen contents, excluding masked bit */ + *(info->vidmem+sofs) = tpv | (val << (8-bofs)); /* write new bit */ + break; + + /* XXX only correct for non-interleaved modes */ + case 4: + sofs = sofs >> 1; /* correct for depth */ + bofs = x & 0x1; /* offset within byte */ + + val &= 0xf; /* mask pixel value */ + mask = bofs ? 0x0f : 0xf0; /* calculate bit mask */ + tpv = *(info->vidmem+sofs) & mask; /* get screen contents, excluding masked bits */ + *(info->vidmem+sofs) = tpv | (val << (bofs ? 0 : 4)); /* write new bits */ + break; + + case 8: + *(info->vidmem+sofs) = val; + break; } - else { - save_mode = scp->mode; - scp->mode = M_VGA_CG320; - scp->status |= UNKNOWN_MODE; - set_mode(scp); - /* load image */ - toggle = 1; +} + +/* +** bmp_DecodeRLE4 +** +** Given (data) pointing to a line of RLE4-format data and (line) being the starting +** line onscreen, decode the line. +*/ +static void +bmp_DecodeRLE4(BMP_INFO *info, int line) +{ + int count; /* run count */ + u_char val; + int x,y; /* screen position */ + + x = 0; /* starting position */ + y = line; + + /* loop reading data */ + for (;;) { + /* + * encoded mode starts with a run length, and then a byte with + * two colour indexes to alternate between for the run + */ + if (*info->index) { + for (count = 0; count < *info->index; count++, x++) { + if (count & 1) { /* odd count, low nybble */ + bmp_SetPix(info, x, y, *(info->index+1) & 0x0f); + } else { /* even count, high nybble */ + bmp_SetPix(info, x, y, (*(info->index+1) >>4) & 0x0f); + } + } + info->index += 2; + /* + * A leading zero is an escape; it may signal the end of the + * bitmap, a cursor move, or some absolute data. + */ + } else { /* zero tag may be absolute mode or an escape */ + switch (*(info->index+1)) { + case 0: /* end of line */ + info->index += 2; + return; + case 1: /* end of bitmap */ + info->index = NULL; + return; + case 2: /* move */ + x += *(info->index + 2); /* new coords */ + y += *(info->index + 3); + info->index += 4; + break; + default: /* literal bitmap data */ + for (count = 0; count < *(info->index + 1); count++, x++) { + val = *(info->index + 2 + (count / 2)); /* byte with nybbles */ + if (count & 1) { + val &= 0xf; /* get low nybble */ + } else { + val = (val >> 4); /* get high nybble */ + } + bmp_SetPix(info, x, y, val); + } + /* warning, this depends on integer truncation, do not hand-optimise! */ + info->index += 2 + ((count + 3) / 4) * 2; + break; + } + } } - splx(s); } -#endif + +/* +** bmp_DecodeRLE8 +** Given (data) pointing to a line of RLE4-format data and (line) being the starting +** line onscreen, decode the line. +*/ +static void +bmp_DecodeRLE8(BMP_INFO *info, int line) +{ + int count; /* run count */ + int x,y; /* screen position */ + + x = 0; /* starting position */ + y = line; + + /* loop reading data */ + for(;;) { + /* + * encoded mode starts with a run length, and then a byte with + * two colour indexes to alternate between for the run + */ + if (*info->index) { + for (count = 0; count < *info->index; count++, x++) + bmp_SetPix(info, x, y, *(info->index+1)); + info->index += 2; + /* + * A leading zero is an escape; it may signal the end of the + * bitmap, a cursor move, or some absolute data. + */ + } else { /* zero tag may be absolute mode or an escape */ + switch(*(info->index+1)) { + case 0: /* end of line */ + info->index += 2; + return; + case 1: /* end of bitmap */ + info->index = NULL; + return; + case 2: /* move */ + x += *(info->index + 2); /* new coords */ + y += *(info->index + 3); + info->index += 4; + break; + default: /* literal bitmap data */ + for (count = 0; count < *(info->index + 1); count++, x++) + bmp_SetPix(info, x, y, *(info->index + 2 + count)); + /* must be an even count */ + info->index += 2 + count + (count & 1); + break; + } + } + } +} + +/* +** bmp_DecodeLine +** +** Given (info) pointing to an image being decoded, (line) being the line currently +** being displayed, decode a line of data. +*/ +static void +bmp_DecodeLine(BMP_INFO *info, int line) +{ + int x; + + switch(info->format) { + case BI_RGB: + for (x = 0; x < info->width; x++, info->index++) + bmp_SetPix(info, x, line, *info->index); + break; + case BI_RLE4: + bmp_DecodeRLE4(info, line); + break; + case BI_RLE8: + bmp_DecodeRLE8(info, line); + break; + } +} + +/* +** bmp_Init +** +** Given a pointer (data) to the image of a BMP file, fill in bmp_info with what +** can be learnt from it. Return nonzero if the file isn't usable. +** +** Take screen dimensions (swidth), (sheight) and (sdepth) and make sure we +** can work with these. Remember that the video memory is at (vidmem) +*/ +static int +bmp_Init(const char *data, int swidth, int sheight, int sdepth, u_char *vidmem) +{ + BITMAPF *bmf = (BITMAPF *)data; + int pind; + + bmp_info.data = NULL; /* assume setup failed */ + bmp_info.vidmem = vidmem; /* remember where */ + + /* check file ID */ + if (bmf->bmfh.bfType != 0x4d42) { + return(1); /* XXX check word ordering for big-endian ports? */ + } + + /* save what we know about the screen */ + bmp_info.swidth = swidth; + bmp_info.sheight = sheight; + bmp_info.sdepth = sdepth; + + /* where's the data? */ + bmp_info.data = (u_char *)data + bmf->bmfh.bfOffBits; + + /* image parameters */ + bmp_info.width = bmf->bmfi.bmiHeader.biWidth; + bmp_info.height = bmf->bmfi.bmiHeader.biHeight; + bmp_info.format = bmf->bmfi.bmiHeader.biCompression; + + switch(bmp_info.format) { /* check compression format */ + case BI_RGB: + case BI_RLE4: + case BI_RLE8: + break; + default: + return(1); /* unsupported compression format */ + } + + /* palette details */ + bmp_info.ncols = (bmf->bmfi.bmiHeader.biClrUsed); + bzero(bmp_info.palette,sizeof(bmp_info.palette)); + if (bmp_info.ncols == 0) { /* uses all of them */ + bmp_info.ncols = 2 << bmf->bmfi.bmiHeader.biBitCount; + } + if ((bmp_info.height > bmp_info.sheight) || + (bmp_info.width > bmp_info.swidth) || + (bmp_info.ncols > (1 << sdepth))) { + return(1); /* beyond screen capacity */ + } + + /* read palette */ + for (pind = 0; pind < bmp_info.ncols; pind++) { + bmp_info.palette[pind][0] = (bmf->bmfi.bmiColors[pind].rgbRed >>2); + bmp_info.palette[pind][1] = (bmf->bmfi.bmiColors[pind].rgbGreen >>2); + bmp_info.palette[pind][2] = (bmf->bmfi.bmiColors[pind].rgbBlue >>2); + } + return(0); +} + +/* +** bmp_Draw +** +** Render the image. Return nonzero if that's not possible. +** +*/ +static int +bmp_Draw(void) +{ + int line, i; + + if (bmp_info.data == NULL) { /* init failed, do nothing */ + return(1); + } + + /* initialise the info structure for drawing */ + bmp_info.index = bmp_info.data; + + /* set the palette for our image */ + load_palette((u_char *)&bmp_info.palette); + + for (line = 0; (line < bmp_info.height) && bmp_info.index; line++) { + bmp_DecodeLine(&bmp_info, line); + } + return(0); +} +#endif /* SC_SPLASH_SCREEN */ #endif /* NSC */ Index: isa/syscons.h =================================================================== RCS file: /local3/ncvs/src/sys/i386/isa/syscons.h,v retrieving revision 1.36 diff -u -r1.36 syscons.h --- syscons.h 1997/11/21 11:37:07 1.36 +++ syscons.h 1998/01/07 08:44:29 @@ -184,6 +184,10 @@ u_short *history_save; /* save area index */ int history_size; /* size of history buffer */ struct apmhook r_hook; /* reconfiguration support */ +#ifdef SC_SPLASH_SCREEN + int splash_up; /* splash screen on this console */ + u_char splash_save_mode; /* saved mode for splash screen */ +#endif } scr_stat; typedef struct default_attr { --==_Exmh_15534752400 Content-Type: text/plain; charset=us-ascii \\ Sometimes you're ahead, \\ Mike Smith \\ sometimes you're behind. \\ mike@smith.net.au \\ The race is long, and in the \\ msmith@freebsd.org \\ end it's only with yourself. \\ --==_Exmh_15534752400--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199801070850.TAA01382>