Enable and test other VGA resolutions.

This commit is contained in:
Enrico Fraccaroli (Galfurian)
2022-07-21 15:35:37 -04:00
parent 259697608f
commit a33d35f47f
8 changed files with 1835 additions and 975 deletions
+33 -1
View File
@@ -11,6 +11,9 @@ void vga_initialize();
/// @brief Finalizes the VGA. /// @brief Finalizes the VGA.
void vga_finalize(); void vga_finalize();
/// @brief Updates the graphic elements.
void vga_update();
/// @brief Checks if the VGA is enabled. /// @brief Checks if the VGA is enabled.
/// @return 1 if enabled, 0 otherwise. /// @return 1 if enabled, 0 otherwise.
int vga_is_enabled(); int vga_is_enabled();
@@ -49,7 +52,7 @@ void vga_draw_char(int x, int y, unsigned char c, unsigned char color);
/// @param y y-axis position. /// @param y y-axis position.
/// @param str string to draw. /// @param str string to draw.
/// @param color color of the character. /// @param color color of the character.
void vga_draw_string(int x, int y, char *str, unsigned char color); void vga_draw_string(int x, int y, const char *str, unsigned char color);
/// @brief Draws a line from point 1 to point 2. /// @brief Draws a line from point 1 to point 2.
/// @param x0 point 1 x-axis position. /// @param x0 point 1 x-axis position.
@@ -84,4 +87,33 @@ void vga_draw_circle(int xc, int yc, int r, unsigned char color);
/// @param color used to draw the triangle. /// @param color used to draw the triangle.
void vga_draw_triangle(int x1, int y1, int x2, int y2, int x3, int y3, unsigned char color); void vga_draw_triangle(int x1, int y1, int x2, int y2, int x3, int y3, unsigned char color);
/// @brief Print the given character on the screen.
/// @param c The character to print.
void vga_putc(int c);
/// @brief Prints the given string on the screen.
/// @param str The string to print.
void vga_puts(const char *str);
/// @brief Move the cursor at the position x, y on the screen.
/// @param x The x coordinate.
/// @param y The y coordinate.
void vga_move_cursor(unsigned int x, unsigned int y);
/// @brief Returns cursor's position on the screen.
/// @param x The output x coordinate.
/// @param y The output y coordinate.
void vga_get_cursor_position(unsigned int * x, unsigned int * y);
/// @brief Returns screen size.
/// @param width The screen width.
/// @param height The screen height.
void vga_get_screen_size(unsigned int * width, unsigned int * height);
/// @brief Move to the following line (the effect of \n character).
void vga_new_line();
/// @brief Change the color.
void vga_set_color(unsigned int color);
void vga_run_test(); void vga_run_test();
+1527 -904
View File
File diff suppressed because it is too large Load Diff
+16 -16
View File
@@ -14,22 +14,22 @@ typedef struct {
/// 16 color palette. /// 16 color palette.
palette_entry_t ansi_16_palette[17] = { palette_entry_t ansi_16_palette[17] = {
{ 0x00, 0x00, 0x00 }, // Black { 0x00, 0x00, 0x00 }, // 0 Black
{ 0xAA, 0x00, 0x00 }, // Red { 0xAA, 0x00, 0x00 }, // 1 Red
{ 0x00, 0xAA, 0x00 }, // Green { 0x00, 0xAA, 0x00 }, // 2 Green
{ 0xAA, 0xAA, 0x00 }, // Yellow { 0xAA, 0xAA, 0x00 }, // 3 Yellow
{ 0x00, 0x00, 0xAA }, // Blue { 0x00, 0x00, 0xAA }, // 4 Blue
{ 0xAA, 0x00, 0xAA }, // Magenta { 0xAA, 0x00, 0xAA }, // 5 Magenta
{ 0x00, 0xAA, 0xAA }, // Cyan { 0x00, 0xAA, 0xAA }, // 6 Cyan
{ 0xAA, 0xAA, 0xAA }, // White { 0xAA, 0xAA, 0xAA }, // 7 White
{ 0x55, 0x55, 0x55 }, // Black { 0x55, 0x55, 0x55 }, // 8 Black
{ 0xFF, 0x55, 0x55 }, // Red { 0xFF, 0x55, 0x55 }, // 9 Red
{ 0x55, 0xFF, 0x55 }, // Green { 0x55, 0xFF, 0x55 }, // 10 Green
{ 0xFF, 0xFF, 0x55 }, // Yellow { 0xFF, 0xFF, 0x55 }, // 11 Yellow
{ 0x55, 0x55, 0xFF }, // Blue { 0x55, 0x55, 0xFF }, // 12 Blue
{ 0xFF, 0x55, 0xFF }, // Magenta { 0xFF, 0x55, 0xFF }, // 13 Magenta
{ 0x55, 0xFF, 0xFF }, // Cyan { 0x55, 0xFF, 0xFF }, // 14 Cyan
{ 0xFF, 0xFF, 0xFF }, // White { 0xFF, 0xFF, 0xFF }, // 15 White
}; };
/// 256 color palette. /// 256 color palette.
+13 -8
View File
@@ -66,6 +66,9 @@
/// @brief Initialize the video. /// @brief Initialize the video.
void video_init(); void video_init();
/// @brief Updates the video.
void video_update();
/// @brief Print the given character on the screen. /// @brief Print the given character on the screen.
/// @param c The character to print. /// @param c The character to print.
void video_putc(int c); void video_putc(int c);
@@ -82,6 +85,16 @@ void video_set_cursor_auto();
/// @param y The y coordinate. /// @param y The y coordinate.
void video_move_cursor(unsigned int x, unsigned int y); void video_move_cursor(unsigned int x, unsigned int y);
/// @brief Returns cursor's position on the screen.
/// @param x The output x coordinate.
/// @param y The output y coordinate.
void video_get_cursor_position(unsigned int * x, unsigned int * y);
/// @brief Returns screen size.
/// @param width The screen width.
/// @param height The screen height.
void video_get_screen_size(unsigned int * width, unsigned int * height);
/// @brief Clears the screen. /// @brief Clears the screen.
void video_clear(); void video_clear();
@@ -91,14 +104,6 @@ void video_new_line();
/// @brief Move to the up line (the effect of \n character). /// @brief Move to the up line (the effect of \n character).
void video_cartridge_return(); void video_cartridge_return();
/// @brief Get the current column number.
/// @return The column number.
uint32_t video_get_x();
/// @brief Get the current row number.
/// @return The row number.
uint32_t video_get_y();
/// @brief The whole screen is shifted up by one line. Used when the cursor /// @brief The whole screen is shifted up by one line. Used when the cursor
/// reaches the last position of the screen. /// reaches the last position of the screen.
void video_shift_one_line_up(); void video_shift_one_line_up();
+4 -2
View File
@@ -16,9 +16,10 @@
#include "process/scheduler.h" #include "process/scheduler.h"
#include "hardware/pic8259.h" #include "hardware/pic8259.h"
#include "io/port_io.h" #include "io/port_io.h"
#include "io/debug.h"
#include "io/video.h"
#include "stdint.h" #include "stdint.h"
#include "mem/kheap.h" #include "mem/kheap.h"
#include "io/debug.h"
#include "process/wait.h" #include "process/wait.h"
#include "drivers/rtc.h" #include "drivers/rtc.h"
#include "descriptor_tables/isr.h" #include "descriptor_tables/isr.h"
@@ -26,7 +27,6 @@
#include "system/signal.h" #include "system/signal.h"
#include "assert.h" #include "assert.h"
#include "sys/errno.h" #include "sys/errno.h"
#include "io/vga/vga.h"
/// @defgroup picregs Programmable Interval Timer Registers /// @defgroup picregs Programmable Interval Timer Registers
/// @brief The list of registers used to set the PIT. /// @brief The list of registers used to set the PIT.
@@ -108,6 +108,8 @@ void timer_handler(pt_regs *reg)
run_timer_softirq(); run_timer_softirq();
// Perform the schedule. // Perform the schedule.
scheduler_run(reg); scheduler_run(reg);
// Update graphics.
video_update();
// Restore fpu state. // Restore fpu state.
unswitch_fpu(); unswitch_fpu();
// The ack is sent to PIC only when all handlers terminated! // The ack is sent to PIC only when all handlers terminated!
+133 -24
View File
@@ -19,6 +19,7 @@
#include "hardware/timer.h" #include "hardware/timer.h"
#include "io/port_io.h" #include "io/port_io.h"
#include "io/debug.h" #include "io/debug.h"
#include "io/video.h"
#include "stdbool.h" #include "stdbool.h"
#include "string.h" #include "string.h"
#include "math.h" #include "math.h"
@@ -73,9 +74,9 @@ typedef struct {
/// VGA font details. /// VGA font details.
typedef struct { typedef struct {
unsigned char *font; ///< Pointer to the array holding the shape of each character. const unsigned char *font; ///< Pointer to the array holding the shape of each character.
unsigned width; ///< Width of the font. unsigned width; ///< Width of the font.
unsigned height; ///< Height of the font. unsigned height; ///< Height of the font.
} vga_font_t; } vga_font_t;
/// VGA driver details. /// VGA driver details.
@@ -539,16 +540,6 @@ unsigned int vga_read_pixel(int x, int y)
return driver->ops->read_pixel(x, y); return driver->ops->read_pixel(x, y);
} }
void vga_clear_screen()
{
unsigned original_plane = __get_plane();
for (unsigned plane = 0; plane < 4; ++plane) {
__set_plane(plane);
memset(driver->address, 0, 64 * 1024);
}
__set_plane(original_plane);
}
void vga_draw_char(int x, int y, unsigned char c, unsigned char color) void vga_draw_char(int x, int y, unsigned char c, unsigned char color)
{ {
static unsigned mask[] = { static unsigned mask[] = {
@@ -562,7 +553,7 @@ void vga_draw_char(int x, int y, unsigned char c, unsigned char color)
1u << 7u, // 128 1u << 7u, // 128
1u << 8u, // 256 1u << 8u, // 256
}; };
unsigned char *glyph = driver->font->font + c * driver->font->height; const unsigned char *glyph = driver->font->font + c * driver->font->height;
for (unsigned cy = 0; cy < driver->font->height; ++cy) { for (unsigned cy = 0; cy < driver->font->height; ++cy) {
for (unsigned cx = 0; cx < driver->font->width; ++cx) { for (unsigned cx = 0; cx < driver->font->width; ++cx) {
vga_draw_pixel(x + (driver->font->width - cx), y + cy, glyph[cy] & mask[cx] ? color : 0x00u); vga_draw_pixel(x + (driver->font->width - cx), y + cy, glyph[cy] & mask[cx] ? color : 0x00u);
@@ -570,7 +561,7 @@ void vga_draw_char(int x, int y, unsigned char c, unsigned char color)
} }
} }
void vga_draw_string(int x, int y, char *str, unsigned char color) void vga_draw_string(int x, int y, const char *str, unsigned char color)
{ {
char i = 0; char i = 0;
while (*str != '\0') { while (*str != '\0') {
@@ -689,16 +680,28 @@ static vga_ops_t ops_320_200_256 = {
.fill_rect = NULL, .fill_rect = NULL,
}; };
static vga_font_t font_4x6 = {
.font = arr_4x6_font,
.width = 4,
.height = 6,
};
static vga_font_t font_5x6 = {
.font = arr_5x6_font,
.width = 5,
.height = 6,
};
static vga_font_t font_8x8 = { static vga_font_t font_8x8 = {
.font = arr_8x8_font, .font = arr_8x8_font,
.width = 8, .width = 8,
.height = 8, .height = 8,
}; };
static vga_font_t font_8x8_basic = { static vga_font_t font_8x14 = {
.font = arr_8x8_basic_font, .font = arr_8x14_font,
.width = 8, .width = 8,
.height = 8, .height = 14,
}; };
static vga_font_t font_8x16 = { static vga_font_t font_8x16 = {
@@ -739,34 +742,39 @@ void vga_initialize()
__save_palette(stored_palette, 256); __save_palette(stored_palette, 256);
// Initialize the desired mode. // Initialize the desired mode.
#if defined(VGA_MODE_320_200_256)
#if defined(VGA_MODE_320_200_256) // 40x25
// Write the registers. // Write the registers.
__set_mode(&_mode_320_200_256); __set_mode(&_mode_320_200_256);
// Initialize the mode. // Initialize the mode.
driver = &driver_320_200_256; driver = &driver_320_200_256;
// Load the color palette. // Load the color palette.
__load_palette(ansi_256_palette, 256); __load_palette(ansi_256_palette, 256);
#elif defined(VGA_MODE_640_480_16) // Set the font.
driver->font = &font_5x6;
#elif defined(VGA_MODE_640_480_16) // 80x60
// Write the registers. // Write the registers.
__set_mode(&_mode_640_480_16); __set_mode(&_mode_640_480_16);
// Initialize the mode. // Initialize the mode.
driver = &driver_640_480_16; driver = &driver_640_480_16;
// Load the color palette. // Load the color palette.
__load_palette(ansi_16_palette, 16); __load_palette(ansi_16_palette, 16);
#elif defined(VGA_MODE_720_480_16) // Set the font.
driver->font = &font_8x14;
#elif defined(VGA_MODE_720_480_16) // 90x60
// Write the registers. // Write the registers.
__set_mode(&_mode_720_480_16); __set_mode(&_mode_720_480_16);
// Initialize the mode. // Initialize the mode.
driver = &driver_720_480_16; driver = &driver_720_480_16;
// Load the color palette. // Load the color palette.
__load_palette(ansi_16_palette, 16); __load_palette(ansi_16_palette, 16);
#else // VGA_TEXT_MODE // Set the font.
driver->font = &font_8x16;
#else // VGA_TEXT_MODE
return; return;
#endif #endif
// Set the address. // Set the address.
driver->address = __get_seg(); driver->address = __get_seg();
// Set the font.
driver->font = &font_8x8;
// Save the content of the memory. // Save the content of the memory.
memcpy(vidmem, driver->address, 0x4000); memcpy(vidmem, driver->address, 0x4000);
// Clears the screen. // Clears the screen.
@@ -782,3 +790,104 @@ void vga_finalize()
__load_palette(stored_palette, 256); __load_palette(stored_palette, 256);
vga_enable = false; vga_enable = false;
} }
static int _x = 0;
static int _y = 0;
static unsigned char _color = 7;
static int _cursor_state = 0;
inline static void __vga_clear_cursor()
{
for (unsigned cy = 0; cy < driver->font->height; ++cy)
for (unsigned cx = 0; cx < driver->font->width; ++cx)
vga_draw_pixel(_x + cx, _y + cy, 0);
}
inline static void __vga_draw_cursor()
{
unsigned char color = (_cursor_state = (_cursor_state == 0)) * _color;
for (unsigned cy = 0; cy < driver->font->height; ++cy)
for (unsigned cx = 0; cx < driver->font->width; ++cx)
vga_draw_pixel(_x + cx, _y + cy, color);
}
void vga_putc(int c)
{
if (_cursor_state)
__vga_clear_cursor();
// If the character is '\n' go the new line.
if (c == '\n') {
vga_new_line();
} else if ((c >= 0x20) && (c <= 0x7E)) {
vga_draw_char(_x, _y, c, _color);
if ((_x += driver->font->width) >= driver->width)
vga_new_line();
} else {
return;
}
}
void vga_puts(const char *str)
{
while ((*str) != 0) {
vga_putc((*str++));
}
}
void vga_move_cursor(unsigned int x, unsigned int y)
{
_x = x * driver->font->width;
_y = y * driver->font->height;
__vga_draw_cursor();
}
void vga_get_cursor_position(unsigned int *x, unsigned int *y)
{
if (x)
*x = _x / driver->font->width;
if (y)
*y = _y / driver->font->height;
}
void vga_get_screen_size(unsigned int *width, unsigned int *height)
{
if (width)
*width = driver->width / driver->font->width;
if (height)
*height = driver->height / driver->font->height;
}
void vga_clear_screen()
{
unsigned original_plane = __get_plane();
for (unsigned plane = 0; plane < 4; ++plane) {
__set_plane(plane);
memset(driver->address, 0, 64 * 1024);
}
__set_plane(original_plane);
_x = 0, _y = 0;
}
void vga_new_line()
{
// Just the 5x6 font needs some space.
const unsigned int vertical_space = (driver->font == &font_5x6);
// Go back at the beginning of the line.
_x = 0;
if ((_y += driver->font->height + vertical_space) >= (driver->height - driver->font->height)) {
_y = 0;
vga_clear_screen();
}
}
void vga_update()
{
if ((timer_get_ticks() % (TICKS_PER_SECOND / 2)) == 0) {
__vga_draw_cursor();
}
}
void vga_set_color(unsigned int color)
{
_color = color;
}
+97 -14
View File
@@ -5,6 +5,7 @@
#include "io/port_io.h" #include "io/port_io.h"
#include "io/video.h" #include "io/video.h"
#include "io/vga/vga.h"
#include "stdbool.h" #include "stdbool.h"
#include "ctype.h" #include "ctype.h"
#include "string.h" #include "string.h"
@@ -68,7 +69,7 @@ ansi_color_map[] = {
/// Pointer to a position of the screen writer. /// Pointer to a position of the screen writer.
char *pointer = ADDR; char *pointer = ADDR;
/// The current color. /// The current color.
char color = 7; unsigned char color = 7;
/// Used to write on the escape_buffer. If -1, we are not parsing an escape sequence. /// Used to write on the escape_buffer. If -1, we are not parsing an escape sequence.
int escape_index = -1; int escape_index = -1;
/// Used to store an escape sequence. /// Used to store an escape sequence.
@@ -80,9 +81,18 @@ char original_page[TOTAL_SIZE] = { 0 };
/// Determines if the screen is currently scrolled. /// Determines if the screen is currently scrolled.
int scrolled_page = 0; int scrolled_page = 0;
void video_init() /// @brief Get the current column number.
/// @return The column number.
static inline unsigned __get_x()
{ {
video_clear(); return ((pointer - ADDR) % (WIDTH * 2)) / 2;
}
/// @brief Get the current row number.
/// @return The row number.
static inline unsigned __get_y()
{
return (pointer - ADDR) / (WIDTH * 2);
} }
/// @brief Draws the given character. /// @brief Draws the given character.
@@ -160,9 +170,22 @@ static inline void __video_set_cursor(unsigned int x, unsigned int y)
outportb(0x3D5, (uint8_t)((position >> 8U) & 0xFFU)); outportb(0x3D5, (uint8_t)((position >> 8U) & 0xFFU));
} }
void video_init()
{
video_clear();
}
void video_update()
{
#ifndef VGA_TEXT_MODE
if (vga_is_enabled())
vga_update();
#endif
}
void video_putc(int c) void video_putc(int c)
{ {
// == ESCAPE SEQUENCES ======================================================================== // ESCAPE SEQUENCES
if (c == '\033') { if (c == '\033') {
escape_index = 0; escape_index = 0;
return; return;
@@ -189,6 +212,13 @@ void video_putc(int c)
return; return;
} }
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_putc(c);
return;
}
#endif
// == NORMAL CHARACTERS ======================================================================= // == NORMAL CHARACTERS =======================================================================
// If the character is '\n' go the new line. // If the character is '\n' go the new line.
if (c == '\n') { if (c == '\n') {
@@ -212,6 +242,12 @@ void video_putc(int c)
void video_puts(const char *str) void video_puts(const char *str)
{ {
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_puts(str);
return;
}
#endif
while ((*str) != 0) { while ((*str) != 0) {
video_putc((*str++)); video_putc((*str++));
} }
@@ -219,23 +255,73 @@ void video_puts(const char *str)
void video_set_cursor_auto() void video_set_cursor_auto()
{ {
#ifndef VGA_TEXT_MODE
if (vga_is_enabled())
return;
#endif
__video_set_cursor(((pointer - ADDR) / 2U) / WIDTH, ((pointer - ADDR) / 2U) % WIDTH); __video_set_cursor(((pointer - ADDR) / 2U) / WIDTH, ((pointer - ADDR) / 2U) % WIDTH);
} }
void video_move_cursor(unsigned int x, unsigned int y) void video_move_cursor(unsigned int x, unsigned int y)
{ {
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_move_cursor(x, y);
return;
}
#endif
pointer = ADDR + ((y * WIDTH * 2) + (x * 2)); pointer = ADDR + ((y * WIDTH * 2) + (x * 2));
video_set_cursor_auto(); video_set_cursor_auto();
} }
void video_get_cursor_position(unsigned int *x, unsigned int *y)
{
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_get_cursor_position(x, y);
return;
}
#endif
if (x)
*x = __get_x();
if (y)
*y = __get_y();
}
void video_get_screen_size(unsigned int *width, unsigned int *height)
{
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_get_screen_size(width, height);
return;
}
#endif
if (width)
*width = WIDTH;
if (height)
*height = HEIGHT;
}
void video_clear() void video_clear()
{ {
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_clear_screen();
return;
}
#endif
memset(upper_buffer, 0, STORED_PAGES * TOTAL_SIZE); memset(upper_buffer, 0, STORED_PAGES * TOTAL_SIZE);
memset(ADDR, 0, TOTAL_SIZE); memset(ADDR, 0, TOTAL_SIZE);
} }
void video_new_line() void video_new_line()
{ {
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_new_line();
return;
}
#endif
pointer = ADDR + ((pointer - ADDR) / W2 + 1) * W2; pointer = ADDR + ((pointer - ADDR) / W2 + 1) * W2;
video_shift_one_line_up(); video_shift_one_line_up();
video_set_cursor_auto(); video_set_cursor_auto();
@@ -243,22 +329,18 @@ void video_new_line()
void video_cartridge_return() void video_cartridge_return()
{ {
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_new_line();
return;
}
#endif
pointer = ADDR + ((pointer - ADDR) / W2 - 1) * W2; pointer = ADDR + ((pointer - ADDR) / W2 - 1) * W2;
video_new_line(); video_new_line();
video_shift_one_line_up(); video_shift_one_line_up();
video_set_cursor_auto(); video_set_cursor_auto();
} }
uint32_t video_get_x()
{
return ((pointer - ADDR) % (WIDTH * 2)) / 2;
}
uint32_t video_get_y()
{
return ((pointer - ADDR) / (WIDTH * 2));
}
void video_shift_one_line_up(void) void video_shift_one_line_up(void)
{ {
if (pointer >= ADDR + TOTAL_SIZE) { if (pointer >= ADDR + TOTAL_SIZE) {
@@ -302,6 +384,7 @@ void video_shift_one_page_down(void)
memcpy(ADDR, upper_buffer + (page_to_load * TOTAL_SIZE), TOTAL_SIZE); memcpy(ADDR, upper_buffer + (page_to_load * TOTAL_SIZE), TOTAL_SIZE);
} }
} }
#if 0 #if 0
void video_scroll_up() void video_scroll_up()
{ {
+10 -4
View File
@@ -85,15 +85,21 @@ boot_info_t boot_info;
/// @brief Prints [OK] at the current row and column 60. /// @brief Prints [OK] at the current row and column 60.
static inline void print_ok() static inline void print_ok()
{ {
video_move_cursor(75, video_get_y()); unsigned y, width;
video_puts("[" FG_GREEN_BRIGHT "OK" FG_WHITE "]\n"); video_get_cursor_position(NULL, &y);
video_get_screen_size(&width, NULL);
video_move_cursor(width - 5, y);
video_puts("[OK]\n");
} }
/// @brief Prints [FAIL] at the current row and column 60. /// @brief Prints [FAIL] at the current row and column 60.
static inline void print_fail() static inline void print_fail()
{ {
video_move_cursor(75, video_get_y()); unsigned y, width;
video_puts("[" FG_RED_BRIGHT "FAIL" FG_WHITE "]\n"); video_get_cursor_position(NULL, &y);
video_get_screen_size(&width, NULL);
video_move_cursor(width - 7, y);
video_puts("[FAIL]\n");
} }
/// @brief Entry point of the kernel. /// @brief Entry point of the kernel.