forked from Bananymous/banan-os
				
			Kernel: Rewrite the whole VESA driver
We dont support vga text mode currently. I might add it later if needed. I also removed mouse 'support' from Shell since it didn't do anything and I didn't implement arbitary bitmap rendering to framebuffer
This commit is contained in:
		
							parent
							
								
									10c7ef7baa
								
							
						
					
					
						commit
						1b9f7aa815
					
				| 
						 | 
				
			
			@ -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		\
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,317 +0,0 @@
 | 
			
		|||
#include <kernel/font.h>
 | 
			
		||||
#include <kernel/IO.h>
 | 
			
		||||
#include <kernel/kmalloc.h>
 | 
			
		||||
#include <kernel/MMU.h>
 | 
			
		||||
#include <kernel/multiboot.h>
 | 
			
		||||
#include <kernel/Panic.h>
 | 
			
		||||
#include <kernel/Serial.h>
 | 
			
		||||
#include <kernel/VESA.h>
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#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));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -9,5 +9,4 @@ $(ARCHDIR)/boot.o		\
 | 
			
		|||
$(ARCHDIR)/CPUID.o		\
 | 
			
		||||
$(ARCHDIR)/IDT.o		\
 | 
			
		||||
$(ARCHDIR)/MMU.o		\
 | 
			
		||||
$(ARCHDIR)/VESA.o		\
 | 
			
		||||
 
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +21,6 @@ namespace Kernel
 | 
			
		|||
		BAN::Vector<BAN::String> ParseArguments(BAN::StringView) const;
 | 
			
		||||
		void ProcessCommand(const BAN::Vector<BAN::String>&);
 | 
			
		||||
		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;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,12 +1,12 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <kernel/VESA.h>
 | 
			
		||||
#include <kernel/TerminalDriver.h>
 | 
			
		||||
#include <kernel/Serial.h>
 | 
			
		||||
 | 
			
		||||
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 };
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,38 +0,0 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <kernel/font.h>
 | 
			
		||||
#include <kernel/TerminalDriver.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
// (c) 2009, 2010 Lutz Sammer, License: AGPLv3
 | 
			
		||||
 | 
			
		||||
	/// bitmap font structure
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,11 @@
 | 
			
		|||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<int32_t>(m_mouse_pos.x + event.dx, 0, m_tty->Width() - 1);
 | 
			
		||||
		m_mouse_pos.y = Math::clamp<int32_t>(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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
#include <BAN/Errors.h>
 | 
			
		||||
#include <kernel/Serial.h>
 | 
			
		||||
#include <kernel/TTY.h>
 | 
			
		||||
#include <kernel/VESA.h>
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,10 +20,11 @@ template<typename T> 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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,167 @@
 | 
			
		|||
#include <BAN/Errors.h>
 | 
			
		||||
#include <kernel/MMU.h>
 | 
			
		||||
#include <kernel/multiboot.h>
 | 
			
		||||
#include <kernel/Serial.h>
 | 
			
		||||
#include <kernel/VesaTerminalDriver.h>
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,7 @@
 | 
			
		|||
#include <kernel/Serial.h>
 | 
			
		||||
#include <kernel/Shell.h>
 | 
			
		||||
#include <kernel/TTY.h>
 | 
			
		||||
#include <kernel/VESA.h>
 | 
			
		||||
#include <kernel/VesaTerminalDriver.h>
 | 
			
		||||
 | 
			
		||||
#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");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue