-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfb.c
106 lines (91 loc) · 2.48 KB
/
fb.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
#include "io.h"
#include "fb.h"
#define FRAMEBUFFER_ADDR 0x000B8000;
#define FB_WIDTH 80
#define FB_HEIGHT 25
#define TAB " "
static unsigned int fb_pos_x = 0;
static unsigned int fb_pos_y = 0;
/**
* fb_write_cell:
* Writes a character with the given foreground and background to position i
* within the frame buffer.
* fb and bg must be between 0 and 15
* i must be between 0 and 80*25 = 2000
*/
void fb_write_cell(short i, char c, unsigned char fg, unsigned char bg) {
unsigned char *fb = (unsigned char*)FRAMEBUFFER_ADDR;
fb[i * 2] = c;
fb[i * 2 + 1] = ((bg & 0x0f) << 4) | (fg & 0x0f);
}
void fb_move_cursor(unsigned short pos) {
outb(FB_COMMAND_PORT, FB_HIGH_BYTE_COMMAND);
outb(FB_DATA_PORT, ((pos >> 8) & 0x00FF));
outb(FB_COMMAND_PORT, FB_LOW_BYTE_COMMAND);
outb(FB_DATA_PORT, pos & 0x00FF);
}
// move cursor to next line
//
void fb_newline() {
if (fb_pos_y >= FB_HEIGHT-1)
fb_shift_up();
else
fb_pos_y++;
fb_pos_x = 0;
fb_move_cursor(fb_pos_x + (fb_pos_y * FB_WIDTH));
}
// advances cursor forward one character
// if at end of line, wrap to next line
void fb_advance_pos() {
if (fb_pos_x >= FB_WIDTH - 1)
fb_newline();
else
fb_pos_x++;
fb_move_cursor(fb_pos_x + (fb_pos_y * FB_WIDTH));
}
void fb_write(char *buf, unsigned int len) {
unsigned int i;
u16int pos;
for (i = 0; i < len; i++) {
char c = buf[i];
if (c == '\n' || c == '\r') {
fb_newline();
} else if (c == '\t') {
fb_write_str(TAB);
} else {
pos = fb_pos_x + (fb_pos_y * FB_WIDTH);
fb_write_cell(pos, c, FB_WHITE, FB_BLACK);
fb_advance_pos();
}
}
}
void fb_write_str(char *buf) {
fb_write(buf, strlen(buf));
}
void fb_clear() {
fb_pos_x = 0;
fb_pos_y = 0;
int i;
for (i=0; i<FB_WIDTH*FB_HEIGHT; i++) {
fb_write_cell(i, ' ', FB_WHITE, FB_BLACK);
}
fb_move_cursor(0);
}
void fb_clear_row(u8int row) {
size_t i;
for (i = 0; i < FB_WIDTH; i++) {
fb_write_cell((row * FB_WIDTH)+i, ' ', FB_WHITE, FB_BLACK);
}
}
void fb_shift_up() {
// use 16-bits here because each cell is 16-bits wide
// this makes the pointer arithmetic work out correctly here
u16int *fb = (u16int*) FRAMEBUFFER_ADDR;
memmove(fb, fb + FB_WIDTH, FB_WIDTH *2 * (FB_HEIGHT * 2 - 1));
fb_clear_row(FB_HEIGHT - 1);
}
void fb_wrap_vertical() {
fb_pos_y = 0;
fb_clear_row(fb_pos_y);
fb_move_cursor(0);
}