865 lines
17 KiB
C
865 lines
17 KiB
C
#include <stdarg.h>
|
|
#include "io.h"
|
|
#include "multiboot.h"
|
|
#include "font.h"
|
|
#include "console.h"
|
|
#include "quinn.xbm"
|
|
#include "gui.h"
|
|
#include "vfs.h"
|
|
#include "tty_fs.h"
|
|
#include "string.h"
|
|
#include "memory.h"
|
|
#include "serial.h"
|
|
|
|
#define KEYBOARD_KEY_LSHIFT 0x2A
|
|
#define KEYBOARD_KEY_RSHIFT 0x36
|
|
|
|
#define KEYBOARD_KEY_ENTER 0x1C
|
|
#define KEYBOARD_KEY_BSPACE 0x66
|
|
|
|
#define KEYBOARD_KEY_LCTRL 0x14
|
|
|
|
#define KEYBOARD_KEY_CAPS 0x58
|
|
|
|
|
|
#define KEYBOARD_KEY_F9 0x01
|
|
#define KEYBOARD_KEY_F5 0x03
|
|
#define KEYBOARD_KEY_F3 0x04
|
|
#define KEYBOARD_KEY_F1 0x05
|
|
#define KEYBOARD_KEY_F2 0x06
|
|
#define KEYBOARD_KEY_F12 0x07
|
|
#define KEYBOARD_KEY_F10 0x09
|
|
#define KEYBOARD_KEY_F8 0x0A
|
|
#define KEYBOARD_KEY_F6 0x0B
|
|
#define KEYBOARD_KEY_F4 0x0C
|
|
#define KEYBOARD_KEY_TAB 0x0D
|
|
|
|
#define KEYBOARD_KEY_LALT 0x11
|
|
|
|
#define BochsConsolePrintChar(c) outportb(0xe9, c)
|
|
|
|
extern const struct bitmap_font font;
|
|
extern unsigned short depth;
|
|
|
|
int x;
|
|
int y;
|
|
unsigned char attrib;
|
|
|
|
unsigned char initialized = 0;
|
|
unsigned int char_width, char_height;
|
|
|
|
extern unsigned char vidmode;
|
|
|
|
void putpixel_24bpp(int x, int y, unsigned int color);
|
|
void console_display_quinn();
|
|
|
|
static unsigned int console_col_map[16] = {
|
|
0x000000, 0x0000AA, 0x00AA00, 0x00AAAA,
|
|
0xAA0000, 0xAA00AA, 0xAA5500, 0xAAAAAA,
|
|
|
|
0x555555, 0x5555FF, 0x55FF55, 0x55FFFF,
|
|
0xFF5555, 0xFF55FF, 0xFFFF55, 0xFFFFFF
|
|
};
|
|
|
|
extern void mem_reserve(char *blk, int pages);
|
|
|
|
struct vfs_device_t *consoletty = (void *)0;
|
|
|
|
unsigned char *consolebuffer;
|
|
unsigned int cons_w;
|
|
unsigned int cons_h;
|
|
|
|
unsigned char capslock;
|
|
unsigned char lshift;
|
|
unsigned char rshift;
|
|
char *cursor_save_buffer;
|
|
int cursor_save_x;
|
|
int cursor_save_y;
|
|
|
|
static const char keyChars_set1[] = {
|
|
0, 27, '1', '2',
|
|
'3', '4', '5', '6',
|
|
'7', '8', '9', '0',
|
|
'-', '=', '\b', '\t',
|
|
'q', 'w', 'e', 'r',
|
|
't', 'y', 'u', 'i',
|
|
'o', 'p', '[', ']',
|
|
'\n', 0, 'a', 's',
|
|
'd', 'f', 'g', 'h',
|
|
'j', 'k', 'l', ';',
|
|
'\'', '`', 0, '\\',
|
|
'z', 'x', 'c', 'v',
|
|
'b', 'n', 'm', ',',
|
|
'.', '/', 0, 0,
|
|
0, ' ', 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0
|
|
};
|
|
|
|
static const char keyChars_set1_s[] = {
|
|
0, 27, '!', '@',
|
|
'#', '$', '%', '^',
|
|
'&', '*', '(', ')',
|
|
'_', '+', '\b', '\t',
|
|
'Q', 'W', 'E', 'R',
|
|
'T', 'Y', 'U', 'I',
|
|
'O', 'P', '{', '}',
|
|
0, 0, 'A', 'S',
|
|
'D', 'F', 'G', 'H',
|
|
'J', 'K', 'L', ':',
|
|
'"', '~', 0, '|',
|
|
'Z', 'X', 'C', 'V',
|
|
'B', 'N', 'M', '<',
|
|
'>', '?', 0, 0,
|
|
0, ' ', 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0
|
|
};
|
|
|
|
static const char keyChars_set2[] = {
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, 0, 0, 0,
|
|
0, '\t', '`', 0,
|
|
0, 0, 0, 0,
|
|
0, 'q', '1', 0,
|
|
0, 0, 'z', 0,
|
|
'a', 'w', '2', 0,
|
|
0, 'c', 'x', 'd',
|
|
'e', '4', '3', 0,
|
|
0, ' ', 'v', 'f',
|
|
't', 'r', '5', 0,
|
|
0, 'n', 'b', 'h',
|
|
'g', 'y', '6', 0,
|
|
0, 0, 'm', 'j',
|
|
'u', '7', '8', 0,
|
|
0, ',', 'k', 'i',
|
|
'o', '0', '9', 0,
|
|
0, '.', '/', 'l',
|
|
';', 'p', '-', 0,
|
|
0, 0, '\'', 0,
|
|
'[', '=', 0, 0,
|
|
0, 0, 0, ']',
|
|
0, '\\', 0, 0};
|
|
|
|
void console_input(unsigned char scancode, unsigned char state) {
|
|
if (state == 0) {
|
|
if (scancode == KEYBOARD_KEY_LSHIFT) {
|
|
lshift = 0;
|
|
|
|
}
|
|
|
|
if (scancode == KEYBOARD_KEY_RSHIFT) {
|
|
rshift = 0;
|
|
}
|
|
} else {
|
|
if (scancode == KEYBOARD_KEY_LSHIFT) {
|
|
lshift = 1;
|
|
}
|
|
|
|
if (scancode == KEYBOARD_KEY_RSHIFT) {
|
|
rshift = 1;
|
|
}
|
|
|
|
if (scancode > 0x00 && scancode < 0x57) {
|
|
if (lshift || rshift) {
|
|
if (keyChars_set1_s[scancode] != 0) {
|
|
tty_input(consoletty, keyChars_set1_s[scancode]);
|
|
}
|
|
} else {
|
|
if (keyChars_set1[scancode] != 0) {
|
|
tty_input(consoletty, keyChars_set1[scancode]);
|
|
}
|
|
}
|
|
} else {
|
|
kprintf("scancode %x\n", scancode);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void init_console() {
|
|
|
|
if (vidmode == 1) {
|
|
|
|
cons_w = 80 * font.Width;
|
|
cons_h = 25 * font.Height;
|
|
|
|
consolebuffer = (char *)malloc((cons_w * cons_h) * depth);
|
|
char_height = 25;//height / font.Height;
|
|
char_width = 80;//width / font.Width;
|
|
|
|
memset(consolebuffer, 0, cons_w * cons_h * depth);
|
|
|
|
cursor_save_buffer = (char *)malloc(8 * 4 * depth);
|
|
cursor_save_x = -1;
|
|
cursor_save_y = -1;
|
|
|
|
gui_add_window(consolebuffer, "System Console", 10, 35, cons_w, cons_h, (void *)0, 0, console_input);
|
|
|
|
console_display_quinn();
|
|
x = 0;
|
|
y = 7;
|
|
|
|
} else {
|
|
char_width = 80;
|
|
char_height = 25;
|
|
x = 0;
|
|
y = 0;
|
|
clear_screen();
|
|
}
|
|
attrib = 0x07;
|
|
capslock = 0;
|
|
lshift = 0;
|
|
rshift = 0;
|
|
initialized = 1;
|
|
}
|
|
|
|
|
|
void console_display_quinn() {
|
|
int x;
|
|
int y;
|
|
|
|
for (y=0;y<quinn_height;y++) {
|
|
for (x=0;x<quinn_width;x++) {
|
|
unsigned long mask, offset, index, i;
|
|
mask = 1;
|
|
index = (y * quinn_width + x) / 8;
|
|
offset = (y * quinn_width + x) % 8;
|
|
|
|
if (!(quinn_bits[index] & (mask << offset))) {
|
|
putpixel_24bpp(x, y, console_col_map[7]);
|
|
}
|
|
}
|
|
}
|
|
//flip();
|
|
}
|
|
|
|
|
|
|
|
void putpixel_24bpp(int x, int y, unsigned int color) {
|
|
if (x < 0 || x >= cons_w || y < 0 || y >= cons_h) {
|
|
return;
|
|
}
|
|
int where = (x * depth) + (y * cons_w * depth);
|
|
consolebuffer[where] = color & 255; // BLUE
|
|
consolebuffer[where + 1] = (color >> 8) & 255; // GREEN
|
|
consolebuffer[where + 2] = (color >> 16) & 255; // RED
|
|
}
|
|
|
|
|
|
|
|
void clear_screen(void) {
|
|
unsigned char *videoram = (char *)0xB8000;
|
|
|
|
if (vidmode == 0) {
|
|
int i;
|
|
int j;
|
|
|
|
for (i=0;i<25;i++) {
|
|
for (j=0;j<80;j++) {
|
|
videoram[(i * 80 + j) * 2] = ' ';
|
|
videoram[(i * 80 + j) * 2 + 1] = attrib;
|
|
}
|
|
}
|
|
} else {
|
|
int j;
|
|
int k;
|
|
unsigned int colour = console_col_map[(attrib & 0xf0) >> 4];
|
|
for (k=0;k<cons_w;k++) {
|
|
for (j=0;j<cons_h;j++) {
|
|
putpixel_24bpp(k, j, colour);
|
|
}
|
|
}
|
|
//flip();
|
|
}
|
|
}
|
|
|
|
void scroll_up(void) {
|
|
unsigned char *videoram = (char *)0xB8000;
|
|
int i;
|
|
int j;
|
|
|
|
if (vidmode == 0) {
|
|
|
|
for (i=0;i<24;i++) {
|
|
for (j=0;j<80;j++) {
|
|
videoram[(i * 80 + j) * 2] = videoram[((i + 1) * 80 + j) * 2];
|
|
videoram[(i * 80 + j) * 2 + 1] = videoram[((i + 1) * 80 + j) * 2 + 1];
|
|
}
|
|
}
|
|
for (j=0;j<80;j++) {
|
|
videoram[(i * 80 + j) * 2] = ' ';
|
|
videoram[(i * 80 + j) * 2 + 1] = 0x07;
|
|
}
|
|
} else {
|
|
unsigned char *read_ptr = consolebuffer + (font.Height * (80 * font.Width * depth));
|
|
unsigned char *write_ptr = consolebuffer;
|
|
unsigned int num_bytes = ((80 * font.Width * depth) * cons_h) - ((80 * font.Width * depth) * font.Height);
|
|
memcpy(write_ptr, read_ptr, num_bytes);
|
|
|
|
read_ptr = (unsigned char *) consolebuffer + ((80 * font.Width * depth) * cons_h) - ((80 * font.Width * depth) * font.Height);
|
|
memset(read_ptr, 0, (80 * font.Width * depth) * font.Height);
|
|
cursor_save_y--;
|
|
//flip();
|
|
}
|
|
update_cursor(1);
|
|
}
|
|
|
|
|
|
void draw_char(unsigned int x, unsigned int y, char c) {
|
|
int i;
|
|
|
|
for (i=0;i<font.Chars;i++) {
|
|
if (font.Index[i] == c) break;
|
|
}
|
|
|
|
const char *font_char = &font.Bitmap[i * font.Height];
|
|
int cx,cy;
|
|
//int mask[8]={1,2,4,8,16,32,64,128};
|
|
int mask[8]={128,64,32,16,8,4,2,1};
|
|
unsigned int fgcolor = console_col_map[attrib & 0x0F];
|
|
unsigned int bgcolor = console_col_map[(attrib & 0xF0) >> 4];
|
|
|
|
for(cy=0;cy<16;cy++){
|
|
for(cx=0;cx<8;cx++){
|
|
if (initialized == 1) {
|
|
putpixel_24bpp(x+cx,y+cy,font_char[cy]&mask[cx]?fgcolor:bgcolor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void console_backspace() {
|
|
unsigned char *videoram = (char *)0xB8000;
|
|
if (x == 0) {
|
|
y--;
|
|
x = char_width - 1;
|
|
} else {
|
|
x--;
|
|
}
|
|
if (vidmode == 0) {
|
|
videoram[(y * 80 + x)* 2] = ' ';
|
|
videoram[(y * 80 + x)* 2 + 1] = attrib;
|
|
} else {
|
|
draw_char(x * font.Width, y * font.Height, ' ');
|
|
}
|
|
update_cursor(1);
|
|
}
|
|
|
|
void putchar(char c) {
|
|
unsigned char *videoram = (char *)0xB8000;
|
|
|
|
serial_write(c);
|
|
if (initialized) {
|
|
switch (c) {
|
|
|
|
case '\n':
|
|
x = 0;
|
|
y++;
|
|
|
|
BochsConsolePrintChar('\n');
|
|
if (y == char_height) {
|
|
scroll_up();
|
|
y = char_height - 1;
|
|
}
|
|
update_cursor(1);
|
|
break;
|
|
default:
|
|
if (vidmode == 0) {
|
|
videoram[(y * 80 + x)* 2] = c;
|
|
videoram[(y * 80 + x)* 2 + 1] = attrib;
|
|
} else {
|
|
BochsConsolePrintChar(c);
|
|
draw_char(x * font.Width, y * font.Height, c);
|
|
}
|
|
|
|
x++;
|
|
if (x==char_width) {
|
|
x = 0;
|
|
y++;
|
|
}
|
|
if (y == char_height) {
|
|
scroll_up();
|
|
y = char_height - 1;
|
|
}
|
|
update_cursor(0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void putstr(char *str) {
|
|
char *ptr = str;
|
|
|
|
while (*ptr != '\0') {
|
|
putchar(*ptr);
|
|
ptr++;
|
|
}
|
|
}
|
|
|
|
void goto_xy(int newx, int newy) {
|
|
if (newx > char_width || newy > char_height || newx < 0 || newy < 0) {
|
|
return;
|
|
}
|
|
x = newx;
|
|
y = newy;
|
|
update_cursor(1);
|
|
}
|
|
|
|
static int state = 0;
|
|
static int params[16];
|
|
static int param_count = 0;
|
|
static int saved_x = 0;
|
|
static int saved_y = 0;
|
|
static int bold = 0;
|
|
static unsigned char saved_attr = 0x07;
|
|
|
|
void putdata(char *str, int len) {
|
|
int i;
|
|
int j;
|
|
int k;
|
|
|
|
|
|
for (i=0;i<len;i++) {
|
|
if (state == 0) {
|
|
if (str[i] == 27) {
|
|
state = 1;
|
|
continue;
|
|
} if ((str[i] > 31 && str[i] < 127) || str[i] == '\n') {
|
|
putchar(str[i]);
|
|
}
|
|
} else if (state == 1) {
|
|
if (str[i] == '[') {
|
|
state = 2;
|
|
continue;
|
|
}
|
|
} else if (state == 2) {
|
|
param_count = 0;
|
|
for (j=0;j<16;j++) {
|
|
params[j] = 0;
|
|
}
|
|
state = 3;
|
|
}
|
|
if (state == 3) {
|
|
if (str[i] == ';') {
|
|
if (param_count < 15) {
|
|
param_count++;
|
|
}
|
|
continue;
|
|
} else if (str[i] >= '0' && str[i] <= '9') {
|
|
if (!param_count) param_count = 1;
|
|
params[param_count-1] = params[param_count-1] * 10 + (str[i] - '0');
|
|
continue;
|
|
} else {
|
|
state = 4;
|
|
}
|
|
}
|
|
|
|
if (state == 4) {
|
|
switch (str[i]) {
|
|
case 'H':
|
|
case 'f':
|
|
if (params[0]) params[0]--;
|
|
if (params[1]) params[1]--;
|
|
goto_xy(params[0], params[1]);
|
|
state = 0;
|
|
break;
|
|
case 'A':
|
|
if (param_count > 0) {
|
|
goto_xy(x, y - params[0]);
|
|
} else {
|
|
goto_xy(x, y - 1);
|
|
}
|
|
state = 0;
|
|
break;
|
|
case 'B':
|
|
if (param_count > 0) {
|
|
goto_xy(x, y + params[0]);
|
|
} else {
|
|
goto_xy(x, y + 1);
|
|
}
|
|
state = 0;
|
|
break;
|
|
case 'C':
|
|
if (param_count > 0) {
|
|
goto_xy(x + params[0], y);
|
|
} else {
|
|
goto_xy(x + 1, y);
|
|
}
|
|
state = 0;
|
|
break;
|
|
case 'D':
|
|
if (param_count > 0) {
|
|
goto_xy(x - params[0], y);
|
|
} else {
|
|
goto_xy(x - 1, y);
|
|
}
|
|
state = 0;
|
|
break;
|
|
case 's':
|
|
saved_x = x;
|
|
saved_y = y;
|
|
state = 0;
|
|
break;
|
|
case 'u':
|
|
goto_xy(saved_x, saved_y);
|
|
state = 0;
|
|
break;
|
|
case '7':
|
|
saved_x = x;
|
|
saved_y = y;
|
|
saved_attr = attrib;
|
|
state = 0;
|
|
break;
|
|
case '8':
|
|
goto_xy(saved_x, saved_y);
|
|
attrib = saved_attr;
|
|
break;
|
|
case 'm':
|
|
for (j=0;j<param_count;j++) {
|
|
switch (params[j]) {
|
|
case 0:
|
|
attrib = 0x07;
|
|
break;
|
|
case 1:
|
|
bold = 1;
|
|
break;
|
|
case 2:
|
|
bold = 0;
|
|
break;
|
|
case 30:
|
|
attrib &= 0xF0;
|
|
if (bold) {
|
|
attrib |= 0x08;
|
|
} else {
|
|
attrib |= 0x00;
|
|
}
|
|
break;
|
|
case 31:
|
|
attrib &= 0xF0;
|
|
if (bold) {
|
|
attrib |= 0x0C;
|
|
} else {
|
|
attrib |= 0x04;
|
|
}
|
|
break;
|
|
case 32:
|
|
attrib &= 0xF0;
|
|
if (bold) {
|
|
attrib |= 0x0A;
|
|
} else {
|
|
attrib |= 0x02;
|
|
}
|
|
break;
|
|
case 33:
|
|
attrib &= 0xF0;
|
|
if (bold) {
|
|
attrib |= 0x0E;
|
|
} else {
|
|
attrib |= 0x06;
|
|
}
|
|
break;
|
|
case 34:
|
|
attrib &= 0xF0;
|
|
if (bold) {
|
|
attrib |= 0x09;
|
|
} else {
|
|
attrib |= 0x01;
|
|
}
|
|
break;
|
|
case 35:
|
|
attrib &= 0xF0;
|
|
if (bold) {
|
|
attrib |= 0x0D;
|
|
} else {
|
|
attrib |= 0x05;
|
|
}
|
|
break;
|
|
case 36:
|
|
attrib &= 0xF0;
|
|
if (bold) {
|
|
attrib |= 0x0B;
|
|
} else {
|
|
attrib |= 0x03;
|
|
}
|
|
break;
|
|
case 37:
|
|
attrib &= 0xF0;
|
|
if (bold) {
|
|
attrib |= 0x0F;
|
|
} else {
|
|
attrib |= 0x07;
|
|
}
|
|
break;
|
|
case 40:
|
|
attrib &= 0x0F;
|
|
attrib |= 0x00;
|
|
break;
|
|
case 41:
|
|
attrib &= 0x0F;
|
|
attrib |= 0x40;
|
|
break;
|
|
case 42:
|
|
attrib &= 0x0F;
|
|
attrib |= 0x20;
|
|
break;
|
|
case 43:
|
|
attrib &= 0x0F;
|
|
attrib |= 0x60;
|
|
break;
|
|
case 44:
|
|
attrib &= 0x0F;
|
|
attrib |= 0x10;
|
|
|
|
break;
|
|
case 45:
|
|
attrib &= 0x0F;
|
|
attrib |= 0x50;
|
|
break;
|
|
case 46:
|
|
attrib &= 0x0F;
|
|
attrib |= 0x30;
|
|
break;
|
|
case 47:
|
|
attrib &= 0x0F;
|
|
attrib |= 0x70;
|
|
break;
|
|
|
|
}
|
|
}
|
|
state = 0;
|
|
break;
|
|
case 'K':
|
|
if (params[0] == 0) {
|
|
j = x;
|
|
for (k=j;k<char_width;k++) {
|
|
putchar(' ');
|
|
}
|
|
x = j;
|
|
} else if (params[0] == 1) {
|
|
j = x;
|
|
x = 0;
|
|
for (k=0;k<j;j++) {
|
|
putchar(' ');
|
|
}
|
|
x = j;
|
|
} else if (params[0] == 2) {
|
|
j = x;
|
|
for (k=0;k<char_width;k++) {
|
|
putchar(' ');
|
|
}
|
|
x = j;
|
|
}
|
|
state = 0;
|
|
break;
|
|
case 'J':
|
|
if (params[0] == 0) {
|
|
fill_rect(consolebuffer, cons_w, cons_h, 0, y * font.Height, cons_w, (char_height - y) * font.Height, attrib & 0xF0 >> 4);
|
|
} else if (params[0] == 1) {
|
|
fill_rect(consolebuffer, cons_w, cons_h, 0, 0, cons_w, y * font.Height, attrib & 0xF0 >> 4);
|
|
} else if (params[0] == 2) {
|
|
clear_screen();
|
|
x = 0;
|
|
y = 0;
|
|
}
|
|
state = 0;
|
|
break;
|
|
case 'h':
|
|
if (params[0] == 12) {
|
|
if (consoletty != 0) {
|
|
((struct tty_dev_data *)consoletty->fs_data)->echo = 0;
|
|
}
|
|
}
|
|
state = 0;
|
|
break;
|
|
case 'i':
|
|
if (params[0] == 12) {
|
|
if (consoletty != 0) {
|
|
((struct tty_dev_data *)consoletty->fs_data)->echo = 1;
|
|
}
|
|
}
|
|
state = 0;
|
|
break;
|
|
default:
|
|
state = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//flip();
|
|
}
|
|
|
|
void putunumber(unsigned int number, int base) {
|
|
char buffer[256];
|
|
char *ptr;
|
|
int i;
|
|
|
|
buffer[255] = '\0';
|
|
|
|
ptr = &buffer[255];
|
|
|
|
if (number == 0) {
|
|
putchar('0');
|
|
return;
|
|
}
|
|
|
|
while (number > 0 && ptr != buffer) {
|
|
ptr--;
|
|
i = number % base;
|
|
*ptr = "fedcba9876543210123456789abcdef"[15 + i];
|
|
number /= base;
|
|
}
|
|
putstr(ptr);
|
|
}
|
|
|
|
void putnumber(int number, int base) {
|
|
char buffer[256];
|
|
char *ptr;
|
|
int i;
|
|
|
|
buffer[255] = '\0';
|
|
|
|
ptr = &buffer[255];
|
|
|
|
if (number < 0) {
|
|
putchar('-');
|
|
number = -number;
|
|
}
|
|
|
|
if (number == 0) {
|
|
putchar('0');
|
|
return;
|
|
}
|
|
|
|
while (number > 0 && ptr != buffer) {
|
|
ptr--;
|
|
i = number % base;
|
|
*ptr = "fedcba9876543210123456789abcdef"[15 + i];
|
|
number /= base;
|
|
}
|
|
putstr(ptr);
|
|
}
|
|
|
|
void do_printf(char *fmt, va_list args) {
|
|
int state = 0;
|
|
char *ptr = fmt;
|
|
int number;
|
|
char *str;
|
|
char c;
|
|
|
|
while (*ptr != '\0') {
|
|
|
|
if (state == 0) {
|
|
if (*ptr == '%') {
|
|
state = 1;
|
|
} else {
|
|
putchar(*ptr);
|
|
}
|
|
} else {
|
|
switch (*ptr) {
|
|
case '%':
|
|
putchar(*ptr);
|
|
break;
|
|
case 'd':
|
|
number = va_arg(args, int);
|
|
putnumber(number, 10);
|
|
break;
|
|
case 's':
|
|
str = va_arg(args, char *);
|
|
putstr(str);
|
|
break;
|
|
case 'x':
|
|
number = va_arg(args, int);
|
|
putnumber(number, 16);
|
|
break;
|
|
case 'p':
|
|
number = va_arg(args, unsigned int);
|
|
putunumber(number, 16);
|
|
break;
|
|
case 'c':
|
|
c = va_arg(args, int);
|
|
putchar(c);
|
|
break;
|
|
}
|
|
|
|
state = 0;
|
|
}
|
|
ptr++;
|
|
}
|
|
}
|
|
|
|
void kprintf(char *fmt, ...) {
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
do_printf(fmt, args);
|
|
va_end(args);
|
|
}
|
|
|
|
|
|
|
|
void update_cursor(int restore) {
|
|
if (vidmode == 0) {
|
|
unsigned short position = y * 80 + x;
|
|
outportb(0x3d4, 0x0f);
|
|
outportb(0x3d5, (unsigned char)(position & 0xFF));
|
|
outportb(0x3d4, 0x0e);
|
|
outportb(0x3d5, (unsigned char)((position >> 8) & 0xFF));
|
|
} else {
|
|
int bpos, i, j;
|
|
|
|
if (restore == 1 && cursor_save_x > -1 && cursor_save_y > -1) {
|
|
// restore the bit of the screen where the cursor was
|
|
bpos = 0;
|
|
for (i=0;i<4;i++) {
|
|
for (j=0;j<8;j++) {
|
|
int where = ((j + (cursor_save_x*font.Width)) * depth) + (((font.Height - i - 1) + (cursor_save_y* font.Height)) * cons_w * depth);
|
|
consolebuffer[where] = cursor_save_buffer[bpos]; // BLUE
|
|
consolebuffer[where + 1] = cursor_save_buffer[bpos + 1]; // GREEN
|
|
consolebuffer[where + 2] = cursor_save_buffer[bpos + 2]; // RED
|
|
|
|
bpos += depth;
|
|
}
|
|
}
|
|
}
|
|
// save the new cursor position buffer;
|
|
bpos = 0;
|
|
for (i=0;i<4;i++) {
|
|
for (j=0;j<8;j++) {
|
|
int where = ((j + (x*font.Width)) * depth) + (((font.Height - i - 1) + (y* font.Height)) * cons_w * depth);
|
|
cursor_save_buffer[bpos] = consolebuffer[where];
|
|
cursor_save_buffer[bpos + 1] = consolebuffer[where + 1];
|
|
cursor_save_buffer[bpos + 2] = consolebuffer[where + 2];
|
|
|
|
bpos += depth;
|
|
}
|
|
}
|
|
|
|
cursor_save_x = x;
|
|
cursor_save_y = y;
|
|
|
|
// draw the cursor
|
|
for (i=0;i<4;i++) {
|
|
for (j=0;j<8;j++) {
|
|
int where = ((j + (cursor_save_x*font.Width)) * depth) + (((font.Height - i - 1) + (cursor_save_y* font.Height)) * cons_w * depth);
|
|
consolebuffer[where] = 0xff; // BLUE
|
|
consolebuffer[where + 1] = 0xff; // GREEN
|
|
consolebuffer[where + 2] = 0xff; // RED
|
|
|
|
bpos += depth;
|
|
}
|
|
}
|
|
}
|
|
}
|