Page 1 of 1

How to implement terminal scrolling

Posted: Mon Feb 24, 2020 7:08 pm
by rfudge02
Hey, I'm completely new to operating system development. I'm currently following the bare bones and meaty skeleton tutorial and am having trouble implementing terminal scrolling. This is the contents of my tty.c:

Code: Select all

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include <kernel/tty.h>

#include "vga.h"

static const size_t VGA_WIDTH = 80;
static const size_t VGA_HEIGHT = 25;
static uint16_t* const VGA_MEMORY = (uint16_t*) 0xB8000;

static size_t terminal_row;
static size_t terminal_column;
static uint8_t terminal_color;
static uint16_t* terminal_buffer;

void terminal_initialize(void) {
	terminal_row = 0;
	terminal_column = 0;
	terminal_color = vga_entry_color(VGA_COLOR_GREEN, VGA_COLOR_BLACK);
	terminal_buffer = VGA_MEMORY;
	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_entry(' ', terminal_color);
		}
	}
}

void terminal_setcolor(uint8_t color) {
	terminal_color = color;
}

void terminal_putentryat(unsigned char c, uint8_t color, size_t x, size_t y) {
	const size_t index = y * VGA_WIDTH + x;
	terminal_buffer[index] = vga_entry(c, color);
}

void terminal_scroll(void) {
	for(size_t y = 0; y < VGA_HEIGHT; y++) {
		for (size_t x = 0; x < VGA_WIDTH; x++) {
			terminal_buffer[y * VGA_WIDTH + x] = terminal_buffer[(y + 1) * VGA_WIDTH + x];
        }
    }
}

void terminal_update(void) {
	memmove(VGA_MEMORY, terminal_buffer);
}
void terminal_putchar(char c) {
	unsigned char uc = c;
	if (c == '\n') {
		terminal_row++;
		terminal_column = 0;
	}
	else {
		terminal_putentryat(uc, terminal_color, terminal_column, terminal_row);
		if (++terminal_column == VGA_WIDTH) {
			terminal_column = 0;
			if (++terminal_row == VGA_HEIGHT) {
			terminal_scroll();
		terminal_update();
			}
		}
	}
}

void terminal_write(const char* data, size_t size) {
	for (size_t i = 0; i < size; i++)
		terminal_putchar(data[i]);
}

void terminal_writestring(const char* data) {
	terminal_write(data, strlen(data));
}
Could someone explain to me why the terminal_scroll() and terminal_update() functions are not functioning. Sorry in advance if the error is obvious

Re: How to implement terminal scrolling

Posted: Tue Feb 25, 2020 6:02 am
by bzt
Hi,

This is all wrong.

First, you don't need memmove, you should use memcpy in terminal_update if the video memory and your terminal_buffer are separate buffers, and if they aren't then there's absolutely no need for terminal_update in the first place.

Second, your terminal_scroll has a buffer overflow, it reads over the terminal buffer.

Third, you should scroll by a single memmove(terminal_buffer, terminal_buffer + ONE_ROW_SIZE, TERMINAL_BUFFER_SIZE - ONE_ROW_SIZE) call, and then clear the last row by spaces and default color attribute (similar to what you do in terminal_initialize, but only for the last row).

Fourth, copying over the entire screen in terminal_putchar after each and every character printed is extremely inefficient.

Fifth, terminal_writestring scans through the string twice, that's absolutely unnecessary. You should do "while(*data) terminal_putchar(*data++);" instead.

Cheers,
bzt