Scrolling support.
This commit is contained in:
parent
d95ab832c3
commit
0be6fbed9d
2
Makefile
2
Makefile
@ -16,7 +16,7 @@ debug: image.bin
|
||||
image.bin: mbr.bin kernel.bin
|
||||
cat $^ >$@
|
||||
|
||||
kernel.bin: kernel.o vga.o
|
||||
kernel.bin: kernel.o vga.o string.o
|
||||
$(LD) -m elf_i386 -o $@ -Ttext 0x1000 $^ --oformat binary
|
||||
|
||||
%.o: %.c
|
||||
|
||||
4
kernel.c
4
kernel.c
@ -4,6 +4,8 @@ asm("jmp main");
|
||||
|
||||
int main() {
|
||||
vga_clear_screen();
|
||||
vga_print_string("hello world");
|
||||
for (int i = 0; i < 24; i++) {
|
||||
vga_print_string("hello world\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
16
string.c
Normal file
16
string.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include "string.h"
|
||||
|
||||
void kmemmove(char* dst, char* src, size_t size) {
|
||||
if (dst == src) return;
|
||||
if (dst > src && dst < src + size) { // s d
|
||||
// copy right-to-left
|
||||
for (; size != 0; size--) {
|
||||
dst[size - 1] = src[size - 1];
|
||||
}
|
||||
} else {
|
||||
// copy left-to-right
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
5
string.h
Normal file
5
string.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
typedef unsigned size_t;
|
||||
|
||||
void kmemmove(char* dst, char* src, size_t size);
|
||||
60
vga.c
60
vga.c
@ -1,11 +1,34 @@
|
||||
#include "port.h"
|
||||
#include "string.h"
|
||||
|
||||
char* const video_memory = (char*) 0xb8000;
|
||||
|
||||
enum colors16 {
|
||||
black = 0,
|
||||
blue,
|
||||
green,
|
||||
cyan,
|
||||
red,
|
||||
magenta,
|
||||
brown,
|
||||
light_gray,
|
||||
dark_gray,
|
||||
light_blue,
|
||||
light_green,
|
||||
light_cyan,
|
||||
light_red,
|
||||
light_magenta,
|
||||
yellow,
|
||||
white,
|
||||
};
|
||||
|
||||
static unsigned char get_color(unsigned char fg, unsigned char bg) {
|
||||
return (bg << 4) + fg;
|
||||
}
|
||||
|
||||
enum {
|
||||
LINES = 25,
|
||||
ROWS = 25,
|
||||
COLS = 80,
|
||||
WHITE_ON_BLACK = 0x0f,
|
||||
|
||||
VGA_CTRL_REGISTER = 0x3d4,
|
||||
VGA_DATA_REGISTER = 0x3d5,
|
||||
@ -13,6 +36,14 @@ enum {
|
||||
VGA_OFFSET_HIGH = 0x0e,
|
||||
};
|
||||
|
||||
static unsigned get_offset(unsigned col, unsigned row) {
|
||||
return row * COLS + col;
|
||||
}
|
||||
|
||||
static unsigned get_row_from_offset(unsigned offset) {
|
||||
return offset / COLS;
|
||||
}
|
||||
|
||||
void vga_set_cursor(unsigned offset) {
|
||||
port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_HIGH);
|
||||
port_byte_out(VGA_DATA_REGISTER, (unsigned char) (offset >> 8));
|
||||
@ -30,22 +61,37 @@ unsigned vga_get_cursor() {
|
||||
|
||||
void vga_set_char(unsigned offset, char c) {
|
||||
video_memory[2 * offset] = c;
|
||||
video_memory[2 * offset + 1] = WHITE_ON_BLACK;
|
||||
video_memory[2 * offset + 1] = get_color(light_gray, black);
|
||||
}
|
||||
|
||||
void vga_clear_screen() {
|
||||
for (unsigned i = 0; i < LINES * COLS; ++i) {
|
||||
for (unsigned i = 0; i < ROWS * COLS; ++i) {
|
||||
vga_set_char(i, ' ');
|
||||
}
|
||||
vga_set_cursor(0);
|
||||
}
|
||||
|
||||
static unsigned scroll() {
|
||||
kmemmove(video_memory, video_memory + COLS, 2 * COLS * (ROWS-1));
|
||||
for (int col = 0; col < COLS; col++) {
|
||||
vga_set_char(get_offset(col, ROWS - 1), ' ');
|
||||
}
|
||||
return get_offset(0, ROWS - 1);
|
||||
}
|
||||
|
||||
void vga_print_string(const char* s) {
|
||||
int offset = vga_get_cursor();
|
||||
unsigned offset = vga_get_cursor();
|
||||
while (*s != 0) {
|
||||
vga_set_char(offset, *s);
|
||||
if (*s == '\n') {
|
||||
offset = get_offset(0, get_row_from_offset(offset) + 1);
|
||||
} else {
|
||||
vga_set_char(offset, *s);
|
||||
offset++;
|
||||
}
|
||||
s++;
|
||||
offset++;
|
||||
if (offset > COLS * ROWS) {
|
||||
offset = scroll();
|
||||
}
|
||||
}
|
||||
vga_set_cursor(offset);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user