diff options
Diffstat (limited to 'src/vgaterminal.cpp')
-rw-r--r-- | src/vgaterminal.cpp | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/vgaterminal.cpp b/src/vgaterminal.cpp new file mode 100644 index 0000000..5f86081 --- /dev/null +++ b/src/vgaterminal.cpp @@ -0,0 +1,63 @@ +#include "portio.hpp" +#include "vgaterminal.hpp" + +#include <algorithm> +#include <cstddef> +#include <cstdint> +#include <utility> + +void VGATerminal::write(char c) noexcept +{ + checkpos(); + + switch (c) { + case '\b': + if (offset % Width) { + --offset; + put(' '); + --offset; + } + break; + case '\n': + offset += Width; + [[fallthrough]]; + case '\r': + offset -= offset % Width; + break; + default: + put(c); + break; + } + + updatecursor(); +} + +void VGATerminal::put(char c) noexcept +{ + std::uint16_t cell = c + | (std::to_underlying(foreground) << 8) + | (std::to_underlying(background) << 12); + + auto ptr = reinterpret_cast<std::uint16_t *>(Videoram); + ptr[offset++] = cell; +} + +void VGATerminal::checkpos() noexcept +{ + if (offset >= Width * Height) { + auto ptr = reinterpret_cast<std::uint16_t *>(Videoram); + const auto end = ptr + Width * Height; + std::copy(ptr + Width, end, ptr); + std::fill(end - Width, end, 0); + offset = Width * Height - Width; + } +} + +void VGATerminal::updatecursor() const noexcept +{ + outb(0x03d4, 0x0f); + outb(0x03d5, static_cast<std::uint8_t>(offset)); + outb(0x03d4, 0x0e); + outb(0x03d5, static_cast<std::uint8_t>(offset >> 8)); +} + |