blob: de5e998e1512ca64773442688b926f7a93f871f4 [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
swissChilid3a652e2021-02-21 22:16:06 -080010static ushort *fb = (ushort *)(0xB8000 + 0xC0000000);
swissChilid8137922021-02-17 15:34:07 -080011
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--;
swissChili19ef4182021-02-21 17:45:51 -080052 fb[cursor_y * 80 + cursor_x] = ' ' | (color << 8);
swissChilid8137922021-02-17 15:34:07 -080053 break;
54 case '\t':
swissChili825d46b2021-02-21 10:14:16 -080055 cursor_x = (cursor_x + 8) & ~7;
swissChilid8137922021-02-17 15:34:07 -080056 break;
57 case '\n':
58 cursor_y++;
59 case '\r':
60 cursor_x = 0;
61 break;
62 default:
swissChilid8137922021-02-17 15:34:07 -080063 fb[cursor_y * 80 + cursor_x] = c | (color << 8);
swissChili19ef4182021-02-21 17:45:51 -080064 cursor_x++;
swissChilid8137922021-02-17 15:34:07 -080065 }
66
67 if (cursor_x >= 80) // off screen
68 {
69 cursor_x = 0;
70 cursor_y++;
71 }
72
73 scroll();
74 move_cursor();
75}
76
77void vga_clear()
78{
79 memset(fb, 0, 80 * 25 * 2);
80 cursor_x = 0;
81 cursor_y = 0;
82 move_cursor();
83}
84
85void vga_write(char *c)
86{
87 for (int i = 0; c[i]; i++)
88 vga_put(c[i]);
89}
90
91void vga_putd(uint d)
92{
swissChili0b35bf22021-02-18 12:49:40 -080093 char str[48];
94 memset(str, 0, 48);
95 uint i = 0;
96
swissChilidefeb0d2021-02-18 15:28:36 -080097 do
swissChili0b35bf22021-02-18 12:49:40 -080098 {
99 str[i++] = (d % 10) + '0';
100 d /= 10;
swissChili825d46b2021-02-21 10:14:16 -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{
swissChili825d46b2021-02-21 10:14:16 -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{
swissChili825d46b2021-02-21 10:14:16 -0800124 bool first = false;
swissChili0b35bf22021-02-18 12:49:40 -0800125
swissChili825d46b2021-02-21 10:14:16 -0800126 for (int shift = 24; shift >= 0; shift -= 8)
swissChilid8137922021-02-17 15:34:07 -0800127 {
swissChili825d46b2021-02-21 10:14:16 -0800128 uchar byte = x >> shift;
swissChilid8137922021-02-17 15:34:07 -0800129
swissChili825d46b2021-02-21 10:14:16 -0800130 first = vga_put_nibble((byte & 0xf0) >> 4, first);
swissChili0b35bf22021-02-18 12:49:40 -0800131 first = vga_put_nibble(byte & 0x0f, first);
swissChilid8137922021-02-17 15:34:07 -0800132 }
133}