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) | BUILDDIR=$(abspath build) | ||||||
|   |   | ||||||
| KERNEL_OBJS=			\
 | KERNEL_OBJS=				\
 | ||||||
| $(KERNEL_ARCH_OBJS)		\ | $(KERNEL_ARCH_OBJS)			\ | ||||||
| kernel/build_libc.o		\ | kernel/build_libc.o			\ | ||||||
| kernel/font.o			\ | kernel/font.o				\ | ||||||
| kernel/Input.o			\ | kernel/Input.o				\ | ||||||
| kernel/kernel.o			\ | kernel/kernel.o				\ | ||||||
| kernel/kmalloc.o		\ | kernel/kmalloc.o			\ | ||||||
| kernel/Panic.o			\ | kernel/Panic.o				\ | ||||||
| kernel/PIC.o			\ | kernel/PIC.o				\ | ||||||
| kernel/PIT.o			\ | kernel/PIT.o				\ | ||||||
| kernel/RTC.o			\ | kernel/RTC.o				\ | ||||||
| kernel/Serial.o			\ | kernel/Serial.o				\ | ||||||
| kernel/Shell.o			\ | kernel/Shell.o				\ | ||||||
| kernel/SSP.o			\ | kernel/SSP.o				\ | ||||||
| kernel/TTY.o			\ | kernel/TTY.o				\ | ||||||
| icxxabi.o				\ | kernel/VesaTerminalDriver.o	\ | ||||||
|  | icxxabi.o					\ | ||||||
|   |   | ||||||
| OBJS=					\
 | OBJS=					\
 | ||||||
| $(ARCHDIR)/crti.o		\ | $(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)/CPUID.o		\ | ||||||
| $(ARCHDIR)/IDT.o		\ | $(ARCHDIR)/IDT.o		\ | ||||||
| $(ARCHDIR)/MMU.o		\ | $(ARCHDIR)/MMU.o		\ | ||||||
| $(ARCHDIR)/VESA.o		\ |  | ||||||
|   |   | ||||||
|  | @ -21,7 +21,6 @@ namespace Kernel | ||||||
| 		BAN::Vector<BAN::String> ParseArguments(BAN::StringView) const; | 		BAN::Vector<BAN::String> ParseArguments(BAN::StringView) const; | ||||||
| 		void ProcessCommand(const BAN::Vector<BAN::String>&); | 		void ProcessCommand(const BAN::Vector<BAN::String>&); | ||||||
| 		void KeyEventCallback(Input::KeyEvent); | 		void KeyEventCallback(Input::KeyEvent); | ||||||
| 		void MouseMoveEventCallback(Input::MouseMoveEvent); |  | ||||||
| 
 | 
 | ||||||
| 	private: | 	private: | ||||||
| 		TTY*						m_tty; | 		TTY*						m_tty; | ||||||
|  | @ -36,13 +35,6 @@ namespace Kernel | ||||||
| 			uint32_t col = 0; | 			uint32_t col = 0; | ||||||
| 			uint32_t index = 0; | 			uint32_t index = 0; | ||||||
| 		} m_cursor_pos; | 		} m_cursor_pos; | ||||||
| 
 |  | ||||||
| 		struct |  | ||||||
| 		{ |  | ||||||
| 			bool	exists = false; |  | ||||||
| 			int32_t x = 0; |  | ||||||
| 			int32_t y = 0; |  | ||||||
| 		} m_mouse_pos; |  | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | @ -1,12 +1,12 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <kernel/VESA.h> | #include <kernel/TerminalDriver.h> | ||||||
| #include <kernel/Serial.h> | #include <kernel/Serial.h> | ||||||
| 
 | 
 | ||||||
| class TTY | class TTY | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	TTY(); | 	TTY(TerminalDriver*); | ||||||
| 	void Clear(); | 	void Clear(); | ||||||
| 	void PutChar(char ch); | 	void PutChar(char ch); | ||||||
| 	void Write(const char* data, size_t size); | 	void Write(const char* data, size_t size); | ||||||
|  | @ -31,8 +31,8 @@ private: | ||||||
| private: | private: | ||||||
| 	struct Cell | 	struct Cell | ||||||
| 	{ | 	{ | ||||||
| 		VESA::Color foreground = VESA::Color::BRIGHT_WHITE; | 		TerminalDriver::Color foreground = TerminalColor::BRIGHT_WHITE; | ||||||
| 		VESA::Color background = VESA::Color::BLACK; | 		TerminalDriver::Color background = TerminalColor::BLACK; | ||||||
| 		uint16_t	character = ' '; | 		uint16_t	character = ' '; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | @ -43,12 +43,13 @@ private: | ||||||
| 		int32_t nums[2]	= { -1, -1 }; | 		int32_t nums[2]	= { -1, -1 }; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	uint32_t	m_width			{ 0 }; | 	uint32_t				m_width			{ 0 }; | ||||||
| 	uint32_t	m_height		{ 0 }; | 	uint32_t				m_height		{ 0 }; | ||||||
| 	uint32_t	m_row			{ 0 }; | 	uint32_t				m_row			{ 0 }; | ||||||
| 	uint32_t	m_column		{ 0 }; | 	uint32_t				m_column		{ 0 }; | ||||||
| 	VESA::Color	m_foreground	{ VESA::Color::BRIGHT_WHITE }; | 	TerminalDriver::Color	m_foreground	{ TerminalColor::BRIGHT_WHITE }; | ||||||
| 	VESA::Color	m_background	{ VESA::Color::BLACK }; | 	TerminalDriver::Color	m_background	{ TerminalColor::BLACK }; | ||||||
| 	Cell*		m_buffer		{ nullptr }; | 	Cell*					m_buffer		{ nullptr }; | ||||||
| 	AnsiState	m_ansi_state; | 	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
 | // (c) 2009, 2010 Lutz Sammer, License: AGPLv3
 | ||||||
| 
 | 
 | ||||||
| 	/// bitmap font structure
 | 	/// bitmap font structure
 | ||||||
|  |  | ||||||
|  | @ -2,6 +2,11 @@ | ||||||
| 
 | 
 | ||||||
| #include <stdint.h> | #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 | struct framebuffer_info_t | ||||||
| { | { | ||||||
| 	uint64_t addr; | 	uint64_t addr; | ||||||
|  |  | ||||||
|  | @ -22,30 +22,10 @@ namespace Kernel | ||||||
| 
 | 
 | ||||||
| 	static auto s_default_prompt = "\\[\e[32m\\]user\\[\e[m\\]# "_sv; | 	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) | 	Shell::Shell(TTY* tty) | ||||||
| 		: m_tty(tty) | 		: m_tty(tty) | ||||||
| 	{ | 	{ | ||||||
| 		Input::register_key_event_callback({ &Shell::KeyEventCallback, this }); | 		Input::register_key_event_callback({ &Shell::KeyEventCallback, this }); | ||||||
| 		Input::register_mouse_move_event_callback({ &Shell::MouseMoveEventCallback, this }); |  | ||||||
| 		SetPrompt(s_default_prompt); | 		SetPrompt(s_default_prompt); | ||||||
| 		MUST(m_buffer.PushBack(""_sv)); | 		MUST(m_buffer.PushBack(""_sv)); | ||||||
| 	} | 	} | ||||||
|  | @ -415,18 +395,6 @@ argument_done: | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		TTY_PRINT("\e[{}G", m_prompt_length + m_cursor_pos.col + 1); | 		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 <BAN/Errors.h> | ||||||
| #include <kernel/Serial.h> | #include <kernel/Serial.h> | ||||||
| #include <kernel/TTY.h> | #include <kernel/TTY.h> | ||||||
| #include <kernel/VESA.h> |  | ||||||
| 
 | 
 | ||||||
| #include <string.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; | static TTY* s_tty = nullptr; | ||||||
| 
 | 
 | ||||||
| TTY::TTY() | TTY::TTY(TerminalDriver* driver) | ||||||
|  | 	: m_terminal_driver(driver) | ||||||
| { | { | ||||||
| 	m_width = VESA::GetTerminalWidth(); | 	m_width = m_terminal_driver->Width(); | ||||||
| 	m_height = VESA::GetTerminalHeight(); | 	m_height = m_terminal_driver->Height(); | ||||||
| 	 | 	 | ||||||
| 	m_buffer = new Cell[m_width * m_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++) | 	for (uint32_t i = 0; i < m_width * m_height; i++) | ||||||
| 		m_buffer[i] = { .foreground = m_foreground, .background = m_background, .character = ' ' }; | 		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) | 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; | 	static uint32_t last_y = -1; | ||||||
| 	if (last_x != uint32_t(-1) && last_y != uint32_t(-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
 | 		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_x = m_column = x; | ||||||
| 	last_y = m_row = y; | 	last_y = m_row = y; | ||||||
| } | } | ||||||
|  | @ -111,27 +111,27 @@ void TTY::HandleAnsiSGR() | ||||||
| 	{ | 	{ | ||||||
| 		case -1: | 		case -1: | ||||||
| 		case 0: | 		case 0: | ||||||
| 			m_foreground = VESA::Color::BRIGHT_WHITE; | 			m_foreground = TerminalColor::BRIGHT_WHITE; | ||||||
| 			m_background = VESA::Color::BLACK; | 			m_background = TerminalColor::BLACK; | ||||||
| 			break; | 			break; | ||||||
| 
 | 
 | ||||||
| 		case 30: m_foreground = VESA::Color::BRIGHT_BLACK;		break; | 		case 30: m_foreground = TerminalColor::BRIGHT_BLACK;	break; | ||||||
| 		case 31: m_foreground = VESA::Color::BRIGHT_RED;		break; | 		case 31: m_foreground = TerminalColor::BRIGHT_RED;		break; | ||||||
| 		case 32: m_foreground = VESA::Color::BRIGHT_GREEN;		break; | 		case 32: m_foreground = TerminalColor::BRIGHT_GREEN;	break; | ||||||
| 		case 33: m_foreground = VESA::Color::BRIGHT_YELLOW;		break; | 		case 33: m_foreground = TerminalColor::BRIGHT_YELLOW;	break; | ||||||
| 		case 34: m_foreground = VESA::Color::BRIGHT_BLUE;		break; | 		case 34: m_foreground = TerminalColor::BRIGHT_BLUE;		break; | ||||||
| 		case 35: m_foreground = VESA::Color::BRIGHT_MAGENTA;	break; | 		case 35: m_foreground = TerminalColor::BRIGHT_MAGENTA;	break; | ||||||
| 		case 36: m_foreground = VESA::Color::BRIGHT_CYAN;		break; | 		case 36: m_foreground = TerminalColor::BRIGHT_CYAN;		break; | ||||||
| 		case 37: m_foreground = VESA::Color::BRIGHT_WHITE;		break; | 		case 37: m_foreground = TerminalColor::BRIGHT_WHITE;	break; | ||||||
| 
 | 
 | ||||||
| 		case 40: m_background = VESA::Color::BRIGHT_BLACK;		break; | 		case 40: m_background = TerminalColor::BRIGHT_BLACK;	break; | ||||||
| 		case 41: m_background = VESA::Color::BRIGHT_RED;		break; | 		case 41: m_background = TerminalColor::BRIGHT_RED;		break; | ||||||
| 		case 42: m_background = VESA::Color::BRIGHT_GREEN;		break; | 		case 42: m_background = TerminalColor::BRIGHT_GREEN;	break; | ||||||
| 		case 43: m_background = VESA::Color::BRIGHT_YELLOW;		break; | 		case 43: m_background = TerminalColor::BRIGHT_YELLOW;	break; | ||||||
| 		case 44: m_background = VESA::Color::BRIGHT_BLUE;		break; | 		case 44: m_background = TerminalColor::BRIGHT_BLUE;		break; | ||||||
| 		case 45: m_background = VESA::Color::BRIGHT_MAGENTA;	break; | 		case 45: m_background = TerminalColor::BRIGHT_MAGENTA;	break; | ||||||
| 		case 46: m_background = VESA::Color::BRIGHT_CYAN;		break; | 		case 46: m_background = TerminalColor::BRIGHT_CYAN;		break; | ||||||
| 		case 47: m_background = VESA::Color::BRIGHT_WHITE;		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); | 	ASSERT(x < m_width && y < m_height); | ||||||
| 	const auto& cell = m_buffer[y * m_width + x]; | 	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) | 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.character = ch; | ||||||
| 	cell.foreground = m_foreground; | 	cell.foreground = m_foreground; | ||||||
| 	cell.background = m_background; | 	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) | 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/Serial.h> | ||||||
| #include <kernel/Shell.h> | #include <kernel/Shell.h> | ||||||
| #include <kernel/TTY.h> | #include <kernel/TTY.h> | ||||||
| #include <kernel/VESA.h> | #include <kernel/VesaTerminalDriver.h> | ||||||
| 
 | 
 | ||||||
| #define DISABLE_INTERRUPTS() asm volatile("cli") | #define DISABLE_INTERRUPTS() asm volatile("cli") | ||||||
| #define ENABLE_INTERRUPTS() asm volatile("sti") | #define ENABLE_INTERRUPTS() asm volatile("sti") | ||||||
|  | @ -76,10 +76,10 @@ extern "C" void kernel_main() | ||||||
| 	MMU::Intialize(); | 	MMU::Intialize(); | ||||||
| 	dprintln("MMU initialized"); | 	dprintln("MMU initialized"); | ||||||
| 
 | 
 | ||||||
| 	if (!VESA::Initialize()) | 	TerminalDriver* terminal_driver = VesaTerminalDriver::Create(); | ||||||
| 		return; | 	ASSERT(terminal_driver); | ||||||
| 	dprintln("VESA initialized"); | 	dprintln("VESA initialized"); | ||||||
| 	TTY* tty1 = new TTY; | 	TTY* tty1 = new TTY(terminal_driver); | ||||||
| 	 | 	 | ||||||
| 	APIC::Initialize(cmdline.force_pic); | 	APIC::Initialize(cmdline.force_pic); | ||||||
| 	dprintln("APIC initialized"); | 	dprintln("APIC initialized"); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue