Finished VGA driver and implemented stdio.h (printf and puts)

This commit is contained in:
Arnau Camprubí 2022-06-17 17:13:55 +02:00
pare deae8de0d5
commit 2160a41e81
S'han modificat 5 arxius amb 123 adicions i 22 eliminacions

Veure arxiu

@ -3,22 +3,22 @@
static uint8_t current_color = VGA_COLOR_DEFAULT;
void set_char(int x, int y, char c){
void vga_set_char(int x, int y, char c){
VGA_MEMORY[(x+y*VGA_WIDTH)*2] = c;
}
void set_color(int x, int y, uint8_t color){
void vga_set_color(int x, int y, uint8_t color){
VGA_MEMORY[(x+y*VGA_WIDTH)*2+1] = color;
}
void set_cursor(int offset){
void vga_set_cursor(int offset){
i686_outb(VGA_PORT_CTRL, 14);
i686_outb(VGA_PORT_DATA, (uint8_t)(offset >> 8));
i686_outb(VGA_PORT_CTRL, 15);
i686_outb(VGA_PORT_DATA, (uint8_t)(offset & 0xff));
}
int get_cursor(){
int vga_get_cursor(){
i686_outb(VGA_PORT_CTRL, 14);
int offset = i686_inb(VGA_PORT_DATA) << 8; // High byte
i686_outb(VGA_PORT_CTRL, 15);
@ -34,7 +34,7 @@ static int get_offset_x(int offset){
return (offset - (get_offset_y(offset)*VGA_WIDTH));
}
int print_char(char c, int x, int y){
int vga_print_char(char c, int x, int y){
if(x >= VGA_WIDTH || y >= VGA_HEIGHT){ // Incorrect coords
VGA_MEMORY[2*VGA_WIDTH*VGA_HEIGHT-2] = 'E';
VGA_MEMORY[2*VGA_WIDTH*VGA_HEIGHT-1] = VGA_COLOR_BG_RED || VGA_COLOR_FG_BLACK;
@ -43,7 +43,7 @@ int print_char(char c, int x, int y){
int offset;
if(x >= 0 && y >= 0) offset = y*VGA_WIDTH+x;
else offset = get_cursor();
else offset = vga_get_cursor();
if(c == '\n'){
y = get_offset_y(offset);
@ -61,17 +61,17 @@ int print_char(char c, int x, int y){
// TODO: Scroll
set_cursor(offset);
vga_set_cursor(offset);
return offset;
}
void puts_at(char *str, int x, int y){
void vga_print_string_at(char *str, int x, int y){
int offset;
if(x >= 0 && y >= 0){
offset = y*VGA_WIDTH+x;
}
else{
offset = get_cursor();
offset = vga_get_cursor();
x = get_offset_x(offset);
y = get_offset_y(offset);
}
@ -105,13 +105,13 @@ void puts_at(char *str, int x, int y){
}
}
else{
offset = print_char(*(str++), x, y);
offset = vga_print_char(*(str++), x, y);
x = get_offset_x(offset);
y = get_offset_y(offset);
}
}
}
void puts(char *str){
puts_at(str, -1, -1);
void vga_print_string(char *str){
vga_print_string_at(str, -1, -1);
}

Veure arxiu

@ -46,10 +46,10 @@
#define VGA_PORT_CTRL 0x3D4
#define VGA_PORT_DATA 0x3D5
void set_char(int x, int y, char c);
void set_color(int x, int y, uint8_t color);
void set_cursor(int offset);
int get_cursor();
int print_char(char c, int x, int y);
void puts_at(char *str, int x, int y);
void puts(char *str);
void vga_set_char(int x, int y, char c);
void vga_set_color(int x, int y, uint8_t color);
void vga_set_cursor(int offset);
int vga_get_cursor();
int vga_print_char(char c, int x, int y);
void vga_print_string_at(char *str, int x, int y);
void vga_print_string(char *str);

Veure arxiu

@ -2,6 +2,8 @@
#include "stdio.h"
void __attribute__((cdecl)) kmain(uint64_t magic, uint64_t addr){
printf("Hello world!\n\x1b[32m:D\x1b[0m\n");
puts("\x1b[33mWARNING\x1b[0m");
printf(": amazing %s ahead!\n", "math");
printf("%i+%i=%i\n", 1, 1, 2);
for(;;); // Halt here
}

Veure arxiu

@ -1,6 +1,103 @@
#include <stdarg.h>
#include <stdbool.h>
#include "stdio.h"
#include "drivers/vga.h"
void printf(char *fmt, ...){
puts(fmt);
static char g_HexChars[] = "0123456789abcdef";
void puts(char *str){
vga_print_string(str);
}
void putc(char c){
char str[2];
str[0] = c;
str[1] = '\0';
vga_print_string(str);
}
static void printf_signed(unsigned long long num, int radix){
char buffer[32];
int pos = 0;
// Convert to ASCII
do{
unsigned long long rem = num % radix;
num /= radix;
buffer[pos++] = g_HexChars[rem];
} while(num > 0);
while(--pos >= 0) putc(buffer[pos]); // Note reverse order
}
static void printf_unsigned(unsigned long long num, int radix){
if(num < 0){
putc('-');
printf_unsigned(-num, radix);
}
else printf_unsigned(num, radix);
}
void printf(char *fmt, ...){
// Variadic function arguments
va_list args;
va_start(args, fmt);
while(*fmt){
if(*fmt == '%'){
bool number = false;
bool sign = false;
int radix = 10;
fmt++;
switch(*fmt){
case '%':
putc('%');
break;
case 'c':
putc((char)va_arg(args, int));
break;
case 's':
puts(va_arg(args, char *));
break;
case 'd':
case 'i':
number = true;
radix = 10;
sign = true;
break;
case 'u':
number = true;
radix = 10;
sign = false;
break;
case 'X':
case 'x':
case 'p':
number = true;
radix = 16;
sign = false;
break;
case 'o':
number = true;
radix = 8;
sign = false;
break;
default: break;
}
// TODO: Implement length modifiers
if(number){
if(sign){
printf_signed(va_arg(args, int), radix);
}
else{
printf_unsigned(va_arg(args, unsigned int), radix);
}
}
fmt++;
}
else putc(*(fmt++));
}
}

Veure arxiu

@ -1,3 +1,5 @@
#pragma once
void puts(char *str);
void putc(char c);
void printf(char *fmt, ...);