diff options
author | Aqua-sama <aqua@iserlohn-fortress.net> | 2021-02-11 16:17:53 +0200 |
---|---|---|
committer | Aqua-sama <aqua@iserlohn-fortress.net> | 2021-02-11 21:33:21 +0200 |
commit | 9a299f2fe91554a1b9d9db402391ae757c591ef8 (patch) | |
tree | 2ec839c869316804954e6b09220140346874aa8d /drivers/cga.cc | |
parent | Generate target dependency files (diff) | |
download | kernel.cpp-9a299f2fe91554a1b9d9db402391ae757c591ef8.tar.xz |
Add comments to explain CGA ports better
Diffstat (limited to 'drivers/cga.cc')
-rw-r--r-- | drivers/cga.cc | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/drivers/cga.cc b/drivers/cga.cc new file mode 100644 index 0000000..79facee --- /dev/null +++ b/drivers/cga.cc @@ -0,0 +1,111 @@ +#include "cga.h" +#include <string.h> + +static_assert(sizeof(CGA::Entry) == 2); + +/* cga registers, see https://www.lowlevel.eu/wiki/Color_Graphics_Adapter */ +constexpr uint8_t cursor_start = 10; // 0xa +constexpr uint8_t cursor_end = 11; // 0xb +constexpr uint8_t cursor_addr_h = 14; // 0xe +constexpr uint8_t cursor_addr_l = 15; // 0xf + +/* cursor format + * register | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + * start | | e | t | scanline | + * end | | scanline | + * e = enable; t = timing + * e t | effect + * 0 0 | no blinking + * 0 1 | hide cursor + * 1 0 | blink normally + * 1 1 | blink fast + */ +constexpr uint8_t cursor_hide = 0b00100000; + +CGA::CGA(Colour fg, Colour bg, uint32_t address) : colour_fg(fg), colour_bg(bg) { + buffer = reinterpret_cast<Entry*>(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].c = ' '; + buffer[index].fg = colour_fg; + buffer[index].bg = colour_bg; + } + } + + enable_cursor(14, 15); + update_cursor(); +} + +void CGA::set_colour(Colour fg, Colour bg) { + colour_fg = fg; + colour_bg = bg; + 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].fg = colour_fg; + buffer[index].bg = colour_bg; + } + } +} + +void CGA::enable_cursor(uint8_t start, uint8_t end) { + p_idx.write(cursor_start); + p_dat.write((p_dat.read() & 0xc0) | start); + + p_idx.write(cursor_end); + p_dat.write((p_dat.read() & 0xe0) | end); +} +void CGA::disable_cursor() { + p_idx.write(cursor_start); + p_dat.write(cursor_hide); +} +void CGA::update_cursor() { + const uint16_t pos = row * max_columns + column; + + p_idx.write(cursor_addr_l); + p_dat.write(static_cast<uint8_t>(pos & 0xff)); + + p_idx.write(cursor_addr_h); + p_dat.write(static_cast<uint8_t>((pos >> 8) & 0xff)); +} + +void CGA::write(char c) { + switch (c) { + case '\n': + column = 0; + ++row; + break; + default: { + const size_t index = row * max_columns + column; + buffer[index].c = c; + ++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 CGA::write(ViewIterator& iter) { + while (iter) { + write(iter.next()); + } +} |