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> #include <memory.h>
void *vidmem; void *vidmem;
struct { struct vga_cell{
uint8_t character; uint8_t c;
uint8_t format; uint8_t f;
}__attribute__((packed)) buffer[VGA_SIZE]; }__attribute__((packed));
struct vga_cell buffer[VGA_SIZE];
uint64_t cursor; uint64_t cursor;
uint8_t format;
void vga_init() void vga_init()
{ {
vidmem = VGA_MEMORY; vidmem = VGA_MEMORY;
memset(vidmem, 0, VGA_SIZE*2); memset(vidmem, 0, VGA_SIZE*2);
format = 0x7;
} }
void flush() void flush()
@ -20,6 +25,20 @@ void flush()
memcpy(vidmem, buffer, sizeof(buffer)); 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) void vga_write(char c)
{ {
switch(c) switch(c)
@ -29,9 +48,9 @@ void vga_write(char c)
cursor -= VGA_COL(cursor); cursor -= VGA_COL(cursor);
break; break;
default: default:
buffer[cursor].character = c; buffer[cursor] = (struct vga_cell){.c = c, .f=format};
buffer[cursor].format = 0x7;
cursor++; cursor++;
} }
scroll();
flush(); flush();
} }

View File

@ -52,10 +52,10 @@ TEST(vga_write_adds_multiple_characters_to_vidmem)
TEST(vga_writes_entire_screen_full) 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_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) TEST(vga_does_not_overflow_memory_area)
{ {
@ -77,3 +77,43 @@ TEST(newline_moves_to_beginning_of_line)
vga_write('b'); vga_write('b');
VGA_ASSERT_EQ(VGA_POS(1,0), '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');
}