Skip site navigation (1)Skip section navigation (2)
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>