blob: 06fe608bd0e3a3192902b0235730ad06255af9d7 [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':
54 cursor_x = (cursor_x + 8) & ~ 7;
55 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;
100 }
swissChilidefeb0d2021-02-18 15:28:36 -0800101 while (d > 0 && i < 48); // should never be more than 48 digits anyway
swissChili0b35bf22021-02-18 12:49:40 -0800102
103 for (uint j = i; j; j--)
104 {
105 vga_put(str[j - 1]);
106 }
swissChilid8137922021-02-17 15:34:07 -0800107}
108
swissChili0b35bf22021-02-18 12:49:40 -0800109static bool vga_put_nibble(uchar n, bool first)
swissChilid8137922021-02-17 15:34:07 -0800110{
swissChili0b35bf22021-02-18 12:49:40 -0800111 if (first && n == 0)
112 return true;
113
swissChilid8137922021-02-17 15:34:07 -0800114 if (n <= 9)
115 vga_put('0' + n);
116 else
117 vga_put('A' + n - 10);
swissChili0b35bf22021-02-18 12:49:40 -0800118
119 return false;
swissChilid8137922021-02-17 15:34:07 -0800120}
121
122void vga_putx(uint x)
123{
swissChili0b35bf22021-02-18 12:49:40 -0800124 bool first = true;
125
swissChilid8137922021-02-17 15:34:07 -0800126 for (uint mask = 0xFF000000, shift = 24; mask; mask >>= 8, shift -= 8)
127 {
128 uchar byte = (x & mask) >> shift;
129
swissChili0b35bf22021-02-18 12:49:40 -0800130 first = vga_put_nibble((byte & 0xf0) >> 8, first);
131 first = vga_put_nibble(byte & 0x0f, first);
swissChilid8137922021-02-17 15:34:07 -0800132 }
133}