blob: 1748116b0e192b36b756eab2059dbb62dc9d0930 [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{
swissChili959aa8a2021-02-23 19:43:00 -080082 for (int i = 0; i < 25 * 80; i++)
83 {
84 fb[i] = ' ' | (WHITE << 8);
85 }
86
swissChilid8137922021-02-17 15:34:07 -080087 cursor_x = 0;
88 cursor_y = 0;
89 move_cursor();
90}
91
92void vga_write(char *c)
93{
94 for (int i = 0; c[i]; i++)
95 vga_put(c[i]);
96}
97
98void vga_putd(uint d)
99{
swissChili0b35bf22021-02-18 12:49:40 -0800100 char str[48];
101 memset(str, 0, 48);
102 uint i = 0;
103
swissChilidefeb0d2021-02-18 15:28:36 -0800104 do
swissChili0b35bf22021-02-18 12:49:40 -0800105 {
106 str[i++] = (d % 10) + '0';
107 d /= 10;
swissChili825d46b2021-02-21 10:14:16 -0800108 } while (d > 0 && i < 48); // should never be more than 48 digits anyway
swissChili0b35bf22021-02-18 12:49:40 -0800109
110 for (uint j = i; j; j--)
111 {
112 vga_put(str[j - 1]);
113 }
swissChilid8137922021-02-17 15:34:07 -0800114}
115
swissChili0b35bf22021-02-18 12:49:40 -0800116static bool vga_put_nibble(uchar n, bool first)
swissChilid8137922021-02-17 15:34:07 -0800117{
swissChilidc25b2b2021-02-23 17:07:13 -0800118 // if (first && n == 0)
119 // return true;
swissChili825d46b2021-02-21 10:14:16 -0800120
swissChilid8137922021-02-17 15:34:07 -0800121 if (n <= 9)
122 vga_put('0' + n);
123 else
124 vga_put('A' + n - 10);
swissChili0b35bf22021-02-18 12:49:40 -0800125
126 return false;
swissChilid8137922021-02-17 15:34:07 -0800127}
128
129void vga_putx(uint x)
130{
swissChili825d46b2021-02-21 10:14:16 -0800131 bool first = false;
swissChili0b35bf22021-02-18 12:49:40 -0800132
swissChili825d46b2021-02-21 10:14:16 -0800133 for (int shift = 24; shift >= 0; shift -= 8)
swissChilid8137922021-02-17 15:34:07 -0800134 {
swissChili825d46b2021-02-21 10:14:16 -0800135 uchar byte = x >> shift;
swissChilid8137922021-02-17 15:34:07 -0800136
swissChili825d46b2021-02-21 10:14:16 -0800137 first = vga_put_nibble((byte & 0xf0) >> 4, first);
swissChili0b35bf22021-02-18 12:49:40 -0800138 first = vga_put_nibble(byte & 0x0f, first);
swissChilid8137922021-02-17 15:34:07 -0800139 }
140}
swissChilidc25b2b2021-02-23 17:07:13 -0800141
142void init_vga()
143{
swissChili959aa8a2021-02-23 19:43:00 -0800144 // Enable and set max scan line
145 outb(0x3D4, 0x09);
swissChilidc25b2b2021-02-23 17:07:13 -0800146 outb(0x3D5, 15);
147
swissChili959aa8a2021-02-23 19:43:00 -0800148 // Cursor end line
149 outb(0x3D4, 0x0B);
swissChilidc25b2b2021-02-23 17:07:13 -0800150 outb(0x3D5, 15);
151
swissChili959aa8a2021-02-23 19:43:00 -0800152 // Cursor start line
153 outb(0x3D4, 0x0A);
154 outb(0x3D5, 14);
swissChilidc25b2b2021-02-23 17:07:13 -0800155}