blob: 49c2701c4ab248cb3c3f6da9ece5a30b232d840f [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);
swissChilid8137922021-02-17 15:34:07 -080021}
22
23static void scroll()
24{
25 ushort blank = ' ' | color << 8;
26
27 while (cursor_y >= 25) // end of line
28 {
29 // scroll everything up
30 memcpy(fb, &fb[80], 24 * 80 * 2);
31
32 for (int i = 24 * 80; i < 25 * 80; i++)
33 {
34 fb[i] = blank;
35 }
36
37 cursor_y--;
38 }
39}
40
41void vga_set_color(enum vga_colors fg, enum vga_colors bg)
42{
swissChilidc25b2b2021-02-23 17:07:13 -080043 color = (bg << 4) | (fg & 0xf);
swissChilid8137922021-02-17 15:34:07 -080044}
45
46void vga_put(char c)
47{
48 switch (c)
49 {
50 case '\b':
51 if (cursor_x > 0)
52 cursor_x--;
swissChili19ef4182021-02-21 17:45:51 -080053 fb[cursor_y * 80 + cursor_x] = ' ' | (color << 8);
swissChilid8137922021-02-17 15:34:07 -080054 break;
55 case '\t':
swissChili825d46b2021-02-21 10:14:16 -080056 cursor_x = (cursor_x + 8) & ~7;
swissChilid8137922021-02-17 15:34:07 -080057 break;
58 case '\n':
59 cursor_y++;
60 case '\r':
61 cursor_x = 0;
62 break;
63 default:
swissChilid8137922021-02-17 15:34:07 -080064 fb[cursor_y * 80 + cursor_x] = c | (color << 8);
swissChili19ef4182021-02-21 17:45:51 -080065 cursor_x++;
swissChilid8137922021-02-17 15:34:07 -080066 }
67
68 if (cursor_x >= 80) // off screen
69 {
70 cursor_x = 0;
71 cursor_y++;
72 }
73
74 scroll();
75 move_cursor();
76}
77
78void vga_clear()
79{
swissChili959aa8a2021-02-23 19:43:00 -080080 for (int i = 0; i < 25 * 80; i++)
81 {
82 fb[i] = ' ' | (WHITE << 8);
83 }
84
swissChilid8137922021-02-17 15:34:07 -080085 cursor_x = 0;
86 cursor_y = 0;
87 move_cursor();
88}
89
90void vga_write(char *c)
91{
92 for (int i = 0; c[i]; i++)
93 vga_put(c[i]);
94}
95
96void vga_putd(uint d)
97{
swissChili0b35bf22021-02-18 12:49:40 -080098 char str[48];
99 memset(str, 0, 48);
100 uint i = 0;
101
swissChilidefeb0d2021-02-18 15:28:36 -0800102 do
swissChili0b35bf22021-02-18 12:49:40 -0800103 {
104 str[i++] = (d % 10) + '0';
105 d /= 10;
swissChili825d46b2021-02-21 10:14:16 -0800106 } while (d > 0 && i < 48); // should never be more than 48 digits anyway
swissChili0b35bf22021-02-18 12:49:40 -0800107
108 for (uint j = i; j; j--)
109 {
110 vga_put(str[j - 1]);
111 }
swissChilid8137922021-02-17 15:34:07 -0800112}
113
swissChili0b35bf22021-02-18 12:49:40 -0800114static bool vga_put_nibble(uchar n, bool first)
swissChilid8137922021-02-17 15:34:07 -0800115{
swissChilidc25b2b2021-02-23 17:07:13 -0800116 // if (first && n == 0)
117 // return true;
swissChili825d46b2021-02-21 10:14:16 -0800118
swissChilid8137922021-02-17 15:34:07 -0800119 if (n <= 9)
120 vga_put('0' + n);
121 else
122 vga_put('A' + n - 10);
swissChili0b35bf22021-02-18 12:49:40 -0800123
124 return false;
swissChilid8137922021-02-17 15:34:07 -0800125}
126
127void vga_putx(uint x)
128{
swissChili825d46b2021-02-21 10:14:16 -0800129 bool first = false;
swissChili0b35bf22021-02-18 12:49:40 -0800130
swissChili825d46b2021-02-21 10:14:16 -0800131 for (int shift = 24; shift >= 0; shift -= 8)
swissChilid8137922021-02-17 15:34:07 -0800132 {
swissChili825d46b2021-02-21 10:14:16 -0800133 uchar byte = x >> shift;
swissChilid8137922021-02-17 15:34:07 -0800134
swissChili825d46b2021-02-21 10:14:16 -0800135 first = vga_put_nibble((byte & 0xf0) >> 4, first);
swissChili0b35bf22021-02-18 12:49:40 -0800136 first = vga_put_nibble(byte & 0x0f, first);
swissChilid8137922021-02-17 15:34:07 -0800137 }
138}
swissChilidc25b2b2021-02-23 17:07:13 -0800139
140void init_vga()
141{
swissChili959aa8a2021-02-23 19:43:00 -0800142 // Enable and set max scan line
143 outb(0x3D4, 0x09);
swissChilidc25b2b2021-02-23 17:07:13 -0800144 outb(0x3D5, 15);
145
swissChili959aa8a2021-02-23 19:43:00 -0800146 // Cursor end line
147 outb(0x3D4, 0x0B);
swissChilidc25b2b2021-02-23 17:07:13 -0800148 outb(0x3D5, 15);
149
swissChili959aa8a2021-02-23 19:43:00 -0800150 // Cursor start line
151 outb(0x3D4, 0x0A);
152 outb(0x3D5, 14);
swissChilidc25b2b2021-02-23 17:07:13 -0800153}