17c478bd9Sstevel@tonic-gate /* graphics.c - graphics mode support for GRUB */
27c478bd9Sstevel@tonic-gate /* Implemented as a terminal type by Jeremy Katz <katzj@redhat.com> based
37c478bd9Sstevel@tonic-gate  * on a patch by Paulo C�sar Pereira de Andrade <pcpa@conectiva.com.br>
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate /*
67c478bd9Sstevel@tonic-gate  *  GRUB  --  GRand Unified Bootloader
77c478bd9Sstevel@tonic-gate  *  Copyright (C) 2001,2002  Red Hat, Inc.
87c478bd9Sstevel@tonic-gate  *  Portions copyright (C) 2000  Conectiva, Inc.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  *  This program is free software; you can redistribute it and/or modify
117c478bd9Sstevel@tonic-gate  *  it under the terms of the GNU General Public License as published by
127c478bd9Sstevel@tonic-gate  *  the Free Software Foundation; either version 2 of the License, or
137c478bd9Sstevel@tonic-gate  *  (at your option) any later version.
147c478bd9Sstevel@tonic-gate  *
157c478bd9Sstevel@tonic-gate  *  This program is distributed in the hope that it will be useful,
167c478bd9Sstevel@tonic-gate  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
177c478bd9Sstevel@tonic-gate  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
187c478bd9Sstevel@tonic-gate  *  GNU General Public License for more details.
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  *  You should have received a copy of the GNU General Public License
217c478bd9Sstevel@tonic-gate  *  along with this program; if not, write to the Free Software
227c478bd9Sstevel@tonic-gate  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate 
26a6e28364SSuhasini Peddada 
277c478bd9Sstevel@tonic-gate #ifdef SUPPORT_GRAPHICS
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <term.h>
307c478bd9Sstevel@tonic-gate #include <shared.h>
317c478bd9Sstevel@tonic-gate #include <graphics.h>
327c478bd9Sstevel@tonic-gate 
33*3d393ee6SWilliam Kucharski #ifdef	OVERLAY_LOGO
341b8adde7SWilliam Kucharski #include <logo.xbm>
35*3d393ee6SWilliam Kucharski #endif	/* OVERLAY_LOGO */
361b8adde7SWilliam Kucharski 
377c478bd9Sstevel@tonic-gate int saved_videomode;
387c478bd9Sstevel@tonic-gate unsigned char *font8x16;
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate int graphics_inited = 0;
419b4e3ac2SWilliam Kucharski 
429b4e3ac2SWilliam Kucharski #define	PALETTE_REDSHIFT	16
439b4e3ac2SWilliam Kucharski #define	PALETTE_GREENSHIFT	8
449b4e3ac2SWilliam Kucharski #define	PALETTE_COLORMASK	63
459b4e3ac2SWilliam Kucharski 
469b4e3ac2SWilliam Kucharski #define	PALETTE_NCOLORS		16
479b4e3ac2SWilliam Kucharski 
489b4e3ac2SWilliam Kucharski #define	PALETTE_RED(entry)	((entry) >> PALETTE_REDSHIFT)
499b4e3ac2SWilliam Kucharski #define	PALETTE_GREEN(entry)	(((entry) >> PALETTE_GREENSHIFT) & \
509b4e3ac2SWilliam Kucharski 				    PALETTE_COLORMASK)
519b4e3ac2SWilliam Kucharski #define	PALETTE_BLUE(entry)	((entry) & PALETTE_COLORMASK)
529b4e3ac2SWilliam Kucharski 
537c478bd9Sstevel@tonic-gate static char splashimage[64];
549b4e3ac2SWilliam Kucharski static int splash_palette[PALETTE_NCOLORS];
557c478bd9Sstevel@tonic-gate 
561b8adde7SWilliam Kucharski #define	HPIXELS		640
571b8adde7SWilliam Kucharski #define	VPIXELS		480
581b8adde7SWilliam Kucharski #define	HPIXELSPERBYTE	8
591b8adde7SWilliam Kucharski 
601b8adde7SWilliam Kucharski #define	ROWBYTES	(HPIXELS / HPIXELSPERBYTE)
611b8adde7SWilliam Kucharski #define	SCREENBYTES	(ROWBYTES * VPIXELS)
621b8adde7SWilliam Kucharski 
637c478bd9Sstevel@tonic-gate #define VSHADOW VSHADOW1
641b8adde7SWilliam Kucharski unsigned char VSHADOW1[SCREENBYTES];
651b8adde7SWilliam Kucharski unsigned char VSHADOW2[SCREENBYTES];
661b8adde7SWilliam Kucharski unsigned char VSHADOW4[SCREENBYTES];
671b8adde7SWilliam Kucharski unsigned char VSHADOW8[SCREENBYTES];
681b8adde7SWilliam Kucharski 
691b8adde7SWilliam Kucharski static unsigned char *s1 = (unsigned char*)VSHADOW1;
701b8adde7SWilliam Kucharski static unsigned char *s2 = (unsigned char*)VSHADOW2;
711b8adde7SWilliam Kucharski static unsigned char *s4 = (unsigned char*)VSHADOW4;
721b8adde7SWilliam Kucharski static unsigned char *s8 = (unsigned char*)VSHADOW8;
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /* constants to define the viewable area */
757c478bd9Sstevel@tonic-gate const int x0 = 0;
761b8adde7SWilliam Kucharski const int x1 = ROWBYTES;
777c478bd9Sstevel@tonic-gate const int y0 = 0;
787c478bd9Sstevel@tonic-gate const int y1 = 30;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /* text buffer has to be kept around so that we can write things as we
817c478bd9Sstevel@tonic-gate  * scroll and the like */
821b8adde7SWilliam Kucharski unsigned short text[ROWBYTES * 30];
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /* why do these have to be kept here? */
85a6e28364SSuhasini Peddada int foreground = (63 << 16) | (63 << 8) | (63), background = 0, border = 0;
867c478bd9Sstevel@tonic-gate 
871b8adde7SWilliam Kucharski 
887c478bd9Sstevel@tonic-gate /* current position */
897c478bd9Sstevel@tonic-gate static int fontx = 0;
907c478bd9Sstevel@tonic-gate static int fonty = 0;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /* global state so that we don't try to recursively scroll or cursor */
937c478bd9Sstevel@tonic-gate static int no_scroll = 0;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /* color state */
967c478bd9Sstevel@tonic-gate static int graphics_standard_color = A_NORMAL;
977c478bd9Sstevel@tonic-gate static int graphics_normal_color = A_NORMAL;
987c478bd9Sstevel@tonic-gate static int graphics_highlight_color = A_REVERSE;
997c478bd9Sstevel@tonic-gate static int graphics_current_color = A_NORMAL;
1007c478bd9Sstevel@tonic-gate static color_state graphics_color_state = COLOR_STATE_STANDARD;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /* graphics local functions */
1047c478bd9Sstevel@tonic-gate static void graphics_setxy(int col, int row);
1059b4e3ac2SWilliam Kucharski static void graphics_scroll(void);
1069b4e3ac2SWilliam Kucharski static int read_image(char *);
1077c478bd9Sstevel@tonic-gate 
108*3d393ee6SWilliam Kucharski #ifdef	OVERLAY_LOGO
109*3d393ee6SWilliam Kucharski static void draw_xbmlogo(void);
110*3d393ee6SWilliam Kucharski #endif	/* OVERLAY_LOGO */
111*3d393ee6SWilliam Kucharski 
1127c478bd9Sstevel@tonic-gate /* FIXME: where do these really belong? */
outb(unsigned short port,unsigned char val)1137c478bd9Sstevel@tonic-gate static inline void outb(unsigned short port, unsigned char val)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate     __asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
MapMask(int value)1187c478bd9Sstevel@tonic-gate static void MapMask(int value) {
1197c478bd9Sstevel@tonic-gate     outb(0x3c4, 2);
1207c478bd9Sstevel@tonic-gate     outb(0x3c5, value);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate /* bit mask register */
BitMask(int value)1247c478bd9Sstevel@tonic-gate static void BitMask(int value) {
1257c478bd9Sstevel@tonic-gate     outb(0x3ce, 8);
1267c478bd9Sstevel@tonic-gate     outb(0x3cf, value);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate 
129a6e28364SSuhasini Peddada 
1307c478bd9Sstevel@tonic-gate /* Set the splash image */
graphics_set_splash(char * splashfile)131a6e28364SSuhasini Peddada void graphics_set_splash(char *splashfile) {
1327c478bd9Sstevel@tonic-gate     grub_strcpy(splashimage, splashfile);
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate /* Get the current splash image */
graphics_get_splash(void)1367c478bd9Sstevel@tonic-gate char *graphics_get_splash(void) {
1377c478bd9Sstevel@tonic-gate     return splashimage;
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate /* Initialize a vga16 graphics display with the palette based off of
1417c478bd9Sstevel@tonic-gate  * the image in splashimage.  If the image doesn't exist, leave graphics
1427c478bd9Sstevel@tonic-gate  * mode.  */
graphics_init()143a6e28364SSuhasini Peddada int graphics_init()
1447c478bd9Sstevel@tonic-gate {
1459b4e3ac2SWilliam Kucharski     int image_read, index, color;
1469b4e3ac2SWilliam Kucharski 
1477c478bd9Sstevel@tonic-gate     if (!graphics_inited) {
1487c478bd9Sstevel@tonic-gate         saved_videomode = set_videomode(0x12);
1497c478bd9Sstevel@tonic-gate     }
1507c478bd9Sstevel@tonic-gate 
1519b4e3ac2SWilliam Kucharski     font8x16 = (unsigned char*)graphics_get_font();
1529b4e3ac2SWilliam Kucharski 
1539b4e3ac2SWilliam Kucharski     image_read = read_image(splashimage);
1549b4e3ac2SWilliam Kucharski 
155a6e28364SSuhasini Peddada     /*
1569b4e3ac2SWilliam Kucharski      * Set VGA palette color 0 to be the system background color, 15 to be the
1579b4e3ac2SWilliam Kucharski      * system foreground color, and 17 to be the system border color.
1589b4e3ac2SWilliam Kucharski      *
1599b4e3ac2SWilliam Kucharski      * If the splashimage was read successfully, program the palette with
1609b4e3ac2SWilliam Kucharski      * its new colors; if not, set them to the background color.
161a6e28364SSuhasini Peddada      */
1629b4e3ac2SWilliam Kucharski 
1639b4e3ac2SWilliam Kucharski     graphics_set_palette(0, PALETTE_RED(background), PALETTE_GREEN(background),
1649b4e3ac2SWilliam Kucharski 	PALETTE_BLUE(background));
1659b4e3ac2SWilliam Kucharski 
1669b4e3ac2SWilliam Kucharski     for (index = 1; index < 15; index++) {
1679b4e3ac2SWilliam Kucharski 	color = (image_read ? splash_palette[index] : background);
1689b4e3ac2SWilliam Kucharski 	graphics_set_palette(index, PALETTE_RED(color),
1699b4e3ac2SWilliam Kucharski 	    PALETTE_GREEN(color), PALETTE_BLUE(color));
170a6e28364SSuhasini Peddada     }
171a6e28364SSuhasini Peddada 
1729b4e3ac2SWilliam Kucharski     graphics_set_palette(15, PALETTE_RED(foreground),
1739b4e3ac2SWilliam Kucharski 	 PALETTE_GREEN(foreground), PALETTE_BLUE(foreground));
1749b4e3ac2SWilliam Kucharski 
1759b4e3ac2SWilliam Kucharski     graphics_set_palette(0x11, PALETTE_RED(border), PALETTE_GREEN(border),
1769b4e3ac2SWilliam Kucharski 	PALETTE_BLUE(border));
1779b4e3ac2SWilliam Kucharski 
178*3d393ee6SWilliam Kucharski #ifdef	OVERLAY_LOGO
1799b4e3ac2SWilliam Kucharski     draw_xbmlogo();
180*3d393ee6SWilliam Kucharski #endif	/* OVERLAY_LOGO */
1817c478bd9Sstevel@tonic-gate 
182a6e28364SSuhasini Peddada     graphics_inited = 1;
183a6e28364SSuhasini Peddada 
1847c478bd9Sstevel@tonic-gate     /* make sure that the highlight color is set correctly */
1857c478bd9Sstevel@tonic-gate     graphics_highlight_color = ((graphics_normal_color >> 4) |
1867c478bd9Sstevel@tonic-gate 				((graphics_normal_color & 0xf) << 4));
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate     return 1;
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate /* Leave graphics mode */
graphics_end(void)1927c478bd9Sstevel@tonic-gate void graphics_end(void)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate     if (graphics_inited) {
1957c478bd9Sstevel@tonic-gate         set_videomode(saved_videomode);
1967c478bd9Sstevel@tonic-gate         graphics_inited = 0;
1977c478bd9Sstevel@tonic-gate     }
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate /* Print ch on the screen.  Handle any needed scrolling or the like */
graphics_putchar(int ch)2017c478bd9Sstevel@tonic-gate void graphics_putchar(int ch) {
2027c478bd9Sstevel@tonic-gate     ch &= 0xff;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate     graphics_cursor(0);
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate     if (ch == '\n') {
2077c478bd9Sstevel@tonic-gate         if (fonty + 1 < y1)
2087c478bd9Sstevel@tonic-gate             graphics_setxy(fontx, fonty + 1);
2097c478bd9Sstevel@tonic-gate         else
2107c478bd9Sstevel@tonic-gate             graphics_scroll();
2117c478bd9Sstevel@tonic-gate         graphics_cursor(1);
2127c478bd9Sstevel@tonic-gate         return;
2137c478bd9Sstevel@tonic-gate     } else if (ch == '\r') {
2147c478bd9Sstevel@tonic-gate         graphics_setxy(x0, fonty);
2157c478bd9Sstevel@tonic-gate         graphics_cursor(1);
2167c478bd9Sstevel@tonic-gate         return;
2177c478bd9Sstevel@tonic-gate     }
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate     graphics_cursor(0);
2207c478bd9Sstevel@tonic-gate 
2211b8adde7SWilliam Kucharski     text[fonty * ROWBYTES + fontx] = ch;
2221b8adde7SWilliam Kucharski     text[fonty * ROWBYTES + fontx] &= 0x00ff;
2237c478bd9Sstevel@tonic-gate     if (graphics_current_color & 0xf0)
2241b8adde7SWilliam Kucharski         text[fonty * ROWBYTES + fontx] |= 0x100;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate     graphics_cursor(0);
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate     if ((fontx + 1) >= x1) {
2297c478bd9Sstevel@tonic-gate         graphics_setxy(x0, fonty);
2307c478bd9Sstevel@tonic-gate         if (fonty + 1 < y1)
2317c478bd9Sstevel@tonic-gate             graphics_setxy(x0, fonty + 1);
2327c478bd9Sstevel@tonic-gate         else
2337c478bd9Sstevel@tonic-gate             graphics_scroll();
2347c478bd9Sstevel@tonic-gate     } else {
2357c478bd9Sstevel@tonic-gate         graphics_setxy(fontx + 1, fonty);
2367c478bd9Sstevel@tonic-gate     }
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate     graphics_cursor(1);
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate /* get the current location of the cursor */
graphics_getxy(void)2427c478bd9Sstevel@tonic-gate int graphics_getxy(void) {
2437c478bd9Sstevel@tonic-gate     return (fontx << 8) | fonty;
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate 
graphics_gotoxy(int x,int y)2467c478bd9Sstevel@tonic-gate void graphics_gotoxy(int x, int y) {
2477c478bd9Sstevel@tonic-gate     graphics_cursor(0);
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate     graphics_setxy(x, y);
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate     graphics_cursor(1);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate 
graphics_cls(void)2547c478bd9Sstevel@tonic-gate void graphics_cls(void) {
2557c478bd9Sstevel@tonic-gate     int i;
2561b8adde7SWilliam Kucharski     unsigned char *mem;
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate     graphics_cursor(0);
2597c478bd9Sstevel@tonic-gate     graphics_gotoxy(x0, y0);
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate     mem = (unsigned char*)VIDEOMEM;
2627c478bd9Sstevel@tonic-gate 
2631b8adde7SWilliam Kucharski     for (i = 0; i < ROWBYTES * 30; i++)
2647c478bd9Sstevel@tonic-gate         text[i] = ' ';
2657c478bd9Sstevel@tonic-gate     graphics_cursor(1);
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate     BitMask(0xff);
2687c478bd9Sstevel@tonic-gate 
2691b8adde7SWilliam Kucharski     /* plane 1 */
2707c478bd9Sstevel@tonic-gate     MapMask(1);
2711b8adde7SWilliam Kucharski     grub_memcpy(mem, s1, SCREENBYTES);
2727c478bd9Sstevel@tonic-gate 
2731b8adde7SWilliam Kucharski     /* plane 2 */
2747c478bd9Sstevel@tonic-gate     MapMask(2);
2751b8adde7SWilliam Kucharski     grub_memcpy(mem, s2, SCREENBYTES);
2767c478bd9Sstevel@tonic-gate 
2771b8adde7SWilliam Kucharski     /* plane 3 */
2787c478bd9Sstevel@tonic-gate     MapMask(4);
2791b8adde7SWilliam Kucharski     grub_memcpy(mem, s4, SCREENBYTES);
2807c478bd9Sstevel@tonic-gate 
2811b8adde7SWilliam Kucharski     /* plane 4 */
2827c478bd9Sstevel@tonic-gate     MapMask(8);
2831b8adde7SWilliam Kucharski     grub_memcpy(mem, s8, SCREENBYTES);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate     MapMask(15);
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate 
graphics_setcolorstate(color_state state)2887c478bd9Sstevel@tonic-gate void graphics_setcolorstate (color_state state) {
2897c478bd9Sstevel@tonic-gate     switch (state) {
2907c478bd9Sstevel@tonic-gate     case COLOR_STATE_STANDARD:
2917c478bd9Sstevel@tonic-gate         graphics_current_color = graphics_standard_color;
2927c478bd9Sstevel@tonic-gate         break;
2937c478bd9Sstevel@tonic-gate     case COLOR_STATE_NORMAL:
2947c478bd9Sstevel@tonic-gate         graphics_current_color = graphics_normal_color;
2957c478bd9Sstevel@tonic-gate         break;
2967c478bd9Sstevel@tonic-gate     case COLOR_STATE_HIGHLIGHT:
2977c478bd9Sstevel@tonic-gate         graphics_current_color = graphics_highlight_color;
2987c478bd9Sstevel@tonic-gate         break;
2997c478bd9Sstevel@tonic-gate     default:
3007c478bd9Sstevel@tonic-gate         graphics_current_color = graphics_standard_color;
3017c478bd9Sstevel@tonic-gate         break;
3027c478bd9Sstevel@tonic-gate     }
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate     graphics_color_state = state;
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate 
graphics_setcolor(int normal_color,int highlight_color)3077c478bd9Sstevel@tonic-gate void graphics_setcolor (int normal_color, int highlight_color) {
3087c478bd9Sstevel@tonic-gate     graphics_normal_color = normal_color;
3097c478bd9Sstevel@tonic-gate     graphics_highlight_color = highlight_color;
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate     graphics_setcolorstate (graphics_color_state);
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate 
graphics_setcursor(int on)3147c478bd9Sstevel@tonic-gate int graphics_setcursor (int on) {
3157c478bd9Sstevel@tonic-gate     /* FIXME: we don't have a cursor in graphics */
3167c478bd9Sstevel@tonic-gate     return 1;
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate 
319*3d393ee6SWilliam Kucharski #ifdef	OVERLAY_LOGO
draw_xbmlogo(void)3209b4e3ac2SWilliam Kucharski static void draw_xbmlogo(void)
3211b8adde7SWilliam Kucharski {
3221b8adde7SWilliam Kucharski     unsigned char mask;
3231b8adde7SWilliam Kucharski     unsigned xbm_index = 0, xbm_incr;
3241b8adde7SWilliam Kucharski     unsigned screenx, logox, logoy, fb_offset, fb_index;
3251b8adde7SWilliam Kucharski 
3261b8adde7SWilliam Kucharski     /*
3271b8adde7SWilliam Kucharski      * Place the logo such that the right hand side will be four pixels from
3281b8adde7SWilliam Kucharski      * the right hand edge of the screen and the bottom will be two pixels
3291b8adde7SWilliam Kucharski      * from the bottom edge.
3301b8adde7SWilliam Kucharski      */
3311b8adde7SWilliam Kucharski     fb_offset = ((VPIXELS - 1) - logo_height - 2) * ROWBYTES;
3321b8adde7SWilliam Kucharski     xbm_incr = (logo_width / 8) + 1;
3331b8adde7SWilliam Kucharski 
3341b8adde7SWilliam Kucharski     for (logoy = 0; logoy < logo_height; logoy++) {
3351b8adde7SWilliam Kucharski 	for (logox = 0, screenx = (HPIXELS - 1) - logo_width - 4;
3361b8adde7SWilliam Kucharski 	  logox < logo_width; logox++, screenx++) {
3371b8adde7SWilliam Kucharski 	    mask = 0x80 >> (screenx & 7);
3381b8adde7SWilliam Kucharski 	    fb_index = fb_offset + (screenx >> 3);
3391b8adde7SWilliam Kucharski 
3401b8adde7SWilliam Kucharski 	    /*
3411b8adde7SWilliam Kucharski 	     * If a bit is clear in the bitmap, draw it onto the
3421b8adde7SWilliam Kucharski 	     * framebuffer in the default foreground color.
3431b8adde7SWilliam Kucharski 	     */
3441b8adde7SWilliam Kucharski 	    if ((logo_bits[xbm_index + (logox >> 3)] &
3451b8adde7SWilliam Kucharski 		(1 << (logox & 7))) == 0) {
3461b8adde7SWilliam Kucharski 		    /* system default foreground color */
3471b8adde7SWilliam Kucharski 		    s1[fb_index] |= mask;
3481b8adde7SWilliam Kucharski 		    s2[fb_index] |= mask;
3491b8adde7SWilliam Kucharski 		    s4[fb_index] |= mask;
3501b8adde7SWilliam Kucharski 		    s8[fb_index] |= mask;
3511b8adde7SWilliam Kucharski 	    }
3521b8adde7SWilliam Kucharski 	}
3531b8adde7SWilliam Kucharski 
3541b8adde7SWilliam Kucharski 	xbm_index += xbm_incr;
3551b8adde7SWilliam Kucharski 	fb_offset += ROWBYTES;
3561b8adde7SWilliam Kucharski     }
3571b8adde7SWilliam Kucharski }
358*3d393ee6SWilliam Kucharski #endif	/* OVERLAY_LOGO */
3591b8adde7SWilliam Kucharski 
3601b8adde7SWilliam Kucharski /*
3611b8adde7SWilliam Kucharski  * Read in the splashscreen image and set the palette up appropriately.
3621b8adde7SWilliam Kucharski  *
3631b8adde7SWilliam Kucharski  * Format of splashscreen is an XPM (can be gzipped) with up to 15 colors and
3641b8adde7SWilliam Kucharski  * is assumed to be of the proper screen dimensions.
3651b8adde7SWilliam Kucharski  */
read_image(char * s)3669b4e3ac2SWilliam Kucharski static int read_image(char *s)
3677c478bd9Sstevel@tonic-gate {
368a6e28364SSuhasini Peddada     char buf[32], pal[16];
3691b8adde7SWilliam Kucharski     unsigned char c, base, mask;
3707c478bd9Sstevel@tonic-gate     unsigned i, len, idx, colors, x, y, width, height;
3717c478bd9Sstevel@tonic-gate 
372a6e28364SSuhasini Peddada     if (!grub_open(s))
3737c478bd9Sstevel@tonic-gate         return 0;
3747c478bd9Sstevel@tonic-gate 
375a6e28364SSuhasini Peddada     /* read XPM header - must match memcmp string PRECISELY. */
3767c478bd9Sstevel@tonic-gate     if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) {
3779b4e3ac2SWilliam Kucharski 	errnum = ERR_NOTXPM;
3787c478bd9Sstevel@tonic-gate         grub_close();
3797c478bd9Sstevel@tonic-gate         return 0;
3807c478bd9Sstevel@tonic-gate     }
3817c478bd9Sstevel@tonic-gate 
3821b8adde7SWilliam Kucharski     /* skip characters until we reach an initial '"' */
3837c478bd9Sstevel@tonic-gate     while (grub_read(&c, 1)) {
3847c478bd9Sstevel@tonic-gate         if (c == '"')
3857c478bd9Sstevel@tonic-gate             break;
3867c478bd9Sstevel@tonic-gate     }
3877c478bd9Sstevel@tonic-gate 
3881b8adde7SWilliam Kucharski     /* skip whitespace */
3897c478bd9Sstevel@tonic-gate     while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
3901b8adde7SWilliam Kucharski 	;
3917c478bd9Sstevel@tonic-gate 
3921b8adde7SWilliam Kucharski     /*
3931b8adde7SWilliam Kucharski      * Format here should be four integers:
3941b8adde7SWilliam Kucharski      *
3951b8adde7SWilliam Kucharski      *     Width Height NumberOfColors CharactersPerPixel
3961b8adde7SWilliam Kucharski      */
3977c478bd9Sstevel@tonic-gate     i = 0;
3987c478bd9Sstevel@tonic-gate     width = c - '0';
3997c478bd9Sstevel@tonic-gate     while (grub_read(&c, 1)) {
4007c478bd9Sstevel@tonic-gate         if (c >= '0' && c <= '9')
4017c478bd9Sstevel@tonic-gate             width = width * 10 + c - '0';
4027c478bd9Sstevel@tonic-gate         else
4037c478bd9Sstevel@tonic-gate             break;
4047c478bd9Sstevel@tonic-gate     }
4051b8adde7SWilliam Kucharski 
4061b8adde7SWilliam Kucharski     /* skip whitespace to advance to next digit */
4077c478bd9Sstevel@tonic-gate     while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
4081b8adde7SWilliam Kucharski 	;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate     height = c - '0';
4117c478bd9Sstevel@tonic-gate     while (grub_read(&c, 1)) {
4127c478bd9Sstevel@tonic-gate         if (c >= '0' && c <= '9')
4137c478bd9Sstevel@tonic-gate             height = height * 10 + c - '0';
4147c478bd9Sstevel@tonic-gate         else
4157c478bd9Sstevel@tonic-gate             break;
4167c478bd9Sstevel@tonic-gate     }
4171b8adde7SWilliam Kucharski 
4181b8adde7SWilliam Kucharski     /* skip whitespace to advance to next digit */
4191b8adde7SWilliam Kucharski     while (grub_read(&c, 1) && (c == ' ' || c == '\t')) ;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate     colors = c - '0';
4227c478bd9Sstevel@tonic-gate     while (grub_read(&c, 1)) {
4237c478bd9Sstevel@tonic-gate         if (c >= '0' && c <= '9')
4247c478bd9Sstevel@tonic-gate             colors = colors * 10 + c - '0';
4257c478bd9Sstevel@tonic-gate         else
4267c478bd9Sstevel@tonic-gate             break;
4277c478bd9Sstevel@tonic-gate     }
4287c478bd9Sstevel@tonic-gate 
4291b8adde7SWilliam Kucharski     /* eat rest of line - assumes chars per pixel is one */
4307c478bd9Sstevel@tonic-gate     while (grub_read(&c, 1) && c != '"')
4317c478bd9Sstevel@tonic-gate         ;
4327c478bd9Sstevel@tonic-gate 
4331b8adde7SWilliam Kucharski     /*
4341b8adde7SWilliam Kucharski      * Parse the XPM palette - the format is:
4351b8adde7SWilliam Kucharski      *
4361b8adde7SWilliam Kucharski      *    identifier colorspace #RRGGBB
4371b8adde7SWilliam Kucharski      *
4381b8adde7SWilliam Kucharski      * The identifier is simply a single character; the colorspace identifier
4391b8adde7SWilliam Kucharski      * is skipped as it's assumed to be "c" denoting RGB color.
4401b8adde7SWilliam Kucharski      *
4411b8adde7SWilliam Kucharski      * The six digits after the "#" are assumed to be a six digit RGB color
4421b8adde7SWilliam Kucharski      * identifier as defined in X11's rgb.txt file.
4431b8adde7SWilliam Kucharski      */
4447c478bd9Sstevel@tonic-gate     for (i = 0, idx = 1; i < colors; i++) {
4457c478bd9Sstevel@tonic-gate         len = 0;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate         while (grub_read(&c, 1) && c != '"')
4487c478bd9Sstevel@tonic-gate             ;
4491b8adde7SWilliam Kucharski 
4507c478bd9Sstevel@tonic-gate         grub_read(&c, 1);       /* char */
4517c478bd9Sstevel@tonic-gate         base = c;
4527c478bd9Sstevel@tonic-gate         grub_read(buf, 4);      /* \t c # */
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate         while (grub_read(&c, 1) && c != '"') {
4557c478bd9Sstevel@tonic-gate             if (len < sizeof(buf))
4567c478bd9Sstevel@tonic-gate                 buf[len++] = c;
4577c478bd9Sstevel@tonic-gate         }
4587c478bd9Sstevel@tonic-gate 
4599b4e3ac2SWilliam Kucharski 	/*
4609b4e3ac2SWilliam Kucharski 	 * The RGB hex digits should be six characters in length.
4619b4e3ac2SWilliam Kucharski 	 *
4629b4e3ac2SWilliam Kucharski 	 * If the color field contains anything other than six
4639b4e3ac2SWilliam Kucharski 	 * characters, such as "None" to denote a transparent color,
4649b4e3ac2SWilliam Kucharski 	 * ignore it.
4659b4e3ac2SWilliam Kucharski 	 */
4661b8adde7SWilliam Kucharski         if (len == 6) {
4677c478bd9Sstevel@tonic-gate             int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2;
4687c478bd9Sstevel@tonic-gate             int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2;
4697c478bd9Sstevel@tonic-gate             int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2;
4707c478bd9Sstevel@tonic-gate 
4719b4e3ac2SWilliam Kucharski 	    if (idx > 14) {
4729b4e3ac2SWilliam Kucharski 		errnum = ERR_TOOMANYCOLORS;
4739b4e3ac2SWilliam Kucharski 		grub_close();
4749b4e3ac2SWilliam Kucharski 		return 0;
4759b4e3ac2SWilliam Kucharski 	    }
4769b4e3ac2SWilliam Kucharski 
4777c478bd9Sstevel@tonic-gate             pal[idx] = base;
4789b4e3ac2SWilliam Kucharski 	    splash_palette[idx++] =
4799b4e3ac2SWilliam Kucharski 		((r & PALETTE_COLORMASK) << PALETTE_REDSHIFT) |
4809b4e3ac2SWilliam Kucharski 		((g & PALETTE_COLORMASK) << PALETTE_GREENSHIFT) |
4819b4e3ac2SWilliam Kucharski 		(b & PALETTE_COLORMASK);
4827c478bd9Sstevel@tonic-gate         }
4837c478bd9Sstevel@tonic-gate     }
4847c478bd9Sstevel@tonic-gate 
4859b4e3ac2SWilliam Kucharski     colors = idx - 1;	/* actual number of colors used in XPM image */
4867c478bd9Sstevel@tonic-gate     x = y = len = 0;
4877c478bd9Sstevel@tonic-gate 
4881b8adde7SWilliam Kucharski     /* clear (zero out) all four planes of the framebuffer */
4891b8adde7SWilliam Kucharski     for (i = 0; i < SCREENBYTES; i++)
4907c478bd9Sstevel@tonic-gate         s1[i] = s2[i] = s4[i] = s8[i] = 0;
4917c478bd9Sstevel@tonic-gate 
4921b8adde7SWilliam Kucharski     /* parse the XPM data */
4937c478bd9Sstevel@tonic-gate     while (y < height) {
4941b8adde7SWilliam Kucharski 	/* exit on EOF, otherwise skip characters until an initial '"' */
4957c478bd9Sstevel@tonic-gate         while (1) {
4967c478bd9Sstevel@tonic-gate             if (!grub_read(&c, 1)) {
4979b4e3ac2SWilliam Kucharski 		errnum = ERR_CORRUPTXPM;
4987c478bd9Sstevel@tonic-gate                 grub_close();
4997c478bd9Sstevel@tonic-gate                 return 0;
5007c478bd9Sstevel@tonic-gate             }
5017c478bd9Sstevel@tonic-gate             if (c == '"')
5027c478bd9Sstevel@tonic-gate                 break;
5037c478bd9Sstevel@tonic-gate         }
5047c478bd9Sstevel@tonic-gate 
5051b8adde7SWilliam Kucharski 	/* read characters until we hit an EOF or a terminating '"' */
5067c478bd9Sstevel@tonic-gate         while (grub_read(&c, 1) && c != '"') {
5079b4e3ac2SWilliam Kucharski 	    int pixel = 0;
5081b8adde7SWilliam Kucharski 
5099b4e3ac2SWilliam Kucharski 	    /*
5109b4e3ac2SWilliam Kucharski 	     * Look up the specified pixel color in the palette; the
5119b4e3ac2SWilliam Kucharski 	     * pixel will not be drawn if its color cannot be found or
5129b4e3ac2SWilliam Kucharski 	     * if no colors were specified in the XPM image itself.
5139b4e3ac2SWilliam Kucharski 	     */
5149b4e3ac2SWilliam Kucharski             for (i = 1; i <= colors; i++)
5157c478bd9Sstevel@tonic-gate                 if (pal[i] == c) {
5169b4e3ac2SWilliam Kucharski                     pixel = i;
5177c478bd9Sstevel@tonic-gate                     break;
5187c478bd9Sstevel@tonic-gate                 }
5197c478bd9Sstevel@tonic-gate 
5201b8adde7SWilliam Kucharski 	    /*
5211b8adde7SWilliam Kucharski 	     * A bit is set in each of the "planes" of the frame buffer to
5221b8adde7SWilliam Kucharski 	     * denote a pixel drawn in each color of the palette.
5231b8adde7SWilliam Kucharski 	     *
5241b8adde7SWilliam Kucharski 	     * The planes are a binary representation of the palette, so a
5251b8adde7SWilliam Kucharski 	     * pixel in color "1" of the palette would be denoted by setting a
5261b8adde7SWilliam Kucharski 	     * bit in plane "s1"; a pixel in color "15" of the palette would
5271b8adde7SWilliam Kucharski 	     * set the same bit in each of the four planes.
5281b8adde7SWilliam Kucharski 	     *
5291b8adde7SWilliam Kucharski 	     * Pixels are represented by set bits in a byte, in the order
5301b8adde7SWilliam Kucharski 	     * left-to-right (e.g. pixel 0 is 0x80, pixel 7 is 1.)
5311b8adde7SWilliam Kucharski 	     */
5329b4e3ac2SWilliam Kucharski 	    if (pixel != 0) {
5339b4e3ac2SWilliam Kucharski 		mask = 0x80 >> (x & 7);
5349b4e3ac2SWilliam Kucharski 
5359b4e3ac2SWilliam Kucharski 		if (pixel & 1)
5369b4e3ac2SWilliam Kucharski 		    s1[len + (x >> 3)] |= mask;
5379b4e3ac2SWilliam Kucharski 		if (pixel & 2)
5389b4e3ac2SWilliam Kucharski 		    s2[len + (x >> 3)] |= mask;
5399b4e3ac2SWilliam Kucharski 		if (pixel & 4)
5409b4e3ac2SWilliam Kucharski 		    s4[len + (x >> 3)] |= mask;
5419b4e3ac2SWilliam Kucharski 		if (pixel & 8)
5429b4e3ac2SWilliam Kucharski 		    s8[len + (x >> 3)] |= mask;
5439b4e3ac2SWilliam Kucharski 	    }
5447c478bd9Sstevel@tonic-gate 
5451b8adde7SWilliam Kucharski 	    /*
5461b8adde7SWilliam Kucharski 	     * Increment "x"; if we hit pixel HPIXELS, wrap to the start of the
5471b8adde7SWilliam Kucharski 	     * next horizontal line if we haven't yet reached the bottom of
5481b8adde7SWilliam Kucharski 	     * the screen.
5491b8adde7SWilliam Kucharski 	     */
5501b8adde7SWilliam Kucharski             if (++x >= HPIXELS) {
5517c478bd9Sstevel@tonic-gate                 x = 0;
5527c478bd9Sstevel@tonic-gate 
5531b8adde7SWilliam Kucharski                 if (y++ < VPIXELS)
5541b8adde7SWilliam Kucharski                     len += ROWBYTES;
5551b8adde7SWilliam Kucharski 		else
5561b8adde7SWilliam Kucharski 		    break;
5577c478bd9Sstevel@tonic-gate             }
5587c478bd9Sstevel@tonic-gate         }
5597c478bd9Sstevel@tonic-gate     }
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate     grub_close();
5627c478bd9Sstevel@tonic-gate 
563a6e28364SSuhasini Peddada     return 1;
5647c478bd9Sstevel@tonic-gate }
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate /* Convert a character which is a hex digit to the appropriate integer */
hex(int v)5677c478bd9Sstevel@tonic-gate int hex(int v)
5687c478bd9Sstevel@tonic-gate {
5697c478bd9Sstevel@tonic-gate     if (v >= 'A' && v <= 'F')
5707c478bd9Sstevel@tonic-gate         return (v - 'A' + 10);
5717c478bd9Sstevel@tonic-gate     if (v >= 'a' && v <= 'f')
5727c478bd9Sstevel@tonic-gate         return (v - 'a' + 10);
5737c478bd9Sstevel@tonic-gate     return (v - '0');
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate /* move the graphics cursor location to col, row */
graphics_setxy(int col,int row)5787c478bd9Sstevel@tonic-gate static void graphics_setxy(int col, int row) {
5797c478bd9Sstevel@tonic-gate     if (col >= x0 && col < x1) {
5807c478bd9Sstevel@tonic-gate         fontx = col;
5817c478bd9Sstevel@tonic-gate         cursorX = col << 3;
5827c478bd9Sstevel@tonic-gate     }
5837c478bd9Sstevel@tonic-gate     if (row >= y0 && row < y1) {
5847c478bd9Sstevel@tonic-gate         fonty = row;
5857c478bd9Sstevel@tonic-gate         cursorY = row << 4;
5867c478bd9Sstevel@tonic-gate     }
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate /* scroll the screen */
graphics_scroll()590a6e28364SSuhasini Peddada static void graphics_scroll() {
5917c478bd9Sstevel@tonic-gate     int i, j;
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate     /* we don't want to scroll recursively... that would be bad */
5947c478bd9Sstevel@tonic-gate     if (no_scroll)
5957c478bd9Sstevel@tonic-gate         return;
5967c478bd9Sstevel@tonic-gate     no_scroll = 1;
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate     /* move everything up a line */
5997c478bd9Sstevel@tonic-gate     for (j = y0 + 1; j < y1; j++) {
6007c478bd9Sstevel@tonic-gate         graphics_gotoxy(x0, j - 1);
6017c478bd9Sstevel@tonic-gate         for (i = x0; i < x1; i++) {
6021b8adde7SWilliam Kucharski             graphics_putchar(text[j * ROWBYTES + i]);
6037c478bd9Sstevel@tonic-gate         }
6047c478bd9Sstevel@tonic-gate     }
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate     /* last line should be blank */
6077c478bd9Sstevel@tonic-gate     graphics_gotoxy(x0, y1 - 1);
6087c478bd9Sstevel@tonic-gate     for (i = x0; i < x1; i++)
6097c478bd9Sstevel@tonic-gate         graphics_putchar(' ');
6107c478bd9Sstevel@tonic-gate     graphics_setxy(x0, y1 - 1);
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate     no_scroll = 0;
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate 
graphics_cursor(int set)6157c478bd9Sstevel@tonic-gate void graphics_cursor(int set) {
6167c478bd9Sstevel@tonic-gate     unsigned char *pat, *mem, *ptr, chr[16 << 2];
6177c478bd9Sstevel@tonic-gate     int i, ch, invert, offset;
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate     if (set && no_scroll)
6207c478bd9Sstevel@tonic-gate         return;
6217c478bd9Sstevel@tonic-gate 
6221b8adde7SWilliam Kucharski     offset = cursorY * ROWBYTES + fontx;
6231b8adde7SWilliam Kucharski     ch = text[fonty * ROWBYTES + fontx] & 0xff;
6241b8adde7SWilliam Kucharski     invert = (text[fonty * ROWBYTES + fontx] & 0xff00) != 0;
6257c478bd9Sstevel@tonic-gate     pat = font8x16 + (ch << 4);
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate     mem = (unsigned char*)VIDEOMEM + offset;
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate     if (!set) {
6307c478bd9Sstevel@tonic-gate         for (i = 0; i < 16; i++) {
6317c478bd9Sstevel@tonic-gate             unsigned char mask = pat[i];
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate             if (!invert) {
6347c478bd9Sstevel@tonic-gate                 chr[i     ] = ((unsigned char*)VSHADOW1)[offset];
6357c478bd9Sstevel@tonic-gate                 chr[16 + i] = ((unsigned char*)VSHADOW2)[offset];
6367c478bd9Sstevel@tonic-gate                 chr[32 + i] = ((unsigned char*)VSHADOW4)[offset];
6377c478bd9Sstevel@tonic-gate                 chr[48 + i] = ((unsigned char*)VSHADOW8)[offset];
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate                 /* FIXME: if (shade) */
6407c478bd9Sstevel@tonic-gate                 if (1) {
6417c478bd9Sstevel@tonic-gate                     if (ch == DISP_VERT || ch == DISP_LL ||
6427c478bd9Sstevel@tonic-gate                         ch == DISP_UR || ch == DISP_LR) {
6437c478bd9Sstevel@tonic-gate                         unsigned char pmask = ~(pat[i] >> 1);
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate                         chr[i     ] &= pmask;
6467c478bd9Sstevel@tonic-gate                         chr[16 + i] &= pmask;
6477c478bd9Sstevel@tonic-gate                         chr[32 + i] &= pmask;
6487c478bd9Sstevel@tonic-gate                         chr[48 + i] &= pmask;
6497c478bd9Sstevel@tonic-gate                     }
6507c478bd9Sstevel@tonic-gate                     if (i > 0 && ch != DISP_VERT) {
6517c478bd9Sstevel@tonic-gate                         unsigned char pmask = ~(pat[i - 1] >> 1);
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate                         chr[i     ] &= pmask;
6547c478bd9Sstevel@tonic-gate                         chr[16 + i] &= pmask;
6557c478bd9Sstevel@tonic-gate                         chr[32 + i] &= pmask;
6567c478bd9Sstevel@tonic-gate                         chr[48 + i] &= pmask;
6577c478bd9Sstevel@tonic-gate                         if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) {
6587c478bd9Sstevel@tonic-gate                             pmask = ~pat[i - 1];
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate                             chr[i     ] &= pmask;
6617c478bd9Sstevel@tonic-gate                             chr[16 + i] &= pmask;
6627c478bd9Sstevel@tonic-gate                             chr[32 + i] &= pmask;
6637c478bd9Sstevel@tonic-gate                             chr[48 + i] &= pmask;
6647c478bd9Sstevel@tonic-gate                         }
6657c478bd9Sstevel@tonic-gate                     }
6667c478bd9Sstevel@tonic-gate                 }
6677c478bd9Sstevel@tonic-gate                 chr[i     ] |= mask;
6687c478bd9Sstevel@tonic-gate                 chr[16 + i] |= mask;
6697c478bd9Sstevel@tonic-gate                 chr[32 + i] |= mask;
6707c478bd9Sstevel@tonic-gate                 chr[48 + i] |= mask;
6717c478bd9Sstevel@tonic-gate 
6721b8adde7SWilliam Kucharski                 offset += ROWBYTES;
6737c478bd9Sstevel@tonic-gate             }
6747c478bd9Sstevel@tonic-gate             else {
6757c478bd9Sstevel@tonic-gate                 chr[i     ] = mask;
6767c478bd9Sstevel@tonic-gate                 chr[16 + i] = mask;
6777c478bd9Sstevel@tonic-gate                 chr[32 + i] = mask;
6787c478bd9Sstevel@tonic-gate                 chr[48 + i] = mask;
6797c478bd9Sstevel@tonic-gate             }
6807c478bd9Sstevel@tonic-gate         }
6817c478bd9Sstevel@tonic-gate     }
6827c478bd9Sstevel@tonic-gate     else {
6837c478bd9Sstevel@tonic-gate         MapMask(15);
6847c478bd9Sstevel@tonic-gate         ptr = mem;
6851b8adde7SWilliam Kucharski         for (i = 0; i < 16; i++, ptr += ROWBYTES) {
6867c478bd9Sstevel@tonic-gate             cursorBuf[i] = pat[i];
6877c478bd9Sstevel@tonic-gate             *ptr = ~pat[i];
6887c478bd9Sstevel@tonic-gate         }
6897c478bd9Sstevel@tonic-gate         return;
6907c478bd9Sstevel@tonic-gate     }
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate     offset = 0;
6937c478bd9Sstevel@tonic-gate     for (i = 1; i < 16; i <<= 1, offset += 16) {
6947c478bd9Sstevel@tonic-gate         int j;
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate         MapMask(i);
6977c478bd9Sstevel@tonic-gate         ptr = mem;
6981b8adde7SWilliam Kucharski         for (j = 0; j < 16; j++, ptr += ROWBYTES)
6997c478bd9Sstevel@tonic-gate             *ptr = chr[j + offset];
7007c478bd9Sstevel@tonic-gate     }
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate     MapMask(15);
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate #endif /* SUPPORT_GRAPHICS */
706