|
|
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:
1.1.1.2 ! root 497: static void Expand4Or8ToN( ConsolePtr console, int x, int y, int width, int height,
! 498: unsigned char * dataPtr, unsigned char * map16)
1.1 root 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) {
1.1.1.2 ! root 507: if( map16) {
! 508: if( bit)
! 509: data8 = *dataPtr++;
! 510: data = map16[ (data8 >> bit) & 15];
! 511: } else {
! 512: data = data8 = *dataPtr++;
! 513: }
1.1 root 514: switch (console->display.bitsPerPixel) {
515: case IO_8BitsPerPixel:
516: if (console->display.colorSpace != IO_OneIsWhiteColorSpace)
517: *(dst + col) = data;
518: else {
519: data *= 3;
520: *(dst + col) = ((19595 * appleClut8[data] +
521: 38470 * appleClut8[data + 1] +
522: 7471 * appleClut8[data + 2] ) / 65536);
523:
524: }
525: break;
526: case IO_24BitsPerPixel:
527: data *= 3;
528: *(((unsigned int *)dst) + col) = (appleClut8[data] << 16)
529: | (appleClut8[data + 1] << 8)
530: | appleClut8[data + 2];
531: break;
532: case IO_15BitsPerPixel:
533: data *= 3;
534: *(((unsigned short *)dst) + col) = ( (0xf8 & (appleClut8[data])) << 7)
535: | ( (0xf8 & (appleClut8[data + 1])) << 2)
536: | ( (0xf8 & (appleClut8[data + 2])) >> 3);
537: break;
538: default:
539: break;
540: }
541: }
542: dst = (unsigned char *) ((int)dst + console->display.rowBytes);
543: }
544: }
545:
1.1.1.2 ! root 546: static void Expand4ToN( ConsolePtr console, int x, int y, int width, int height,
! 547: unsigned char * dataPtr, unsigned char * map16)
! 548: {
! 549: Expand4Or8ToN(console, x, y, width, height, dataPtr, map16);
! 550: }
1.1 root 551:
1.1.1.2 ! root 552: static void Expand8ToN( ConsolePtr console, int x, int y, int width, int height,
! 553: unsigned char * dataPtr)
! 554: {
! 555: Expand4Or8ToN(console, x, y, width, height, dataPtr, 0);
! 556: }
1.1 root 557:
558: static void DrawColorRect( ConsolePtr console, int x, int y, int width, int height, unsigned char * dataPtr)
559: {
560: unsigned char *dst8;
561: int line,col;
562: unsigned int data;
563:
564: dst8 = (unsigned char *) PixelAddress(console, x, y);
565: for( line = 0; line < height; line++) {
566: for( col = 0; col < width; col++) {
567:
568: data = *dataPtr++;
569: if( data != 0x01) {
570: switch (console->display.bitsPerPixel) {
571: case IO_8BitsPerPixel:
572: if (console->display.colorSpace == IO_OneIsWhiteColorSpace) {
573: data *= 3;
574: *(dst8 + col) = ((19595 * appleClut8[data] +
575: 38470 * appleClut8[data + 1] +
576: 7471 * appleClut8[data + 2] ) / 65536);
577: } else {
578: *(dst8 + col) = data;
579: }
580: break;
581: case IO_24BitsPerPixel:
582: data *= 3;
583: *(((unsigned int *)dst8) + col) = (appleClut8[data] << 16)
584: | (appleClut8[data + 1] << 8)
585: | appleClut8[data + 2];
586: break;
587: case IO_15BitsPerPixel:
588: data *= 3;
589: *(((unsigned short *)dst8) + col) = ( (0xf8 & (appleClut8[data])) << 7)
590: | ( (0xf8 & (appleClut8[data + 1])) << 2)
591: | ( (0xf8 & (appleClut8[data + 2])) >> 3);
592: break;
593: default:
594: break;
595: }
596: }
597: }
598: dst8 = (unsigned char *) ((int)dst8 + console->display.rowBytes);
599: }
600: }
601:
602: static void DrawIcon( ConsolePtr console)
603: {
604:
605: #define ICON_WIDTH 11
606: #define ICON_HEIGHT 14
607:
608: static unsigned char iconData[ICON_WIDTH*ICON_HEIGHT] = {
609: 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xE3,0xE5,0x01,0x01,
610: 0x01,0x01,0x01,0x01,0x01,0x01,0xE3,0xE5,0xE8,0x01,0x01,
611: 0x01,0x01,0x01,0x01,0x01,0x01,0xE5,0xE8,0x01,0x01,0x01,
612: 0x01,0x01,0xE3,0xE3,0xE5,0x01,0x01,0xE3,0xE3,0xE8,0x01,
613: 0x01,0xE5,0x6F,0x26,0xE3,0xE3,0xE3,0xE3,0xE5,0xE6,0xE8,
614: 0x10,0x05,0x01,0x05,0x05,0x0A,0x11,0x10,0x17,0x5E,0x01,
615: 0x10,0x00,0x05,0x05,0x0B,0x0A,0x11,0x10,0x5F,0x01,0x01,
616: 0x3B,0x00,0x08,0x11,0x11,0x17,0x3B,0x3B,0x65,0x01,0x01,
617: 0x3B,0x00,0x08,0x11,0x17,0x17,0x17,0x3B,0x65,0x65,0x01,
618: 0xD8,0x07,0x14,0xD8,0xD8,0xD8,0xD8,0xD9,0xD9,0xDB,0x8F,
619: 0x14,0x3E,0x06,0x14,0x20,0x20,0x20,0x3E,0x3E,0x62,0x8D,
620: 0x01,0x3E,0x3E,0x14,0x20,0x20,0x3E,0x3E,0x62,0x8D,0x8D,
621: 0x01,0x01,0xEE,0xA3,0xA3,0xEF,0xCE,0xA3,0xCE,0xEF,0x01,
622: 0x01,0x01,0x01,0xEF,0xEF,0x01,0x01,0xEF,0xEF,0x01,0x01
623: };
624: int x,y; // location of upper left corner of glyph
625:
626: x = console->window_origin_x + console->curr_column * CHAR_W - ICON_WIDTH - 7; // left: BG_MARGIN + FG_MARGIN + 2;
627: y = console->window_origin_y + console->curr_row * CHAR_H - 4;
628:
629: DrawColorRect( console, x, y, ICON_WIDTH, ICON_HEIGHT, &iconData[0]);
630: }
631:
632: /*
633: * Expand a 1-bit PS bitmap, origin is lower left corner.
634: */
635: #import "kmFontPriv.h"
636:
637: void
638: BltPSBitmap(IOConsoleInfo *cso, int xpos, int ypos, bitmap_t *bmp,
639: const unsigned char *bits, int grayValue)
640: {
641: ConsolePtr console = (ConsolePtr)cso->priv;
642: int x, y;
643: int bitoffset;
644: unsigned char *pixAddr;
645: int fg;
646:
647: pixAddr = PixelAddress(console, (console->display.width / 2) + xpos + bmp->bbx.xoff,
648: ((console->display.height - 480) / 2) + ypos - bmp->bbx.yoff - bmp->bbx.height + 1);
649: fg = console->grayTable[ grayValue & 3 ];
650:
651: /*
652: * x and y are in fb coordinate system
653: * xoff and yoff are in ps coordinate system
654: */
655: for (y = 0; y < bmp->bbx.height; y++)
656: {
657: for (x = 0; x < bmp->bbx.width; x++)
658: {
659: bitoffset = bmp->bitx + y * bmp->bbx.width + x;
660: if( bits[bitoffset >> 3] & (0x80 >> (bitoffset & 0x7)))
661:
662: switch (console->display.bitsPerPixel)
663: {
664: case IO_8BitsPerPixel:
665: ((unsigned char *)pixAddr)[ x ] = fg;
666: break;
667: case IO_12BitsPerPixel:
668: case IO_15BitsPerPixel:
669: ((unsigned short *)pixAddr)[ x ] = fg;
670: break;
671:
672: case IO_24BitsPerPixel:
673: ((unsigned int *)pixAddr)[ x ] = fg;
674: break;
675: }
676: }
677: pixAddr += console->display.rowBytes;
678: }
679: }
680:
681: static void BltChar(ConsolePtr console, const char c)
682: // Description: Paint one character at (curr_column, curr_row).
683: {
684: unsigned char *glyphbase; // the glyph we're rendering
685: unsigned char byte;
686: unsigned char *pixAddr;
687: int x,y; // location of upper left corner of glyph
688: int source_y, bold;
689: unsigned char *dst8, fg8;
690: unsigned short *dst16, fg16;
691: unsigned int *dst32, fg32;
692:
693:
694: // Erase current contents of {curr_row, curr_column}.
695: Erase(console);
696:
697: // Skip non-printing characters.
698: if (c < ENCODEBASE) {
699: return;
700: }
701: bold = console->bolding;
702: x = console->window_origin_x + console->curr_column * CHAR_W;
703: y = console->window_origin_y + console->curr_row * CHAR_H;
704:
705: do {
706: glyphbase = ohlfs12[c - ENCODEBASE];
707: pixAddr = PixelAddress(console, x + bold, y);
708: switch (console->display.bitsPerPixel) {
709: case IO_8BitsPerPixel:
710: fg8 = (unsigned char) console->foreground;
711: dst8 = (unsigned char *) pixAddr;
712: for (source_y = CHAR_H; source_y != 0; source_y--) {
713: byte = *glyphbase++;
714: if (byte & 0x80) dst8[0] = fg8;
715: if (byte & 0x40) dst8[1] = fg8;
716: if (byte & 0x20) dst8[2] = fg8;
717: if (byte & 0x10) dst8[3] = fg8;
718: if (byte & 0x08) dst8[4] = fg8;
719: if (byte & 0x04) dst8[5] = fg8;
720: if (byte & 0x02) dst8[6] = fg8;
721: if (byte & 0x01) dst8[7] = fg8;
722: dst8 = (unsigned char *)
723: ((int)dst8 + console->display.rowBytes);
724: }
725: break;
726: case IO_12BitsPerPixel:
727: case IO_15BitsPerPixel:
728: fg16 = (unsigned short) console->foreground;
729: dst16 = (unsigned short *) pixAddr;
730: for (source_y = CHAR_H; source_y != 0; source_y--) {
731: byte = *glyphbase++;
732: if (byte & 0x80) dst16[0] = fg16;
733: if (byte & 0x40) dst16[1] = fg16;
734: if (byte & 0x20) dst16[2] = fg16;
735: if (byte & 0x10) dst16[3] = fg16;
736: if (byte & 0x08) dst16[4] = fg16;
737: if (byte & 0x04) dst16[5] = fg16;
738: if (byte & 0x02) dst16[6] = fg16;
739: if (byte & 0x01) dst16[7] = fg16;
740: dst16 = (unsigned short *)
741: ((int)dst16 + console->display.rowBytes);
742: }
743: break;
744: case IO_24BitsPerPixel:
745: fg32 = (unsigned int) console->foreground;
746: dst32 = (unsigned int *) pixAddr;
747: for (source_y = CHAR_H; source_y != 0; source_y--) {
748: byte = *glyphbase++;
749: if (byte & 0x80) dst32[0] = fg32;
750: if (byte & 0x40) dst32[1] = fg32;
751: if (byte & 0x20) dst32[2] = fg32;
752: if (byte & 0x10) dst32[3] = fg32;
753: if (byte & 0x08) dst32[4] = fg32;
754: if (byte & 0x04) dst32[5] = fg32;
755: if (byte & 0x02) dst32[6] = fg32;
756: if (byte & 0x01) dst32[7] = fg32;
757: dst32 = (unsigned int *)
758: ((int)dst32 + console->display.rowBytes);
759: }
760: break;
761: }
762: } while( bold--);
763: console->curr_column++;
764: return;
765: }
766:
767: extern void video_scroll_up(unsigned char * start, unsigned char * end, unsigned char * dest);
768:
769: static void FBPutC(ConsolePtr console, char c)
770: // Write one character to screen. Cursor is 'on' on entry and exit.
771: {
772: int repeat;
773: int i;
774:
775: /*
776: * First deal with ANSI escape sequences.
777: * This is a very bizarre implementation, copied from the m68k
778: * version.
779: */
780: switch(console->ansi_state) {
781: case AS_NORMAL:
782: if(c == esc) {
783: console->ansi_state = AS_ESCAPE;
784: return;
785: }
786: else {
787: break; // continue
788: }
789:
790: case AS_ESCAPE:
791: switch(c) {
792: case '[':
793: console->ansi_state = AS_BRACKET;
794: return;
795: default:
796: console->ansi_state = AS_NORMAL;
797: break; // continue
798: }
799:
800: case AS_BRACKET:
801: if(c >= '0' && c <= '9') {
802: *console->ansi_stack_p =
803: *console->ansi_stack_p * 10 + (c - '0');
804: return;
805: }
806: else if (c == ';') {
807: if(console->ansi_stack_p <
808: &console->ansi_stack[ANSI_STACK_SIZE]) {
809: console->ansi_stack_p++;
810: }
811: return;
812: }
813: else {
814: for(i=0; i<ANSI_STACK_SIZE; i++) {
815: if (console->ansi_stack[i] == 0) {
816: console->ansi_stack[i] = 1;
817: }
818: }
819: repeat = *console->ansi_stack_p;
820: FlipCursor(console); // cursor off
821: switch (c) {
822:
823: case 'A':
824: while (repeat--) {
825: if(console->curr_row) {
826: console->curr_row--;
827: }
828: }
829: break;
830:
831: case 'B':
832: while (repeat--) {
833: console->curr_row++;
834: }
835: break;
836:
837: case 'C': // non destructive space
838: while (repeat--) {
839: console->curr_column++;
840: }
841: break;
842:
843: case 'D': // not in termcap
844: while (repeat--) {
845: if(console->curr_column) {
846: console->curr_column--;
847: }
848: }
849: break;
850:
851: case 'E': // not in termcap
852: console->curr_column = 0;
853: while (repeat--) {
854: console->curr_row++;
855: }
856: break;
857:
858: case 'H': // should be home
859: case 'f': // not in termcap
860: console->curr_column =
861: *console->ansi_stack_p - 1;
862: console->ansi_stack_p--;
863: console->curr_row =
864: *console->ansi_stack_p - 1;
865: console->ansi_stack_p--;
866: break;
867:
868: case 'K':
869: ClearToEOL(console);
870: break;
871:
872: case 'm': /* FIXME */
873: console->ansi_stack_p--;
874: console->ansi_stack_p--;
875: break;
876: }
877: }
878: console->ansi_stack_p = &console->ansi_stack[1];
879: for(i=0; i<ANSI_STACK_SIZE; i++)
880: console->ansi_stack[i] = 0;
881: console->ansi_state = AS_NORMAL;
882: goto proceed;
883: }
884:
885: FlipCursor(console); // cursor off
886: switch(c) {
887: case '\r': // Carriage return
888: console->curr_column = 0;
889: break;
890:
891: case '\n': // line feed
892: console->curr_column = 0;
893: console->curr_row++;
894: break;
895:
896: case '\b': // backspace
897: if (console->curr_column == 0)
898: break;
899: console->curr_column--;
900: break;
901:
902: case '\t':
903: // tab. Erase all characters up to and including the
904: // next tab stop.
905: {
906: int col, num_cols;
907:
908: num_cols = TAB_SIZE - (console->curr_column % TAB_SIZE);
909: FlipCursor(console); // cursor on
910: for (col = 0; col<num_cols; col++) {
911: FBPutC(console, ' '); // cursor on at return
912: }
913: FlipCursor(console); // cursor off
914: break;
915: }
916:
917: case np: // aka ff, form feed
918: console->curr_row = console->curr_column = 0;
919: ClearWindow(console);
920: break;
921:
922: case del:
923: console->curr_column++;
924: break;
925:
926: default:
927: // Normal case.
928: BltChar(console, c);
929: break;
930: }
931:
932: // Cursor is off.
933: proceed:
934: if (console->curr_column >= console->chars_per_row) {
935: // End-of-line wrap.
936: console->curr_column = 0;
937: console->curr_row++;
938: }
939:
940: if (console->curr_row >= console->chars_per_column) {
941: //
942: // Screen scroll. Copy the whole window down in memory
943: // (pixels_per_row * CHAR_H) pixels, starting at
944: // the first character in row 1.
945: //
946: unsigned char *src;
947: unsigned char *dst;
948: int source_y;
949: unsigned windowRowBytes;
950:
951: console->curr_row = console->chars_per_column - 1;
952: switch (console->display.bitsPerPixel) {
953: case IO_8BitsPerPixel:
954: windowRowBytes = console->pixels_per_row;
955: break;
956: case IO_12BitsPerPixel:
957: case IO_15BitsPerPixel:
958: windowRowBytes = 2*console->pixels_per_row;
959: break;
960: case IO_24BitsPerPixel:
961: windowRowBytes = 4*console->pixels_per_row;
962: break;
963: default:
964: panic("FBConsole/FBPutC: bogus bitsPerPixel");
965: }
966:
967: // Copy one row at a time, moving each one up
968: // CHAR_H rows. Within the loop, just increment
969: // pixel pointers by one row's worth of pixels.
970: // Source starts at the left top of row 1; destination
971: // starts at left top of row 0.
972: //
973: src = PixelAddress(console,
974: console->window_origin_x,
975: console->window_origin_y + CHAR_H);
976: dst = PixelAddress(console,
977: console->window_origin_x,
978: console->window_origin_y);
979: for (source_y = CHAR_H; // top, row 1
980: source_y < console->pixels_per_column; // bottom
981: source_y++) {
982: #ifndef notDefUseFPU
983: video_scroll_up( src, src + windowRowBytes, dst);
984: #else
985: videoMemMove(dst, src, windowRowBytes);
986: #endif
987: src += console->display.rowBytes;
988: dst += console->display.rowBytes;
989: }
990:
991: console->curr_column = 0;
992: ClearToEOL(console);
993: }
994:
995: // Cursor back on.
996: FlipCursor(console);
997: }
998:
999: static void SetTitle(ConsolePtr console, const char *title)
1000: // Description: Draw title bar if none exists, write specified title into it.
1001: // Drawing a title bar involves snarfing up row 0 of the window
1002: // and decreasing the usable size of the window by one row.
1003: // Preconditions:
1004: // * Cursor is 'on' on entry and will remain so on exit.
1005: {
1006: int saved_curr_row = console->curr_row;
1007: int saved_curr_column = console->curr_column;
1008: int saved_origin_y;
1009: int title_len = strlen(title);
1010: int pixel_num;
1011:
1012: if ((title_len == 0) || (title_len > console->chars_per_row)) {
1013: IOLog("console: Illegal title length (%d)\n", title_len);
1014: return;
1015: }
1016: FlipCursor(console); // old cursor off
1017: if (console->has_title) {
1018: // First grow window by two rows - this absorbs the existing
1019: // title bar.
1020: console->window_origin_y -= CHAR_H * 2;
1021: console->chars_per_column += 2;
1022: console->pixels_per_column += CHAR_H * 2;
1023: saved_curr_row += 2;
1024: }
1025:
1026: // Clear row 0, center new title in it.
1027: console->curr_row = 0;
1028: Rect(console,
1029: console->window_origin_x - (BG_MARGIN - TS_MARGIN),
1030: console->window_origin_y - (BG_MARGIN - TS_MARGIN),
1031: CHAR_W * console->chars_per_row + 2 * (BG_MARGIN - TS_MARGIN),
1032: CHAR_H * 2 - TS_MARGIN,
1033: console->light_grey);
1034: saved_origin_y = console->window_origin_y;
1035: console->window_origin_y += CHAR_H / 2;
1036: console->curr_column = (console->chars_per_row - title_len) / 2;
1037: DrawIcon(console);
1038: // SwapForegroundAndBackground(console);
1039: console->bolding = 1;
1040: console->background = console->light_grey;
1041: FlipCursor(console); // new cursor on
1042: while (*title) {
1043: FBPutC(console, *title++);
1044: }
1045: FlipCursor(console); // new cursor off
1046: console->background = console->grayTable[0];
1047: console->bolding = 0;
1048: // SwapForegroundAndBackground(console);
1049: console->window_origin_y = saved_origin_y;
1050:
1051: // Draw grey lines one pixel away from border of title bar.
1052: // Origin is currently at first pixel in top line of title bar.
1053:
1054: Rect(console, // inside top
1055: console->window_origin_x - BG_MARGIN,
1056: console->window_origin_y - BG_MARGIN,
1057: console->pixels_per_row + (BG_MARGIN * 2),
1058: TS_MARGIN,
1059: console->background);
1060: Rect(console, // inside bottom
1061: console->window_origin_x - BG_MARGIN,
1062: console->window_origin_y + CHAR_H * 2 - TOTAL_MARGIN - TS_MARGIN,
1063: console->pixels_per_row + BG_MARGIN * 2,
1064: TS_MARGIN,
1065: console->dark_grey);
1066: for (pixel_num = 0; pixel_num < TS_MARGIN; pixel_num++) {
1067: Rect(console, // left
1068: console->window_origin_x - BG_MARGIN + pixel_num,
1069: console->window_origin_y - BG_MARGIN + pixel_num,
1070: 1,
1071: CHAR_H * 2 - 1 - (pixel_num * 2),
1072: console->background);
1073: }
1074: for (pixel_num = 1 + BG_MARGIN - TS_MARGIN; pixel_num <= BG_MARGIN; pixel_num++) {
1075: Rect(console, // right
1076: console->window_origin_x + console->pixels_per_row + pixel_num - 1,
1077: console->window_origin_y - pixel_num,
1078: 1,
1079: CHAR_H * 2 - 1 - (BG_MARGIN - pixel_num) * 2,
1080: console->dark_grey);
1081: }
1082: Rect(console, // outside bottom
1083: console->window_origin_x - TOTAL_MARGIN,
1084: console->window_origin_y + CHAR_H * 2 - FG_MARGIN - BG_MARGIN,
1085: console->pixels_per_row + TOTAL_MARGIN * 2,
1086: FG_MARGIN,
1087: console->foreground);
1088:
1089: // Diminish window size by two rows.
1090: console->window_origin_y += CHAR_H * 2;
1091: console->chars_per_column -= 2;
1092: console->pixels_per_column -= CHAR_H * 2;
1093:
1094:
1095: // Restore old cursor. Careful, the y axis just changed...
1096: console->curr_column = saved_curr_column;
1097: if (saved_curr_row > 0) {
1098: console->curr_row = saved_curr_row - 2;
1099: }
1100: else {
1101: // New row 0 - clear it.
1102: ClearToEOL(console);
1103: }
1104: FlipCursor(console); // old cursor on
1105: console->has_title = TRUE;
1106: }
1107:
1108:
1109: static void UpdateWindowChars(ConsolePtr console)
1110: // Description: Calculate window size in characters. Used when either window
1111: // size or font changes.
1112: {
1113: console->chars_per_row = console->pixels_per_row / CHAR_W;
1114: console->chars_per_column =
1115: console->pixels_per_column / CHAR_H;
1116: }
1117:
1118:
1119:
1120: static void InitWindow(ConsolePtr console,
1121: int width,
1122: int height,
1123: const char *title,
1124: boolean_t initWindow,
1125: boolean_t saveUnder)
1126: // Description: Initialize window parameters. If initWindow is TRUE, an empty
1127: // window is drawn in the screen, else we assume that a window
1128: // already exists. Screen and font parameters must be valid on
1129: // entry.
1130: {
1131: // Truncate specified size to integral mutliple of character size
1132: // in both dimensions.
1133: width /= CHAR_W; // now in chars
1134: height /= CHAR_H;
1135: width *= CHAR_W; // now in pixels
1136: height *= CHAR_H;
1137:
1138: // Ensure there's enough room for a border.
1139: if (width > (console->display.width - HORIZ_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW))
1140: width = console->display.width - HORIZ_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW;
1141: if (height > (console->display.height - VERT_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW))
1142: height = console->display.height - VERT_BORDER - TOTAL_MARGIN * 2 - DROP_SHADOW;
1143: width &= 0xfffffffe;
1144:
1145: //
1146: // Init console window variables. The window is centered in the
1147: // ! screen, minus a pixel or two to guarantee double word alignment
1148: // ! for the first pixel of a row (until further developments...when
1149: // ! we do alert panels, we can enumerate some cases here...).
1150: //
1151: console->window_origin_x = (console->display.width - width) / 2;
1152: console->window_origin_y = (console->display.height - height) / 2;
1153: console->pixels_per_row = width;
1154: console->pixels_per_column = height;
1155: (unsigned)console->window_origin_x &= 0xfffffffe;
1156:
1157: UpdateWindowChars(console);
1158:
1159: console->curr_column = 0;
1160: console->has_title = FALSE;
1161:
1162: if (initWindow) {
1163: // Before we start drawing anything, save under if needed
1164: if (saveUnder) {
1165: int i, bytesPerPixel = 0;
1166: unsigned char *save, *sp;
1167:
1168: // Compute size of save under region in bytes and allocate
1169: switch (console->display.bitsPerPixel) {
1170: case IO_8BitsPerPixel: bytesPerPixel = 1; break;
1171: case IO_12BitsPerPixel:
1172: case IO_15BitsPerPixel: bytesPerPixel = 2; break;
1173: case IO_24BitsPerPixel: bytesPerPixel = 4; break;
1174: }
1175: console->saveHeight = height + TOTAL_MARGIN * 2 + DROP_SHADOW;
1176: console->saveRowBytes = (width + TOTAL_MARGIN * 2 + DROP_SHADOW)*bytesPerPixel;
1177: console->saveBytes = console->saveHeight*console->saveRowBytes;
1178: save = console->saveBits = (unsigned char *)
1179: kalloc_noblock(console->saveBytes);
1180: sp = console->saveLocation =
1181: PixelAddress(console, console->window_origin_x - TOTAL_MARGIN,
1182: console->window_origin_y - TOTAL_MARGIN);
1183:
1184: // Copy the window contents into the save under
1185: if( save)
1186: for (i = console->saveHeight; i != 0; i--) {
1187: videoMemMove(save, sp, console->saveRowBytes);
1188: sp += console->display.rowBytes;
1189: save += console->saveRowBytes;
1190: }
1191: }
1192:
1193: // New window - cursor at origin.
1194: console->curr_row = 0;
1195: console->has_title = FALSE;
1196:
1197: // Draw the border. The border goes outside of the specified
1198: // window. Outside lines are black; inside lines are
1199: // half-tone.
1200: Rect(console, // outside top
1201: console->window_origin_x - TOTAL_MARGIN,
1202: console->window_origin_y - TOTAL_MARGIN,
1203: width + TOTAL_MARGIN * 2,
1204: FG_MARGIN,
1205: console->foreground);
1206: Rect(console, // inside top
1207: console->window_origin_x - BG_MARGIN,
1208: console->window_origin_y - BG_MARGIN,
1209: width + BG_MARGIN * 2,
1210: BG_MARGIN,
1211: console->background);
1212: Rect(console, // inside bottom
1213: console->window_origin_x - BG_MARGIN,
1214: console->window_origin_y + height,
1215: width + BG_MARGIN * 2,
1216: BG_MARGIN,
1217: console->background);
1218: Rect(console, // outside bottom
1219: console->window_origin_x - TOTAL_MARGIN,
1220: console->window_origin_y + height + BG_MARGIN,
1221: width + TOTAL_MARGIN * 2,
1222: FG_MARGIN,
1223: console->foreground);
1224: if( DROP_SHADOW) Rect(console, // outside bottom shadow
1225: console->window_origin_x - TOTAL_MARGIN + DROP_SHADOW,
1226: console->window_origin_y + height + BG_MARGIN + DROP_SHADOW,
1227: width + TOTAL_MARGIN * 2,
1228: DROP_SHADOW,
1229: console->dark_grey);
1230: Rect(console, // outside left
1231: console->window_origin_x - TOTAL_MARGIN,
1232: console->window_origin_y - TOTAL_MARGIN,
1233: FG_MARGIN,
1234: height + TOTAL_MARGIN * 2,
1235: console->foreground);
1236: Rect(console, // inside left
1237: console->window_origin_x - BG_MARGIN,
1238: console->window_origin_y - BG_MARGIN,
1239: BG_MARGIN,
1240: height + BG_MARGIN * 2,
1241: console->background);
1242: Rect(console, // inside right
1243: console->window_origin_x + width,
1244: console->window_origin_y - BG_MARGIN,
1245: BG_MARGIN,
1246: height + BG_MARGIN * 2,
1247: console->background);
1248: Rect(console, // outside right
1249: console->window_origin_x + width + BG_MARGIN,
1250: console->window_origin_y - TOTAL_MARGIN,
1251: FG_MARGIN,
1252: height + TOTAL_MARGIN * 2,
1253: console->foreground);
1254: if( DROP_SHADOW) Rect(console, // outside right shadow
1255: console->window_origin_x + width + BG_MARGIN + DROP_SHADOW,
1256: console->window_origin_y - TOTAL_MARGIN + DROP_SHADOW,
1257: DROP_SHADOW,
1258: height + TOTAL_MARGIN * 2,
1259: console->dark_grey);
1260:
1261: // Clear the contents of the window and draw a cursor.
1262: ClearWindow(console);
1263: FlipCursor(console); // cursor on
1264: SetTitle(console, title);
1265: }
1266: else {
1267: /* Leave current window contents, just updating title.
1268: * We'll do a newline to make sure we have room for
1269: * our font and proceed.Initial cursor will be at
1270: * lower left corner.
1271: */
1272: console->curr_row = console->chars_per_column - 1;
1273: SetTitle(console, title);
1274: FBPutC(console, '\n');
1275: }
1276: return;
1277: }
1278:
1279: //
1280: // END: Private utility routines
1281: //
1282:
1283: //
1284: // BEGIN: Implementation of IOConsoleInfo functions
1285: //
1286: static void Free(IOConsoleInfo *cso)
1287: // Description: Free a FB Console object
1288: {
1289: IOFree(cso->priv, sizeof(ConsoleRep));
1290: IOFree(cso, sizeof(IOConsoleInfo));
1291: }
1292:
1293: static void Init(
1294: IOConsoleInfo *cso,
1295: ScreenMode mode,
1296: boolean_t initScreenOrSaveUnder,
1297: boolean_t initWindow,
1298: const char *title)
1299: {
1300: ConsolePtr console = (ConsolePtr)cso->priv;
1301: int i;
1302:
1303: switch (console->display.bitsPerPixel) {
1304: case IO_8BitsPerPixel:
1305: if (console->display.colorSpace == IO_OneIsWhiteColorSpace) {
1306: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 107 : 0x55;
1307: console->background = 0xff;
1308: console->foreground = 0x00;
1309: console->dark_grey = 85;
1310: console->light_grey = 187;
1311: } else {
1312: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 0x80 : 0x7e;
1313: console->background = 0x00;
1314: console->foreground = 0xff;
1315: console->dark_grey = 0xfb;
1316: console->light_grey = 0xf7;
1317: }
1318: break;
1319: case IO_15BitsPerPixel:
1320: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 0x3193 : 0x295f;
1321: console->background = 0x7fff;
1322: console->foreground = 0x0000;
1323: console->dark_grey = 0x294a;
1324: console->light_grey = 0x5ef7;
1325: break;
1326: case IO_24BitsPerPixel:
1327: console->baseground = (TRUE || (mode == SCM_GRAPHIC)) ? 0xff666699 : 0xff5555ff;
1328: console->background = 0xffffffff;
1329: console->foreground = 0xff000000;
1330: console->dark_grey = 0xff555555;
1331: console->light_grey = 0xffbbbbbb;
1332: break;
1333: }
1334:
1335: console->grayTable[0] = console->background;
1336: console->grayTable[1] = console->light_grey;
1337: console->grayTable[2] = console->dark_grey;
1338: console->grayTable[3] = console->foreground;
1339:
1340: console->ansi_state = AS_NORMAL;
1341: for(i=0; i<ANSI_STACK_SIZE; i++) {
1342: console->ansi_stack[i] = 0;
1343: }
1344: console->ansi_stack_p = &console->ansi_stack[1]; // FIXME - why not 0?
1345:
1346: // Initialize the screen, if appropriate.
1347: if (initScreenOrSaveUnder && (mode != SCM_ALERT)) {
1348: WipeScreen(console, console->baseground);
1349: }
1350:
1351: console->window_type = mode;
1352: switch(console->window_type) {
1353: case SCM_TEXT:
1354: InitWindow(console, TEXT_WIN_WIDTH, TEXT_WIN_HEIGHT,
1355: title, initWindow, 0 /* Don't save under */);
1356: break;
1357: case SCM_ALERT:
1358: InitWindow(console, ALERT_WIN_WIDTH, ALERT_WIN_HEIGHT,
1359: title, initWindow, initScreenOrSaveUnder );
1360: break;
1361: case SCM_GRAPHIC:
1362: if( initScreenOrSaveUnder) {
1363: int cx, cy;
1364:
1365: cx = console->display.width / 2;
1366: cy = console->display.height / 2;
1.1.1.2 ! root 1367: #if 0
1.1 root 1368: Expand4ToN( console, cx + RIGHT_DX, cy + RIGHT_DY,
1369: RIGHT_WIDTH, RIGHT_HEIGHT, rightData, rightBotColors );
1370: Expand4ToN( console, cx + CENTER_DX, cy + CENTER_DY,
1371: CENTER_WIDTH, CENTER_HEIGHT, centerData, centerColors );
1372: Expand4ToN( console, cx + BOTTOM_DX, cy + BOTTOM_DY,
1373: BOTTOM_WIDTH, BOTTOM_HEIGHT, bottomData, rightBotColors );
1.1.1.2 ! root 1374: #else
! 1375: Expand8ToN( console, cx + CENTER_DX, cy + CENTER_DY,
! 1376: CENTER_WIDTH, CENTER_HEIGHT, centerData );
! 1377: #endif
1.1 root 1378: }
1379: break;
1380:
1381: default:
1382: panic("FBConsole/FBInitConsole: can't init");
1383: break;
1384: }
1385: return;
1386: }
1387:
1388: static int Restore(IOConsoleInfo *cso)
1389: {
1390: ConsolePtr console = (ConsolePtr)cso->priv;
1391: unsigned char *save, *dp;
1392: int i;
1393:
1394: if (console->window_type != SCM_ALERT) {
1395: IOLog("frameBuffer: bogus restore, mode %d\n", console->window_type);
1396: return -1;
1397: }
1398:
1399: // Copy save under bits back onto screen
1400: save = console->saveBits;
1401: dp = console->saveLocation;
1402: if( save) {
1403: for (i = console->saveHeight; i != 0; i--) {
1404: videoMemMove(dp, save, console->saveRowBytes);
1405: dp += console->display.rowBytes;
1406: save += console->saveRowBytes;
1407: }
1408:
1409: // Free bits
1410: kfree(console->saveBits, console->saveBytes);
1411: console->saveBits = 0;
1412: }
1413: return 0;
1414: }
1415:
1416: #define VIDEO_W 640
1417: #define VIDEO_H 480
1418:
1419: static int DrawRect(IOConsoleInfo *cso, const struct km_drawrect *km_rect)
1420: // Description: Given a 2 bit raster, convert it to the format appropriate for
1421: // the display. The co-ordinates passed in by these ioctls assume
1422: // an (VIDEO_W x VIDEO_H) screen. All screen sizes are
1423: // assumed to share a common center point. We scale the X and Y
1424: // values to maintain a constant offset from the center point,
1425: // so that boot animations, popup windows, and related goodies
1426: // don't break with screens larger or smaller than the 'default'
1427: // screen.
1428: // Preconditions:
1429: // * The rectangle that we are to draw must start on a 4 pixel boundary
1430: // and should be a multiple of 4 pixels in width.
1431: {
1432: ConsolePtr console = (ConsolePtr)cso->priv;
1433: int pixel; /* Starting pixel in screen */
1434: int i, x, y;
1435: unsigned char *data;
1436: unsigned char value;
1437: unsigned int * table;
1438: struct km_drawrect *rect = (struct km_drawrect *) km_rect;
1439: int bgX, bgY, bgH;
1440: unsigned char * bg;
1441:
1442: table = console->grayTable;
1443:
1444: /* copyin is done in km */
1445: data = rect->data.bits;
1446:
1447: x = (rect->x & 0x1ffc) + (console->display.width - VIDEO_W)/2;
1448: y = rect->y + (console->display.height - VIDEO_H)/2;
1449:
1450: /* Correct the x and y values for screen size */
1451: if( (rect->x & 3) == 3) {
1452: DrawColorRect( console, x, y, rect->width, rect->height, data);
1453: return 0;
1454: }
1455:
1456: #if TEXTURE_BACKGND
1457: bgX = console->display.width / 2 + CENTER_DX;
1458: bgY = console->display.height / 2 + CENTER_DY;
1459:
1460: bgH = (y - bgY) & -2;
1461: if( bgH > 0) {
1462: bgY += bgH;
1.1.1.2 ! root 1463: bg = centerData + (bgH * CENTER_WIDTH);
1.1 root 1464: bgH = CENTER_HEIGHT - bgH;
1465: } else
1466: bg = (unsigned char *)0;
1467: #endif
1468:
1469: rect->x &= 0x1ffc;
1470:
1471: /* Sanity check */
1472: if ((x + rect->width > console->display.width)
1473: || (y + rect->height) > console->display.height)
1474: return( -1 );
1475:
1476:
1477: pixel = x + (y * console->display.totalWidth);
1478:
1479: switch ( console->display.bitsPerPixel )
1480: {
1481: case IO_2BitsPerPixel: /* 2 bit pixels */
1482: {
1483: unsigned char *dst = (unsigned char *)console->display.frameBuffer;
1484: unsigned char *fb;
1485: unsigned char final_value;
1486:
1487: dst += pixel >> 2;
1488: for ( y = 0; y < rect->height; ++y ) {
1489: fb = dst;
1490: for ( x = 0; x < rect->width; x += 4) {
1491: value = *data++;
1492: final_value = 0;
1493: for ( i = 0; i < 8; i += 2 ) {
1494: final_value |= ((table[(value>>i)&3] & 3) << i);
1495: }
1496: *fb++ = final_value;
1497: }
1498: dst += console->display.rowBytes;
1499: }
1500: break;
1501: }
1502: case IO_8BitsPerPixel: /* 8 bit pixels */
1503: {
1504: unsigned char *dst = (unsigned char *)console->display.frameBuffer;
1505: unsigned char *fb;
1506:
1507: dst += pixel;
1508: for ( y = 0; y < rect->height; ++y ) {
1509: fb = dst;
1510: #if TEXTURE_BACKGND
1.1.1.2 ! root 1511: Expand8ToN( console, bgX, bgY,
! 1512: CENTER_WIDTH, 1, bg );
! 1513: bgY += 1;
! 1514: bg += CENTER_WIDTH;
1.1 root 1515: #endif
1516: for ( x = 0; x < rect->width; x += 4) {
1517: value = *data++;
1518: if( value) {
1519: int pix;
1520: pix = (value >> 6) & 3;
1521: if( pix)
1522: fb[0] = table[pix];
1523: pix = (value >> 4) & 3;
1524: if( pix)
1525: fb[1] = table[pix];
1526: pix = (value >> 2) & 3;
1527: if( pix)
1528: fb[2] = table[pix];
1529: pix = value & 3;
1530: if( pix)
1531: fb[3] = table[pix];
1532: }
1533: fb += 4;
1534: }
1535: dst += console->display.rowBytes;
1536: }
1537: break;
1538: }
1539: case IO_12BitsPerPixel: /* 16 bit pixels */
1540: case IO_15BitsPerPixel: /* 16 bit pixels */
1541: {
1542:
1543: unsigned short *dst = (unsigned short *)console->display.frameBuffer;
1544: unsigned short *fb;
1545: dst += pixel;
1546:
1547: for ( y = 0; y < rect->height; ++y ) {
1548: fb = dst;
1549: #if TEXTURE_BACKGND
1.1.1.2 ! root 1550: Expand8ToN( console, bgX, bgY,
! 1551: CENTER_WIDTH, 1, bg );
! 1552: bgY += 1;
! 1553: bg += CENTER_WIDTH;
1.1 root 1554: #endif
1555: for ( x = 0; x < rect->width; x += 4) {
1556: value = *data++;
1557: if( value) {
1558: int pix;
1559: pix = (value >> 6) & 3;
1560: if( pix)
1561: fb[0] = table[pix];
1562: pix = (value >> 4) & 3;
1563: if( pix)
1564: fb[1] = table[pix];
1565: pix = (value >> 2) & 3;
1566: if( pix)
1567: fb[2] = table[pix];
1568: pix = value & 3;
1569: if( pix)
1570: fb[3] = table[pix];
1571: }
1572: fb += 4;
1573: }
1574: dst = (unsigned short *)(((char*)dst) +
1575: console->display.rowBytes);
1576: }
1577: break;
1578: }
1579: case IO_24BitsPerPixel: /* 32 bit pixels */
1580: {
1581: unsigned int *dst = (unsigned int *) console->display.frameBuffer;
1582: unsigned int *fb;
1583:
1584: dst += pixel;
1585: for ( y = 0; y < rect->height; ++y ) {
1586: fb = dst;
1587: #if TEXTURE_BACKGND
1.1.1.2 ! root 1588: Expand8ToN( console, bgX, bgY,
! 1589: CENTER_WIDTH, 1, bg );
! 1590: bgY += 1;
! 1591: bg += CENTER_WIDTH;
1.1 root 1592: #endif
1593: for ( x = 0; x < rect->width; x += 4) {
1594: value = *data++;
1595: if( value) {
1596: int pix;
1597: pix = (value >> 6) & 3;
1598: if( pix)
1599: fb[0] = table[pix];
1600: pix = (value >> 4) & 3;
1601: if( pix)
1602: fb[1] = table[pix];
1603: pix = (value >> 2) & 3;
1604: if( pix)
1605: fb[2] = table[pix];
1606: pix = value & 3;
1607: if( pix)
1608: fb[3] = table[pix];
1609: }
1610: fb += 4;
1611: }
1612: dst = (unsigned int *)(((char*)dst) +
1613: console->display.rowBytes);
1614: }
1615: break;
1616: }
1617: }
1618: return 0;
1619: }
1620:
1621: static int EraseRect(IOConsoleInfo *cso, const struct km_drawrect *km_rect)
1622: // Description: Erase the specified rectangle to the color specified
1623: // in the km_rect structure.
1624: // Preconditions:
1625: // * The rectangle that we are to erase must start on a 4 pixel boundary
1626: // and should be a multiple of 4 pixels in width.
1627: {
1628: ConsolePtr console = (ConsolePtr)cso->priv;
1629: int pixel; // Starting pixel in screen
1630: int x, y, w, h;
1631: unsigned int value;
1632: struct km_drawrect *rect = (struct km_drawrect *) km_rect;
1633: int bgX, bgY, bgH;
1634: unsigned char * bg;
1635:
1636: value = console->grayTable[ rect->data.fill & 3 ];
1637:
1638: /* Correct the x and y values for screen size */
1639: x = rect->x + (console->display.width - VIDEO_W)/2;
1640: y = rect->y + (console->display.height - VIDEO_H)/2;
1641:
1642: x &= ~3; // Trunc to 4 pixel boundary
1643: w = (rect->width) & ~3; // Round dn to 4 pixel boundary
1644: h = rect->height;
1645:
1646: /* Sanity check */
1647: /* Sanity check */
1648: if (((x + w) > console->display.width)
1649: || ((y + h) > console->display.height) )
1650: return( -1 );
1651:
1652:
1653: #if TEXTURE_BACKGND
1654: bgX = console->display.width / 2 + CENTER_DX;
1655: bgY = console->display.height / 2 + CENTER_DY;
1656:
1657: bgH = (y - bgY) & -2;
1658: if( bgH > 0) {
1659: bgY += bgH;
1.1.1.2 ! root 1660: bg = centerData + (bgH * CENTER_WIDTH);
1.1 root 1661: bgH = CENTER_HEIGHT - bgH;
1662: Expand4ToN( console, bgX, bgY,
1663: CENTER_WIDTH, bgH, bg, centerColors );
1664: }
1665:
1666: #else
1667: Rect( console, x, y, w, h, value);
1668: #endif
1669:
1670: return 0;
1671: }
1672:
1673: //extern void czputc( char c);
1674:
1675: static void PutC(IOConsoleInfo *cso, char c)
1676: // Write one character to screen. Cursor is 'on' on entry and exit.
1677: {
1678: FBPutC((ConsolePtr)cso->priv, c);
1679: // czputc(c);
1680: }
1681:
1682: static void GetSize(IOConsoleInfo *cso, struct ConsoleSize *s)
1683: // Return the size of the screen in pixels
1684: {
1685: ConsolePtr console = (ConsolePtr)cso->priv;
1686: s->cols = console->chars_per_row;
1687: s->rows = console->chars_per_column;
1688: s->pixel_width = console->display.width;
1689: s->pixel_height = console->display.height;
1690: }
1691:
1692: //
1693: // END: Implementation of IOConsoleInfo functions
1694: //
1695:
1696: static IOConsoleInfo staticConsoleInfo;
1697: static ConsoleRep staticConsoleRep;
1698:
1699: static void InitializeConsole( IOConsoleInfo *cso, IODisplayInfo *display )
1700: {
1701: cso->Init = Init;
1702: cso->Restore = Restore;
1703: cso->DrawRect = DrawRect;
1704: cso->EraseRect = EraseRect;
1705: cso->PutC = PutC;
1706: cso->GetSize = GetSize;
1707: ((ConsolePtr)cso->priv)->display = *display;
1708: ((ConsolePtr)cso->priv)->window_type = SCM_UNINIT;
1709: return;
1710: }
1711:
1712: //
1713: // BEGIN: Exported routines
1714: //
1715:
1716: static void DoNothing(IOConsoleInfo *cso)
1717: {
1718: }
1719:
1720: IOConsoleInfo *BasicAllocateConsole(IODisplayInfo *display)
1721: {
1722: // No memory allocation. Assume non backed window.
1723: IOConsoleInfo *cso = &staticConsoleInfo;
1724: cso->priv = (void *)&staticConsoleRep;
1725: InitializeConsole(cso, display);
1726: cso->Free = DoNothing;
1727: #if 0
1728: printf("base:%x rowBytes:%x width:%x height:%x\n",display->frameBuffer,
1729: display->rowBytes, display->width, display->height);
1730: #endif
1731: return cso;
1732: }
1733:
1734:
1735: IOConsoleInfo *FBAllocateConsole(IODisplayInfo *display)
1736: {
1737: IOConsoleInfo *cso = (IOConsoleInfo *)IOMalloc(sizeof(IOConsoleInfo));
1738:
1739: if (cso == NIL)
1740: return NIL;
1741: cso->priv = (void *)IOMalloc(sizeof(ConsoleRep));
1742: if (cso->priv == NIL)
1743: {
1744: IOFree(cso, sizeof(IOConsoleInfo));
1745: return NIL;
1746: }
1747: InitializeConsole(cso, display);
1748: cso->Free = Free;
1749: return cso;
1750: }
1751:
1752:
1753: //
1754: // END: Exported routines
1755: //
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.