diff options
Diffstat (limited to 'arch/x86_64/src/vga/text.cpp')
| -rw-r--r-- | arch/x86_64/src/vga/text.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/arch/x86_64/src/vga/text.cpp b/arch/x86_64/src/vga/text.cpp new file mode 100644 index 0000000..c9eee71 --- /dev/null +++ b/arch/x86_64/src/vga/text.cpp @@ -0,0 +1,84 @@ +#include "x86_64/vga/text.hpp" + +#include "kapi/boot.hpp" + +#include "x86_64/boot/boot.hpp" +#include "x86_64/boot/ld.hpp" +#include "x86_64/vga/crtc.hpp" + +#include <algorithm> +#include <bit> +#include <cstddef> +#include <cstdint> +#include <span> +#include <string_view> +#include <utility> + +namespace teachos::vga::x86_64::text +{ + namespace + { + constexpr auto BUFFER_BASE_ADDRESS = std::uintptr_t{0xb8000}; + constexpr auto DEFAULT_TEXT_BUFFER_WIDTH = 80U; + constexpr auto DEFAULT_TEXT_BUFFER_HEIGHT = 25U; + constexpr auto CURSOR_ENABLED_BIT = 5U; + } // namespace + + std::span<device::glyph> const device::buffer = + std::span{std::bit_cast<device::glyph *>(BUFFER_BASE_ADDRESS + + std::bit_cast<std::uintptr_t>(&teachos::boot::x86_64::TEACHOS_VMA)), + DEFAULT_TEXT_BUFFER_WIDTH * DEFAULT_TEXT_BUFFER_HEIGHT}; + + device::device() + : m_position{boot::bootstrap_information.vga_buffer_index} + {} + + auto device::clear(attribute attribute) -> void + { + m_position = 0; + std::ranges::fill(buffer, std::pair{' ', std::bit_cast<std::byte>(attribute)}); + } + + auto device::cursor(bool enabled) -> void + { + auto cursor_disable_byte = std::byte{!enabled} << CURSOR_ENABLED_BIT; + + crtc::address::write(crtc::registers::cursor_start); + crtc::data::write(crtc::data::read() | cursor_disable_byte); + } + + auto device::newline() -> void + { + auto current_line = m_position / DEFAULT_TEXT_BUFFER_WIDTH; + auto next_line = current_line + 1; + + if (std::cmp_greater_equal(next_line, DEFAULT_TEXT_BUFFER_HEIGHT)) + { + auto begin = buffer.begin() + DEFAULT_TEXT_BUFFER_WIDTH; + auto end = buffer.begin() + DEFAULT_TEXT_BUFFER_WIDTH * DEFAULT_TEXT_BUFFER_HEIGHT; + std::ranges::move(begin, end, buffer.begin()); + m_position = current_line * DEFAULT_TEXT_BUFFER_WIDTH; + } + else + { + m_position = next_line * DEFAULT_TEXT_BUFFER_WIDTH; + } + } + + auto device::write(std::string_view code_points, attribute attribute) -> void + { + std::ranges::for_each(code_points, [&](auto code_point) -> void { write(code_point, attribute); }); + } + + auto device::write(char code_point, attribute attribute) -> void + { + buffer[m_position++] = std::pair{code_point, std::bit_cast<std::byte>(attribute)}; + }; + + auto device::writeln(std::string_view code_points, attribute attribute) -> void + { + std::ranges::for_each(code_points, [&](auto code_point) -> void { write(code_point, attribute); }); + newline(); + } + +} // namespace teachos::vga::x86_64::text |
