diff options
Diffstat (limited to 'src/vga.cc')
-rw-r--r-- | src/vga.cc | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/vga.cc b/src/vga.cc new file mode 100644 index 0000000..83d0060 --- /dev/null +++ b/src/vga.cc @@ -0,0 +1,61 @@ +#include "vga.h" +#include <string.h> + +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()); + } +} |