#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];
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;
}
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 {
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':
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++;
}
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);
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 == '%') {
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);
}
+
#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 <stdint.h>
#define SCREEN_TOP_WIDTH 400
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