-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscreen.c
108 lines (88 loc) · 2.28 KB
/
screen.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "screen.h"
#include "io.h"
static volatile uint8_t currentRow = 0;
static volatile uint8_t currentColumn = 0;
static char* const video_memory = (char*)0xb8000;
void screen_set_cursor (uint8_t row, uint8_t column) {
size_t pos = row * 80 + column;
outb(0x3D4, 0xe); // tell VGA board to receive higher cursor byte
outb(0x3D5, (uint8_t)(pos >> 8)); // send higher cursor byte
outb(0x3D4, 0xf); // tell VGA board to receive lower cursor byte
outb(0x3D5, (uint8_t)pos); // send lower cursor byte
currentRow = row;
currentColumn = column;
}
void screen_clear () {
uint32_t i = 0;
while (i < 80 * 25 * 2) {
video_memory[i] = ' ';
video_memory[i+1] = COLOR_CODE;
i += 2;
}
screen_set_cursor(0, 0);
}
static void scroll(uint8_t row) {
if (row < 25) {
return;
}
size_t i = 0;
for (; i < 24*80*2; ++i) {
video_memory[i] = video_memory[i+160];
}
for (i = 24*80*2; i < 25*80*2; i += 2) {
video_memory[i] = ' ';
video_memory[i+1] = COLOR_CODE;
}
}
void screen_put_char(const char c) {
__asm__ volatile ("pushf"); // save eflags
__asm__ volatile ("cli"); // clear interrupts flag to make printing char atomic
if (c == '\r') {
currentColumn = 0;
} else if (c == '\n') {
currentRow++;
currentColumn = 0;
} else if (c == 0x8 && currentColumn > 0) { // backspace
currentColumn--;
} else if (c == '\t') {
currentColumn = (currentColumn + 8) & ~7;
} else if (c >= ' ') {
const size_t pos = (currentRow*80 + currentColumn) * 2;
video_memory[pos] = c;
video_memory[pos+1] = COLOR_CODE;
currentColumn++;
}
if (currentColumn >= 80) {
currentColumn = 0;
currentRow++;
}
scroll(currentRow);
if (currentRow >= 25) {
currentRow = 24;
}
screen_set_cursor(currentRow, currentColumn);
__asm__ volatile ("popf"); // restore eflags
}
void screen_print (const char* const str) {
size_t i = 0;
while(str[i]) {
screen_put_char(str[i]);
++i;
}
}
void screen_print_hex (uint32_t number) {
screen_put_char('0');
screen_put_char('x');
uint32_t offset = 32;
do {
offset -= 4;
uint32_t part = (number >> offset) & 0xF;
char c;
if (part < 10) {
c = ((char)('0' + part));
} else {
c = ((char)('A' + (part - 10)));
}
screen_put_char(c);
} while (offset);
}