1
/* graphics.c - graphics mode support for GRUB */
2
/* Implemented as a terminal type by Jeremy Katz <katzj@redhat.com> based
3
* on a patch by Paulo C�sar Pereira de Andrade <pcpa@conectiva.com.br>
6
* GRUB -- GRand Unified Bootloader
7
* Copyright (C) 2001,2002 Red Hat, Inc.
8
* Portions copyright (C) 2000 Conectiva, Inc.
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27
#ifdef SUPPORT_GRAPHICS
33
static int saved_videomode = 0;
34
static unsigned char *font8x16 = 0;
37
int disable_space_highlight = 0;
38
int graphics_inited = 0;
41
#define VSHADOW VSHADOW1
42
/* 8x16 dot array, total chars = 80*30. plano size = 80*30*16 = 38400 bytes */
43
static unsigned char *VSHADOW1 = (unsigned char *)0x3A0000; //unsigned char VSHADOW1[38400];
44
static unsigned char *VSHADOW2 = (unsigned char *)0x3A9600; //unsigned char VSHADOW2[38400];
45
static unsigned char *VSHADOW4 = (unsigned char *)0x3B2C00; //unsigned char VSHADOW4[38400];
46
static unsigned char *VSHADOW8 = (unsigned char *)0x3BC200; //unsigned char VSHADOW8[38400];
47
/* text buffer has to be kept around so that we can write things as we
48
* scroll and the like */
49
//static unsigned short text[80 * 30];
50
static unsigned long *text = (unsigned long *)0x3C5800; // length in bytes = 80*30*4
52
/* constants to define the viewable area */
58
/* why do these have to be kept here? */
59
int foreground = (63 << 16) | (63 << 8) | (63), background = 0, border = 0;
61
/* current position */
65
/* global state so that we don't try to recursively scroll or cursor */
66
static int no_scroll = 0;
69
static int graphics_standard_color = A_NORMAL;
70
static int graphics_normal_color = A_NORMAL;
71
static int graphics_highlight_color = A_REVERSE;
72
static int graphics_current_color = A_NORMAL;
73
static color_state graphics_color_state = COLOR_STATE_STANDARD;
76
/* graphics local functions */
77
static void graphics_setxy (int col, int row);
78
static void graphics_scroll (void);
79
static int read_image (char *s);
81
/* FIXME: where do these really belong? */
82
static inline void outb(unsigned short port, unsigned char val)
84
__asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
87
static void MapMask(int value) {
92
/* bit mask register */
93
static void BitMask(int value) {
100
///* Set the splash image */
101
//void graphics_set_splash(char *splashfile) {
102
// grub_strcpy(splashimage, splashfile);
105
///* Get the current splash image */
106
//char *graphics_get_splash(void) {
107
// return splashimage;
110
/* Initialize a vga16 graphics display with the palette based off of
111
* the image in splashimage. If the image doesn't exist, leave graphics
116
/* graphics mode will corrupt the extended memory. so we should
117
* invalidate the kernel_type. */
118
kernel_type = KERNEL_TYPE_NONE;
120
if (! graphics_inited)
122
saved_videomode = set_videomode (0x12);
125
if (! read_image (splashimage))
127
set_videomode (saved_videomode);
128
grub_printf("failed to read image\n");
132
font8x16 = (unsigned char *) graphics_get_font (); /* code in asm.S */
136
/* make sure that the highlight color is set correctly */
137
graphics_highlight_color = ((graphics_normal_color >> 4) |
138
((graphics_normal_color & 0xf) << 4));
143
/* Leave graphics mode */
149
set_videomode (saved_videomode);
154
/* Print ch on the screen. Handle any needed scrolling or the like */
156
graphics_putchar (int ch)
164
graphics_setxy(fontx, fonty + 1);
169
} else if (ch == '\r') {
170
graphics_setxy(x0, fonty);
177
text[fonty * 80 + fontx] = ch;
178
text[fonty * 80 + fontx] &= 0x00ff;
179
if (graphics_current_color & 0xf0)
180
text[fonty * 80 + fontx] |= 0x10000;//0x100;
184
if ((fontx + 1) >= x1) {
185
graphics_setxy(x0, fonty);
187
graphics_setxy(x0, fonty + 1);
191
graphics_setxy(fontx + 1, fonty);
197
/* get the current location of the cursor */
201
return (fontx << 8) | fonty;
205
graphics_gotoxy (int x, int y)
209
graphics_setxy(x, y);
218
unsigned char *mem, *s1, *s2, *s4, *s8;
221
graphics_gotoxy(x0, y0);
223
mem = (unsigned char*)VIDEOMEM;
224
s1 = (unsigned char*)VSHADOW1;
225
s2 = (unsigned char*)VSHADOW2;
226
s4 = (unsigned char*)VSHADOW4;
227
s8 = (unsigned char*)VSHADOW8;
229
for (i = 0; i < 80 * 30; i++)
237
grub_memcpy(mem, s1, 38400);
241
grub_memcpy(mem, s2, 38400);
245
grub_memcpy(mem, s4, 38400);
249
grub_memcpy(mem, s8, 38400);
256
graphics_setcolorstate (color_state state)
260
case COLOR_STATE_STANDARD:
261
graphics_current_color = graphics_standard_color;
263
case COLOR_STATE_NORMAL:
264
graphics_current_color = graphics_normal_color;
266
case COLOR_STATE_HIGHLIGHT:
267
graphics_current_color = graphics_highlight_color;
270
graphics_current_color = graphics_standard_color;
274
graphics_color_state = state;
278
graphics_setcolor (int normal_color, int highlight_color)
280
graphics_normal_color = normal_color;
281
graphics_highlight_color = highlight_color;
283
graphics_setcolorstate (graphics_color_state);
287
graphics_setcursor (int on)
289
/* FIXME: we don't have a cursor in graphics */
293
/* Read in the splashscreen image and set the palette up appropriately.
294
* Format of splashscreen is an xpm (can be gzipped) with 16 colors and
299
char buf[32], pal[16];
300
unsigned char c, base, mask;
301
unsigned i, len, idx, colors, x, y, width, height;
303
unsigned char *s1 = (unsigned char*)VSHADOW1;
304
unsigned char *s2 = (unsigned char*)VSHADOW2;
305
unsigned char *s4 = (unsigned char*)VSHADOW4;
306
unsigned char *s8 = (unsigned char*)VSHADOW8;
311
//graphics_set_palette(1, 0, 0, 0);
313
for (i = 0; i < 38400 / 4; i++)
314
((long *)s1)[i] = ((long *)s2)[i] = ((long *)s4)[i] = ((long *)s8)[i] = 0;
316
//for (y = 0, len = 0; y < 480; y++, len += 80) {
317
// for (x = 0; x < 640; x++) {
318
// s1[len + (x >> 3)] |= 0x80 >> (x & 7);
322
goto set_palette; //return 0;
326
if (! grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) {
332
while (grub_read((char *)&c, 1)) {
337
while (grub_read((char *)&c, 1) && (c == ' ' || c == '\t'))
342
while (grub_read((char *)&c, 1)) {
343
if (c >= '0' && c <= '9')
344
width = width * 10 + c - '0';
348
while (grub_read((char *)&c, 1) && (c == ' ' || c == '\t'))
352
while (grub_read((char *)&c, 1)) {
353
if (c >= '0' && c <= '9')
354
height = height * 10 + c - '0';
358
while (grub_read((char *)&c, 1) && (c == ' ' || c == '\t'))
362
while (grub_read((char *)&c, 1)) {
363
if (c >= '0' && c <= '9')
364
colors = colors * 10 + c - '0';
370
while (grub_read((char *)&c, 1) && c != '"')
374
for (i = 0, idx = 1; i < colors; i++) {
377
while (grub_read((char *)&c, 1) && c != '"')
379
grub_read((char *)&c, 1); /* char */
381
grub_read(buf, 4); /* \t c # */
383
while (grub_read((char *)&c, 1) && c != '"') {
384
if (len < sizeof(buf))
388
if (len == 6 && idx < 15) {
389
int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2;
390
int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2;
391
int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2;
394
graphics_set_palette(idx, r, g, b);
401
for (i = 0; i < 38400 / 4; i++)
402
((long *)s1)[i] = ((long *)s2)[i] = ((long *)s4)[i] = ((long *)s8)[i] = 0;
407
if (!grub_read((char *)&c, 1)) {
415
while (grub_read((char *)&c, 1) && c != '"') {
416
for (i = 1; i < 15; i++)
422
mask = 0x80 >> (x & 7);
424
s1[len + (x >> 3)] |= mask;
426
s2[len + (x >> 3)] |= mask;
428
s4[len + (x >> 3)] |= mask;
430
s8[len + (x >> 3)] |= mask;
446
graphics_set_palette(0, (background >> 16), (background >> 8) & 63,
448
graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63,
450
graphics_set_palette(0x11, (border >> 16), (border >> 8) & 63,
457
/* Convert a character which is a hex digit to the appropriate integer */
461
if (v >= 'A' && v <= 'F')
462
return (v - 'A' + 10);
463
if (v >= 'a' && v <= 'f')
464
return (v - 'a' + 10);
469
/* move the graphics cursor location to col, row */
471
graphics_setxy (int col, int row)
473
if (col >= x0 && col < x1)
479
if (row >= y0 && row < y1)
486
/* scroll the screen */
488
graphics_scroll (void)
492
/* we don't want to scroll recursively... that would be bad */
497
/* move everything up a line */
498
for (j = y0 + 1; j < y1; j++)
500
graphics_gotoxy (x0, j - 1);
502
for (i = x0; i < x1; i++)
504
graphics_putchar (text[j * 80 + i]);
508
/* last line should be blank */
509
graphics_gotoxy (x0, y1 - 1);
511
for (i = x0; i < x1; i++)
512
graphics_putchar (' ');
514
graphics_setxy (x0, y1 - 1);
520
static unsigned char chr[16 << 2];
521
static unsigned char mask[16];
524
graphics_cursor (int set)
526
unsigned char *pat, *mem, *ptr;
530
if (set && no_scroll)
533
offset = cursorY * 80 + fontx;
534
ch = text[fonty * 80 + fontx] & 0xff;
535
if (ch != ' ' || ! disable_space_highlight)
536
invert = (text[fonty * 80 + fontx] & /*0xff00*/ 0xffff0000) != 0;
537
pat = font8x16 + (ch << 4);
539
mem = (unsigned char*)VIDEOMEM + offset;
545
for (i = 0; i < 16; i++, ptr += 80)
547
cursorBuf[i] = pat[i];
554
for (i = 0; i < 16; i++)
561
mask[i] |= (mask[i] << 1) | (mask[i] >> 1);
562
mask[i] = ~(mask[i]);
565
for (i = 0; i < 16; i++, offset += 80)
567
unsigned char m, p, c1, c2, c4, c8;
581
c1 = ((unsigned char*)VSHADOW1)[offset];
582
c2 = ((unsigned char*)VSHADOW2)[offset];
583
c4 = ((unsigned char*)VSHADOW4)[offset];
584
c8 = ((unsigned char*)VSHADOW8)[offset];
618
for (i = 1; i < 16; i <<= 1, offset += 16)
624
for (j = 0; j < 16; j++, ptr += 80)
625
*ptr = chr[j + offset];
631
#endif /* SUPPORT_GRAPHICS */