Scrolling screen when necessary

This commit is contained in:
Thomas Lovén 2017-12-04 01:30:18 +01:00
parent 4f00d428bf
commit 055c41adb3
2 changed files with 67 additions and 8 deletions

View File

@ -2,17 +2,22 @@
#include <memory.h>
void *vidmem;
struct {
uint8_t character;
uint8_t format;
}__attribute__((packed)) buffer[VGA_SIZE];
struct vga_cell{
uint8_t c;
uint8_t f;
}__attribute__((packed));
struct vga_cell buffer[VGA_SIZE];
uint64_t cursor;
uint8_t format;
void vga_init()
{
vidmem = VGA_MEMORY;
memset(vidmem, 0, VGA_SIZE*2);
format = 0x7;
}
void flush()
@ -20,6 +25,20 @@ void flush()
memcpy(vidmem, buffer, sizeof(buffer));
}
void scroll()
{
while(cursor >= VGA_SIZE)
{
for(int i = 0; i < VGA_ROWS-1; i++)
for(int j = 0; j < VGA_COLS; j++)
buffer[VGA_POS(i, j)] = buffer[VGA_POS(i+1, j)];
for(int i = 0; i < VGA_COLS; i++)
buffer[VGA_POS(VGA_ROWS-1, i)] = (struct vga_cell){.c='\0', .f=format};
cursor -= VGA_COLS;
}
}
void vga_write(char c)
{
switch(c)
@ -29,9 +48,9 @@ void vga_write(char c)
cursor -= VGA_COL(cursor);
break;
default:
buffer[cursor].character = c;
buffer[cursor].format = 0x7;
buffer[cursor] = (struct vga_cell){.c = c, .f=format};
cursor++;
}
scroll();
flush();
}

View File

@ -52,10 +52,10 @@ TEST(vga_write_adds_multiple_characters_to_vidmem)
TEST(vga_writes_entire_screen_full)
{
for(int i = 0; i < VGA_COLS*VGA_ROWS; i++)
for(int i = 0; i < (VGA_COLS*VGA_ROWS-1); i++)
vga_write('x');
VGA_ASSERT_EQ(VGA_POS(VGA_ROWS-1, VGA_COLS-1), 'x');
VGA_ASSERT_EQ(VGA_POS(VGA_ROWS-1, VGA_COLS-2), 'x');
}
TEST(vga_does_not_overflow_memory_area)
{
@ -77,3 +77,43 @@ TEST(newline_moves_to_beginning_of_line)
vga_write('b');
VGA_ASSERT_EQ(VGA_POS(1,0), 'b');
}
void vga_write_str(char *str)
{
while(*str) vga_write(*str++);
}
TEST(writing_past_end_of_screen_scrolls_screen_one_line)
{
vga_write_str("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n");
vga_write_str("11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n");
vga_write_str("21\n22\n23\n24\n");
vga_write_str("abcde");
VGA_ASSERT_EQ(0, '2');
}
TEST(screen_does_not_scroll_until_write)
{
vga_write_str("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n");
vga_write_str("11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n");
vga_write_str("21\n22\n23\n24");
vga_write_str("34567890123456789012345678901234567890123456789012345678901234567890123456789");
VGA_ASSERT_EQ(0, '1');
}
TEST(writing_past_end_of_screen_clears_last_line)
{
vga_write_str("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n");
vga_write_str("11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n");
vga_write_str("21\n22\n23\n24\n");
vga_write('a');
VGA_ASSERT_EQ(VGA_POS(VGA_ROWS-1, 1), '\0');
}
TEST(first_character_of_new_line_is_not_cleared)
{
vga_write_str("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n");
vga_write_str("11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n");
vga_write_str("21\n22\n23\n24\n");
vga_write('a');
VGA_ASSERT_EQ(VGA_POS(VGA_ROWS-1, 0), 'a');
}