currsos/src/print.c

213 lines
4.6 KiB
C

#include "print.h"
#include "clib.h"
#include "memory_layout.h"
#include "spin_lock.h"
#define FBUF (uintptr)R_PADDR(0xb8000)
#define GET_ROW(pos) ((pos) / 80)
#define GET_POS(row, col) ((row) * 80 + (col))
static struct spin_lock lock;
static uint64 text_pos;
void print_init()
{
spin_init(&lock);
text_pos = 0;
clear_screen();
}
static void
print_scroll(void)
{
mem_mv((void*)(FBUF + GET_POS(1, 0) * 2), (void *) (FBUF + GET_POS(0, 0) * 2), (80 * 24) * 2);
}
static void
print_str(char const *str)
{
if (str == NULL)
{
return;
}
while (*str != 0)
{
if (*str == '\n')
{
text_pos = 80 * (GET_ROW(text_pos) + 1);
if (text_pos > 80 * 25 - 1)
{
//can't hold
print_scroll();
mem_set((void *) (FBUF + 80 * 24 * 2), 0, 80 * 2); // clear last row
text_pos = 80 * 24;
}
str++;
}
else
{
if (text_pos > 80 * 25 - 1)
{
//can't hold
print_scroll();
text_pos = 80 * 24;
}
*((char *) (FBUF) + text_pos * 2) = *str;
*((char *) (FBUF) + text_pos * 2 + 1) = 7;
str++;
text_pos++;
}
}
}
static void
print_uint(uint64 number)
{
char arr[21]; // do not need to initialize
arr[20] = 0; //zero-terminated
uint32 index = 19;
uint32 const div = 10;
while (1)
{
uint64 quo = number / div;
uint64 rmd = number % div;
number = quo;
arr[index--] = (char) ('0' + rmd);
if (number == 0)
{
break;
}
}
print_str(&(arr[index + 1]));
}
static void
print_int(int64 number)
{
char arr[21]; // do not need to initialize
arr[20] = 0; //zero-terminated
uint32 index = 19;
uint32 isNegative = 0;
uint32 const div = 10;
if (number < 0)
{
isNegative = 1;
number *= -1;
}
while (1)
{
int64 quo = number / div;
int64 rmd = number % div;
number = quo;
arr[index--] = (char) ('0' + rmd);
if (number == 0)
{
break;
}
}
if (isNegative)
{
arr[index--] = '-';
}
print_str(&(arr[index + 1]));
}
static void
print_hex(uint64 number, uint64 capital)
{
char const lookup_table_cap[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char const lookup_table[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
char const *const look_up = capital == 1 ? &lookup_table_cap[0] : &lookup_table[0];
char arr[17];
arr[16] = 0; //zero-terminated
uint32 index = 15;
uint32 const div = 16;
while (1)
{
uint64 quo = number / div;
uint64 rmd = number % div;
number = quo;
arr[index--] = look_up[rmd];
if (number == 0)
{
break;
}
}
print_str(&(arr[index + 1]));
}
void
clear_screen(void)
{
uint64 irq;
irq = spin_lock_irq_save(&lock);
text_pos = 0; // reset text_pos
mem_set((void *) FBUF, 0, 25 * 80 * 2);
spin_unlock_irq_restore(&lock, irq);
}
static void
kvprintf(char const *format, va_list args)
{
char buf[2];
int64 d;
uint64 u;
char *s;
buf[1] = '\0';
for (; *format != '\0'; format++)
{
if (*format != '%')
{
buf[0] = *format;
print_str(buf);
continue;
}
format++;
switch (*format)
{
case 'd':
d = va_arg(args, int64);
print_int(d);
break;
case 'u':
u = va_arg(args, uint64);
print_uint(u);
break;
case 's':
s = va_arg(args, char *);
print_str(s);
break;
case 'x':
u = va_arg(args, uint64);
print_hex(u, 0);
break;
case 'X':
u = va_arg(args, uint64);
print_hex(u, 1);
break;
case '%':
buf[0] = '%';
print_str(buf);
break;
default:
buf[0] = '%';
print_str(buf);
format--;
break;
}
}
}
void
kprintf(char const *format, ...)
{
va_list args;
va_start(args, format);
uint64 irq;
irq = spin_lock_irq_save(&lock);
kvprintf(format, args);
spin_unlock_irq_restore(&lock, irq);
va_end(args);
}