Scrolling support.

This commit is contained in:
Alexander Myltsev 2022-11-14 01:01:22 +03:00
parent d95ab832c3
commit 0be6fbed9d
5 changed files with 78 additions and 9 deletions

View File

@ -16,7 +16,7 @@ debug: image.bin
image.bin: mbr.bin kernel.bin image.bin: mbr.bin kernel.bin
cat $^ >$@ cat $^ >$@
kernel.bin: kernel.o vga.o kernel.bin: kernel.o vga.o string.o
$(LD) -m elf_i386 -o $@ -Ttext 0x1000 $^ --oformat binary $(LD) -m elf_i386 -o $@ -Ttext 0x1000 $^ --oformat binary
%.o: %.c %.o: %.c

View File

@ -4,6 +4,8 @@ asm("jmp main");
int main() { int main() {
vga_clear_screen(); vga_clear_screen();
vga_print_string("hello world"); for (int i = 0; i < 24; i++) {
vga_print_string("hello world\n");
}
return 0; return 0;
} }

16
string.c Normal file
View 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
View File

@ -0,0 +1,5 @@
#pragma once
typedef unsigned size_t;
void kmemmove(char* dst, char* src, size_t size);

60
vga.c
View File

@ -1,11 +1,34 @@
#include "port.h" #include "port.h"
#include "string.h"
char* const video_memory = (char*) 0xb8000; 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 { enum {
LINES = 25, ROWS = 25,
COLS = 80, COLS = 80,
WHITE_ON_BLACK = 0x0f,
VGA_CTRL_REGISTER = 0x3d4, VGA_CTRL_REGISTER = 0x3d4,
VGA_DATA_REGISTER = 0x3d5, VGA_DATA_REGISTER = 0x3d5,
@ -13,6 +36,14 @@ enum {
VGA_OFFSET_HIGH = 0x0e, 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) { void vga_set_cursor(unsigned offset) {
port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_HIGH); port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_HIGH);
port_byte_out(VGA_DATA_REGISTER, (unsigned char) (offset >> 8)); 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) { void vga_set_char(unsigned offset, char c) {
video_memory[2 * offset] = 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() { 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_char(i, ' ');
} }
vga_set_cursor(0); 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) { void vga_print_string(const char* s) {
int offset = vga_get_cursor(); unsigned offset = vga_get_cursor();
while (*s != 0) { 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++; s++;
offset++; if (offset > COLS * ROWS) {
offset = scroll();
}
} }
vga_set_cursor(offset); vga_set_cursor(offset);
} }