|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
26: *
27: * FBConsole.c - FrameBuffer based console implementation.
28: *
29: *
30: * HISTORY
31: * 01 Sep 92 Joe Pasqua
32: * Created.
33: * 25 Mar 97 Simon Douglas
34: * Rhapsodized.
35: */
36:
37: // TO DO:
38: // * Implement other cases of FlipCursor, HorizLine, VertLine, ClearWindow.
39: // Erase
40: // * Find the #defines for np and del are, then get rid of our #defines.
41: //
42: // Notes:
43: // * This module implements the console functionality required by the
44: // ConsoleSupport protocol. If you have a device which is a framebuffer
45: // with a depth supported by this module, then you can use this code.
46: // * To find things that need to be fixed, search for FIX, to find questions
47: // to be resolved, search for ASK, to find stuff that still needs to be
48: // done, search for TO DO.
49:
50: #define BRINGUP 1
51:
52: #import <sys/syslog.h>
53: #import <bsd/dev/ppc/FBConsole.h>
54: #import <bsd/dev/ppc/FBConsPriv.h>
55: #import <architecture/ascii_codes.h>
56: #import "BootImages.h"
57:
58: #if defined(NOTINKERNEL)
59: #define panic(str)
60: #define copyin(src, dst, size) bcopy(src, dst, size)
61: #define kalloc(size) malloc(size)
62: #define kfree(ptr, size) free(ptr)
63: #endif
64:
65: #ifdef DRIVERKIT
66: #else
67: #define IOMalloc(size) kalloc(size)
68: #define IOFree(ptr,size) kfree(ptr,size)
69: #define IOLog(s,a) printf(s,a)
70: #endif // DRIVERKIT
71:
72: #define TEXTURE_BACKGND 1
73:
74: /*
75: * Standard font.
76: */
77: extern char ohlfs12[][];
78:
79: #import "ohlfs12.h"
80:
81: #define NIL (0)
82:
83: /* Window margins */
84: #define BG_MARGIN 2 // pixels of background to leave as margin
85: #define FG_MARGIN 1 // pixels of foreground to leave as margin
86: #define TOTAL_MARGIN (BG_MARGIN + FG_MARGIN)
87: #define DROP_SHADOW 1 // pixels of dark_grey, bottom & right
88: #define TS_MARGIN 1 //
89:
90: #define HORIZ_BORDER 32 // 40 on VGA
91: #define VERT_BORDER 22 // 30 on VGA
92:
93: /*
94: * Ansi sequence state.
95: */
96: typedef enum {
97: AS_NORMAL,
98: AS_ESCAPE,
99: AS_BRACKET,
100: AS_R
101: } ansi_state_t;
102:
103: #define ANSI_STACK_SIZE 3
104:
105: typedef struct _t_Console {
106: ScreenMode window_type;
107:
108: IODisplayInfo display;
109:
110: //
111: // The remaining fields are window parameters. These are only
112: // meaningful for text-type windows (window_type == SCM_TEXT or
113: // SCM_ALERT).
114: //
115:
116: //
117: // Current window origin in pixels, relative to origin of screen.
118: //
119: int window_origin_x;
120: int window_origin_y;
121:
122: //
123: // Window size information, in pixels and in characters.
124: //
125: int chars_per_row;
126: int pixels_per_row;
127: int chars_per_column;
128: int pixels_per_column;
129:
130: //
131: // Cursor location, in characters. Origin is top
132: // left corner of window = {0,0}.
133: //
134: int curr_row; // in characters
135: int curr_column; // in characters
136:
137: //
138: // Misc. video parameters. The background and foreground fields
139: // are slightly dependent on the hardware implementation; they'll
140: // work as long as bits per pixel <= 32.
141: //
142:
143: unsigned int background; // bits for background pixel
144: unsigned int light_grey; // bits for light grey
145: unsigned int dark_grey; // bits for dark grey
146: unsigned int foreground; // bits for foreground pixel
147: unsigned int baseground; // bits for base color
148: unsigned int grayTable[4]; // bits for drawing bitmaps
149:
150: boolean_t has_title;
151: boolean_t prettyPanelUp;
152: unsigned int bolding; // bold text pixel count
153:
154: //
155: // Storage for saved region under an alert panel.
156: //
157: unsigned char *saveBits;
158: int saveHeight;
159: int saveRowBytes;
160: int saveBytes;
161: unsigned char *saveLocation;
162: ansi_state_t ansi_state; /* track ansi escape sequence state */
163: u_char ansi_stack[ANSI_STACK_SIZE];
164: u_char *ansi_stack_p;
165:
166: } ConsoleRep, *ConsolePtr;
167:
168: //
169: // BEGIN: Private utility routines
170: //
171:
172: static void videoMemMove( char * dst, char * src, unsigned int len )
173: {
174: #if 1
175: bcopy_nc( src, dst, len );
176: #else
177: memmove( dst, src, len );
178: #endif
179: }
180:
181: static unsigned int BPPToPPW(int bpp)
182: {
183: if (bpp == IO_2BitsPerPixel) return(16);
184: if (bpp == IO_8BitsPerPixel) return(4);
185: if (bpp == IO_12BitsPerPixel) return(2);
186: if (bpp == IO_15BitsPerPixel) return(2);
187: if (bpp == IO_24BitsPerPixel) return(1);
188: else return(-1);
189: }
190:
191: static unsigned char *PixelAddress(ConsolePtr console, int xPix, int yPix)
192: {
193: switch (console->display.bitsPerPixel) {
194: case IO_8BitsPerPixel:
195: return ((unsigned char *)console->display.frameBuffer) +
196: yPix * console->display.rowBytes + xPix;
197: case IO_12BitsPerPixel:
198: case IO_15BitsPerPixel:
199: return ((unsigned char *)console->display.frameBuffer) +
200: yPix * console->display.rowBytes + xPix * 2;
201: case IO_24BitsPerPixel:
202: return ((unsigned char *)console->display.frameBuffer) +
203: yPix * console->display.rowBytes + xPix * 4;
204: default:
205: panic("FBConsole/PixelAddress: bogus bitsPerPixel");
206: }
207: }
208:
209: static void Fill(ConsolePtr console,
210: unsigned char *dst, // Where to start filling
211: unsigned pixel, // pattern to fill
212: unsigned len) // in pixels
213: // Descritpion: Fill the framebuffer with 'pixel' starting at dst
214: // and for 'len' pixels.
215: {
216: switch (console->display.bitsPerPixel) {
217: case IO_8BitsPerPixel:
218: {
219: unsigned char *dst8 = (unsigned char *)dst;
220: for (; len--; dst8++)
221: *dst8 = pixel;
222: break;
223: }
224: case IO_12BitsPerPixel:
225: case IO_15BitsPerPixel:
226: {
227: unsigned short *dst16 = (unsigned short *)dst;
228: for (; len--; dst16++)
229: *dst16 = pixel;
230: break;
231: }
232: case IO_24BitsPerPixel:
233: {
234: unsigned int *dst32 = (unsigned int *)dst;
235: for (; len--; dst32++)
236: *dst32 = pixel;
237: break;
238: }
239: default:
240: panic("FBConsole/Fill: bogus bitsPerPixel");
241: }
242: }
243:
244: static void FlipCursor(ConsolePtr console)
245: // Description: Turn cursor on/off. This just inverts every pixel at the
246: // character at (curr_rown, curr_column).
247: {
248: int y;
249: unsigned char *dst8;
250: unsigned short *dst16;
251: unsigned int *dst32;
252: unsigned pixel_num;
253:
254: // Screen-relative pixel coordinates of bounds of current character.
255: int start_y = console->window_origin_y +
256: console->curr_row * CHAR_H;
257: int end_y = start_y + CHAR_H;
258: int start_x = console->window_origin_x +
259: console->curr_column * CHAR_W;
260:
261: for (y=start_y; y < end_y; y++) {
262: switch (console->display.bitsPerPixel) {
263: case IO_8BitsPerPixel:
264: dst8 = (unsigned char *)PixelAddress(console, start_x, y);
265: for (pixel_num = 0; pixel_num < CHAR_W; pixel_num++) {
266: if ((*dst8 & PIXEL_MASK_16) ==
267: (console->background & PIXEL_MASK_16)) {
268: *dst8 = console->foreground;
269: }
270: else {
271: *dst8 = console->background;
272: }
273: dst8++;
274: }
275: break;
276: case IO_12BitsPerPixel:
277: case IO_15BitsPerPixel:
278: dst16 = (unsigned short *)PixelAddress(console, start_x, y);
279: for (pixel_num = 0; pixel_num < CHAR_W; pixel_num++) {
280: if ((*dst16 & PIXEL_MASK_16) ==
281: (console->background & PIXEL_MASK_16)) {
282: *dst16 = console->foreground;
283: }
284: else {
285: *dst16 = console->background;
286: }
287: dst16++;
288: }
289: break;
290: case IO_24BitsPerPixel:
291: dst32 = (unsigned int *)PixelAddress(console, start_x, y);
292: for (pixel_num = 0; pixel_num < CHAR_W; pixel_num++) {
293: if ((*dst32 & PIXEL_MASK_32) ==
294: (console->background & PIXEL_MASK_32)) {
295: *dst32 = console->foreground;
296: }
297: else {
298: *dst32 = console->background;
299: }
300: dst32++;
301: }
302: break;
303:
304: default:
305: panic("FBConsole/FlipCursor: bogus bits per pixel");
306: }
307: }
308: }
309:
310: static void SwapForegroundAndBackground(ConsolePtr console)
311: {
312: int temp_color;
313:
314: temp_color = console->foreground;
315: console->foreground = console->background;
316: console->background = temp_color;
317: }
318:
319: static void Rect(
320: ConsolePtr console,
321: int origin_x, int origin_y,
322: int width, int height,
323: unsigned pixel)
324: // Description: Draws a single pixel wide horizontal line
325: {
326: while (height--)
327: Fill(console,
328: PixelAddress(console, origin_x, origin_y++),
329: pixel, width);
330: }
331:
332: #ifdef notdef
333: static void HorizLine(
334: ConsolePtr console,
335: int origin_x, int origin_y, int length,
336: unsigned pixel)
337: // Description: Draws a single pixel wide horizontal line
338: {
339: Fill(console, PixelAddress(console, origin_x, origin_y), pixel, length);
340: }
341:
342: static void VertLine(
343: ConsolePtr console,
344: int origin_x, int origin_y, int length,
345: unsigned pixel)
346: // Description: Draws a single pixel wide vertical line
347: {
348: unsigned char *dstPixel = PixelAddress(console, origin_x, origin_y);
349:
350: switch(console->display.bitsPerPixel) {
351: case IO_8BitsPerPixel:
352: {
353: unsigned char *dst = (unsigned char *)dstPixel;
354: while (length--) {
355: *dst = pixel;
356: dst += console->display.totalWidth;
357: }
358: }
359: break;
360: case IO_12BitsPerPixel:
361: case IO_15BitsPerPixel:
362: {
363: unsigned short *dst = (unsigned short *)dstPixel;
364: while (length--) {
365: *dst = pixel;
366: dst += console->display.totalWidth;
367: }
368: }
369: break;
370: case IO_24BitsPerPixel:
371: {
372: unsigned long *dst = (unsigned long *)dstPixel;
373: while (length--) {
374: *dst = pixel;
375: dst += console->display.totalWidth;
376: }
377: }
378: break;
379:
380: default:
381: panic("FBConsole/VertLine: bogus bits per pixel");
382: }
383: }
384: #endif
385:
386: static void ClearWindow(ConsolePtr console)
387: // Description: Set contents of entire current window to background.
388: // Preconditions:
389: // * Cursor is off on entry and will remain so on exit.
390: {
391: int line;
392: unsigned char *dstPixel = PixelAddress(
393: console, console->window_origin_x, console->window_origin_y);
394:
395: for (line=0; line < console->pixels_per_column; line++) {
396: // One loop per scan line in the window.
397: Fill(console, dstPixel, console->background,
398: console->pixels_per_row);
399: dstPixel += console->display.rowBytes;
400: }
401: }
402:
403: static void WipeScreen(ConsolePtr console, const unsigned pixel)
404: // Description: Fill the screen with specific pixel value.
405: {
406: static int horstArray[5] = { 5,3,2,1,1 };
407: int i,horst;
408:
409: Rect( console, 0, 0, console->display.width, console->display.height, pixel );
410:
411: // Round rect
412: for( i=0; i < 5; i++) {
413: horst = horstArray[i];
414: // top left
415: Fill(console, PixelAddress(console, 0, i), console->foreground, horst);
416: // bottom left
417: Fill(console, PixelAddress(console, 0, console->display.height - i - 1), console->foreground, horst);
418: // top right
419: Fill(console, PixelAddress(console, console->display.width - horst, i), console->foreground, horst);
420: // bottom right
421: Fill(console, PixelAddress(console, console->display.width - horst, console->display.height - i - 1),
422: console->foreground, horst);
423: }
424: }
425:
426: static void ClearToEOL(ConsolePtr console)
427: // Description: Clear to end of line (within window), including current pos.
428: // Preconditions:
429: // * Cursor is 'off' on entry and will remain so on exit.
430: {
431: unsigned pixel_count;
432: int starting_x; // window-relative 'x' coordinate
433: int y;
434: int line;
435:
436: starting_x = console->window_origin_x +
437: (console->curr_column * CHAR_W);
438: y = console->window_origin_y + (console->curr_row * CHAR_H);
439:
440: pixel_count = console->pixels_per_row -
441: (starting_x - console->window_origin_x);
442:
443: for (line=0; line < CHAR_H; line++) {
444: // One loop per scan line in the row.
445: Fill(
446: console, PixelAddress(console, starting_x, y++),
447: console->background, pixel_count);
448: }
449: }
450:
451: static void Erase(ConsolePtr console)
452: // Description: Erase current cursor location.
453: {
454: int y;
455: unsigned char *dst8;
456: unsigned short *dst16;
457: unsigned int *dst32;
458: int x;
459: // Screen-relative pixel coordinates of bounds of current character.
460: int start_y = console->window_origin_y +
461: console->curr_row * CHAR_H;
462: int end_y = start_y + CHAR_H;
463: int start_x = console->window_origin_x +
464: console->curr_column * CHAR_W;
465:
466: for (y=start_y; y<end_y; y++) {
467: // I think it's quicker not to use Fill() here...
468: switch (console->display.bitsPerPixel) {
469: case IO_8BitsPerPixel:
470: dst8 = (unsigned char *)PixelAddress(console, start_x, y);
471: for (x=0; x < CHAR_W; x++) {
472: *dst8++ = console->background;
473: }
474: break;
475: case IO_12BitsPerPixel:
476: case IO_15BitsPerPixel:
477: dst16 = (unsigned short *)PixelAddress(console, start_x, y);
478: for (x=0; x < CHAR_W; x++) {
479: *dst16++ = console->background;
480: }
481: break;
482: case IO_24BitsPerPixel:
483: dst32 = (unsigned int *)PixelAddress(console, start_x, y);
484: for (x=0; x < CHAR_W; x++) {
485: *dst32++ = console->background;
486: }
487: break;
488:
489: default:
490: panic("FBConsole/Erase: bogus bits per pixel");
491: }
492: }
493: }
494:
495: extern unsigned char appleClut8[ 768 ];
496:
497: static void Expand4ToN( ConsolePtr console, int x, int y, int width, int height,
498: unsigned char * dataPtr, unsigned char colors[ 16 ])
499: {
500: unsigned char *dst;
501: int line, col, bit = 4;
502: unsigned int data, data8;
503:
504: dst = (unsigned char *) PixelAddress(console, x, y);
505: for( line = 0; line < height; line++) {
506: for( col = 0; col < width; col++, bit ^= 4) {
507: if( bit)
508: data8 = *dataPtr++;
509: data = colors[ (data8 >> bit) & 15];
510:
511: switch (console->display.bitsPerPixel) {
512: case IO_8BitsPerPixel:
513: if (console->display.colorSpace != IO_OneIsWhiteColorSpace)
514: *(dst + col) = data;
515: else {
516: data *= 3;
517: *(dst + col) = ((19595 * appleClut8[data] +
518: 38470 * appleClut8[data + 1] +
519: 7471 * appleClut8[data + 2] ) / 65536);
520:
521: }
522: break;
523: case IO_24BitsPerPixel:
524: data *= 3;
525: *(((unsigned int *)dst) + col) = (appleClut8[data] << 16)
526: | (appleClut8[data + 1] << 8)
527: | appleClut8[data + 2];
528: break;
529: case IO_15BitsPerPixel:
530: data *= 3;
531: *(((unsigned short *)dst) + col) = ( (0xf8 & (appleClut8[data])) << 7)
532: | ( (0xf8 & (appleClut8[data + 1])) << 2)
533: | ( (0xf8 & (appleClut8[data + 2])) >> 3);
534: break;
535: default:
536: break;
537: }
538: }
539: dst = (unsigned char *) ((int)dst + console->display.rowBytes);
540: }
541: }
542:
543:
544:
545:
546: static void DrawColorRect( ConsolePtr console, int x, int y, int width, int height, unsigned char * dataPtr)
547: {
548: unsigned char *dst8;
549: int line,col;
550: unsigned int data;
551:
552: dst8 = (unsigned char *) PixelAddress(console, x, y);
553: for( line = 0; line < height; line++) {
554: for( col = 0; col < width; col++) {
555:
556: data = *dataPtr++;
557: if( data != 0x01) {
558: switch (console->display.bitsPerPixel) {
559: case IO_8BitsPerPixel:
560: if (console->display.colorSpace == IO_OneIsWhiteColorSpace) {
561: data *= 3;
562: *(dst8 + col) = ((19595 * appleClut8[data] +
563: 38470 * appleClut8[data + 1] +
564: 7471 * appleClut8[data + 2] ) / 65536);
565: } else {
566: *(dst8 + col) = data;
567: }
568: break;
569: case IO_24BitsPerPixel:
570: data *= 3;
571: *(((unsigned int *)dst8) + col) = (appleClut8[data] << 16)
572: | (appleClut8[data + 1] << 8)
573: | appleClut8[data + 2];
574: break;
575: case IO_15BitsPerPixel:
576: data *= 3;
577: *(((unsigned short *)dst8) + col) = ( (0xf8 & (appleClut8[data])) << 7)
578: | ( (0xf8 & (appleClut8[data + 1])) << 2)
579: | ( (0xf8 & (appleClut8[data + 2])) >> 3);
580: break;
581: default:
582: break;
583: }
584: }
585: }
586: dst8 = (unsigned char *) ((int)dst8 + console->display.rowBytes);
587: }
588: }
589:
590: static void DrawIcon( ConsolePtr console)
591: {
592:
593: #define ICON_WIDTH 11
594: #define ICON_HEIGHT 14
595:
596: static unsigned char iconData[ICON_WIDTH*ICON_HEIGHT] = {
597: 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xE3,0xE5,0x01,0x01,
598: 0x01,0x01,0x01,0x01,0x01,0x01,0xE3,0xE5,0xE8,0x01,0x01,
599: 0x01,0x01,0x01,0x01,0x01,0x01,0xE5,0xE8,0x01,0x01,0x01,
600: 0x01,0x01,0xE3,0xE3,0xE5,0x01,0x01,0xE3,0xE3,0xE8,0x01,
601: 0x01,0xE5,0x6F,0x26,0xE3,0xE3,0xE3,0xE3,0xE5,0xE6,0xE8,
602: 0x10,0x05,0x01,0x05,0x05,0x0A,0x11,0x10,0x17,0x5E,0x01,
603: 0x10,0x00,0x05,0x05,0x0B,0x0A,0x11,0x10,0x5F,0x01,0x01,
604: 0x3B,0x00,0x08,0x11,0x11,0x17,0x3B,0x3B,0x65,0x01,0x01,
605: 0x3B,0x00,0x08,0x11,0x17,0x17,0x17,0x3B,0x65,0x65,0x01,
606: 0xD8,0x07,0x14,0xD8,0xD8,0xD8,0xD8,0xD9,0xD9,0xDB,0x8F,
607: 0x14,0x3E,0x06,0x14,0x20,0x20,0x20,0x3E,0x3E,0x62,0x8D,
608: 0x01,0x3E,0x3E,0x14,0x20,0x20,0x3E,0x3E,0x62,0x8D,0x8D,
609: 0x01,0x01,0xEE,0xA3,0xA3,0xEF,0xCE,0xA3,0xCE,0xEF,0x01,
610: 0x01,0x01,0x01,0xEF,0xEF,0x01,0x01,0xEF,0xEF,0x01,0x01
611: };
612: int x,y; // location of upper left corner of glyph
613:
614: x = console->window_origin_x + console->curr_column * CHAR_W - ICON_WIDTH - 7; // left: BG_MARGIN + FG_MARGIN + 2;
615: y = console->window_origin_y + console->curr_row * CHAR_H - 4;
616:
617: DrawColorRect( console, x, y, ICON_WIDTH, ICON_HEIGHT, &iconData[0]);
618: }
619:
620: /*
621: * Expand a 1-bit PS bitmap, origin is lower left corner.
622: */
623: #import "kmFontPriv.h"
624:
625: void
626: BltPSBitmap(IOConsoleInfo *cso, int xpos, int ypos, bitmap_t *bmp,
627: const unsigned char *bits, int grayValue)
628: {
629: ConsolePtr console = (ConsolePtr)cso->priv;
630: int x, y;
631: int bitoffset;
632: unsigned char *pixAddr;
633: int fg;
634:
635: pixAddr = PixelAddress(console, (console->display.width / 2) + xpos + bmp->bbx.xoff,
636: ((console->display.height - 480) / 2) + ypos - bmp->bbx.yoff - bmp->bbx.height + 1);
637: fg = console->grayTable[ grayValue & 3 ];
638:
639: /*
640: * x and y are in fb coordinate system
641: * xoff and yoff are in ps coordinate system
642: */
643: for (y = 0; y < bmp->bbx.height; y++)
644: {
645: for (x = 0; x < bmp->bbx.width; x++)
646: {
647: bitoffset = bmp->bitx + y * bmp->bbx.width + x;
648: if( bits[bitoffset >> 3] & (0x80 >> (bitoffset & 0x7)))
649:
650: switch (console->display.bitsPerPixel)
651: {
652: case IO_8BitsPerPixel:
653: ((unsigned char *)pixAddr)[ x ] = fg;
654: break;
655: case IO_12BitsPerPixel:
656: case IO_15BitsPerPixel:
657: ((unsigned short *)pixAddr)[ x ] = fg;
658: break;
659:
660: case IO_24BitsPerPixel:
661: ((unsigned int *)pixAddr)[ x ] = fg;
662: break;
663: }
664: }
665: pixAddr += console->display.rowBytes;
666: }
667: }
668:
669: static void BltChar(ConsolePtr console, const char c)
670: // Description: Paint one character at (curr_column, curr_row).
671: {
672: unsigned char *glyphbase; // the glyph we're rendering
673: unsigned char byte;
674: unsigned char *pixAddr;
675: int x,y; // location of upper left corner of glyph
676: int source_y, bold;
677: unsigned char *dst8, fg8;
678: unsigned short *dst16, fg16;
679: unsigned int *dst32, fg32;
680:
681:
682: // Erase current contents of {curr_row, curr_column}.
683: Erase(console);
684:
685: // Skip non-printing characters.
686: if (c < ENCODEBASE) {
687: return;
688: }
689: bold = console->bolding;
690: x = console->window_origin_x + console->curr_column * CHAR_W;
691: y = console->window_origin_y + console->curr_row * CHAR_H;
692:
693: do {
694: glyphbase = ohlfs12[c - ENCODEBASE];
695: pixAddr = PixelAddress(console, x + bold, y);
696: switch (console->display.bitsPerPixel) {
697: case IO_8BitsPerPixel:
698: fg8 = (unsigned char) console->foreground;
699: dst8 = (unsigned char *) pixAddr;
700: for (source_y = CHAR_H; source_y != 0; source_y--) {
701: byte = *glyphbase++;
702: if (byte & 0x80) dst8[0] = fg8;
703: if (byte & 0x40) dst8[1] = fg8;
704: if (byte & 0x20) dst8[2] = fg8;
705: if (byte & 0x10) dst8[3] = fg8;
706: if (byte & 0x08) dst8[4] = fg8;
707: if (byte & 0x04) dst8[5] = fg8;
708: if (byte & 0x02) dst8[6] = fg8;
709: if (byte & 0x01) dst8[7] = fg8;
710: dst8 = (unsigned char *)
711: ((int)dst8 + console->display.rowBytes);
712: }
713: break;
714: case IO_12BitsPerPixel:
715: case IO_15BitsPerPixel:
716: fg16 = (unsigned short) console->foreground;
717: dst16 = (unsigned short *) pixAddr;
718: for (source_y = CHAR_H; source_y != 0; source_y--) {
719: byte = *glyphbase++;
720: if (byte & 0x80) dst16[0] = fg16;
721: if (byte & 0x40) dst16[1] = fg16;
722: if (byte & 0x20) dst16[2] = fg16;
723: if (byte & 0x10) dst16[3] = fg16;
724: if (byte & 0x08) dst16[4] = fg16;
725: if (byte & 0x04) dst16[5] = fg16;
726: if (byte & 0x02) dst16[6] = fg16;
727: if (byte & 0x01) dst16[7] = fg16;
728: dst16 = (unsigned short *)
729: ((int)dst16 + console->display.rowBytes);
730: }
731: break;
732: case IO_24BitsPerPixel:
733: fg32 = (unsigned int) console->foreground;
734: dst32 = (unsigned int *) pixAddr;
735: for (source_y = CHAR_H; source_y != 0; source_y--) {
736: byte = *glyphbase++;
737: if (byte & 0x80) dst32[0] = fg32;
738: if (byte & 0x40) dst32[1] = fg32;
739: if (byte & 0x20) dst32[2] = fg32;
740: if (byte & 0x10) dst32[3] = fg32;
741: if (byte & 0x08) dst32[4] = fg32;
742: if (byte & 0x04) dst32[5] = fg32;
743: if (byte & 0x02) dst32[6] = fg32;
744: if (byte & 0x01) dst32[7] = fg32;
745: dst32 = (unsigned int *)
746: ((int)dst32 + console->display.rowBytes);
747: }
748: break;
749: }
750: } while( bold--);
751: console->curr_column++;
752: return;
753: }
754:
755: extern void video_scroll_up(unsigned char * start, unsigned char * end, unsigned char * dest);
756:
757: static void FBPutC(ConsolePtr console, char c)
758: // Write one character to screen. Cursor is 'on' on entry and exit.
759: {
760: int repeat;
761: int i;
762:
763: /*
764: * First deal with ANSI escape sequences.
765: * This is a very bizarre implementation, copied from the m68k
766: * version.
767: */
768: switch(console->ansi_state) {
769: case AS_NORMAL:
770: if(c == esc) {
771: console->ansi_state = AS_ESCAPE;
772: return;
773: }
774: else {
775: break; // continue
776: }
777:
778: case AS_ESCAPE:
779: switch(c) {
780: case '[':
781: console->ansi_state = AS_BRACKET;
782: return;
783: default:
784: console->ansi_state = AS_NORMAL;
785: break; // continue
786: }
787:
788: case AS_BRACKET:
789: if(c >= '0' && c <= '9') {
790: *console->ansi_stack_p =
791: *console->ansi_stack_p * 10 + (c - '0');
792: return;
793: }
794: else if (c == ';') {
795: if(console->ansi_stack_p <
796: &console->ansi_stack[ANSI_STACK_SIZE]) {
797: console->ansi_stack_p++;
798: }
799: return;
800: }
801: else {
802: for(i=0; i<ANSI_STACK_SIZE; i++) {
803: if (console->ansi_stack[i] == 0) {
804: console->ansi_stack[i] = 1;
805: }
806: }
807: repeat = *console->ansi_stack_p;
808: FlipCursor(console); // cursor off
809: switch (c) {
810:
811: case 'A':
812: while (repeat--) {
813: if(console->curr_row) {
814: console->curr_row--;
815: }
816: }
817: break;
818:
819: case 'B':
820: while (repeat--) {
821: console->curr_row++;
822: }
823: break;
824:
825: case 'C': // non destructive space
826: while (repeat--) {
827: console->curr_column++;
828: }
829: break;
830:
831: case 'D': // not in termcap
832: while (repeat--) {
833: if(console->curr_column) {
834: console->curr_column--;
835: }
836: }
837: break;
838:
839: case 'E': // not in termcap
840: console->curr_column = 0;
841: while (repeat--) {
842: console->curr_row++;
843: }
844: break;
845:
846: case 'H': // should be home
847: case 'f': // not in termcap
848: console->curr_column =
849: *console->ansi_stack_p - 1;
850: console->ansi_stack_p--;
851: console->curr_row =
852: *console->ansi_stack_p - 1;
853: console->ansi_stack_p--;
854: break;
855:
856: case 'K':
857: ClearToEOL(console);
858: break;
859:
860: case 'm': /* FIXME */
861: console->ansi_stack_p--;
862: console->ansi_stack_p--;
863: break;
864: }
865: }
866: console->ansi_stack_p = &console->ansi_stack[1];
867: for(i=0; i<ANSI_STACK_SIZE; i++)
868: console->ansi_stack[i] = 0;
869: console->ansi_state = AS_NORMAL;
870: goto proceed;
871: }
872:
873: FlipCursor(console); // cursor off
874: switch(c) {
875: case '\r': // Carriage return
876: console->curr_column = 0;
877: break;
878:
879: case '\n': // line feed
880: console->curr_column = 0;
881: console->curr_row++;
882: break;
883:
884: case '\b': // backspace
885: if (console->curr_column == 0)
886: break;
887: console->curr_column--;
888: break;
889:
890: case '\t':
891: // tab. Erase all characters up to and including the
892: // next tab stop.
893: {
894: int col, num_cols;
895:
896: num_cols = TAB_SIZE - (console->curr_column % TAB_SIZE);
897: FlipCursor(console); // cursor on
898: for (col = 0; col<num_cols; col++) {
899: FBPutC(console, ' '); // cursor on at return
900: }
901: FlipCursor(console); // cursor off
902: break;
903: }
904:
905: case np: // aka ff, form feed
906: console->curr_row = console->curr_column = 0;
907: ClearWindow(console);
908: break;
909:
910: case del:
911: console->curr_column++;
912: break;
913:
914: default:
915: // Normal case.
916: BltChar(console, c);
917: break;
918: }
919:
920: // Cursor is off.
921: proceed:
922: if (console->curr_column >= console->chars_per_row) {
923: // End-of-line wrap.
924: console->curr_column = 0;
925: console->curr_row++;
926: }
927:
928: if (console->curr_row >= console->chars_per_column) {
929: //
930: // Screen scroll. Copy the whole window down in memory
931: // (pixels_per_row * CHAR_H) pixels, starting at
932: // the first character in row 1.
933: //
934: unsigned char *src;
935: unsigned char *dst;
936: int source_y;
937: unsigned windowRowBytes;
938:
939: console->curr_row = console->chars_per_column - 1;
940: switch (console->display.bitsPerPixel) {
941: case IO_8BitsPerPixel:
942: windowRowBytes = console->pixels_per_row;
943: break;
944: case IO_12BitsPerPixel:
945: case IO_15BitsPerPixel:
946: windowRowBytes = 2*console->pixels_per_row;
947: break;
948: case IO_24BitsPerPixel:
949: windowRowBytes = 4*console->pixels_per_row;
950: break;
951: default:
952: panic("FBConsole/FBPutC: bogus bitsPerPixel");
953: }
954:
955: // Copy one row at a time, moving each one up
956: // CHAR_H rows. Within the loop, just increment
957: // pixel pointers by one row's worth of pixels.
958: // Source starts at the left top of row 1; destination
959: // starts at left top of row 0.
960: //
961: src = PixelAddress(console,
962: console->window_origin_x,
963: console->window_origin_y + CHAR_H);
964: dst = PixelAddress(console,
965: console->window_origin_x,
966: console->window_origin_y);
967: for (source_y = CHAR_H; // top, row 1
968: source_y < console->pixels_per_column; // bottom
969: source_y++) {
970: #ifndef notDefUseFPU
971: video_scroll_up( src, src + windowRowBytes, dst);
972: #else
973: videoMemMove(dst, src, windowRowBytes);
974: #endif
975: src += console->display.rowBytes;
976: dst += console->display.rowBytes;
977: }
978:
979: console->curr_column = 0;
980: ClearToEOL(console);
981: }
982:
983: // Cursor back on.
984: FlipCursor(console);
985: }
986:
987: static void SetTitle(ConsolePtr console, const char *title)
988: // Description: Draw title bar if none exists, write specified title into it.
989: // Drawing a title bar involves snarfing up row 0 of the window
990: // and decreasing the usable size of the window by one row.
991: // Preconditions:
992: // * Cursor is 'on' on entry and will remain so on exit.
993: {
994: int saved_curr_row = console->curr_row;
995: int saved_curr_column = console->curr_column;
996: int saved_origin_y;
997: int title_len = strlen(title);
998: int pixel_num;
999:
1000: if ((title_len == 0) || (title_len > console->chars_per_row)) {
1001: IOLog("console: Illegal title length (%d)\n", title_len);
1002: return;
1003: }
1004: FlipCursor(console); // old cursor off
1005: if (console->has_title) {
1006: // First grow window by two rows - this absorbs the existing
1007: // title bar.
1008: console->window_origin_y -= CHAR_H * 2;
1009: console->chars_per_column += 2;
1010: console->pixels_per_column += CHAR_H * 2;
1011: saved_curr_row += 2;
1012: }
1013:
1014: // Clear row 0, center new title in it.
1015: console->curr_row = 0;
1016: Rect(console,
1017: console->window_origin_x - (BG_MARGIN - TS_MARGIN),
1018: console->window_origin_y - (BG_MARGIN - TS_MARGIN),
1019: CHAR_W * console->chars_per_row + 2 * (BG_MARGIN - TS_MARGIN),
1020: CHAR_H * 2 - TS_MARGIN,
1021: console->light_grey);
1022: saved_origin_y = console->window_origin_y;
1023: console->window_origin_y += CHAR_H / 2;
1024: console->curr_column = (console->chars_per_row - title_len) / 2;
1025: DrawIcon(console);
1026: // SwapForegroundAndBackground(console);
1027: console->bolding = 1;
1028: console->background = console->light_grey;
1029: FlipCursor(console); // new cursor on
1030: while (*title) {
1031: FBPutC(console, *title++);
1032: }
1033: FlipCursor(console); // new cursor off
1034: console->background = console->grayTable[0];
1035: console->bolding = 0;
1036: // SwapForegroundAndBackground(console);
1037: console->window_origin_y = saved_origin_y;
1038:
1039: // Draw grey lines one pixel away from border of title bar.
1040: // Origin is currently at first pixel in top line of title bar.
1041:
1042: Rect(console, // inside top
1043: console->window_origin_x - BG_MARGIN,
1044: console->window_origin_y - BG_MARGIN,
1045: console->pixels_per_row + (BG_MARGIN * 2),
1046: TS_MARGIN,
1047: console->background);
1048: Rect(console, // inside bottom
1049: console->window_origin_x - BG_MARGIN,
1050: console->window_origin_y + CHAR_H * 2 - TOTAL_MARGIN - TS_MARGIN,
1051: console->pixels_per_row + BG_MARGIN * 2,
1052: TS_MARGIN,
1053: console->dark_grey);
1054: for (pixel_num = 0; pixel_num < TS_MARGIN; pixel_num++) {
1055: Rect(console, // left
1056: console->window_origin_x - BG_MARGIN + pixel_num,
1057: console->window_origin_y - BG_MARGIN + pixel_num,
1058: 1,
1059: CHAR_H * 2 - 1 - (pixel_num * 2),
1060: console->background);
1061: }
1062: for (pixel_num = 1 + BG_MARGIN - TS_MARGIN; pixel_num <= BG_MARGIN; pixel_num++) {
1063: Rect(console, // right
1064: console->window_origin_x + console->pixels_per_row + pixel_num - 1,
1065: console->window_origin_y - pixel_num,
1066: 1,
1067: CHAR_H * 2 - 1 - (BG_MARGIN - pixel_num) * 2,
1068: console->dark_grey);
1069: }
1070: Rect(console, // outside bottom
1071: console->window_origin_x - TOTAL_MARGIN,
1072: console->window_origin_y + CHAR_H * 2 - FG_MARGIN - BG_MARGIN,
1073: console->pixels_per_row + TOTAL_MARGIN * 2,
1074: FG_MARGIN,
1075: console->foreground);
1076:
1077: // Diminish window size by two rows.
1078: console->window_origin_y += CHAR_H * 2;
1079: console->chars_per_column -= 2;
1080: console->pixels_per_column -= CHAR_H * 2;
1081:
1082:
1083: // Restore old cursor. Careful, the y axis just changed...
1084: console->curr_column = saved_curr_column;
1085: if (saved_curr_row > 0) {
1086: console->curr_row = saved_curr_row - 2;
1087: }
1088: else {
1089: // New row 0 - clear it.
1090: ClearToEOL(console);
1091: }
1092: FlipCursor(console); // old cursor on
1093: console->has_title = TRUE;
1094: }
1095:
1096:
1097: static void UpdateWindowChars(ConsolePtr console)
1098: // Description: Calculate window size in characters. Used when either window
1099: // size or font changes.
1100: {
1101: console->chars_per_row = console->pixels_per_row / CHAR_W;
1102: console->chars_per_column =
1103: console->pixels_per_column / CHAR_H;
1104: }
1105:
1106:
1107:
1108: static void InitWindow(ConsolePtr console,
1109: int width,
1110: int height,
1111: const char *title,
1112: boolean_t initWindow,
1113: boolean_t saveUnder)
1114: // Description: Initialize window parameters. If initWindow is TRUE, an empty
1115: // window is drawn in the screen, else we assume that a window
1116: // already exists. Screen and font parameters must be valid on
1117: // entry.
1118: {
1119: // Truncate specified size to integral mutliple of character size
1120: // in both dimensions.
1121: width /= CHAR_W; // now in chars
1122: height /= CHAR_H;
1123: width *= CHAR_W; // now in pixels
1124: height *= CHAR_H;
1125:
1126: // Ensure there's enough room for a border.
1127: if (width > (console->display.width - HORIZ_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW))
1128: width = console->display.width - HORIZ_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW;
1129: if (height > (console->display.height - VERT_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW))
1130: height = console->display.height - VERT_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW;
1131: width &= 0xfffffffe;
1132:
1133: //
1134: // Init console window variables. The window is centered in the
1135: // ! screen, minus a pixel or two to guarantee double word alignment
1136: // ! for the first pixel of a row (until further developments...when
1137: // ! we do alert panels, we can enumerate some cases here...).
1138: //
1139: console->window_origin_x = (console->display.width - width) / 2;
1140: console->window_origin_y = (console->display.height - height) / 2;
1141: console->pixels_per_row = width;
1142: console->pixels_per_column = height;
1143: (unsigned)console->window_origin_x &= 0xfffffffe;
1144:
1145: UpdateWindowChars(console);
1146:
1147: console->curr_column = 0;
1148: console->has_title = FALSE;
1149:
1150: if (initWindow) {
1151: // Before we start drawing anything, save under if needed
1152: if (saveUnder) {
1153: int i, bytesPerPixel = 0;
1154: unsigned char *save, *sp;
1155:
1156: // Compute size of save under region in bytes and allocate
1157: switch (console->display.bitsPerPixel) {
1158: case IO_8BitsPerPixel: bytesPerPixel = 1; break;
1159: case IO_12BitsPerPixel:
1160: case IO_15BitsPerPixel: bytesPerPixel = 2; break;
1161: case IO_24BitsPerPixel: bytesPerPixel = 4; break;
1162: }
1163: console->saveHeight = height + TOTAL_MARGIN * 2 + DROP_SHADOW;
1164: console->saveRowBytes = (width + TOTAL_MARGIN * 2 + DROP_SHADOW)*bytesPerPixel;
1165: console->saveBytes = console->saveHeight*console->saveRowBytes;
1166: save = console->saveBits = (unsigned char *)
1167: kalloc_noblock(console->saveBytes);
1168: sp = console->saveLocation =
1169: PixelAddress(console, console->window_origin_x - TOTAL_MARGIN,
1170: console->window_origin_y - TOTAL_MARGIN);
1171:
1172: // Copy the window contents into the save under
1173: if( save)
1174: for (i = console->saveHeight; i != 0; i--) {
1175: videoMemMove(save, sp, console->saveRowBytes);
1176: sp += console->display.rowBytes;
1177: save += console->saveRowBytes;
1178: }
1179: }
1180:
1181: // New window - cursor at origin.
1182: console->curr_row = 0;
1183: console->has_title = FALSE;
1184:
1185: // Draw the border. The border goes outside of the specified
1186: // window. Outside lines are black; inside lines are
1187: // half-tone.
1188: Rect(console, // outside top
1189: console->window_origin_x - TOTAL_MARGIN,
1190: console->window_origin_y - TOTAL_MARGIN,
1191: width + TOTAL_MARGIN * 2,
1192: FG_MARGIN,
1193: console->foreground);
1194: Rect(console, // inside top
1195: console->window_origin_x - BG_MARGIN,
1196: console->window_origin_y - BG_MARGIN,
1197: width + BG_MARGIN * 2,
1198: BG_MARGIN,
1199: console->background);
1200: Rect(console, // inside bottom
1201: console->window_origin_x - BG_MARGIN,
1202: console->window_origin_y + height,
1203: width + BG_MARGIN * 2,
1204: BG_MARGIN,
1205: console->background);
1206: Rect(console, // outside bottom
1207: console->window_origin_x - TOTAL_MARGIN,
1208: console->window_origin_y + height + BG_MARGIN,
1209: width + TOTAL_MARGIN * 2,
1210: FG_MARGIN,
1211: console->foreground);
1212: if( DROP_SHADOW) Rect(console, // outside bottom shadow
1213: console->window_origin_x - TOTAL_MARGIN + DROP_SHADOW,
1214: console->window_origin_y + height + BG_MARGIN + DROP_SHADOW,
1215: width + TOTAL_MARGIN * 2,
1216: DROP_SHADOW,
1217: console->dark_grey);
1218: Rect(console, // outside left
1219: console->window_origin_x - TOTAL_MARGIN,
1220: console->window_origin_y - TOTAL_MARGIN,
1221: FG_MARGIN,
1222: height + TOTAL_MARGIN * 2,
1223: console->foreground);
1224: Rect(console, // inside left
1225: console->window_origin_x - BG_MARGIN,
1226: console->window_origin_y - BG_MARGIN,
1227: BG_MARGIN,
1228: height + BG_MARGIN * 2,
1229: console->background);
1230: Rect(console, // inside right
1231: console->window_origin_x + width,
1232: console->window_origin_y - BG_MARGIN,
1233: BG_MARGIN,
1234: height + BG_MARGIN * 2,
1235: console->background);
1236: Rect(console, // outside right
1237: console->window_origin_x + width + BG_MARGIN,
1238: console->window_origin_y - TOTAL_MARGIN,
1239: FG_MARGIN,
1240: height + TOTAL_MARGIN * 2,
1241: console->foreground);
1242: if( DROP_SHADOW) Rect(console, // outside right shadow
1243: console->window_origin_x + width + BG_MARGIN + DROP_SHADOW,
1244: console->window_origin_y - TOTAL_MARGIN + DROP_SHADOW,
1245: DROP_SHADOW,
1246: height + TOTAL_MARGIN * 2,
1247: console->dark_grey);
1248:
1249: // Clear the contents of the window and draw a cursor.
1250: ClearWindow(console);
1251: FlipCursor(console); // cursor on
1252: SetTitle(console, title);
1253: }
1254: else {
1255: /* Leave current window contents, just updating title.
1256: * We'll do a newline to make sure we have room for
1257: * our font and proceed.Initial cursor will be at
1258: * lower left corner.
1259: */
1260: console->curr_row = console->chars_per_column - 1;
1261: SetTitle(console, title);
1262: FBPutC(console, '\n');
1263: }
1264: return;
1265: }
1266:
1267: //
1268: // END: Private utility routines
1269: //
1270:
1271: //
1272: // BEGIN: Implementation of IOConsoleInfo functions
1273: //
1274: static void Free(IOConsoleInfo *cso)
1275: // Description: Free a FB Console object
1276: {
1277: IOFree(cso->priv, sizeof(ConsoleRep));
1278: IOFree(cso, sizeof(IOConsoleInfo));
1279: }
1280:
1281: static void Init(
1282: IOConsoleInfo *cso,
1283: ScreenMode mode,
1284: boolean_t initScreenOrSaveUnder,
1285: boolean_t initWindow,
1286: const char *title)
1287: {
1288: ConsolePtr console = (ConsolePtr)cso->priv;
1289: int i;
1290:
1291: switch (console->display.bitsPerPixel) {
1292: case IO_8BitsPerPixel:
1293: if (console->display.colorSpace == IO_OneIsWhiteColorSpace) {
1294: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 107 : 0x55;
1295: console->background = 0xff;
1296: console->foreground = 0x00;
1297: console->dark_grey = 85;
1298: console->light_grey = 187;
1299: } else {
1300: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 0x80 : 0x7e;
1301: console->background = 0x00;
1302: console->foreground = 0xff;
1303: console->dark_grey = 0xfb;
1304: console->light_grey = 0xf7;
1305: }
1306: break;
1307: case IO_15BitsPerPixel:
1308: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 0x3193 : 0x295f;
1309: console->background = 0x7fff;
1310: console->foreground = 0x0000;
1311: console->dark_grey = 0x294a;
1312: console->light_grey = 0x5ef7;
1313: break;
1314: case IO_24BitsPerPixel:
1315: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 0xff666699 : 0xff5555ff;
1316: console->background = 0xffffffff;
1317: console->foreground = 0xff000000;
1318: console->dark_grey = 0xff555555;
1319: console->light_grey = 0xffbbbbbb;
1320: break;
1321: }
1322:
1323: console->grayTable[0] = console->background;
1324: console->grayTable[1] = console->light_grey;
1325: console->grayTable[2] = console->dark_grey;
1326: console->grayTable[3] = console->foreground;
1327:
1328: console->ansi_state = AS_NORMAL;
1329: for(i=0; i<ANSI_STACK_SIZE; i++) {
1330: console->ansi_stack[i] = 0;
1331: }
1332: console->ansi_stack_p = &console->ansi_stack[1]; // FIXME - why not 0?
1333:
1334: // Initialize the screen, if appropriate.
1335: if (initScreenOrSaveUnder && (mode != SCM_ALERT)) {
1336: WipeScreen(console, console->baseground);
1337: }
1338:
1339: console->window_type = mode;
1340: switch(console->window_type) {
1341: case SCM_TEXT:
1342: InitWindow(console, TEXT_WIN_WIDTH, TEXT_WIN_HEIGHT,
1343: title, initWindow, 0 /* Don't save under */);
1344: break;
1345: case SCM_ALERT:
1346: InitWindow(console, ALERT_WIN_WIDTH, ALERT_WIN_HEIGHT,
1347: title, initWindow, initScreenOrSaveUnder );
1348: break;
1349: case SCM_GRAPHIC:
1350: if( initScreenOrSaveUnder) {
1351: int cx, cy;
1352:
1353: cx = console->display.width / 2;
1354: cy = console->display.height / 2;
1355: Expand4ToN( console, cx + RIGHT_DX, cy + RIGHT_DY,
1356: RIGHT_WIDTH, RIGHT_HEIGHT, rightData, rightBotColors );
1357: Expand4ToN( console, cx + CENTER_DX, cy + CENTER_DY,
1358: CENTER_WIDTH, CENTER_HEIGHT, centerData, centerColors );
1359: Expand4ToN( console, cx + BOTTOM_DX, cy + BOTTOM_DY,
1360: BOTTOM_WIDTH, BOTTOM_HEIGHT, bottomData, rightBotColors );
1361: }
1362: break;
1363:
1364: default:
1365: panic("FBConsole/FBInitConsole: can't init");
1366: break;
1367: }
1368: return;
1369: }
1370:
1371: static int Restore(IOConsoleInfo *cso)
1372: {
1373: ConsolePtr console = (ConsolePtr)cso->priv;
1374: unsigned char *save, *dp;
1375: int i;
1376:
1377: if (console->window_type != SCM_ALERT) {
1378: IOLog("frameBuffer: bogus restore, mode %d\n", console->window_type);
1379: return -1;
1380: }
1381:
1382: // Copy save under bits back onto screen
1383: save = console->saveBits;
1384: dp = console->saveLocation;
1385: if( save) {
1386: for (i = console->saveHeight; i != 0; i--) {
1387: videoMemMove(dp, save, console->saveRowBytes);
1388: dp += console->display.rowBytes;
1389: save += console->saveRowBytes;
1390: }
1391:
1392: // Free bits
1393: kfree(console->saveBits, console->saveBytes);
1394: console->saveBits = 0;
1395: }
1396: return 0;
1397: }
1398:
1399: #define VIDEO_W 640
1400: #define VIDEO_H 480
1401:
1402: static int DrawRect(IOConsoleInfo *cso, const struct km_drawrect *km_rect)
1403: // Description: Given a 2 bit raster, convert it to the format appropriate for
1404: // the display. The co-ordinates passed in by these ioctls assume
1405: // an (VIDEO_W x VIDEO_H) screen. All screen sizes are
1406: // assumed to share a common center point. We scale the X and Y
1407: // values to maintain a constant offset from the center point,
1408: // so that boot animations, popup windows, and related goodies
1409: // don't break with screens larger or smaller than the 'default'
1410: // screen.
1411: // Preconditions:
1412: // * The rectangle that we are to draw must start on a 4 pixel boundary
1413: // and should be a multiple of 4 pixels in width.
1414: {
1415: ConsolePtr console = (ConsolePtr)cso->priv;
1416: int pixel; /* Starting pixel in screen */
1417: int i, x, y;
1418: unsigned char *data;
1419: unsigned char value;
1420: unsigned int * table;
1421: struct km_drawrect *rect = (struct km_drawrect *) km_rect;
1422: int bgX, bgY, bgH;
1423: unsigned char * bg;
1424:
1425: table = console->grayTable;
1426:
1427: /* copyin is done in km */
1428: data = rect->data.bits;
1429:
1430: x = (rect->x & 0x1ffc) + (console->display.width - VIDEO_W)/2;
1431: y = rect->y + (console->display.height - VIDEO_H)/2;
1432:
1433: /* Correct the x and y values for screen size */
1434: if( (rect->x & 3) == 3) {
1435: DrawColorRect( console, x, y, rect->width, rect->height, data);
1436: return 0;
1437: }
1438:
1439: #if TEXTURE_BACKGND
1440: bgX = console->display.width / 2 + CENTER_DX;
1441: bgY = console->display.height / 2 + CENTER_DY;
1442:
1443: bgH = (y - bgY) & -2;
1444: if( bgH > 0) {
1445: bgY += bgH;
1446: bg = centerData + (bgH * CENTER_WIDTH) / 2;
1447: bgH = CENTER_HEIGHT - bgH;
1448: } else
1449: bg = (unsigned char *)0;
1450: #endif
1451:
1452: rect->x &= 0x1ffc;
1453:
1454: /* Sanity check */
1455: if ((x + rect->width > console->display.width)
1456: || (y + rect->height) > console->display.height)
1457: return( -1 );
1458:
1459:
1460: pixel = x + (y * console->display.totalWidth);
1461:
1462: switch ( console->display.bitsPerPixel )
1463: {
1464: case IO_2BitsPerPixel: /* 2 bit pixels */
1465: {
1466: unsigned char *dst = (unsigned char *)console->display.frameBuffer;
1467: unsigned char *fb;
1468: unsigned char final_value;
1469:
1470: dst += pixel >> 2;
1471: for ( y = 0; y < rect->height; ++y ) {
1472: fb = dst;
1473: for ( x = 0; x < rect->width; x += 4) {
1474: value = *data++;
1475: final_value = 0;
1476: for ( i = 0; i < 8; i += 2 ) {
1477: final_value |= ((table[(value>>i)&3] & 3) << i);
1478: }
1479: *fb++ = final_value;
1480: }
1481: dst += console->display.rowBytes;
1482: }
1483: break;
1484: }
1485: case IO_8BitsPerPixel: /* 8 bit pixels */
1486: {
1487: unsigned char *dst = (unsigned char *)console->display.frameBuffer;
1488: unsigned char *fb;
1489:
1490: dst += pixel;
1491: for ( y = 0; y < rect->height; ++y ) {
1492: fb = dst;
1493: #if TEXTURE_BACKGND
1494: if( ((y & 1) == 0) && bg) {
1495: Expand4ToN( console, bgX, bgY,
1496: CENTER_WIDTH, 2, bg, centerColors );
1497: bgY += 2;
1498: bg += CENTER_WIDTH;
1499: }
1500: #endif
1501: for ( x = 0; x < rect->width; x += 4) {
1502: value = *data++;
1503: if( value) {
1504: int pix;
1505: pix = (value >> 6) & 3;
1506: if( pix)
1507: fb[0] = table[pix];
1508: pix = (value >> 4) & 3;
1509: if( pix)
1510: fb[1] = table[pix];
1511: pix = (value >> 2) & 3;
1512: if( pix)
1513: fb[2] = table[pix];
1514: pix = value & 3;
1515: if( pix)
1516: fb[3] = table[pix];
1517: }
1518: fb += 4;
1519: }
1520: dst += console->display.rowBytes;
1521: }
1522: break;
1523: }
1524: case IO_12BitsPerPixel: /* 16 bit pixels */
1525: case IO_15BitsPerPixel: /* 16 bit pixels */
1526: {
1527:
1528: unsigned short *dst = (unsigned short *)console->display.frameBuffer;
1529: unsigned short *fb;
1530: dst += pixel;
1531:
1532: for ( y = 0; y < rect->height; ++y ) {
1533: fb = dst;
1534: #if TEXTURE_BACKGND
1535: if( ((y & 1) == 0) && bg) {
1536: Expand4ToN( console, bgX, bgY,
1537: CENTER_WIDTH, 2, bg, centerColors );
1538: bgY += 2;
1539: bg += CENTER_WIDTH;
1540: }
1541: #endif
1542: for ( x = 0; x < rect->width; x += 4) {
1543: value = *data++;
1544: if( value) {
1545: int pix;
1546: pix = (value >> 6) & 3;
1547: if( pix)
1548: fb[0] = table[pix];
1549: pix = (value >> 4) & 3;
1550: if( pix)
1551: fb[1] = table[pix];
1552: pix = (value >> 2) & 3;
1553: if( pix)
1554: fb[2] = table[pix];
1555: pix = value & 3;
1556: if( pix)
1557: fb[3] = table[pix];
1558: }
1559: fb += 4;
1560: }
1561: dst = (unsigned short *)(((char*)dst) +
1562: console->display.rowBytes);
1563: }
1564: break;
1565: }
1566: case IO_24BitsPerPixel: /* 32 bit pixels */
1567: {
1568: unsigned int *dst = (unsigned int *) console->display.frameBuffer;
1569: unsigned int *fb;
1570:
1571: dst += pixel;
1572: for ( y = 0; y < rect->height; ++y ) {
1573: fb = dst;
1574: #if TEXTURE_BACKGND
1575: if( ((y & 1) == 0) && bg) {
1576: Expand4ToN( console, bgX, bgY,
1577: CENTER_WIDTH, 2, bg, centerColors );
1578: bgY += 2;
1579: bg += CENTER_WIDTH;
1580: }
1581: #endif
1582: for ( x = 0; x < rect->width; x += 4) {
1583: value = *data++;
1584: if( value) {
1585: int pix;
1586: pix = (value >> 6) & 3;
1587: if( pix)
1588: fb[0] = table[pix];
1589: pix = (value >> 4) & 3;
1590: if( pix)
1591: fb[1] = table[pix];
1592: pix = (value >> 2) & 3;
1593: if( pix)
1594: fb[2] = table[pix];
1595: pix = value & 3;
1596: if( pix)
1597: fb[3] = table[pix];
1598: }
1599: fb += 4;
1600: }
1601: dst = (unsigned int *)(((char*)dst) +
1602: console->display.rowBytes);
1603: }
1604: break;
1605: }
1606: }
1607: return 0;
1608: }
1609:
1610: static int EraseRect(IOConsoleInfo *cso, const struct km_drawrect *km_rect)
1611: // Description: Erase the specified rectangle to the color specified
1612: // in the km_rect structure.
1613: // Preconditions:
1614: // * The rectangle that we are to erase must start on a 4 pixel boundary
1615: // and should be a multiple of 4 pixels in width.
1616: {
1617: ConsolePtr console = (ConsolePtr)cso->priv;
1618: int pixel; // Starting pixel in screen
1619: int x, y, w, h;
1620: unsigned int value;
1621: struct km_drawrect *rect = (struct km_drawrect *) km_rect;
1622: int bgX, bgY, bgH;
1623: unsigned char * bg;
1624:
1625: value = console->grayTable[ rect->data.fill & 3 ];
1626:
1627: /* Correct the x and y values for screen size */
1628: x = rect->x + (console->display.width - VIDEO_W)/2;
1629: y = rect->y + (console->display.height - VIDEO_H)/2;
1630:
1631: x &= ~3; // Trunc to 4 pixel boundary
1632: w = (rect->width) & ~3; // Round dn to 4 pixel boundary
1633: h = rect->height;
1634:
1635: /* Sanity check */
1636: /* Sanity check */
1637: if (((x + w) > console->display.width)
1638: || ((y + h) > console->display.height) )
1639: return( -1 );
1640:
1641:
1642: #if TEXTURE_BACKGND
1643: bgX = console->display.width / 2 + CENTER_DX;
1644: bgY = console->display.height / 2 + CENTER_DY;
1645:
1646: bgH = (y - bgY) & -2;
1647: if( bgH > 0) {
1648: bgY += bgH;
1649: bg = centerData + (bgH * CENTER_WIDTH) / 2;
1650: bgH = CENTER_HEIGHT - bgH;
1651: Expand4ToN( console, bgX, bgY,
1652: CENTER_WIDTH, bgH, bg, centerColors );
1653: }
1654:
1655: #else
1656: Rect( console, x, y, w, h, value);
1657: #endif
1658:
1659: return 0;
1660: }
1661:
1662: //extern void czputc( char c);
1663:
1664: static void PutC(IOConsoleInfo *cso, char c)
1665: // Write one character to screen. Cursor is 'on' on entry and exit.
1666: {
1667: FBPutC((ConsolePtr)cso->priv, c);
1668: // czputc(c);
1669: }
1670:
1671: static void GetSize(IOConsoleInfo *cso, struct ConsoleSize *s)
1672: // Return the size of the screen in pixels
1673: {
1674: ConsolePtr console = (ConsolePtr)cso->priv;
1675: s->cols = console->chars_per_row;
1676: s->rows = console->chars_per_column;
1677: s->pixel_width = console->display.width;
1678: s->pixel_height = console->display.height;
1679: }
1680:
1681: //
1682: // END: Implementation of IOConsoleInfo functions
1683: //
1684:
1685: static IOConsoleInfo staticConsoleInfo;
1686: static ConsoleRep staticConsoleRep;
1687:
1688: static void InitializeConsole( IOConsoleInfo *cso, IODisplayInfo *display )
1689: {
1690: cso->Init = Init;
1691: cso->Restore = Restore;
1692: cso->DrawRect = DrawRect;
1693: cso->EraseRect = EraseRect;
1694: cso->PutC = PutC;
1695: cso->GetSize = GetSize;
1696: ((ConsolePtr)cso->priv)->display = *display;
1697: ((ConsolePtr)cso->priv)->window_type = SCM_UNINIT;
1698: return;
1699: }
1700:
1701: //
1702: // BEGIN: Exported routines
1703: //
1704:
1705: static void DoNothing(IOConsoleInfo *cso)
1706: {
1707: }
1708:
1709: IOConsoleInfo *BasicAllocateConsole(IODisplayInfo *display)
1710: {
1711: // No memory allocation. Assume non backed window.
1712: IOConsoleInfo *cso = &staticConsoleInfo;
1713: cso->priv = (void *)&staticConsoleRep;
1714: InitializeConsole(cso, display);
1715: cso->Free = DoNothing;
1716: #if 0
1717: printf("base:%x rowBytes:%x width:%x height:%x\n",display->frameBuffer,
1718: display->rowBytes, display->width, display->height);
1719: #endif
1720: return cso;
1721: }
1722:
1723:
1724: IOConsoleInfo *FBAllocateConsole(IODisplayInfo *display)
1725: {
1726: IOConsoleInfo *cso = (IOConsoleInfo *)IOMalloc(sizeof(IOConsoleInfo));
1727:
1728: if (cso == NIL)
1729: return NIL;
1730: cso->priv = (void *)IOMalloc(sizeof(ConsoleRep));
1731: if (cso->priv == NIL)
1732: {
1733: IOFree(cso, sizeof(IOConsoleInfo));
1734: return NIL;
1735: }
1736: InitializeConsole(cso, display);
1737: cso->Free = Free;
1738: return cso;
1739: }
1740:
1741:
1742: //
1743: // END: Exported routines
1744: //
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.