blob: b6edbb0d1a5c6065485b27161b07bbd3ec982019 [file] [log] [blame]
swissChilid8137922021-02-17 15:34:07 -08001#include "vga.h"
swissChili9b3584b2021-02-18 13:57:27 -08002#include "io.h"
swissChili0b35bf22021-02-18 12:49:40 -08003#include "log.h"
swissChilid8137922021-02-17 15:34:07 -08004
5static uint cursor_x = 0;
6static uint cursor_y = 0;
7
8static ushort color = WHITE;
9
10static ushort *fb = (ushort *)0xB8000;
11
12static void move_cursor()
13{
14 ushort loc = cursor_y * 80 + cursor_x;
15 outb(0x3d4, 14); // Setting high cursor byte
16 outb(0x3d4, loc >> 8);
17
18 outb(0x3d4, 15); // low byte
19 outb(0x3d4, loc & 0xff);
20}
21
22static void scroll()
23{
24 ushort blank = ' ' | color << 8;
25
26 while (cursor_y >= 25) // end of line
27 {
28 // scroll everything up
29 memcpy(fb, &fb[80], 24 * 80 * 2);
30
31 for (int i = 24 * 80; i < 25 * 80; i++)
32 {
33 fb[i] = blank;
34 }
35
36 cursor_y--;
37 }
38}
39
40void vga_set_color(enum vga_colors fg, enum vga_colors bg)
41{
42 color = (bg << 4) | fg & 0xf;
43}
44
45void vga_put(char c)
46{
47 switch (c)
48 {
49 case '\b':
50 if (cursor_x > 0)
51 cursor_x--;
52 break;
53 case '\t':
swissChili825d46b2021-02-21 10:14:16 -080054 cursor_x = (cursor_x + 8) & ~7;
swissChilid8137922021-02-17 15:34:07 -080055 break;
56 case '\n':
57 cursor_y++;
58 case '\r':
59 cursor_x = 0;
60 break;
61 default:
62 cursor_x++;
63 fb[cursor_y * 80 + cursor_x] = c | (color << 8);
64 }
65
66 if (cursor_x >= 80) // off screen
67 {
68 cursor_x = 0;
69 cursor_y++;
70 }
71
72 scroll();
73 move_cursor();
74}
75
76void vga_clear()
77{
78 memset(fb, 0, 80 * 25 * 2);
79 cursor_x = 0;
80 cursor_y = 0;
81 move_cursor();
82}
83
84void vga_write(char *c)
85{
86 for (int i = 0; c[i]; i++)
87 vga_put(c[i]);
88}
89
90void vga_putd(uint d)
91{
swissChili0b35bf22021-02-18 12:49:40 -080092 char str[48];
93 memset(str, 0, 48);
94 uint i = 0;
95
swissChilidefeb0d2021-02-18 15:28:36 -080096 do
swissChili0b35bf22021-02-18 12:49:40 -080097 {
98 str[i++] = (d % 10) + '0';
99 d /= 10;
swissChili825d46b2021-02-21 10:14:16 -0800100 } while (d > 0 && i < 48); // should never be more than 48 digits anyway
swissChili0b35bf22021-02-18 12:49:40 -0800101
102 for (uint j = i; j; j--)
103 {
104 vga_put(str[j - 1]);
105 }
swissChilid8137922021-02-17 15:34:07 -0800106}
107
swissChili0b35bf22021-02-18 12:49:40 -0800108static bool vga_put_nibble(uchar n, bool first)
swissChilid8137922021-02-17 15:34:07 -0800109{
swissChili825d46b2021-02-21 10:14:16 -0800110// if (first && n == 0)
111// return true;
112
swissChilid8137922021-02-17 15:34:07 -0800113 if (n <= 9)
114 vga_put('0' + n);
115 else
116 vga_put('A' + n - 10);
swissChili0b35bf22021-02-18 12:49:40 -0800117
118 return false;
swissChilid8137922021-02-17 15:34:07 -0800119}
120
121void vga_putx(uint x)
122{
swissChili825d46b2021-02-21 10:14:16 -0800123 bool first = false;
swissChili0b35bf22021-02-18 12:49:40 -0800124
swissChili825d46b2021-02-21 10:14:16 -0800125 for (int shift = 24; shift >= 0; shift -= 8)
swissChilid8137922021-02-17 15:34:07 -0800126 {
swissChili825d46b2021-02-21 10:14:16 -0800127 uchar byte = x >> shift;
swissChilid8137922021-02-17 15:34:07 -0800128
swissChili825d46b2021-02-21 10:14:16 -0800129 first = vga_put_nibble((byte & 0xf0) >> 4, first);
swissChili0b35bf22021-02-18 12:49:40 -0800130 first = vga_put_nibble(byte & 0x0f, first);
swissChilid8137922021-02-17 15:34:07 -0800131 }
132}