| |
| /* |
| * Simple text console |
| * |
| * (C) Copyright 2002 Geert Uytterhoeven |
| * |
| * This file is subject to the terms and conditions of the GNU General Public |
| * License. See the file COPYING in the main directory of this archive for |
| * more details. |
| */ |
| |
| #include <stdarg.h> |
| #include <stdio.h> |
| |
| #include "types.h" |
| #include "font.h" |
| #include "console.h" |
| #include "fb.h" |
| #include "drawops.h" |
| #include "visual.h" |
| #include "clut.h" |
| #include "util.h" |
| |
| |
| #define PRINTF_BUFFER_SIZE 1024 |
| #define BITMAP_SIZE 1024 |
| |
| static char printf_buffer[PRINTF_BUFFER_SIZE]; |
| |
| static const struct font *con_font; |
| static unsigned int con_pitch, con_charsize; |
| static unsigned int con_cols, con_rows; |
| static unsigned int con_x, con_y; |
| static pixel_t con_fgcolor, con_bgcolor; |
| |
| static unsigned char bitmap[BITMAP_SIZE]; |
| static unsigned int bitmap_width, bitmap_pitch, bitmap_max_width; |
| static unsigned int bitmap_x; |
| |
| static void con_flush(void) |
| { |
| if (bitmap_width) { |
| expand_bitmap(bitmap_x*con_font->width, con_y*con_font->height, |
| bitmap_width, con_font->height, (const u8 *)bitmap, |
| bitmap_pitch, con_bgcolor, con_fgcolor); |
| bitmap_width = 0; |
| } |
| } |
| |
| static void con_clear(void) |
| { |
| con_flush(); |
| fill_rect(0, 0, con_cols*con_font->width, con_rows*con_font->height, |
| con_bgcolor); |
| } |
| |
| static void con_reset(void) |
| { |
| con_flush(); |
| |
| con_x = 0; |
| con_y = 0; |
| con_fgcolor = idx_pixel[7]; |
| con_bgcolor = idx_pixel[0]; |
| |
| con_clear(); |
| } |
| |
| |
| static void con_scrollup(void) |
| { |
| con_flush(); |
| copy_rect(0, 0, con_cols*con_font->width, (con_rows-1)*con_font->height, |
| 0, con_font->height); |
| fill_rect(0, (con_rows-1)*con_font->height, con_cols*con_font->width, |
| con_font->height, con_bgcolor); |
| } |
| |
| |
| void con_init(const struct font *font) |
| { |
| int i; |
| |
| fill_rect(0, 0, fb_var.xres, fb_var.yres, 0); |
| |
| con_font = font; |
| con_pitch = (font->width+7)/8; |
| con_charsize = con_pitch*font->height; |
| |
| con_cols = fb_var.xres/font->width; |
| con_rows = fb_var.yres/font->height; |
| |
| for (i = 0; i < 16; i++) |
| clut[i] = clut_console[i]; |
| clut_update(); |
| |
| bitmap_pitch = (sizeof(bitmap)/(font->height*sizeof(unsigned long)))* |
| sizeof(unsigned long); |
| bitmap_max_width = bitmap_pitch*8; |
| bitmap_width = 0; |
| bitmap_x = 0; |
| |
| con_reset(); |
| } |
| |
| static void con_newline(void) |
| { |
| con_flush(); |
| con_x = 0; |
| con_y++; |
| if (con_y == con_rows) { |
| con_y--; |
| con_scrollup(); |
| } |
| } |
| |
| static void con_store_char(unsigned char c) |
| { |
| const unsigned char *src; |
| unsigned char *dst; |
| int y; |
| |
| if (bitmap_width+con_font->width > bitmap_max_width) |
| con_flush(); |
| if (!bitmap_width) |
| bitmap_x = con_x; |
| src = con_font->data+c*con_charsize; |
| switch (con_font->width) { |
| case 4: |
| dst = bitmap+bitmap_width/8; |
| if (bitmap_width & 4) { |
| for (y = 0; y < con_font->height; y++) { |
| *dst |= *src++ & 0x0f; |
| dst += bitmap_pitch; |
| } |
| } else { |
| for (y = 0; y < con_font->height; y++) { |
| *dst = *src++ & 0xf0; |
| dst += bitmap_pitch; |
| } |
| } |
| break; |
| |
| case 8: |
| dst = bitmap+bitmap_width/8; |
| for (y = 0; y < con_font->height; y++) { |
| *dst = *src++; |
| dst += bitmap_pitch; |
| } |
| break; |
| |
| case 12: |
| dst = bitmap+bitmap_width/8; |
| if (bitmap_width & 4) { |
| for (y = 0; y < con_font->height; y++) { |
| unsigned char d = *src++; |
| dst[0] |= d >> 4; |
| dst[1] = d << 4 | *src++ >> 4; |
| dst += bitmap_pitch; |
| } |
| } else { |
| for (y = 0; y < con_font->height; y++) { |
| dst[0] = *src++; |
| dst[1] = *src++ & 0xf0; |
| dst += bitmap_pitch; |
| } |
| } |
| break; |
| |
| case 16: |
| dst = bitmap+bitmap_width/8; |
| for (y = 0; y < con_font->height; y++) { |
| dst[0] = *src++; |
| dst[1] = *src++; |
| dst += bitmap_pitch; |
| } |
| break; |
| |
| default: |
| Fatal("Fontwidth %d is not yet supported\n", con_font->width); |
| } |
| bitmap_width += con_font->width; |
| } |
| |
| static void con_do_putc(unsigned char c) |
| { |
| switch (c) { |
| case '\n': |
| con_newline(); |
| break; |
| |
| default: |
| con_store_char(c); |
| con_x++; |
| if (con_x == con_cols) |
| con_newline(); |
| break; |
| } |
| } |
| |
| void con_putc(char c) |
| { |
| con_do_putc(c); |
| con_flush(); |
| } |
| |
| void con_puts(const char *s) |
| { |
| unsigned char c; |
| |
| while ((c = *s++)) |
| con_do_putc(c); |
| con_flush(); |
| } |
| |
| |
| void con_printf(const char *fmt, ...) |
| { |
| va_list ap; |
| |
| va_start(ap, fmt); |
| vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap); |
| va_end(ap); |
| con_puts(printf_buffer); |
| } |
| |