summaryrefslogtreecommitdiff
path: root/src/vga.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vga.c')
-rw-r--r--src/vga.c103
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;
+}
+