diff options
Diffstat (limited to 'src/vga.c')
-rw-r--r-- | src/vga.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/vga.c b/src/vga.c new file mode 100644 index 0000000..3ff8342 --- /dev/null +++ b/src/vga.c @@ -0,0 +1,103 @@ + +#include "vga.h" +#include "string.h" +#include "port.h" +#include <stdint.h> +#include <stddef.h> + +uint16_t* terminal_buffer = (uint16_t*) 0xB8000;; + +uint8_t vga_color(enum vga_color fg, enum vga_color bg) { + return fg | bg << 4; +} + +uint16_t vga_entry(unsigned char uc, uint8_t color) { + return (uint16_t) uc | (uint16_t) color << 8; +} + +void vclear(void) { + terminal_row = 0; + terminal_column = 0; + for (size_t y = 0; y < VGA_HEIGHT; y++) + { + for (size_t x = 0; x < VGA_WIDTH; x++) + { + const size_t index = y * VGA_WIDTH + x; + terminal_buffer[index] = vga_entry(' ', terminal_color); + } + } +} + +void vsetcolor(uint8_t color) { + terminal_color = color; +} + +void vsetchar(char c, uint8_t color, size_t x, size_t y) { + const size_t index = y * VGA_WIDTH + x; + terminal_buffer[index] = vga_entry(c, color); +} + +void vscroll() { + for (unsigned int row=1; row < VGA_HEIGHT; row++) + { + size_t row_bytesize = VGA_WIDTH * 2; // A VGA entry is 2 bytes + // Copy each line one line up + memcpy(&terminal_buffer[(row - 1) * VGA_WIDTH], + &terminal_buffer[row * VGA_WIDTH], row_bytesize); + } + // Clear last line + for (unsigned int col=0; col < VGA_WIDTH; col++) + { + terminal_buffer[VGA_WIDTH * (VGA_HEIGHT - 1) + col] = vga_entry(' ', terminal_color); + } + terminal_row--; +} + +void vputchar(char c) { + void newline() { + terminal_column = 0; + if (++terminal_row >= VGA_HEIGHT) + vscroll(); + } + switch (c) { + default: + vsetchar(c, terminal_color, terminal_column, terminal_row); + terminal_column++; + break; + case '\n': + newline(); + break; + case '\t': + // tab width of 4 + terminal_column = (terminal_column / 4 + 1) * 4; + break; + case '\b': + if (terminal_column > 0) terminal_column--; + break; + case '\r': + terminal_column = 0; + break; + case '\f': + vclear(); + break; + case '\a': + break; + } + if (terminal_column >= VGA_WIDTH) + newline(); +} + +void _putchar(char c) { + vputchar(c); +} + +void vprint(const char* str) { + for (size_t i = 0; i < strlen(str); i++) + vputchar(str[i]); +} + +void vlocate(size_t column, size_t row) { + terminal_column = column % VGA_WIDTH; + terminal_row = row % VGA_HEIGHT; +} + |