From 7573ae15a0712e4adeae8122ce8af52e4b1dad8e Mon Sep 17 00:00:00 2001 From: msh356 Date: Sun, 19 Jul 2026 15:40:50 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B3=D1=80=D0=B0=D1=84=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- src/drawing.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ src/drawing.h | 17 ++++++++++++++++ src/kmain.c | 44 +++++++++++++++++++++++++++++++++++++++- src/mouse.c | 15 +++++++------- src/mouse.h | 5 +++++ src/multiboot.h | 18 +++++++++++------ 7 files changed, 141 insertions(+), 16 deletions(-) create mode 100644 src/drawing.c create mode 100644 src/drawing.h diff --git a/README.md b/README.md index 9a65a60..a842e62 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ ZalupaCalc 2 - это инновационная операционная сис ### 2. Графика -- [ ] Вывод на экран попиксельно -- [ ] Вывод на экран прямоугольников и прочих фигур +- [x] Вывод на экран попиксельно +- [x] Вывод на экран прямоугольников и прочих фигур - [ ] Вывод на экран текста - [ ] Двойная буферизация - [ ] Вывод курсора мыши на экран, движение diff --git a/src/drawing.c b/src/drawing.c new file mode 100644 index 0000000..b108790 --- /dev/null +++ b/src/drawing.c @@ -0,0 +1,54 @@ +#include "drawing.h" +#include "multiboot.h" +#include "serial.h" +#include "vmm.h" // Для маппинга + +uint32_t* fb_ptr = 0; +uint32_t screen_width = 0; +uint32_t screen_height = 0; + +void draw_init(struct multiboot_info* mbi) { + if (!(mbi->flags & (1 << 12))) { + kprint_serial("DRAWING: NO FRAMEBUFFER!"); + return; + } + + uint32_t fb_phys = (uint32_t)mbi->framebuffer_addr; + uint32_t width = mbi->framebuffer_width; + uint32_t height = mbi->framebuffer_height; + + // Считаем размер и мапим сразу внутри + uint32_t size = width * height * 4; + uint32_t num_pages = (size + 0xFFF) / 0x1000; + + for (uint32_t i = 0; i < num_pages; i++) { + vmm_map_page(fb_phys + (i * 0x1000), + fb_phys + (i * 0x1000), + 0x3 | 0x10); // Present + RW + PCD + } + + // Сохраняем в глобальные переменные модуля + fb_ptr = (uint32_t*)fb_phys; + screen_width = width; + screen_height = height; +} + +void put_pixel(int x, int y, uint32_t color) { + if (x >= 0 && x < (int)screen_width && y >= 0 && y < (int)screen_height) { + fb_ptr[y * screen_width + x] = color; + } +} + +void draw_rect(int x, int y, int w, int h, uint32_t color) { + for (int i = y; i < y + h; i++) { + for (int j = x; j < x + w; j++) { + put_pixel(j, i, color); + } + } +} + +void clear_screen(uint32_t color) { + for (uint32_t i = 0; i < screen_width * screen_height; i++) { + fb_ptr[i] = color; + } +} diff --git a/src/drawing.h b/src/drawing.h new file mode 100644 index 0000000..c39bb3d --- /dev/null +++ b/src/drawing.h @@ -0,0 +1,17 @@ +#ifndef DRAWING_H +#define DRAWING_H + +#include +#include "multiboot.h" + +// Основные параметры экрана (можно заполнять динамически из multiboot) +extern uint32_t* fb_ptr; +extern uint32_t screen_width; +extern uint32_t screen_height; + +void draw_init(struct multiboot_info* mbi); +void put_pixel(int x, int y, uint32_t color); +void draw_rect(int x, int y, int w, int h, uint32_t color); +void clear_screen(uint32_t color); + +#endif diff --git a/src/kmain.c b/src/kmain.c index d9bf1f1..4240ee8 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -1,4 +1,5 @@ #include "serial.h" +#include "drawing.h" #include "mouse.h" #include "timer.h" #include "speaker.h" @@ -12,6 +13,12 @@ #include "string.h" #include "multiboot.h" +uint32_t bg_color = 0x00008080; +uint32_t color_sky_blue = 0x0087CEEB; +uint32_t color_orange = 0x00FFA500; +uint32_t color_white = 0x00FFFFFF; +uint32_t color_black = 0x00000000; + extern uint32_t _kernel_end; // Символ 'end' прописан в конце любого стандартного linker.ld uint32_t kernel_end = (uint32_t)&_kernel_end; @@ -153,6 +160,26 @@ void kernel_main(uint32_t mboot_addr, uint32_t magic) { kfree(arr2); kprint_serial("Kfree done. It don't died twice!\n"); + if (mbi->flags & (1 << 12)) { + log_info(LOG_NORMAL, "Framebuffer detected!"); + + uint32_t fb_addr = mbi->framebuffer_addr; + uint32_t width = mbi->framebuffer_width; + uint32_t height = mbi->framebuffer_height; + uint32_t bpp = mbi->framebuffer_bpp; + + char buf[16]; + kprint_serial("FB Addr: "); + kprint_serial_hex(fb_addr); + kprint_serial("\nSize: "); + kprint_serial_dec(width); + kprint_serial("x"); + kprint_serial_dec(height); + kprint_serial("\n"); + draw_init(mbi); + } else { + log_error(LOG_NORMAL, "No Framebuffer provided by GRUB!"); + } log_info(LOG_NORMAL, "Enabling IRQ..."); __asm__ __volatile__("sti"); speaker_beep(100, 10); @@ -167,5 +194,20 @@ void kernel_main(uint32_t mboot_addr, uint32_t magic) { speaker_beep(325, 10); speaker_beep(350, 400); log_info(LOG_NORMAL, "OK!"); - while (1); + clear_screen(bg_color); + int old_mouse_x = 0; + int old_mouse_y = 0; + while (1) { + if (mouse_x != old_mouse_x || mouse_y != old_mouse_y) { + // Стираем старый + draw_rect(old_mouse_x - 5, old_mouse_y - 5, 10, 10, bg_color); + + // Рисуем новый + int color = left_click ? color_orange : (right_click ? color_sky_blue : color_white); + draw_rect(mouse_x - 5, mouse_y - 5, 10, 10, color); + + old_mouse_x = mouse_x; + old_mouse_y = mouse_y; + } + } } diff --git a/src/mouse.c b/src/mouse.c index a9bd082..2b8adb4 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -62,8 +62,10 @@ void mouse_init(void) { static uint8_t mouse_cycle = 0; static uint8_t mouse_packet[3]; -static int mouse_x = 40; // Стартуем по центру текстового экрана 80x25 -static int mouse_y = 12; +volatile int mouse_x = 200; +volatile int mouse_y = 200; +volatile int left_click = 0; +volatile int right_click = 0; void mouse_handler(void) { uint8_t status = inb(PS2_STATUS); @@ -99,15 +101,14 @@ void mouse_handler(void) { mouse_x += offset_x; mouse_y -= offset_y; // Инвертируем Y, так как в VGA координатах 0 верх - // Ограничиваем рамками консоли 80x25 if (mouse_x < 0) mouse_x = 0; - if (mouse_x >= 80) mouse_x = 79; + if (mouse_x >= 1024) mouse_x = 1023; if (mouse_y < 0) mouse_y = 0; - if (mouse_y >= 25) mouse_y = 24; + if (mouse_y >= 768) mouse_y = 767; // Чек кнопок - int left_click = flags & 0x01; - int right_click = flags & 0x02; + left_click = flags & 0x01; + right_click = flags & 0x02; // Выводим инфу в UART через itoa char buf[16]; diff --git a/src/mouse.h b/src/mouse.h index f42b004..b97a689 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -3,6 +3,11 @@ #include +extern volatile int mouse_x; +extern volatile int mouse_y; +extern volatile int left_click; +extern volatile int right_click; + void mouse_init(void); void mouse_handler(void); diff --git a/src/multiboot.h b/src/multiboot.h index bc41b3a..9788d59 100644 --- a/src/multiboot.h +++ b/src/multiboot.h @@ -25,12 +25,9 @@ struct multiboot_info { uint32_t cmdline; uint32_t mods_count; uint32_t mods_addr; - uint32_t num; - uint32_t size; - uint32_t addr; - uint32_t shndx; + uint32_t syms[4]; uint32_t mmap_length; - uint32_t mmap_addr; // <-- Вот это нам нужно! Адрес карты памяти + uint32_t mmap_addr; uint32_t drives_length; uint32_t drives_addr; uint32_t config_table; @@ -42,6 +39,15 @@ struct multiboot_info { uint16_t vbe_interface_seg; uint16_t vbe_interface_off; uint16_t vbe_interface_len; -} __attribute__((packed)); + + // ДОБАВЬ ЭТИ ПОЛЯ САМ, ЕСЛИ ИХ НЕТ: + uint64_t framebuffer_addr; + uint32_t framebuffer_pitch; + uint32_t framebuffer_width; + uint32_t framebuffer_height; + uint8_t framebuffer_bpp; + uint8_t framebuffer_type; + uint16_t framebuffer_color_info; +}; #endif