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.
void vga_finalize();
/// @brief Updates the graphic elements.
void vga_update();
/// @brief Checks if the VGA is enabled.
/// @return 1 if enabled, 0 otherwise.
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 str string to draw.
/// @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.
/// @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.
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();
+1272 -649
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.
palette_entry_t ansi_16_palette[17] = {
{ 0x00, 0x00, 0x00 }, // Black
{ 0xAA, 0x00, 0x00 }, // Red
{ 0x00, 0xAA, 0x00 }, // Green
{ 0xAA, 0xAA, 0x00 }, // Yellow
{ 0x00, 0x00, 0xAA }, // Blue
{ 0xAA, 0x00, 0xAA }, // Magenta
{ 0x00, 0xAA, 0xAA }, // Cyan
{ 0xAA, 0xAA, 0xAA }, // White
{ 0x55, 0x55, 0x55 }, // Black
{ 0xFF, 0x55, 0x55 }, // Red
{ 0x55, 0xFF, 0x55 }, // Green
{ 0xFF, 0xFF, 0x55 }, // Yellow
{ 0x55, 0x55, 0xFF }, // Blue
{ 0xFF, 0x55, 0xFF }, // Magenta
{ 0x55, 0xFF, 0xFF }, // Cyan
{ 0xFF, 0xFF, 0xFF }, // White
{ 0x00, 0x00, 0x00 }, // 0 Black
{ 0xAA, 0x00, 0x00 }, // 1 Red
{ 0x00, 0xAA, 0x00 }, // 2 Green
{ 0xAA, 0xAA, 0x00 }, // 3 Yellow
{ 0x00, 0x00, 0xAA }, // 4 Blue
{ 0xAA, 0x00, 0xAA }, // 5 Magenta
{ 0x00, 0xAA, 0xAA }, // 6 Cyan
{ 0xAA, 0xAA, 0xAA }, // 7 White
{ 0x55, 0x55, 0x55 }, // 8 Black
{ 0xFF, 0x55, 0x55 }, // 9 Red
{ 0x55, 0xFF, 0x55 }, // 10 Green
{ 0xFF, 0xFF, 0x55 }, // 11 Yellow
{ 0x55, 0x55, 0xFF }, // 12 Blue
{ 0xFF, 0x55, 0xFF }, // 13 Magenta
{ 0x55, 0xFF, 0xFF }, // 14 Cyan
{ 0xFF, 0xFF, 0xFF }, // 15 White
};
/// 256 color palette.
+13 -8
View File
@@ -66,6 +66,9 @@
/// @brief Initialize the video.
void video_init();
/// @brief Updates the video.
void video_update();
/// @brief Print the given character on the screen.
/// @param c The character to print.
void video_putc(int c);
@@ -82,6 +85,16 @@ void video_set_cursor_auto();
/// @param y The y coordinate.
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.
void video_clear();
@@ -91,14 +104,6 @@ void video_new_line();
/// @brief Move to the up line (the effect of \n character).
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
/// reaches the last position of the screen.
void video_shift_one_line_up();
+4 -2
View File
@@ -16,9 +16,10 @@
#include "process/scheduler.h"
#include "hardware/pic8259.h"
#include "io/port_io.h"
#include "io/debug.h"
#include "io/video.h"
#include "stdint.h"
#include "mem/kheap.h"
#include "io/debug.h"
#include "process/wait.h"
#include "drivers/rtc.h"
#include "descriptor_tables/isr.h"
@@ -26,7 +27,6 @@
#include "system/signal.h"
#include "assert.h"
#include "sys/errno.h"
#include "io/vga/vga.h"
/// @defgroup picregs Programmable Interval Timer Registers
/// @brief The list of registers used to set the PIT.
@@ -108,6 +108,8 @@ void timer_handler(pt_regs *reg)
run_timer_softirq();
// Perform the schedule.
scheduler_run(reg);
// Update graphics.
video_update();
// Restore fpu state.
unswitch_fpu();
// The ack is sent to PIC only when all handlers terminated!
+130 -21
View File
@@ -19,6 +19,7 @@
#include "hardware/timer.h"
#include "io/port_io.h"
#include "io/debug.h"
#include "io/video.h"
#include "stdbool.h"
#include "string.h"
#include "math.h"
@@ -73,7 +74,7 @@ typedef struct {
/// VGA font details.
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 height; ///< Height of the font.
} vga_font_t;
@@ -539,16 +540,6 @@ unsigned int vga_read_pixel(int x, int 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)
{
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 << 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 cx = 0; cx < driver->font->width; ++cx) {
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;
while (*str != '\0') {
@@ -689,16 +680,28 @@ static vga_ops_t ops_320_200_256 = {
.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 = {
.font = arr_8x8_font,
.width = 8,
.height = 8,
};
static vga_font_t font_8x8_basic = {
.font = arr_8x8_basic_font,
static vga_font_t font_8x14 = {
.font = arr_8x14_font,
.width = 8,
.height = 8,
.height = 14,
};
static vga_font_t font_8x16 = {
@@ -739,34 +742,39 @@ void vga_initialize()
__save_palette(stored_palette, 256);
// Initialize the desired mode.
#if defined(VGA_MODE_320_200_256)
#if defined(VGA_MODE_320_200_256) // 40x25
// Write the registers.
__set_mode(&_mode_320_200_256);
// Initialize the mode.
driver = &driver_320_200_256;
// Load the color palette.
__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.
__set_mode(&_mode_640_480_16);
// Initialize the mode.
driver = &driver_640_480_16;
// Load the color palette.
__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.
__set_mode(&_mode_720_480_16);
// Initialize the mode.
driver = &driver_720_480_16;
// Load the color palette.
__load_palette(ansi_16_palette, 16);
// Set the font.
driver->font = &font_8x16;
#else // VGA_TEXT_MODE
return;
#endif
// Set the address.
driver->address = __get_seg();
// Set the font.
driver->font = &font_8x8;
// Save the content of the memory.
memcpy(vidmem, driver->address, 0x4000);
// Clears the screen.
@@ -782,3 +790,104 @@ void vga_finalize()
__load_palette(stored_palette, 256);
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/video.h"
#include "io/vga/vga.h"
#include "stdbool.h"
#include "ctype.h"
#include "string.h"
@@ -68,7 +69,7 @@ ansi_color_map[] = {
/// Pointer to a position of the screen writer.
char *pointer = ADDR;
/// 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.
int escape_index = -1;
/// Used to store an escape sequence.
@@ -80,9 +81,18 @@ char original_page[TOTAL_SIZE] = { 0 };
/// Determines if the screen is currently scrolled.
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.
@@ -160,9 +170,22 @@ static inline void __video_set_cursor(unsigned int x, unsigned int y)
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)
{
// == ESCAPE SEQUENCES ========================================================================
// ESCAPE SEQUENCES
if (c == '\033') {
escape_index = 0;
return;
@@ -189,6 +212,13 @@ void video_putc(int c)
return;
}
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_putc(c);
return;
}
#endif
// == NORMAL CHARACTERS =======================================================================
// If the character is '\n' go the new line.
if (c == '\n') {
@@ -212,6 +242,12 @@ void video_putc(int c)
void video_puts(const char *str)
{
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_puts(str);
return;
}
#endif
while ((*str) != 0) {
video_putc((*str++));
}
@@ -219,23 +255,73 @@ void video_puts(const char *str)
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);
}
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));
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()
{
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_clear_screen();
return;
}
#endif
memset(upper_buffer, 0, STORED_PAGES * TOTAL_SIZE);
memset(ADDR, 0, TOTAL_SIZE);
}
void video_new_line()
{
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_new_line();
return;
}
#endif
pointer = ADDR + ((pointer - ADDR) / W2 + 1) * W2;
video_shift_one_line_up();
video_set_cursor_auto();
@@ -243,22 +329,18 @@ void video_new_line()
void video_cartridge_return()
{
#ifndef VGA_TEXT_MODE
if (vga_is_enabled()) {
vga_new_line();
return;
}
#endif
pointer = ADDR + ((pointer - ADDR) / W2 - 1) * W2;
video_new_line();
video_shift_one_line_up();
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)
{
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);
}
}
#if 0
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.
static inline void print_ok()
{
video_move_cursor(75, video_get_y());
video_puts("[" FG_GREEN_BRIGHT "OK" FG_WHITE "]\n");
unsigned y, width;
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.
static inline void print_fail()
{
video_move_cursor(75, video_get_y());
video_puts("[" FG_RED_BRIGHT "FAIL" FG_WHITE "]\n");
unsigned y, width;
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.