diff --git a/kernel/arch/i386/TTY.cpp b/kernel/arch/i386/TTY.cpp index a3d5cd810..949b07e1d 100644 --- a/kernel/arch/i386/TTY.cpp +++ b/kernel/arch/i386/TTY.cpp @@ -36,12 +36,8 @@ TTY::TTY() void TTY::Clear() { - for (uint32_t i = 0; i < m_width * m_height; i++) - { - m_buffer[i].foreground = m_foreground; - m_buffer[i].background = m_background; - m_buffer[i].character = ' '; - } + for (size_t i = 0; i < m_width * m_height; i++) + m_buffer[i] = { .foreground = m_foreground, .background = m_background, .character = ' ' }; 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) { uint16_t cp = handle_unicode(ch); @@ -285,7 +290,7 @@ void TTY::PutChar(char ch) m_ansi_state.mode = '\1'; break; default: - VESA::PutEntryAt(cp, m_column, m_row, m_foreground, m_background); + PutCharAt(cp, m_column, m_row); m_column++; break; } @@ -298,9 +303,18 @@ void TTY::PutChar(char ch) 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++) - 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_row--; @@ -332,6 +346,31 @@ void TTY::PutCharCurrent(char ch) } 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); + } } } diff --git a/kernel/arch/i386/VESA.cpp b/kernel/arch/i386/VESA.cpp index 079280830..27d8e1114 100644 --- a/kernel/arch/i386/VESA.cpp +++ b/kernel/arch/i386/VESA.cpp @@ -18,7 +18,7 @@ extern const struct bitmap_font font; namespace VESA { - static void* s_buffer = nullptr; + static void* s_addr = nullptr; static uint8_t s_bpp = 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 GraphicsClear(Color color); - static void GraphicsScroll(); static void TextPutCharAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg); static void TextClear(Color color); - static void TextScroll(); void PutEntryAt(uint16_t ch, uint32_t x, uint32_t y, Color fg, Color bg) { @@ -54,14 +52,6 @@ namespace VESA 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() { if (s_mode == MULTIBOOT_FRAMEBUFFER_TYPE_GRAPHICS) @@ -138,33 +128,14 @@ namespace VESA static void GraphicsSetPixel(uint32_t offset, uint32_t color) { uint32_t* address = (uint32_t*)((uint32_t)s_addr + offset); - - if (s_buffer) + switch (s_bpp) { - uint32_t* buffer = (uint32_t*)((uint32_t)s_buffer + offset); - switch (s_bpp) - { - case 24: - *buffer = (*buffer & 0xFF000000) | (color & 0x00FFFFFF); - *address = *buffer; - 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; - } + 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 x = 0; x < s_width; x++) ((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; } @@ -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) { return (((uint8_t)bg & 0x0F) << 4) | ((uint8_t)fg & 0x0F); @@ -303,17 +224,4 @@ namespace VESA 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]; - } - } - } - } \ No newline at end of file diff --git a/kernel/include/kernel/TTY.h b/kernel/include/kernel/TTY.h index 413b40d7d..81c2cac98 100644 --- a/kernel/include/kernel/TTY.h +++ b/kernel/include/kernel/TTY.h @@ -19,13 +19,19 @@ private: void ResetAnsiEscape(); void HandleAnsiSGR(); 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: struct Cell { VESA::Color foreground = VESA::Color::BRIGHT_WHITE; VESA::Color background = VESA::Color::BLACK; - uint8_t character = ' '; + uint16_t character = ' '; }; struct AnsiState @@ -39,7 +45,7 @@ private: 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_foreground { VESA::Color::BRIGHT_WHITE }; VESA::Color m_background { VESA::Color::BLACK }; Cell* m_buffer { nullptr }; AnsiState m_ansi_state; diff --git a/kernel/include/kernel/VESA.h b/kernel/include/kernel/VESA.h index 11325d6a9..80acae98a 100644 --- a/kernel/include/kernel/VESA.h +++ b/kernel/include/kernel/VESA.h @@ -28,7 +28,6 @@ namespace VESA bool Initialize(); void PutEntryAt(uint16_t, uint32_t, uint32_t, Color, Color); void Clear(Color); - void Scroll(); uint32_t GetTerminalWidth(); uint32_t GetTerminalHeight();