Kernel: TTY now handles keeping terminal buffer

VESA Driver cannot scroll anymore, this is handled by tty
This commit is contained in:
Bananymous 2022-12-27 17:06:33 +02:00
parent f7eb85babd
commit 2535eb1c4c
4 changed files with 64 additions and 112 deletions

View File

@ -36,12 +36,8 @@ TTY::TTY()
void TTY::Clear() void TTY::Clear()
{ {
for (uint32_t i = 0; i < m_width * m_height; i++) for (size_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;
m_buffer[i].background = m_background;
m_buffer[i].character = ' ';
}
VESA::Clear(m_background); VESA::Clear(m_background);
} }
@ -248,6 +244,15 @@ void TTY::HandleAnsiEscape(uint16_t ch)
} }
} }
void TTY::PutCharAt(uint16_t ch, size_t x, size_t y)
{
auto& cell = m_buffer[y * m_width + x];
cell.character = ch;
cell.foreground = m_foreground;
cell.background = m_background;
VESA::PutEntryAt(ch, x, y, m_foreground, m_background);
}
void TTY::PutChar(char ch) void TTY::PutChar(char ch)
{ {
uint16_t cp = handle_unicode(ch); uint16_t cp = handle_unicode(ch);
@ -285,7 +290,7 @@ void TTY::PutChar(char ch)
m_ansi_state.mode = '\1'; m_ansi_state.mode = '\1';
break; break;
default: default:
VESA::PutEntryAt(cp, m_column, m_row, m_foreground, m_background); PutCharAt(cp, m_column, m_row);
m_column++; m_column++;
break; break;
} }
@ -298,9 +303,18 @@ void TTY::PutChar(char ch)
while (m_row >= m_height) while (m_row >= m_height)
{ {
VESA::Scroll(); // Shift buffer one line up
for (size_t y = 1; y < m_height; y++)
for (size_t x = 0; x < m_width; x++)
m_buffer[(y - 1) * m_width + x] = m_buffer[y * m_width + x];
// Clear last line in buffer
for (size_t x = 0; x < m_width; x++) for (size_t x = 0; x < m_width; x++)
VESA::PutEntryAt(' ', x, m_height - 1, m_foreground, m_background); m_buffer[(m_height - 1) * m_width + x] = { .foreground = m_foreground, .background = m_background, .character = ' ' };
// Render the whole buffer to the screen
for (size_t y = 0; y < m_height; y++)
for (size_t x = 0; x < m_width; x++)
RenderFromBuffer(x, y);
m_column = 0; m_column = 0;
m_row--; m_row--;
@ -332,6 +346,31 @@ void TTY::PutCharCurrent(char ch)
} }
else else
{ {
static size_t x = 0;
static size_t y = 0;
switch (ch)
{
case '\n':
x = 0;
y++;
break;
default:
VESA::PutEntryAt(ch, x, y, VESA::Color::BRIGHT_WHITE, VESA::Color::BLACK);
break;
}
if (++x == VESA::GetTerminalWidth())
{
x = 0;
y++;
}
if (y == VESA::GetTerminalHeight())
{
x = 0;
y = 0;
VESA::Clear(VESA::Color::BLACK);
}
} }
} }

View File

@ -18,7 +18,7 @@ extern const struct bitmap_font font;
namespace VESA namespace VESA
{ {
static void* s_buffer = nullptr;
static void* s_addr = nullptr; static void* s_addr = nullptr;
static uint8_t s_bpp = 0; static uint8_t s_bpp = 0;
static uint32_t s_pitch = 0; static uint32_t s_pitch = 0;
@ -28,11 +28,9 @@ namespace VESA
static void GraphicsPutCharAt(uint16_t ch, 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 GraphicsClear(Color color);
static void GraphicsScroll();
static void TextPutCharAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg); static void TextPutCharAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg);
static void TextClear(Color color); static void TextClear(Color color);
static void TextScroll();
void PutEntryAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg) void PutEntryAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg)
{ {
@ -54,14 +52,6 @@ namespace VESA
return TextClear(color); return TextClear(color);
} }
void Scroll()
{
if (s_mode == MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS)
return GraphicsScroll();
if (s_mode == MULTIBOOT_FRAMEBUFFER_TYPE_TEXT)
return TextScroll();
}
uint32_t GetTerminalWidth() uint32_t GetTerminalWidth()
{ {
if (s_mode == MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS) if (s_mode == MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS)
@ -138,33 +128,14 @@ namespace VESA
static void GraphicsSetPixel(uint32_t offset, uint32_t color) static void GraphicsSetPixel(uint32_t offset, uint32_t color)
{ {
uint32_t* address = (uint32_t*)((uint32_t)s_addr + offset); uint32_t* address = (uint32_t*)((uint32_t)s_addr + offset);
switch (s_bpp)
if (s_buffer)
{ {
uint32_t* buffer = (uint32_t*)((uint32_t)s_buffer + offset); case 24:
switch (s_bpp) *address = (*address & 0xFF000000) | (color & 0x00FFFFFF);
{ break;
case 24: case 32:
*buffer = (*buffer & 0xFF000000) | (color & 0x00FFFFFF); *address = color;
*address = *buffer; break;
break;
case 32:
*buffer = color;
*address = color;
break;
}
}
else
{
switch (s_bpp)
{
case 24:
*address = (*address & 0xFF000000) | (color & 0x00FFFFFF);
break;
case 32:
*address = color;
break;
}
} }
} }
@ -214,10 +185,6 @@ namespace VESA
for (uint32_t y = 0; y < s_height; y++) for (uint32_t y = 0; y < s_height; y++)
for (uint32_t x = 0; x < s_width; x++) for (uint32_t x = 0; x < s_width; x++)
((uint32_t*)s_addr)[y * bytes_per_row + x] = u32_color; ((uint32_t*)s_addr)[y * bytes_per_row + x] = u32_color;
if (s_buffer)
for (uint32_t y = 0; y < s_height; y++)
for (uint32_t x = 0; x < s_width; x++)
((uint32_t*)s_buffer)[y * bytes_per_row + x] = u32_color;
return; return;
} }
@ -234,52 +201,6 @@ namespace VESA
} }
} }
static void GraphicsScroll()
{
if (s_bpp == 32)
{
uint32_t bytes_per_row = s_pitch / 4;
for (uint32_t y = 0; y < s_height - font.Height; y++)
{
for (uint32_t x = 0; x < s_width; x++)
{
if (s_buffer)
{
((uint32_t*)s_buffer)[y * bytes_per_row + x] = ((uint32_t*)s_buffer)[(y + font.Height) * bytes_per_row + x];
((uint32_t*)s_addr )[y * bytes_per_row + x] = ((uint32_t*)s_buffer)[(y + font.Height) * bytes_per_row + x];
}
else
{
((uint32_t*)s_addr )[y * bytes_per_row + x] = ((uint32_t*)s_addr )[(y + font.Height) * bytes_per_row + x];
}
}
}
return;
}
uint32_t row_offset_out = 0;
uint32_t row_offset_in = font.Height * s_pitch;
for (uint32_t y = 0; y < s_height - 1; y++)
{
if (s_buffer)
{
memcpy((void*)((uint32_t)s_buffer + row_offset_out), (void*)((uint32_t)s_buffer + row_offset_in), s_width * s_bpp);
memcpy((void*)((uint32_t)s_addr + row_offset_out), (void*)((uint32_t)s_buffer + row_offset_in), s_width * s_bpp);
}
else
{
memcpy((void*)((uint32_t)s_addr + row_offset_out), (void*)((uint32_t)s_addr + row_offset_in), s_width * s_bpp);
}
row_offset_out += s_pitch;
row_offset_in += s_pitch;
}
}
static inline uint8_t TextColor(Color fg, Color bg) static inline uint8_t TextColor(Color fg, Color bg)
{ {
return (((uint8_t)bg & 0x0F) << 4) | ((uint8_t)fg & 0x0F); return (((uint8_t)bg & 0x0F) << 4) | ((uint8_t)fg & 0x0F);
@ -303,17 +224,4 @@ namespace VESA
TextPutCharAt(' ', x, y, Color::BRIGHT_WHITE, color); TextPutCharAt(' ', x, y, Color::BRIGHT_WHITE, color);
} }
static void TextScroll()
{
for (uint32_t y = 1; y < s_height; y++)
{
for (uint32_t x = 0; x < s_width; x++)
{
uint32_t index1 = (y - 0) * s_width + x;
uint32_t index2 = (y - 1) * s_width + x;
((uint16_t*)s_addr)[index2] = ((uint16_t*)s_addr)[index1];
}
}
}
} }

View File

@ -19,13 +19,19 @@ private:
void ResetAnsiEscape(); void ResetAnsiEscape();
void HandleAnsiSGR(); void HandleAnsiSGR();
void HandleAnsiEscape(uint16_t ch); void HandleAnsiEscape(uint16_t ch);
void PutCharAt(uint16_t ch, size_t x, size_t y);
inline void RenderFromBuffer(size_t x, size_t y)
{
const auto& cell = m_buffer[y * m_width + x];
VESA::PutEntryAt(cell.character, x, y, cell.foreground, cell.background);
}
private: private:
struct Cell struct Cell
{ {
VESA::Color foreground = VESA::Color::BRIGHT_WHITE; VESA::Color foreground = VESA::Color::BRIGHT_WHITE;
VESA::Color background = VESA::Color::BLACK; VESA::Color background = VESA::Color::BLACK;
uint8_t character = ' '; uint16_t character = ' ';
}; };
struct AnsiState struct AnsiState
@ -39,7 +45,7 @@ private:
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}; VESA::Color m_foreground { VESA::Color::BRIGHT_WHITE };
VESA::Color m_background { VESA::Color::BLACK }; VESA::Color m_background { VESA::Color::BLACK };
Cell* m_buffer { nullptr }; Cell* m_buffer { nullptr };
AnsiState m_ansi_state; AnsiState m_ansi_state;

View File

@ -28,7 +28,6 @@ namespace VESA
bool Initialize(); bool Initialize();
void PutEntryAt(uint16_t, uint32_t, uint32_t, Color, Color); void PutEntryAt(uint16_t, uint32_t, uint32_t, Color, Color);
void Clear(Color); void Clear(Color);
void Scroll();
uint32_t GetTerminalWidth(); uint32_t GetTerminalWidth();
uint32_t GetTerminalHeight(); uint32_t GetTerminalHeight();