From 36aa3925343afe6ec04b8fd3bc062ec7cf871b9e Mon Sep 17 00:00:00 2001 From: "Enrico Fraccaroli (Galfurian)" Date: Wed, 13 Jul 2022 11:53:13 -0400 Subject: [PATCH] Fix VGA drawing functions. --- mentos/inc/io/vga/vga.h | 32 +++--- mentos/src/drivers/ata.c | 4 - mentos/src/io/vga/vga.c | 213 +++++++++++++++++++-------------------- mentos/src/kernel.c | 10 +- 4 files changed, 133 insertions(+), 126 deletions(-) diff --git a/mentos/inc/io/vga/vga.h b/mentos/inc/io/vga/vga.h index fd3f1f6..f6c3d94 100644 --- a/mentos/inc/io/vga/vga.h +++ b/mentos/inc/io/vga/vga.h @@ -26,12 +26,18 @@ int vga_height(); /// @brief Clears the screen. void vga_clear_screen(); +/// @brief Draws a pixel at the given position. +/// @param x x-axis position. +/// @param y y-axis position. +/// @param color color of the character. +void vga_draw_pixel(int x, int y, unsigned char color); + /// @brief Draws a character at the given position. /// @param x x-axis position. /// @param y y-axis position. /// @param c character to draw. /// @param color color of the character. -void vga_draw_char(unsigned int x, unsigned int y, unsigned char c, unsigned char color); +void vga_draw_char(int x, int y, unsigned char c, unsigned char color); /// @brief Draws a string at the given position. /// @param x x-axis position. @@ -46,22 +52,22 @@ void vga_draw_string(int x, int y, char *str, unsigned char color); /// @param x1 point 2 x-axis position. /// @param y1 point 2 y-axis position. /// @param color color of the line. -void vga_draw_line(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned char color); +void vga_draw_line(int x0, int y0, int x1, int y1, unsigned char color); /// @brief Draws a rectangle provided the position of the starting corner and the ending corner. -/// @param sx starting corner x-axis position. -/// @param sy starting corner y-axis position. -/// @param ex ending corner x-axis position. -/// @param ey ending corner y-axis position. -/// @param fill color used to fill the rectangle. -void vga_draw_rectangle(unsigned int sx, unsigned int sy, unsigned int ex, unsigned int ey, unsigned char fill); +/// @param sx top-left corner x-axis position. +/// @param sy top-left corner y-axis position. +/// @param w width. +/// @param h height. +/// @param color color of the rectangle. +void vga_draw_rectangle(int sx, int sy, int w, int h, unsigned char color); /// @brief Draws a circle provided the position of the center and the radius. /// @param xc x-axis position. /// @param yc y-axis position. /// @param r radius. -/// @param fill color used to fill the circle. -void vga_draw_circle(unsigned int xc, unsigned int yc, unsigned int r, unsigned char fill); +/// @param color used to draw the circle. +void vga_draw_circle(int xc, int yc, int r, unsigned char color); /// @brief Draws a triangle. /// @param x1 1st point x-axis position. @@ -70,5 +76,7 @@ void vga_draw_circle(unsigned int xc, unsigned int yc, unsigned int r, unsigned /// @param y2 2nd point y-axis position. /// @param x3 3rd point x-axis position. /// @param y3 3rd point y-axis position. -/// @param fill color used to fill the triangle. -void vga_draw_triangle(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int x3, unsigned int y3, unsigned char fill); \ No newline at end of file +/// @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_run_test(); \ No newline at end of file diff --git a/mentos/src/drivers/ata.c b/mentos/src/drivers/ata.c index e94b3bb..039ba2a 100644 --- a/mentos/src/drivers/ata.c +++ b/mentos/src/drivers/ata.c @@ -1137,22 +1137,18 @@ int ata_initialize() ata_device_type_t type; type = ata_device_detect(&ata_primary_master); if ((type != ata_dev_type_no_device) && (type != ata_dev_type_unknown)) { - printf(" Found %s device connected to primary master.\n", ata_get_device_type_str(type)); pr_info(" Found %s device connected to primary master.\n", ata_get_device_type_str(type)); } type = ata_device_detect(&ata_primary_slave); if ((type != ata_dev_type_no_device) && (type != ata_dev_type_unknown)) { - printf(" Found %s device connected to primary slave.\n", ata_get_device_type_str(type)); pr_info(" Found %s device connected to primary slave.\n", ata_get_device_type_str(type)); } type = ata_device_detect(&ata_secondary_master); if ((type != ata_dev_type_no_device) && (type != ata_dev_type_unknown)) { - printf(" Found %s device connected to secondary master.\n", ata_get_device_type_str(type)); pr_info(" Found %s device connected to secondary master.\n", ata_get_device_type_str(type)); } type = ata_device_detect(&ata_secondary_slave); if ((type != ata_dev_type_no_device) && (type != ata_dev_type_unknown)) { - printf(" Found %s device connected to secondary slave.\n", ata_get_device_type_str(type)); pr_info(" Found %s device connected to secondary slave.\n", ata_get_device_type_str(type)); } return 0; diff --git a/mentos/src/io/vga/vga.c b/mentos/src/io/vga/vga.c index 8767cd4..7462163 100644 --- a/mentos/src/io/vga/vga.c +++ b/mentos/src/io/vga/vga.c @@ -16,10 +16,11 @@ #include "io/vga/vga_mode.h" #include "io/vga/vga_font.h" +#include "hardware/timer.h" #include "io/port_io.h" +#include "io/debug.h" #include "stdbool.h" #include "string.h" -#include "io/debug.h" #include "math.h" /// Counts the number of elements of an array. @@ -61,13 +62,13 @@ /// VGA pointers for drawing operations. typedef struct { /// Writes a pixel. - void (*write_pixel)(unsigned int x, unsigned int y, unsigned char c); + void (*write_pixel)(int x, int y, unsigned char c); /// Reads a pixel. - unsigned (*read_pixel)(unsigned int x, unsigned int y); + unsigned (*read_pixel)(int x, int y); /// Draws a rectangle. - void (*draw_rect)(unsigned int x, unsigned int y, unsigned int wd, unsigned int ht, unsigned char c); + void (*draw_rect)(int x, int y, int wd, int ht, unsigned char c); /// Fills a rectangle. - void (*fill_rect)(unsigned int x, unsigned int y, unsigned int wd, unsigned int ht, unsigned char c); + void (*fill_rect)(int x, int y, int wd, int ht, unsigned char c); } vga_ops_t; /// VGA font details. @@ -361,17 +362,42 @@ assume: chain-4 addressing already off */ outportb(GC_DATA, gc6); } +/// @brief Reverses the bits of the given number. +/// @param num the number of which we want to reverse the bits. +/// @return reversed bits. +static inline unsigned int __reverse_bits(char num) +{ + unsigned int NO_OF_BITS = sizeof(num) * 8; + unsigned int reverse_num = 0; + int i; + for (i = 0; i < NO_OF_BITS; i++) { + if ((num & (1 << i))) + reverse_num |= 1 << ((NO_OF_BITS - 1) - i); + } + return reverse_num; +} + +/// @brief Sets the given font. +/// @param font the new font. +void __vga_setfont(const vga_font_t *font) +{ + __font->font = font->font; + __font->width = font->width; + __font->height = font->height; +} + +// ============================================================================ +// = WRITE PIXEL FUNCTIONS (and support) // ============================================================================ -// == WRITE PIXEL FUNCTIONS =================================================== /// @brief Writes a pixel. /// @param x x coordinates. /// @param y y coordinates. /// @param c color. -static void __write_pixel_1(unsigned int x, unsigned int y, unsigned char c) +static inline void __write_pixel_1(int x, int y, unsigned char c) { - unsigned wd_in_bytes; - unsigned off, mask; + int wd_in_bytes; + int off, mask; c = (c & 1) * 0xFF; wd_in_bytes = driver->width / 8; @@ -385,10 +411,10 @@ static void __write_pixel_1(unsigned int x, unsigned int y, unsigned char c) /// @param x x coordinates. /// @param y y coordinates. /// @param c color. -static void __write_pixel_2(unsigned int x, unsigned int y, unsigned char c) +static inline void __write_pixel_2(int x, int y, unsigned char c) { - unsigned wd_in_bytes; - unsigned off, mask; + int wd_in_bytes; + int off, mask; c = (c & 3) * 0x55; wd_in_bytes = driver->width / 4; @@ -402,7 +428,7 @@ static void __write_pixel_2(unsigned int x, unsigned int y, unsigned char c) /// @param x x coordinates. /// @param y y coordinates. /// @param c color. -static void __write_pixel_4(unsigned int x, unsigned int y, unsigned char color) +static inline void __write_pixel_4(int x, int y, unsigned char color) { int rotation = 0; int16_t t; @@ -423,7 +449,7 @@ static void __write_pixel_4(unsigned int x, unsigned int y, unsigned char color) break; } - unsigned wd_in_bytes, off, mask, p, pmask; + int wd_in_bytes, off, mask, p, pmask; wd_in_bytes = driver->width / 8; off = wd_in_bytes * y + x / 8; @@ -444,27 +470,16 @@ static void __write_pixel_4(unsigned int x, unsigned int y, unsigned char color) /// @param x x coordinates. /// @param y y coordinates. /// @param c color. -static inline void __write_pixel_8(unsigned int x, unsigned int y, unsigned char color) +static inline void __write_pixel_8(int x, int y, unsigned char color) { __set_plane(x); __write_byte(((y * driver->width) + x) / 4, color); // (y << 6) + (y << 4) + (x >> 2) } -/// @brief Reverses the bits of the given number. -/// @param num the number of which we want to reverse the bits. -/// @return reversed bits. -unsigned int reverseBits(char num) -{ - unsigned int NO_OF_BITS = sizeof(num) * 8; - unsigned int reverse_num = 0; - int i; - for (i = 0; i < NO_OF_BITS; i++) { - if ((num & (1 << i))) - reverse_num |= 1 << ((NO_OF_BITS - 1) - i); - } - return reverse_num; -} +// ============================================================================ +// = VGA PUBLIC FUNCTIONS +// ============================================================================ int vga_is_enabled() { @@ -485,15 +500,6 @@ int vga_height() return 0; } -/// @brief Sets the given font. -/// @param font the new font. -void __vga_setfont(const vga_font_t *font) -{ - __font->font = font->font; - __font->width = font->width; - __font->height = font->height; -} - void vga_clear_screen() { for (int p = 0; p < 4; p++) { @@ -502,7 +508,12 @@ void vga_clear_screen() } } -void vga_draw_char(unsigned int x, unsigned int y, unsigned char c, unsigned char color) +void vga_draw_pixel(int x, int y, unsigned char color) +{ + driver->ops->write_pixel(x, y, color); +} + +void vga_draw_char(int x, int y, unsigned char c, unsigned char color) { static unsigned mask[] = { 1u << 0u, // 1 @@ -518,7 +529,7 @@ void vga_draw_char(unsigned int x, unsigned int y, unsigned char c, unsigned cha unsigned char *glyph = __font->font + c * __font->height; for (unsigned cy = 0; cy < __font->height; ++cy) { for (unsigned cx = 0; cx < __font->width; ++cx) { - driver->ops->write_pixel(x + (__font->width - cx), y + cy, glyph[cy] & mask[cx] ? color : 0x00u); + vga_draw_pixel(x + (__font->width - cx), y + cy, glyph[cy] & mask[cx] ? color : 0x00u); } } } @@ -533,76 +544,56 @@ void vga_draw_string(int x, int y, char *str, unsigned char color) } } -void vga_draw_line(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned char color) +void vga_draw_line(int x0, int y0, int x1, int y1, unsigned char color) { - bool_t steep = abs(y1 - y0) > abs(x1 - x0); - int tmp = 0; - if (steep) { - tmp = x0; - x0 = y0; - y0 = tmp; - - tmp = x1; - x1 = y1; - y1 = tmp; - } - if (x0 > x1) { - tmp = x0; - x0 = x1; - x1 = tmp; - - tmp = y0; - y0 = y1; - y1 = tmp; - } - int deltax = x1 - x0; - int deltay = abs(y1 - y0); - int error = deltax / 2; - int ystep; - int y = y0; - if (y0 < y1) - ystep = 1; - else - ystep = -1; - for (int x = x0; x < x1; x++) { - if (steep) - driver->ops->write_pixel(y, x, color); - else - driver->ops->write_pixel(x, y, color); - error = error - deltay; - if (error < 0) { - y = y + ystep; - error = error + deltax; + int dx = abs(x1 - x0), sx = sign(x1 - x0); + int dy = abs(y1 - y0), sy = sign(y1 - y0); + int err = (dx > dy ? dx : -dy) / 2; + while (true) { + vga_draw_pixel(x0, y0, color); + if ((x0 == x1) && (y0 == y1)) + break; + if (dx > dy) { + x0 += sx; + err -= dy; + if (err < 0) + err += dx; + y0 += sy; + } else { + y0 += sy; + err -= dx; + if (err < 0) + err += dy; + x0 += sx; } } } -void vga_draw_rectangle(unsigned int sx, unsigned int sy, unsigned int ex, unsigned int ey, unsigned char fill) +void vga_draw_rectangle(int sx, int sy, int w, int h, unsigned char color) { - vga_draw_line(sx, sy, ex, sy, fill); - vga_draw_line(sx, sy, sx, ey, fill); - vga_draw_line(sx, ey, ex, ey, fill); - vga_draw_line(ex, ey, ex, sy, fill); + vga_draw_line(sx, sy, sx + w, sy, color); + vga_draw_line(sx, sy, sx, sy + h, color); + vga_draw_line(sx, sy + h, sx + w, sy + h, color); + vga_draw_line(sx + w, sy, sx + w, sy + h, color); } -void vga_draw_circle(unsigned int xc, unsigned int yc, unsigned int r, unsigned char fill) +void vga_draw_circle(int xc, int yc, int r, unsigned char color) { - unsigned int x = 0; - unsigned int y = r; - unsigned int p = 3 - 2 * r; + int x = 0; + int y = r; + int p = 3 - 2 * r; if (!r) return; - while (y >= x) // only formulate 1/8 of circle { - driver->ops->write_pixel(xc - x, yc - y, fill); //upper left left - driver->ops->write_pixel(xc - y, yc - x, fill); //upper upper left - driver->ops->write_pixel(xc + y, yc - x, fill); //upper upper right - driver->ops->write_pixel(xc + x, yc - y, fill); //upper right right - driver->ops->write_pixel(xc - x, yc + y, fill); //lower left left - driver->ops->write_pixel(xc - y, yc + x, fill); //lower lower left - driver->ops->write_pixel(xc + y, yc + x, fill); //lower lower right - driver->ops->write_pixel(xc + x, yc + y, fill); //lower right right + vga_draw_pixel(xc - x, yc - y, color); //upper left left + vga_draw_pixel(xc - y, yc - x, color); //upper upper left + vga_draw_pixel(xc + y, yc - x, color); //upper upper right + vga_draw_pixel(xc + x, yc - y, color); //upper right right + vga_draw_pixel(xc - x, yc + y, color); //lower left left + vga_draw_pixel(xc - y, yc + x, color); //lower lower left + vga_draw_pixel(xc + y, yc + x, color); //lower lower right + vga_draw_pixel(xc + x, yc + y, color); //lower right right if (p < 0) p += 4 * x++ + 6; else @@ -610,21 +601,29 @@ void vga_draw_circle(unsigned int xc, unsigned int yc, unsigned int r, unsigned } } -void vga_draw_triangle(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int x3, unsigned int y3, unsigned char fill) +void vga_draw_triangle(int x1, int y1, int x2, int y2, int x3, int y3, unsigned char color) { - vga_draw_line(x1, y1, x2, y2, fill); - vga_draw_line(x2, y2, x3, y3, fill); - vga_draw_line(x3, y3, x1, y1, fill); + vga_draw_line(x1, y1, x2, y2, color); + vga_draw_line(x2, y2, x3, y3, color); + vga_draw_line(x3, y3, x1, y1, color); } -static void __test_vga(void) +void vga_run_test(void) { vga_clear_screen(); - vga_draw_rectangle(1, 1, driver->width - 1, driver->height - 1, 3); - for (unsigned i = 1; i < driver->height - 1; i++) { - driver->ops->write_pixel((driver->width - driver->height) / 2 + i, i, 1); - driver->ops->write_pixel((driver->height + driver->width) / 2 - i, i, 1); - } + int w2h = (vga_width() / 2); + int h2h = (vga_height() / 2); + + for (unsigned r = 0; r <= min(vga_width() / 2, vga_height() / 2); r += 4) + vga_draw_circle(vga_width() / 2, vga_height() / 2, r, 2); + + for (unsigned y = 0; y < vga_height(); y += 2) + vga_draw_line(0, y, vga_width(), y, 3); + + for (unsigned dim = 0; dim < min(vga_width(), vga_height()); dim += 4) + vga_draw_rectangle(w2h - (dim / 2), h2h - (dim / 2), dim, dim, 4); + + vga_draw_triangle(0, 50, 50, 0, 100, 50, 2); } // == MODEs and DRIVERs ======================================================= diff --git a/mentos/src/kernel.c b/mentos/src/kernel.c index a8d10f5..8594d57 100644 --- a/mentos/src/kernel.c +++ b/mentos/src/kernel.c @@ -229,27 +229,30 @@ int kmain(boot_info_t *boot_informations) //========================================================================== // Scan for ata devices. pr_notice("Initialize ATA devices...\n"); - printf("Initialize ATA devices...\n"); + printf("Initialize ATA devices..."); if (ata_initialize()) { pr_emerg("Failed to initialize ATA devices!\n"); return 1; } + print_ok(); //========================================================================== pr_notice("Initialize EXT2 filesystem...\n"); - printf("Initialize EXT2 filesystem...\n"); + printf("Initialize EXT2 filesystem..."); if (ext2_initialize()) { pr_emerg("Failed to initialize EXT2 filesystem!\n"); return 1; } + print_ok(); //========================================================================== pr_notice("Mount EXT2 filesystem...\n"); - printf("Mount EXT2 filesystem...\n"); + printf("Mount EXT2 filesystem..."); if (do_mount("ext2", "/", "/dev/hda")) { pr_emerg("Failed to mount EXT2 filesystem...\n"); return 1; } + print_ok(); //========================================================================== pr_notice(" Initialize 'procfs'...\n"); @@ -268,6 +271,7 @@ int kmain(boot_info_t *boot_informations) pr_emerg("Failed to mount procfs at `/proc`!\n"); return 1; } + print_ok(); //========================================================================== pr_notice("Initialize video procfs file...\n");