From 759eb4c448ad546bd27a47414180b9c911228532 Mon Sep 17 00:00:00 2001 From: chaoskagami Date: Tue, 26 Apr 2016 00:01:00 -0400 Subject: [PATCH] Fix up cprintf --- source/main.c | 11 ++- source/std/draw.c | 191 +++++++++++++++++++++++++------------------- source/std/draw.h | 40 ++++++++-- source/std/memory.c | 6 ++ source/std/memory.h | 1 + 5 files changed, 156 insertions(+), 93 deletions(-) diff --git a/source/main.c b/source/main.c index 6667468..42053ce 100644 --- a/source/main.c +++ b/source/main.c @@ -5,17 +5,24 @@ void load_options() { } void init_system() {} + int menu_handler() { - render_textbufs(); return 1; } void main() { if (fmount()) { // Failed to mount SD. Bomb out. + cprintf(BOTTOM_SCREEN, "%pFailed to mount SD card.\n", COLOR(RED, BLACK)); + } else { + cprintf(BOTTOM_SCREEN, "Mounted SD card.\n"); + } + + for (int i = 0; i < 200; i++) { + cprintf(TOP_SCREEN, "%d\n", i); } - cprintf(TOP_SCREEN, "Hello, %d, %s!\n", 5042, "person"); + cprintf(TOP_SCREEN, "Done printing."); load_options(); // Load configuration. diff --git a/source/std/draw.c b/source/std/draw.c index e4f6aeb..0a01481 100644 --- a/source/std/draw.c +++ b/source/std/draw.c @@ -6,8 +6,8 @@ #include "memory.h" #include "font.h" -static uint8_t cursor_x = 0, cursor_y = 0; -static uint8_t dirty_text = 0; // We need to redraw. +static unsigned int top_cursor_x = 0, top_cursor_y = 0; +static unsigned int bottom_cursor_x = 0, bottom_cursor_y = 0; static char text_buffer_top [TEXT_TOP_SIZE]; static char text_buffer_bottom [TEXT_BOTTOM_SIZE]; @@ -43,7 +43,7 @@ void clear_screen(uint8_t* screen) { size = SCREEN_TOP_SIZE; buffer = text_buffer_top; buffer_size = TEXT_TOP_SIZE; - } else if(screen == framebuffers->top_left) { + } else if(screen == framebuffers->bottom) { size = SCREEN_BOTTOM_SIZE; buffer = text_buffer_bottom; buffer_size = TEXT_BOTTOM_SIZE; @@ -56,20 +56,25 @@ void clear_screen(uint8_t* screen) { } void clear_screens() { - clear_screen(screen_top_left); - clear_screen(screen_bottom); - cursor_x = 0; - cursor_y = 0; + clear_screen(framebuffers->top_left); + clear_screen(framebuffers->bottom); + top_cursor_x = 0; + top_cursor_y = 0; + bottom_cursor_x = 0; + bottom_cursor_y = 0; } -void draw_character(char* screen, const char character, const unsigned int buf_x, const unsigned int buf_y, const uint32_t color) { +void draw_character(uint8_t* screen, const char character, const unsigned int buf_x, const unsigned int buf_y, const uint32_t color_fg, const uint32_t color_bg) { + if (!isprint(character)) + return; // Don't output non-printables. + int width = 0; int height = 0; if(screen == framebuffers->top_left || screen == framebuffers->top_right) { width = SCREEN_TOP_WIDTH; height = SCREEN_TOP_HEIGHT; - } else if(screen == framebuffers->top_left) { + } else if(screen == framebuffers->bottom) { width = SCREEN_BOTTOM_WIDTH; height = SCREEN_BOTTOM_HEIGHT; } else { @@ -85,41 +90,63 @@ void draw_character(char* screen, const char character, const unsigned int buf_x for (int x = 7; x >= 0; x--) { int screen_pos = (pos_x * height * 3 + (height - y - pos_y - 1) * 3) + (7 - x) * 3 * height; + screen[screen_pos] = color_bg >> 16; + screen[screen_pos + 1] = color_bg >> 8; + screen[screen_pos + 2] = color_bg; + if ((char_pos >> x) & 1) { - screen[screen_pos] = color >> 16; - screen[screen_pos + 1] = color >> 8; - screen[screen_pos + 2] = color; + screen[screen_pos] = color_fg >> 16; + screen[screen_pos + 1] = color_fg >> 8; + screen[screen_pos + 2] = color_fg; } } } } -void putc(int buf, const char c) { - int width = 0; - int height = 0; - int size = 0; +void putc(int buf, unsigned char color, const char c) { + unsigned int width = 0; + unsigned int height = 0; + unsigned int size = 0; + unsigned int cursor_x; + unsigned int cursor_y; char* colorbuf; char* strbuf; - if(buf == TOP_SCREEN) { + + if (buf == TOP_SCREEN) { width = TEXT_TOP_WIDTH; height = TEXT_TOP_HEIGHT; size = TEXT_TOP_SIZE; colorbuf = color_buffer_top; strbuf = text_buffer_top; - } else if(buf == BOTTOM_SCREEN) { + cursor_x = top_cursor_x; + cursor_y = top_cursor_y; + } else if (buf == BOTTOM_SCREEN) { width = TEXT_BOTTOM_WIDTH; height = TEXT_BOTTOM_HEIGHT; size = TEXT_BOTTOM_SIZE; colorbuf = color_buffer_bottom; strbuf = text_buffer_bottom; + cursor_x = bottom_cursor_x; + cursor_y = bottom_cursor_y; } else { return; // Invalid buffer. } unsigned int offset = width * cursor_y + cursor_x; - if (offset > size) - return; // TODO - Scrollback. + if (offset >= size) { + // Scroll a line back. This involves memcpy. + // Yes, memcpy overwrites part of the buffer it is reading. + memcpy(strbuf, strbuf+width, size-width); + memcpy(colorbuf, colorbuf+width, size-width); + cursor_y -= 1; + offset = width * cursor_y + cursor_x; + } + + if (offset >= size) { + // So if we're being real, this won't ever happen. + return; + } switch(c) { case '\n': @@ -131,7 +158,7 @@ void putc(int buf, const char c) { break; default: strbuf[offset] = c; - colorbuf[offset] = 0xf0; // White on black. + colorbuf[offset] = color; // White on black. cursor_x++; if (cursor_x >= width) { cursor_y++; @@ -139,76 +166,57 @@ void putc(int buf, const char c) { } break; } -} - -void puts(int buf, const char *string) { - char *ref = string; - while(*ref != '\0') { - putc(buf, *ref); - *ref++; + if (buf == TOP_SCREEN) { + top_cursor_x = cursor_x; + top_cursor_y = cursor_y; + } else if (buf == BOTTOM_SCREEN) { + bottom_cursor_x = cursor_x; + bottom_cursor_y = cursor_y; } - - dirty_text = 1; // Framebuffer needs update. } -void render_textbufs() { - if(!dirty_text) - return; - - dirty_text = 0; // We're updating it. +void puts(int buf, unsigned char color, const char *string) { + char *ref = (char*)string; - for(int x=0; x < TEXT_TOP_WIDTH; x++) { - for(int y=0; y < TEXT_TOP_HEIGHT; y++) { - char c = text_buffer_top[y*TEXT_TOP_WIDTH+x]; - uint32_t color_fg = colors[((color_buffer_top[y*TEXT_TOP_WIDTH+x] >> 4) & 0x0f)]; - uint32_t color_bg = colors[(color_buffer_top[y*TEXT_TOP_WIDTH+x] & 0x0f)]; - draw_character(framebuffers->top_left, c, x, y, color_fg); - } - } - - for(int x=0; x < TEXT_BOTTOM_WIDTH; x++) { - for(int y=0; y < TEXT_BOTTOM_HEIGHT; y++) { - char c = text_buffer_top[y*TEXT_TOP_WIDTH+x]; - uint32_t color_fg = colors[((color_buffer_top[y*TEXT_TOP_WIDTH+x] >> 4) & 0x0f)]; - uint32_t color_bg = colors[(color_buffer_top[y*TEXT_TOP_WIDTH+x] & 0x0f)]; - draw_character(framebuffers->top_left, c, x, y, color_fg); - } - } + while(*ref != '\0') { + putc(buf, color, *ref); + ref++; + } } -void put_int(int channel, int n) { +void put_int(int channel, unsigned char color, int n) { char conv[16], out[16]; memset(conv, 0, 16); memset(out, 0, 16); - int i = 0, sign = n; - int inter; + int i = 0, sign = 0; + if (n < 0) { + n = -n; + sign = 1; + } do { conv[i] = n % 10; - if (conv[i] < 0) - conv[i] = -conv[i]; conv[i] += '0'; ++i; } while((n /= 10) != 0); - if (sign < 0) + if (sign) conv[i++] = '-'; int len = strlen(conv); for(int i=0; i < len; i++) out[i] = conv[(len-1) - i]; - puts(channel, out); + puts(channel, color, out); } -void put_uint(int channel, unsigned int n) { +void put_uint(int channel, unsigned char color, unsigned int n) { char conv[16], out[16]; memset(conv, 0, 16); memset(out, 0, 16); int i = 0; - unsigned int inter; do { conv[i++] = (n % 10) + '0'; } while((n /= 10) != 0); @@ -217,20 +225,37 @@ void put_uint(int channel, unsigned int n) { for(int i=0; i < len; i++) out[i] = conv[(len-1) - i]; - puts(channel, out); + puts(channel, color, out); +} + +void cflush(int channel) { + if (channel == TOP_SCREEN) { + for(int x=0; x < TEXT_TOP_WIDTH; x++) { + for(int y=0; y < TEXT_TOP_HEIGHT; y++) { + char c = text_buffer_top[y*TEXT_TOP_WIDTH+x]; + uint32_t color_fg = colors[((color_buffer_top[y*TEXT_TOP_WIDTH+x] >> 4) & 0x0f)]; + uint32_t color_bg = colors[(color_buffer_top[y*TEXT_TOP_WIDTH+x] & 0x0f)]; + draw_character(framebuffers->top_left, c, x, y, color_fg, color_bg); + } + } + } else if (channel == BOTTOM_SCREEN) { + for(int x=0; x < TEXT_BOTTOM_WIDTH; x++) { + for(int y=0; y < TEXT_BOTTOM_HEIGHT; y++) { + char c = text_buffer_bottom[y*TEXT_BOTTOM_WIDTH+x]; + uint32_t color_fg = colors[((color_buffer_bottom[y*TEXT_BOTTOM_WIDTH+x] >> 4) & 0x0f)]; + uint32_t color_bg = colors[(color_buffer_top[y*TEXT_TOP_WIDTH+x] & 0x0f)]; + draw_character(framebuffers->bottom, c, x, y, color_fg, color_bg); + } + } + } } -int cprintf(int channel, const char* format, ...) { - int rc; +void cprintf(int channel, const char* format, ...) { va_list ap; va_start( ap, format ); - int i; - unsigned int u; - char* s; - char c; - - char *ref = format; + char *ref = (char*)format; + unsigned char color = 0xf0; while(*ref != '\0') { if(*ref == '%') { @@ -238,34 +263,34 @@ int cprintf(int channel, const char* format, ...) { ref++; switch(*ref) { case 'd': - i = va_arg( ap, int ); - put_int(channel, i); + put_int(channel, color, va_arg( ap, int )); break; case 'u': - u = va_arg( ap, unsigned int ); - put_uint(channel, u); + put_uint(channel, color, va_arg( ap, unsigned int )); break; case 's': - s = va_arg( ap, char* ); - puts(channel, s); + puts(channel, color, va_arg( ap, char* )); break; case 'c': - c = va_arg( ap, char ); - putc(channel, c); + putc(channel, color, va_arg( ap, int )); + break; + case 'p': + color = va_arg( ap, unsigned int ); break; case '%': - putc(channel, '%'); + putc(channel, color, '%'); break; default: break; } - ref++; } else { - putc(channel, *ref); - *ref++; + putc(channel, color, *ref); } + ref++; } va_end( ap ); - return rc; + + cflush(channel); } + diff --git a/source/std/draw.h b/source/std/draw.h index 3ce23bf..26b5831 100644 --- a/source/std/draw.h +++ b/source/std/draw.h @@ -1,6 +1,9 @@ #ifndef __STD_DRAW_H #define __STD_DRAW_H +/* This is in a nutshell a partial implementation of stdio. + It isn't perfect, but it does work. */ + #include #define SCREEN_TOP_WIDTH 400 @@ -43,20 +46,41 @@ static struct framebuffers { void clear_screen(uint8_t* screen); void clear_screens(); -void draw_character(char* screen, const char character, const unsigned int pos_x, const unsigned int pos_y, const uint32_t color); +void draw_character(uint8_t* screen, const char character, const unsigned int pos_x, const unsigned int pos_y, const uint32_t color_fg, const uint32_t color_bg); #define TOP_SCREEN 0 -#define BOTTOM_SCREEN 0 +#define BOTTOM_SCREEN 1 -void putc(int buf, const char c); -void puts(int buf, const char *string); -void render_textbufs(); +void putc(int buf, unsigned char color, const char c); +void puts(int buf, unsigned char color, const char *string); +void cflush(int channel); -void put_int(int channel, int n); -void put_uint(int channel, unsigned int n); +void put_int(int channel, unsigned char color, int n); +void put_uint(int channel, unsigned char color, unsigned int n); // Like printf. Supports the following format specifiers: // %s %c %d %u -int cprintf(int channel, const char* format, ...); +// The following non-standard formats are also supported (but are subject to replacement) +// %p - unsigned char, changes color of text (will be replaced with ANSI codes eventually) +void cprintf(int channel, const char* format, ...); + +#define BLACK 0 +#define BLUE 1 +#define GREEN 2 +#define CYAN 3 +#define RED 4 +#define MAGENTA 5 +#define BROWN 6 +#define GRAY 7 +#define D_GRAY 8 +#define B_BLUE 9 +#define B_GREEN 10 +#define B_CYAN 11 +#define B_RED 12 +#define B_MAGENTA 13 +#define YELLOW 14 +#define WHITE 15 + +#define COLOR(fg, bg) (((fg & 0x0f) << 4) | (bg & 0x0f)) #endif diff --git a/source/std/memory.c b/source/std/memory.c index 249fc33..e71a4a9 100644 --- a/source/std/memory.c +++ b/source/std/memory.c @@ -10,6 +10,12 @@ int strlen(const char *string) return string_end - string; } +int isprint(char c) { + if (c >= 32 && c <= 127) + return 1; + return 0; +} + void memcpy(void *dest, const void *src, size_t size) { char *destc = (char *)dest; diff --git a/source/std/memory.h b/source/std/memory.h index 3345d37..4afbc76 100644 --- a/source/std/memory.h +++ b/source/std/memory.h @@ -13,5 +13,6 @@ void strncpy(void *dest, const void *src, const size_t size); int strncmp(const void *buf1, const void *buf2, const size_t size); int atoi(const char *str); uint8_t* memfind (uint8_t *string, uint32_t stringlen, uint8_t *pat, uint32_t patlen); +int isprint(char c); #endif -- 2.39.5