aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/vga/text.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/src/vga/text.cpp')
-rw-r--r--arch/x86_64/src/vga/text.cpp66
1 files changed, 66 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..9b7946d
--- /dev/null
+++ b/arch/x86_64/src/vga/text.cpp
@@ -0,0 +1,66 @@
+#include "x86_64/vga/text.hpp"
+
+#include "arch/asm_pointer.hpp"
+#include "x86_64/vga/io.hpp"
+
+#include <algorithm>
+#include <cstddef>
+#include <string_view>
+#include <utility>
+
+extern "C" teachos::arch::asm_pointer<std::pair<char, teachos::x86_64::vga::text::attribute>> vga_buffer_pointer;
+
+namespace teachos::x86_64::vga::text
+{
+ namespace
+ {
+ // auto constexpr DEFAULT_VGA_TEXT_BUFFER_ADDRESS = 0xB8000;
+
+ auto buffer_offset = std::ptrdiff_t{};
+
+ auto constexpr DEFAULT_TEXT_BUFFER_WIDTH = 80U;
+ auto constexpr DEFAULT_TEXT_BUFFER_HEIGHT = 25U;
+ } // namespace
+
+ auto clear(attribute attribute) -> void
+ {
+ buffer_offset = 0;
+ std::ranges::fill_n(vga_buffer_pointer.get(), 2000, std::pair{' ', attribute});
+ }
+
+ auto cursor(bool enabled) -> void
+ {
+ auto cursor_disable_byte = std::byte{!enabled} << 5;
+
+ io::crtc::address_port::write(io::crtc::registers::cursor_start);
+ io::crtc::data_port::write(io::crtc::data_port::read() | cursor_disable_byte);
+ }
+
+ auto newline() -> void
+ {
+ auto current_line = buffer_offset / DEFAULT_TEXT_BUFFER_WIDTH;
+ auto next_line = current_line + 1;
+
+ if (next_line >= DEFAULT_TEXT_BUFFER_HEIGHT)
+ {
+ auto begin = vga_buffer_pointer + DEFAULT_TEXT_BUFFER_WIDTH;
+ auto end = vga_buffer_pointer + DEFAULT_TEXT_BUFFER_WIDTH * DEFAULT_TEXT_BUFFER_HEIGHT;
+ std::ranges::move(begin, end, vga_buffer_pointer.get());
+ buffer_offset = current_line * DEFAULT_TEXT_BUFFER_WIDTH;
+ }
+ else
+ {
+ buffer_offset = next_line * DEFAULT_TEXT_BUFFER_WIDTH;
+ }
+ }
+
+ auto write_char(char code_point, attribute attribute) -> void
+ {
+ vga_buffer_pointer[buffer_offset++] = std::pair{code_point, attribute};
+ };
+
+ auto write(std::string_view code_points, attribute attribute) -> void
+ {
+ std::ranges::for_each(code_points, [&](auto code_point) { write_char(code_point, attribute); });
+ }
+} // namespace teachos::x86_64::vga::text