diff --git a/kernel/Makefile b/kernel/Makefile index 53841a3f..449c88ed 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -29,22 +29,23 @@ LIBS:=$(LIBS) $(KERNEL_ARCH_LIBS) BUILDDIR=$(abspath build) -KERNEL_OBJS= \ -$(KERNEL_ARCH_OBJS) \ -kernel/build_libc.o \ -kernel/font.o \ -kernel/Input.o \ -kernel/kernel.o \ -kernel/kmalloc.o \ -kernel/Panic.o \ -kernel/PIC.o \ -kernel/PIT.o \ -kernel/RTC.o \ -kernel/Serial.o \ -kernel/Shell.o \ -kernel/SSP.o \ -kernel/TTY.o \ -icxxabi.o \ +KERNEL_OBJS= \ +$(KERNEL_ARCH_OBJS) \ +kernel/build_libc.o \ +kernel/font.o \ +kernel/Input.o \ +kernel/kernel.o \ +kernel/kmalloc.o \ +kernel/Panic.o \ +kernel/PIC.o \ +kernel/PIT.o \ +kernel/RTC.o \ +kernel/Serial.o \ +kernel/Shell.o \ +kernel/SSP.o \ +kernel/TTY.o \ +kernel/VesaTerminalDriver.o \ +icxxabi.o \ OBJS= \ $(ARCHDIR)/crti.o \ diff --git a/kernel/arch/i386/VESA.cpp b/kernel/arch/i386/VESA.cpp deleted file mode 100644 index 1a68bb2b..00000000 --- a/kernel/arch/i386/VESA.cpp +++ /dev/null @@ -1,317 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define MULTIBOOT_FLAGS_FRAMEBUFFER (1 << 12) -#define MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS 1 -#define MULTIBOOT_FRAMEBUFFER_TYPE_TEXT 2 - - -extern multiboot_info_t* s_multiboot_info; -extern const struct bitmap_font font; - -namespace VESA -{ - - static uintptr_t s_addr = 0; - static uint8_t s_bpp = 0; - static uint32_t s_pitch = 0; - static uint32_t s_width = 0; - static uint32_t s_height = 0; - static uint8_t s_mode = 0; - - static uint32_t s_terminal_width = 0; - static uint32_t s_terminal_height = 0; - - static void (*PutCharAtImpl)(uint16_t, uint32_t, uint32_t, Color, Color) = nullptr; - static void (*ClearImpl)(Color) = nullptr; - static void (*SetCursorPositionImpl)(uint32_t, uint32_t, Color) = nullptr; - - static void GraphicsPutBitmapAt(const uint8_t* bitmap, uint32_t x, uint32_t y, Color fg); - static void GraphicsPutBitmapAt(const uint8_t* bitmap, uint32_t x, uint32_t y, Color fg, Color bg); - static void GraphicsPutCharAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg); - static void GraphicsClear(Color color); - static void GraphicsSetCursorPosition(uint32_t x, uint32_t y, Color fg); - - static void TextPutCharAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg); - static void TextClear(Color color); - static void TextSetCursorPosition(uint32_t x, uint32_t y, Color fg); - - void PutBitmapAt(const uint8_t* bitmap, uint32_t x, uint32_t y, Color fg) - { - if (s_mode == MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS) - GraphicsPutBitmapAt(bitmap, x, y, fg); - } - void PutBitmapAt(const uint8_t* bitmap, uint32_t x, uint32_t y, Color fg, Color bg) - { - if (s_mode == MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS) - GraphicsPutBitmapAt(bitmap, x, y, fg, bg); - } - - void PutCharAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg) - { - if (x >= s_width || y >= s_height) - return; - PutCharAtImpl(ch, x, y, fg, bg); - } - - void Clear(Color color) - { - ClearImpl(color); - } - - void SetCursorPosition(uint32_t x, uint32_t y, Color fg) - { - SetCursorPositionImpl(x, y, fg); - } - - uint32_t GetTerminalWidth() - { - return s_terminal_width; - } - - uint32_t GetTerminalHeight() - { - return s_terminal_height; - } - - bool Initialize() - { - if (!(g_multiboot_info->flags & MULTIBOOT_FLAGS_FRAMEBUFFER)) - { - derrorln("bootloader did not provide a memory map"); - return false; - } - - auto& framebuffer = g_multiboot_info->framebuffer; - s_addr = framebuffer.addr; - s_bpp = framebuffer.bpp; - s_pitch = framebuffer.pitch; - s_width = framebuffer.width; - s_height = framebuffer.height; - s_mode = framebuffer.type; - - MMU::Get().AllocateRange(s_addr, s_pitch * s_height); - - if (s_mode == MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS) - { - if (s_bpp != 24 && s_bpp != 32) - { - derrorln("Unsupported bpp {}", s_bpp); - return false; - } - - dprintln("Graphics Mode {}x{} ({} bpp)", s_width, s_height, s_bpp); - PutCharAtImpl = GraphicsPutCharAt; - ClearImpl = GraphicsClear; - SetCursorPositionImpl = GraphicsSetCursorPosition; - s_terminal_width = s_width / font.Width; - s_terminal_height = s_height / font.Height; - } - else if (s_mode == MULTIBOOT_FRAMEBUFFER_TYPE_TEXT) - { - dprintln("Text Mode {}x{}", s_width, s_height); - PutCharAtImpl = TextPutCharAt; - ClearImpl = TextClear; - SetCursorPositionImpl = TextSetCursorPosition; - s_terminal_width = s_width; - s_terminal_height = s_height; - } - else - { - derrorln("Unsupported type for VESA framebuffer"); - return false; - } - - SetCursorPositionImpl(0, 0, Color::BRIGHT_WHITE); - ClearImpl(Color::BLACK); - return true; - } - - static uint32_t s_graphics_colors[] - { - 0x00'00'00'00, - 0x00'00'00'AA, - 0x00'00'AA'00, - 0x00'00'AA'AA, - 0x00'AA'00'00, - 0x00'AA'00'AA, - 0x00'AA'55'00, - 0x00'AA'AA'AA, - 0x00'55'55'55, - 0x00'55'55'FF, - 0x00'55'FF'55, - 0x00'55'FF'FF, - 0x00'FF'55'55, - 0x00'FF'55'FF, - 0x00'FF'FF'55, - 0x00'FF'FF'FF, - }; - - static void GraphicsSetPixel(uint32_t offset, uint32_t color) - { - uint32_t* address = (uint32_t*)(s_addr + offset); - switch (s_bpp) - { - case 24: - *address = (*address & 0xFF000000) | (color & 0x00FFFFFF); - break; - case 32: - *address = color; - break; - } - } - - static void GraphicsPutBitmapAt(const uint8_t* bitmap, uint32_t x, uint32_t y, Color fg) - { - uint32_t u32_fg = s_graphics_colors[(uint8_t)fg]; - - uint32_t fx = x * font.Width; - uint32_t fy = y * font.Height; - - uint32_t row_offset = (fy * s_pitch) + (fx * (s_bpp / 8)); - for (uint32_t gy = 0; gy < font.Height; gy++) - { - uint32_t pixel_offset = row_offset; - for (uint32_t gx = 0; gx < font.Width; gx++) - { - if (bitmap[gy] & (1 << (font.Width - gx - 1))) - GraphicsSetPixel(pixel_offset, u32_fg); - pixel_offset += s_bpp / 8; - } - row_offset += s_pitch; - } - } - - static void GraphicsPutBitmapAt(const uint8_t* bitmap, uint32_t x, uint32_t y, Color fg, Color bg) - { - uint32_t u32_fg = s_graphics_colors[(uint8_t)fg]; - uint32_t u32_bg = s_graphics_colors[(uint8_t)bg]; - - uint32_t fx = x * font.Width; - uint32_t fy = y * font.Height; - - uint32_t row_offset = (fy * s_pitch) + (fx * (s_bpp / 8)); - for (uint32_t gy = 0; gy < font.Height; gy++) - { - uint32_t pixel_offset = row_offset; - for (uint32_t gx = 0; gx < font.Width; gx++) - { - GraphicsSetPixel(pixel_offset, (bitmap[gy] & (1 << (font.Width - gx - 1))) ? u32_fg : u32_bg); - pixel_offset += s_bpp / 8; - } - row_offset += s_pitch; - } - } - - static void GraphicsPutCharAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg) - { - // find correct bitmap - uint32_t index = 0; - for (uint32_t i = 0; i < font.Chars; i++) - { - if (font.Index[i] == ch) - { - index = i; - break; - } - } - - const uint8_t* glyph = font.Bitmap + index * font.Height; - - GraphicsPutBitmapAt(glyph, x, y, fg, bg); - } - - static void GraphicsClear(Color color) - { - uint32_t u32_color = s_graphics_colors[(uint8_t)color]; - - if (s_bpp == 32) - { - uint32_t bytes_per_row = s_pitch / 4; - for (uint32_t y = 0; y < s_height; y++) - for (uint32_t x = 0; x < s_width; x++) - ((uint32_t*)s_addr)[y * bytes_per_row + x] = u32_color; - return; - } - - uint32_t row_offset = 0; - for (uint32_t y = 0; y < s_height; y++) - { - uint32_t pixel_offset = row_offset; - for (uint32_t x = 0; x < s_width; x++) - { - GraphicsSetPixel(pixel_offset, u32_color); - pixel_offset += s_bpp / 8; - } - row_offset += s_pitch; - } - } - - static void GraphicsSetCursorPosition(uint32_t x, uint32_t y, Color fg) - { - if (font.Width == 8 && font.Height == 16) - { - uint8_t cursor[] = { - ________, - ________, - ________, - ________, - ________, - ________, - ________, - ________, - ________, - ________, - ________, - ________, - ________, - XXXXXXXX, - XXXXXXXX, - ________, - }; - - GraphicsPutBitmapAt(cursor, x, y, fg); - } - } - - static inline uint8_t TextColor(Color fg, Color bg) - { - return (((uint8_t)bg & 0x0F) << 4) | ((uint8_t)fg & 0x0F); - } - - static inline uint16_t TextEntry(uint8_t ch, uint8_t color) - { - return ((uint16_t)color << 8) | ch; - } - - static void TextPutCharAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg) - { - uint32_t index = y * s_width + x; - ((uint16_t*)s_addr)[index] = TextEntry(ch, TextColor(fg, bg)); - } - - static void TextClear(Color color) - { - for (uint32_t y = 0; y < s_height; y++) - for (uint32_t x = 0; x < s_width; x++) - TextPutCharAt(' ', x, y, Color::BRIGHT_WHITE, color); - } - - static void TextSetCursorPosition(uint32_t x, uint32_t y, Color) - { - uint16_t position = y * s_width + x; - IO::outb(0x3D4, 0x0F); - IO::outb(0x3D5, (uint8_t) (position & 0xFF)); - IO::outb(0x3D4, 0x0E); - IO::outb(0x3D5, (uint8_t) ((position >> 8) & 0xFF)); - } - -} \ No newline at end of file diff --git a/kernel/arch/i386/make.config b/kernel/arch/i386/make.config index dc1fb78a..04d6851b 100644 --- a/kernel/arch/i386/make.config +++ b/kernel/arch/i386/make.config @@ -9,5 +9,4 @@ $(ARCHDIR)/boot.o \ $(ARCHDIR)/CPUID.o \ $(ARCHDIR)/IDT.o \ $(ARCHDIR)/MMU.o \ -$(ARCHDIR)/VESA.o \ \ No newline at end of file diff --git a/kernel/include/kernel/Shell.h b/kernel/include/kernel/Shell.h index 697f4833..fe19effa 100644 --- a/kernel/include/kernel/Shell.h +++ b/kernel/include/kernel/Shell.h @@ -21,7 +21,6 @@ namespace Kernel BAN::Vector ParseArguments(BAN::StringView) const; void ProcessCommand(const BAN::Vector&); void KeyEventCallback(Input::KeyEvent); - void MouseMoveEventCallback(Input::MouseMoveEvent); private: TTY* m_tty; @@ -36,13 +35,6 @@ namespace Kernel uint32_t col = 0; uint32_t index = 0; } m_cursor_pos; - - struct - { - bool exists = false; - int32_t x = 0; - int32_t y = 0; - } m_mouse_pos; }; } \ No newline at end of file diff --git a/kernel/include/kernel/TTY.h b/kernel/include/kernel/TTY.h index 7ac37261..69ff3b31 100644 --- a/kernel/include/kernel/TTY.h +++ b/kernel/include/kernel/TTY.h @@ -1,12 +1,12 @@ #pragma once -#include +#include #include class TTY { public: - TTY(); + TTY(TerminalDriver*); void Clear(); void PutChar(char ch); void Write(const char* data, size_t size); @@ -31,8 +31,8 @@ private: private: struct Cell { - VESA::Color foreground = VESA::Color::BRIGHT_WHITE; - VESA::Color background = VESA::Color::BLACK; + TerminalDriver::Color foreground = TerminalColor::BRIGHT_WHITE; + TerminalDriver::Color background = TerminalColor::BLACK; uint16_t character = ' '; }; @@ -43,12 +43,13 @@ private: int32_t nums[2] = { -1, -1 }; }; - uint32_t m_width { 0 }; - uint32_t m_height { 0 }; - uint32_t m_row { 0 }; - uint32_t m_column { 0 }; - VESA::Color m_foreground { VESA::Color::BRIGHT_WHITE }; - VESA::Color m_background { VESA::Color::BLACK }; - Cell* m_buffer { nullptr }; - AnsiState m_ansi_state; + uint32_t m_width { 0 }; + uint32_t m_height { 0 }; + uint32_t m_row { 0 }; + uint32_t m_column { 0 }; + TerminalDriver::Color m_foreground { TerminalColor::BRIGHT_WHITE }; + TerminalDriver::Color m_background { TerminalColor::BLACK }; + Cell* m_buffer { nullptr }; + AnsiState m_ansi_state; + TerminalDriver* m_terminal_driver { nullptr }; }; diff --git a/kernel/include/kernel/TerminalDriver.h b/kernel/include/kernel/TerminalDriver.h new file mode 100644 index 00000000..a088514c --- /dev/null +++ b/kernel/include/kernel/TerminalDriver.h @@ -0,0 +1,53 @@ +#pragma once + +#include + +class TerminalDriver +{ +public: + struct Color + { + constexpr Color(uint32_t rgb) + : rgb(rgb) + { } + constexpr Color(uint8_t r, uint8_t g, uint8_t b) + : rgb(((uint32_t)r << 16) | ((uint32_t)g << 8) | b) + { } + uint8_t red() const { return (rgb >> 0x10) & 0xFF; } + uint8_t green() const { return (rgb >> 0x08) & 0xFF; } + uint8_t blue() const { return (rgb >> 0x00) & 0xFF; } + uint32_t rgb; + }; + +public: + virtual ~TerminalDriver() {} + + virtual uint32_t Width() const = 0; + virtual uint32_t Height() const = 0; + + virtual void PutCharAt(uint16_t, uint32_t, uint32_t, Color, Color) = 0; + virtual void Clear(Color) = 0; + + virtual void SetCursorPosition(uint32_t, uint32_t) = 0; +}; + +namespace TerminalColor +{ + static constexpr TerminalDriver::Color BLACK = 0x000000; + static constexpr TerminalDriver::Color BLUE = 0x0000AA; + static constexpr TerminalDriver::Color GREEN = 0x00AA00; + static constexpr TerminalDriver::Color CYAN = 0x00AAAA; + static constexpr TerminalDriver::Color RED = 0xAA0000; + static constexpr TerminalDriver::Color MAGENTA = 0xAA00AA; + static constexpr TerminalDriver::Color YELLOW = 0xAA5500; + static constexpr TerminalDriver::Color WHITE = 0xAAAAAA; + + static constexpr TerminalDriver::Color BRIGHT_BLACK = 0x555555; + static constexpr TerminalDriver::Color BRIGHT_BLUE = 0x5555FF; + static constexpr TerminalDriver::Color BRIGHT_GREEN = 0x55FF55; + static constexpr TerminalDriver::Color BRIGHT_CYAN = 0x55FFFF; + static constexpr TerminalDriver::Color BRIGHT_RED = 0xFF5555; + static constexpr TerminalDriver::Color BRIGHT_MAGENTA = 0xFF55FF; + static constexpr TerminalDriver::Color BRIGHT_YELLOW = 0xFFFF55; + static constexpr TerminalDriver::Color BRIGHT_WHITE = 0xFFFFFF; +} \ No newline at end of file diff --git a/kernel/include/kernel/VESA.h b/kernel/include/kernel/VESA.h deleted file mode 100644 index 32ae4868..00000000 --- a/kernel/include/kernel/VESA.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -namespace VESA -{ - - enum class Color : uint8_t - { - BLACK = 0, - BLUE = 1, - GREEN = 2, - CYAN = 3, - RED = 4, - MAGENTA = 5, - YELLOW = 6, - WHITE = 7, - BRIGHT_BLACK = 8, - BRIGHT_BLUE = 9, - BRIGHT_GREEN = 10, - BRIGHT_CYAN = 11, - BRIGHT_RED = 12, - BRIGHT_MAGENTA = 13, - BRIGHT_YELLOW = 14, - BRIGHT_WHITE = 15, - }; - - bool Initialize(); - void PutBitmapAt(const uint8_t*, uint32_t, uint32_t, Color); - void PutBitmapAt(const uint8_t*, uint32_t, uint32_t, Color, Color); - void PutCharAt(uint16_t, uint32_t, uint32_t, Color, Color); - void Clear(Color); - void SetCursorPosition(uint32_t, uint32_t, Color); - - uint32_t GetTerminalWidth(); - uint32_t GetTerminalHeight(); - -} \ No newline at end of file diff --git a/kernel/include/kernel/VesaTerminalDriver.h b/kernel/include/kernel/VesaTerminalDriver.h new file mode 100644 index 00000000..12fd4dbb --- /dev/null +++ b/kernel/include/kernel/VesaTerminalDriver.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +class VesaTerminalDriver final : public TerminalDriver +{ +public: + static VesaTerminalDriver* Create(); + ~VesaTerminalDriver(); + + virtual uint32_t Width() const override { return m_width / m_font.Width; } + virtual uint32_t Height() const override { return m_height / m_font.Height; } + + virtual void PutCharAt(uint16_t, uint32_t, uint32_t, Color, Color) override; + virtual void Clear(Color) override; + + virtual void SetCursorPosition(uint32_t, uint32_t) override; + +private: + VesaTerminalDriver(uint32_t width, uint32_t height, uint32_t pitch, uint8_t bpp, uintptr_t address, bitmap_font font) + : m_width(width) + , m_height(height) + , m_pitch(pitch) + , m_bpp(bpp) + , m_address(address) + , m_font(font) + { } + + void SetPixel(uint32_t, Color); + +private: + uint32_t m_width = 0; + uint32_t m_height = 0; + uint32_t m_pitch = 0; + uint8_t m_bpp = 0; + uintptr_t m_address = 0; + bitmap_font m_font; + + static constexpr Color s_cursor_color = TerminalColor::BRIGHT_WHITE; +}; \ No newline at end of file diff --git a/kernel/include/kernel/font.h b/kernel/include/kernel/font.h index 7d172652..96518dda 100644 --- a/kernel/include/kernel/font.h +++ b/kernel/include/kernel/font.h @@ -1,3 +1,4 @@ +#pragma once // (c) 2009, 2010 Lutz Sammer, License: AGPLv3 /// bitmap font structure diff --git a/kernel/include/kernel/multiboot.h b/kernel/include/kernel/multiboot.h index 44d301f1..29df36d2 100644 --- a/kernel/include/kernel/multiboot.h +++ b/kernel/include/kernel/multiboot.h @@ -2,6 +2,11 @@ #include +#define MULTIBOOT_FLAGS_FRAMEBUFFER (1 << 12) + +#define MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_TEXT 2 + struct framebuffer_info_t { uint64_t addr; diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index ac407393..985fa87a 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -22,30 +22,10 @@ namespace Kernel static auto s_default_prompt = "\\[\e[32m\\]user\\[\e[m\\]# "_sv; - static uint8_t s_pointer[] { - ________, - ________, - ________, - ________, - ________, - X_______, - XX______, - XXX_____, - XXXX____, - XXXXX___, - XXXXXX__, - XXXXXXX_, - XXXXXXXX, - XXX_____, - XX______, - X_______, - }; - Shell::Shell(TTY* tty) : m_tty(tty) { Input::register_key_event_callback({ &Shell::KeyEventCallback, this }); - Input::register_mouse_move_event_callback({ &Shell::MouseMoveEventCallback, this }); SetPrompt(s_default_prompt); MUST(m_buffer.PushBack(""_sv)); } @@ -415,18 +395,6 @@ argument_done: } TTY_PRINT("\e[{}G", m_prompt_length + m_cursor_pos.col + 1); - - if (m_mouse_pos.exists) - VESA::PutBitmapAt(s_pointer, m_mouse_pos.x, m_mouse_pos.y, VESA::Color::BRIGHT_WHITE); - } - - void Shell::MouseMoveEventCallback(Input::MouseMoveEvent event) - { - m_mouse_pos.exists = true; - m_tty->RenderFromBuffer(m_mouse_pos.x, m_mouse_pos.y); - m_mouse_pos.x = Math::clamp(m_mouse_pos.x + event.dx, 0, m_tty->Width() - 1); - m_mouse_pos.y = Math::clamp(m_mouse_pos.y - event.dy, 0, m_tty->Height() - 1); - VESA::PutBitmapAt(s_pointer, m_mouse_pos.x, m_mouse_pos.y, VESA::Color::BRIGHT_WHITE); } } \ No newline at end of file diff --git a/kernel/kernel/TTY.cpp b/kernel/kernel/TTY.cpp index 34e27dd0..6615336e 100644 --- a/kernel/kernel/TTY.cpp +++ b/kernel/kernel/TTY.cpp @@ -1,7 +1,6 @@ #include #include #include -#include #include @@ -21,10 +20,11 @@ template inline constexpr T clamp(T x, T a, T b) { return x < a ? a static TTY* s_tty = nullptr; -TTY::TTY() +TTY::TTY(TerminalDriver* driver) + : m_terminal_driver(driver) { - m_width = VESA::GetTerminalWidth(); - m_height = VESA::GetTerminalHeight(); + m_width = m_terminal_driver->Width(); + m_height = m_terminal_driver->Height(); m_buffer = new Cell[m_width * m_height]; @@ -36,7 +36,7 @@ void TTY::Clear() { for (uint32_t i = 0; i < m_width * m_height; i++) m_buffer[i] = { .foreground = m_foreground, .background = m_background, .character = ' ' }; - VESA::Clear(m_background); + m_terminal_driver->Clear(m_background); } void TTY::SetCursorPosition(uint32_t x, uint32_t y) @@ -45,7 +45,7 @@ void TTY::SetCursorPosition(uint32_t x, uint32_t y) static uint32_t last_y = -1; if (last_x != uint32_t(-1) && last_y != uint32_t(-1)) RenderFromBuffer(last_x, last_y); // Hacky way to clear previous cursor in graphics mode :D - VESA::SetCursorPosition(x, y, VESA::Color::BRIGHT_WHITE); + m_terminal_driver->SetCursorPosition(x, y); last_x = m_column = x; last_y = m_row = y; } @@ -111,27 +111,27 @@ void TTY::HandleAnsiSGR() { case -1: case 0: - m_foreground = VESA::Color::BRIGHT_WHITE; - m_background = VESA::Color::BLACK; + m_foreground = TerminalColor::BRIGHT_WHITE; + m_background = TerminalColor::BLACK; break; - case 30: m_foreground = VESA::Color::BRIGHT_BLACK; break; - case 31: m_foreground = VESA::Color::BRIGHT_RED; break; - case 32: m_foreground = VESA::Color::BRIGHT_GREEN; break; - case 33: m_foreground = VESA::Color::BRIGHT_YELLOW; break; - case 34: m_foreground = VESA::Color::BRIGHT_BLUE; break; - case 35: m_foreground = VESA::Color::BRIGHT_MAGENTA; break; - case 36: m_foreground = VESA::Color::BRIGHT_CYAN; break; - case 37: m_foreground = VESA::Color::BRIGHT_WHITE; break; + case 30: m_foreground = TerminalColor::BRIGHT_BLACK; break; + case 31: m_foreground = TerminalColor::BRIGHT_RED; break; + case 32: m_foreground = TerminalColor::BRIGHT_GREEN; break; + case 33: m_foreground = TerminalColor::BRIGHT_YELLOW; break; + case 34: m_foreground = TerminalColor::BRIGHT_BLUE; break; + case 35: m_foreground = TerminalColor::BRIGHT_MAGENTA; break; + case 36: m_foreground = TerminalColor::BRIGHT_CYAN; break; + case 37: m_foreground = TerminalColor::BRIGHT_WHITE; break; - case 40: m_background = VESA::Color::BRIGHT_BLACK; break; - case 41: m_background = VESA::Color::BRIGHT_RED; break; - case 42: m_background = VESA::Color::BRIGHT_GREEN; break; - case 43: m_background = VESA::Color::BRIGHT_YELLOW; break; - case 44: m_background = VESA::Color::BRIGHT_BLUE; break; - case 45: m_background = VESA::Color::BRIGHT_MAGENTA; break; - case 46: m_background = VESA::Color::BRIGHT_CYAN; break; - case 47: m_background = VESA::Color::BRIGHT_WHITE; break; + case 40: m_background = TerminalColor::BRIGHT_BLACK; break; + case 41: m_background = TerminalColor::BRIGHT_RED; break; + case 42: m_background = TerminalColor::BRIGHT_GREEN; break; + case 43: m_background = TerminalColor::BRIGHT_YELLOW; break; + case 44: m_background = TerminalColor::BRIGHT_BLUE; break; + case 45: m_background = TerminalColor::BRIGHT_MAGENTA; break; + case 46: m_background = TerminalColor::BRIGHT_CYAN; break; + case 47: m_background = TerminalColor::BRIGHT_WHITE; break; } } @@ -246,7 +246,7 @@ void TTY::RenderFromBuffer(uint32_t x, uint32_t y) { ASSERT(x < m_width && y < m_height); const auto& cell = m_buffer[y * m_width + x]; - VESA::PutCharAt(cell.character, x, y, cell.foreground, cell.background); + m_terminal_driver->PutCharAt(cell.character, x, y, cell.foreground, cell.background); } void TTY::PutCharAt(uint16_t ch, uint32_t x, uint32_t y) @@ -256,7 +256,7 @@ void TTY::PutCharAt(uint16_t ch, uint32_t x, uint32_t y) cell.character = ch; cell.foreground = m_foreground; cell.background = m_background; - VESA::PutCharAt(ch, x, y, m_foreground, m_background); + m_terminal_driver->PutCharAt(ch, x, y, m_foreground, m_background); } void TTY::PutChar(char ch) diff --git a/kernel/kernel/VesaTerminalDriver.cpp b/kernel/kernel/VesaTerminalDriver.cpp new file mode 100644 index 00000000..b3b6f409 --- /dev/null +++ b/kernel/kernel/VesaTerminalDriver.cpp @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include + +extern const struct bitmap_font font; + +VesaTerminalDriver* VesaTerminalDriver::Create() +{ + if (!(g_multiboot_info->flags & MULTIBOOT_FLAGS_FRAMEBUFFER)) + { + dprintln("Bootloader did not provide framebuffer"); + return nullptr; + } + + auto& framebuffer = g_multiboot_info->framebuffer; + + if (framebuffer.type == MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS) + { + if (framebuffer.bpp != 24 && framebuffer.bpp != 32) + { + dprintln("Unsupported bpp {}", framebuffer.bpp); + return nullptr; + } + dprintln("Graphics Mode {}x{} ({} bpp)", framebuffer.width, framebuffer.height, framebuffer.bpp); + } + else if (framebuffer.type == MULTIBOOT_FRAMEBUFFER_TYPE_TEXT) + { + dprintln("Text Mode is currently not supported"); + return nullptr; + } + else + { + dprintln("Unknown framebuffer type {}", framebuffer.type); + return nullptr; + } + + MMU::Get().AllocateRange(framebuffer.addr, framebuffer.pitch * framebuffer.height); + + auto* driver = new VesaTerminalDriver( + framebuffer.width, + framebuffer.height, + framebuffer.pitch, + framebuffer.bpp, + framebuffer.addr, + font + ); + driver->SetCursorPosition(0, 0); + driver->Clear(TerminalColor::BLACK); + return driver; +} + + +VesaTerminalDriver::~VesaTerminalDriver() +{ + MMU::Get().UnAllocateRange(m_address, m_pitch * m_height); +} + +void VesaTerminalDriver::SetPixel(uint32_t offset, Color color) +{ + uint32_t* pixel = (uint32_t*)(m_address + offset); + switch (m_bpp) + { + case 24: + *pixel = (*pixel & 0xFF000000) | (color.rgb & 0x00FFFFFF); + break; + case 32: + *pixel = color.rgb; + break; + } +} + +void VesaTerminalDriver::PutCharAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg) +{ + uint32_t glyph_index = 0; + for (uint32_t i = 0; i < m_font.Chars; i++) + { + if (m_font.Index[i] == ch) + { + glyph_index = i; + break; + } + } + + const uint8_t* glyph = m_font.Bitmap + glyph_index * m_font.Height; + + x *= m_font.Width; + y *= m_font.Height; + + uint32_t row_offset = y * m_pitch + x * m_bpp / 8; + for (uint32_t dy = 0; dy < m_font.Height && y + dy < m_height; dy++) + { + uint32_t pixel_offset = row_offset; + for (uint32_t dx = 0; dx < m_font.Width && x + dx < m_width; dx++) + { + uint8_t bitmask = 1 << (font.Width - dx - 1); + SetPixel(pixel_offset, glyph[dy] & bitmask ? fg : bg); + pixel_offset += m_bpp / 8; + } + row_offset += m_pitch; + } +} + +void VesaTerminalDriver::Clear(Color color) +{ + if (m_bpp == 32) + { + uint32_t cells_per_row = m_pitch / 4; + for (uint32_t y = 0; y < m_height; y++) + for (uint32_t x = 0; x < m_width; x++) + ((uint32_t*)m_address)[y * cells_per_row + x] = color.rgb; + return; + } + + uint32_t row_offset = 0; + for (uint32_t y = 0; y < m_height; y++) + { + uint32_t pixel_offset = row_offset; + for (uint32_t x = 0; x < m_width; x++) + { + SetPixel(pixel_offset, color); + pixel_offset += m_bpp / 8; + } + row_offset += m_pitch; + } +} + +void VesaTerminalDriver::SetCursorPosition(uint32_t x, uint32_t y) +{ + ASSERT(m_font.Height == 16 && m_font.Width == 8); + constexpr uint8_t cursor[] = { + ________, + ________, + ________, + ________, + ________, + ________, + ________, + ________, + ________, + ________, + ________, + ________, + ________, + XXXXXXXX, + XXXXXXXX, + ________, + }; + + x *= m_font.Width; + y *= m_font.Height; + + uint32_t row_offset = y * m_pitch + x * m_bpp / 8; + for (uint32_t dy = 0; dy < m_font.Height && y + dy < m_height; dy++) + { + uint32_t pixel_offset = row_offset; + for (uint32_t dx = 0; dx < m_font.Width && x + dx < m_width; dx++) + { + uint8_t bitmask = 1 << (font.Width - dx - 1); + if (cursor[dy] & bitmask) + SetPixel(pixel_offset, s_cursor_color); + pixel_offset += m_bpp / 8; + } + row_offset += m_pitch; + } +} \ No newline at end of file diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 55585574..09eeb489 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #define DISABLE_INTERRUPTS() asm volatile("cli") #define ENABLE_INTERRUPTS() asm volatile("sti") @@ -76,10 +76,10 @@ extern "C" void kernel_main() MMU::Intialize(); dprintln("MMU initialized"); - if (!VESA::Initialize()) - return; + TerminalDriver* terminal_driver = VesaTerminalDriver::Create(); + ASSERT(terminal_driver); dprintln("VESA initialized"); - TTY* tty1 = new TTY; + TTY* tty1 = new TTY(terminal_driver); APIC::Initialize(cmdline.force_pic); dprintln("APIC initialized");