blob: 9edbdc466850c4ddada7c2d8caa702170d08643e [file] [log] [blame]
swissChilid8137922021-02-17 15:34:07 -08001#include "vga.h"
swissChili9b3584b2021-02-18 13:57:27 -08002#include "io.h"
swissChilidc25b2b2021-02-23 17:07:13 -08003#include "paging.h"
swissChili0b35bf22021-02-18 12:49:40 -08004#include "log.h"
swissChilid8137922021-02-17 15:34:07 -08005
6static uint cursor_x = 0;
7static uint cursor_y = 0;
8
9static ushort color = WHITE;
10
swissChilidc25b2b2021-02-23 17:07:13 -080011static ushort *fb = (ushort *)PHYS_TO_VIRT(0xB8000);
swissChilid8137922021-02-17 15:34:07 -080012
13static void move_cursor()
14{
swissChilidc25b2b2021-02-23 17:07:13 -080015 ushort pos = cursor_y * 80 + cursor_x;
swissChilid8137922021-02-17 15:34:07 -080016
swissChilidc25b2b2021-02-23 17:07:13 -080017 outb(0x3d4, 0x0e);
18 outb(0x3d5, pos >> 8);
19 outb(0x3d4, 0x0f);
20 outb(0x3d5, pos & 0xff);
21
22 io_wait();
swissChilid8137922021-02-17 15:34:07 -080023}
24
25static void scroll()
26{
27 ushort blank = ' ' | color << 8;
28
29 while (cursor_y >= 25) // end of line
30 {
31 // scroll everything up
32 memcpy(fb, &fb[80], 24 * 80 * 2);
33
34 for (int i = 24 * 80; i < 25 * 80; i++)
35 {
36 fb[i] = blank;
37 }
38
39 cursor_y--;
40 }
41}
42
43void vga_set_color(enum vga_colors fg, enum vga_colors bg)
44{
swissChilidc25b2b2021-02-23 17:07:13 -080045 color = (bg << 4) | (fg & 0xf);
swissChilid8137922021-02-17 15:34:07 -080046}
47
48void vga_put(char c)
49{
50 switch (c)
51 {
52 case '\b':
53 if (cursor_x > 0)
54 cursor_x--;
swissChili19ef4182021-02-21 17:45:51 -080055 fb[cursor_y * 80 + cursor_x] = ' ' | (color << 8);
swissChilid8137922021-02-17 15:34:07 -080056 break;
57 case '\t':
swissChili825d46b2021-02-21 10:14:16 -080058 cursor_x = (cursor_x + 8) & ~7;
swissChilid8137922021-02-17 15:34:07 -080059 break;
60 case '\n':
61 cursor_y++;
62 case '\r':
63 cursor_x = 0;
64 break;
65 default:
swissChilid8137922021-02-17 15:34:07 -080066 fb[cursor_y * 80 + cursor_x] = c | (color << 8);
swissChili19ef4182021-02-21 17:45:51 -080067 cursor_x++;
swissChilid8137922021-02-17 15:34:07 -080068 }
69
70 if (cursor_x >= 80) // off screen
71 {
72 cursor_x = 0;
73 cursor_y++;
74 }
75
76 scroll();
77 move_cursor();
78}
79
80void vga_clear()
81{
82 memset(fb, 0, 80 * 25 * 2);
83 cursor_x = 0;
84 cursor_y = 0;
85 move_cursor();
86}
87
88void vga_write(char *c)
89{
90 for (int i = 0; c[i]; i++)
91 vga_put(c[i]);
92}
93
94void vga_putd(uint d)
95{
swissChili0b35bf22021-02-18 12:49:40 -080096 char str[48];
97 memset(str, 0, 48);
98 uint i = 0;
99
swissChilidefeb0d2021-02-18 15:28:36 -0800100 do
swissChili0b35bf22021-02-18 12:49:40 -0800101 {
102 str[i++] = (d % 10) + '0';
103 d /= 10;
swissChili825d46b2021-02-21 10:14:16 -0800104 } while (d > 0 && i < 48); // should never be more than 48 digits anyway
swissChili0b35bf22021-02-18 12:49:40 -0800105
106 for (uint j = i; j; j--)
107 {
108 vga_put(str[j - 1]);
109 }
swissChilid8137922021-02-17 15:34:07 -0800110}
111
swissChili0b35bf22021-02-18 12:49:40 -0800112static bool vga_put_nibble(uchar n, bool first)
swissChilid8137922021-02-17 15:34:07 -0800113{
swissChilidc25b2b2021-02-23 17:07:13 -0800114 // if (first && n == 0)
115 // return true;
swissChili825d46b2021-02-21 10:14:16 -0800116
swissChilid8137922021-02-17 15:34:07 -0800117 if (n <= 9)
118 vga_put('0' + n);
119 else
120 vga_put('A' + n - 10);
swissChili0b35bf22021-02-18 12:49:40 -0800121
122 return false;
swissChilid8137922021-02-17 15:34:07 -0800123}
124
125void vga_putx(uint x)
126{
swissChili825d46b2021-02-21 10:14:16 -0800127 bool first = false;
swissChili0b35bf22021-02-18 12:49:40 -0800128
swissChili825d46b2021-02-21 10:14:16 -0800129 for (int shift = 24; shift >= 0; shift -= 8)
swissChilid8137922021-02-17 15:34:07 -0800130 {
swissChili825d46b2021-02-21 10:14:16 -0800131 uchar byte = x >> shift;
swissChilid8137922021-02-17 15:34:07 -0800132
swissChili825d46b2021-02-21 10:14:16 -0800133 first = vga_put_nibble((byte & 0xf0) >> 4, first);
swissChili0b35bf22021-02-18 12:49:40 -0800134 first = vga_put_nibble(byte & 0x0f, first);
swissChilid8137922021-02-17 15:34:07 -0800135 }
136}
swissChilidc25b2b2021-02-23 17:07:13 -0800137
138void init_vga()
139{
140 return;
141
142 outb(0x3D4, 0x09); // set maximum scan line register to 15
143 outb(0x3D5, 15);
144
145 outb(0x3D4, 0x0B); // set the cursor end line to 15
146 outb(0x3D5, 15);
147
148 outb(0x3D4, 0x0A); // set the cursor start line to 14 and enable cursor
149 // visibility
150 outb(0x3D5, 10);
151}