#include "vga.h" #include constexpr uint8_t vga_entry_color(VGA::vga_color fg, VGA::vga_color bg) { return fg | bg << 4; } constexpr uint16_t vga_entry(unsigned char uc, uint8_t color) { return (uint16_t)uc | (uint16_t)color << 8; } VGA::VGA(vga_color fg, vga_color bg, uint32_t address) { color = vga_entry_color(fg, bg); buffer = (uint16_t*)address; // clear buffer for (size_t y = 0; y < max_rows; y++) { for (size_t x = 0; x < max_columns; x++) { const size_t index = y * max_columns + x; buffer[index] = vga_entry(' ', color); } } } void VGA::write(char c) { switch (c) { case '\n': column = 0; ++row; break; default: { const size_t index = row * max_columns + column; buffer[index] = vga_entry(c, (color == 0) ? this->color : color); ++column; } } if (column == max_columns) { column = 0; ++row; } if (row == max_rows) { // scroll up - move rows 1~25 up by one for (size_t y = 1; y < max_rows; y++) { const auto prev_y = y - 1; for (size_t x = 0; x < max_columns; ++x) { const auto prev = prev_y * max_columns + x; const auto idx = y * max_columns + x; buffer[prev] = buffer[idx]; } } --row; } } void VGA::write(ViewIterator& iter) { while (iter) { write(iter.next()); } }