aboutsummaryrefslogtreecommitdiff
path: root/drivers/vgatext.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vgatext.c')
-rw-r--r--drivers/vgatext.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/drivers/vgatext.c b/drivers/vgatext.c
new file mode 100644
index 0000000..d0633af
--- /dev/null
+++ b/drivers/vgatext.c
@@ -0,0 +1,124 @@
+#include <stdint.h>
+#include <stdio.h>
+#include "gfx.h"
+#include "io.h"
+#include "panic.h"
+#include "vgatext.h"
+
+static int term_x, term_y;
+static uint8_t term_col;
+/* VGA buffer starts at 0xB8000 on color or 0xB0000 on monochrome */
+static uint16_t *term_buf;
+
+static uint16_t video_detect_hardware(void)
+{
+ const uint16_t *ptr = (const uint16_t*)0x410;
+ return *ptr;
+}
+
+void vgatext_init(void)
+{
+ uint16_t vid_type = video_detect_hardware() & 0x30;
+ if(vid_type == 0x20)
+ {
+ /* color */
+ term_buf = (uint16_t*)0xB8000;
+ }
+ else if(vid_type == 0x30)
+ {
+ term_buf = (uint16_t*)0xB0000;
+ }
+ else
+ {
+ /* none */
+ panic("VGATEXT init failed!");
+ }
+ vgatext_set_color(VGA_MAKE_COLOR(VGA_LIGHT_GRAY, VGA_BLACK));
+ vgatext_clear();
+ set_putchar(vgatext_putchar);
+ set_puts(vgatext_puts);
+}
+
+static void move_cursor(uint16_t cursor_idx)
+{
+ outb(0x3D4, 14);
+ outb(0x3D5, cursor_idx >> 8); // high byte
+ outb(0x3D4, 15);
+ outb(0x3D5, cursor_idx); // low byte
+}
+
+static void update_cursor(void)
+{
+ move_cursor(term_y * VGA_WIDTH + term_x);
+}
+
+void vgatext_clear(void)
+{
+ term_x = 0;
+ term_y = 0;
+ for(int y = 0; y < VGA_HEIGHT; ++y)
+ {
+ for(int x = 0; x < VGA_WIDTH; ++x)
+ {
+ term_buf[y * VGA_WIDTH + x] = VGA_MAKE_ENTRY(' ', term_col);
+ }
+ }
+}
+
+void vgatext_set_color(uint8_t color)
+{
+ term_col = color;
+}
+
+uint8_t vgatext_get_color(void)
+{
+ return term_col;
+}
+
+void vgatext_putchar_at(int ch, uint8_t col, int x, int y)
+{
+ term_buf[y * VGA_WIDTH + x] = VGA_MAKE_ENTRY((char)ch, col);
+}
+
+void vgatext_putchar(int ch)
+{
+ if(ch != '\n' && ch != '\b')
+ {
+ vgatext_putchar_at(ch, term_col, term_x, term_y);
+ if(++term_x == VGA_WIDTH)
+ {
+ term_x = 0;
+ if(++term_y == VGA_HEIGHT)
+ {
+ vgatext_clear();
+ term_y = 0;
+ }
+ }
+ }
+ else if(ch == '\n')
+ {
+ term_x = 0;
+ if(++term_y == VGA_HEIGHT)
+ {
+ vgatext_clear();
+ term_y = 0;
+ }
+ }
+ else if(ch == '\b')
+ {
+ int temp_x = term_x - 1;
+ if(temp_x >= 0)
+ term_x = temp_x;
+ vgatext_putchar_at(' ', term_col, term_x, term_y);
+ }
+
+ update_cursor();
+}
+
+void vgatext_puts(const char *str)
+{
+ while(*str)
+ {
+ vgatext_putchar(*str++);
+ }
+}