-
Notifications
You must be signed in to change notification settings - Fork 0
/
terminal.c
109 lines (101 loc) · 2.71 KB
/
terminal.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
109
#include "terminal.h"
#include "vga.h"
#include "sys.h"
#include "string.h"
static size_t terminal_row;
static size_t terminal_column;
static uint8_t terminal_color;
static uint16_t* terminal_buffer;
const uint32_t VIDEO_CHARACTER_MEMORY_START = 0xB8000;
/* Updates the hardware cursor: the little blinking line
* on the screen under the last character pressed! */
static void move_cursor(void)
{
unsigned temp;
/* The equation for finding the index in a linear
* chunk of memory can be represented by:
* Index = [(y * width) + x] */
temp = terminal_row * VGA_WIDTH + terminal_column;
/* This sends a command to indicies 14 and 15 in the
* CRT Control Register of the VGA controller. These
* are the high and low bytes of the index that show
* where the hardware cursor is to be 'blinking'.
* To
* learn more, you should look up some VGA
* specific
* programming documents. A great start to
* graphics:
* http://www.brackeen.com/home/vga */
outb(0x3D4, 14);
outb(0x3D5, temp >> 8);
outb(0x3D4, 15);
outb(0x3D5, temp);
}
void terminal_initialize()
{
terminal_row = 0;
terminal_column = 0;
move_cursor();
terminal_color = vga_make_color(COLOR_GREEN, COLOR_BLACK);
terminal_buffer = (uint16_t*) VIDEO_CHARACTER_MEMORY_START;
for (size_t y = 0; y < VGA_HEIGHT; y++) {
for (size_t x = 0; x < VGA_WIDTH; x++) {
const size_t index = y * VGA_WIDTH + x;
terminal_buffer[index] = vga_make_color_entry(' ',
terminal_color);
}
}
}
void terminal_setcolor(uint8_t color)
{
terminal_color = color;
}
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y)
{
const size_t index = y * VGA_WIDTH + x;
terminal_buffer[index] = vga_make_color_entry(c, color);
}
void scroll(){
for (size_t i = 0; i < (VGA_HEIGHT - 1) * VGA_WIDTH; ++i){
terminal_buffer[i] = terminal_buffer[i + VGA_WIDTH];
}
for (size_t i = (VGA_HEIGHT - 1) * VGA_WIDTH; i < VGA_HEIGHT * VGA_WIDTH; ++i){
terminal_buffer[i] = vga_make_color_entry(' ', terminal_color);
}
}
void terminal_putchar(char c)
{
switch(c){
case '\n':
terminal_column = 0;
if (++terminal_row >= VGA_HEIGHT) {
scroll();
terminal_row=VGA_HEIGHT-1;;
}
break;
case '\b':
if (terminal_column > 0){
--terminal_column;
terminal_putchar(' ');
--terminal_column;
}
break;
default:
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
if (++terminal_column >= VGA_WIDTH) {
terminal_column = 0;
if (++terminal_row >= VGA_HEIGHT) {
scroll();
}
}
}
move_cursor();
}
void terminal_writestring(const char* data)
{
size_t datalen = strnlen(data, VGA_WIDTH * VGA_HEIGHT);
for (size_t i = 0; i < datalen; i++) {
char character = data[i];
terminal_putchar(character);
}
}