добавлена графика

This commit is contained in:
msh356 2026-07-19 15:40:50 +03:00
parent 417bcb30ef
commit 7573ae15a0
7 changed files with 141 additions and 16 deletions

View file

@ -21,8 +21,8 @@ ZalupaCalc 2 - это инновационная операционная сис
### 2. Графика
- [ ] Вывод на экран попиксельно
- [ ] Вывод на экран прямоугольников и прочих фигур
- [x] Вывод на экран попиксельно
- [x] Вывод на экран прямоугольников и прочих фигур
- [ ] Вывод на экран текста
- [ ] Двойная буферизация
- [ ] Вывод курсора мыши на экран, движение

54
src/drawing.c Normal file
View file

@ -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;
}
}

17
src/drawing.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef DRAWING_H
#define DRAWING_H
#include <stdint.h>
#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

View file

@ -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;
}
}
}

View file

@ -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];

View file

@ -3,6 +3,11 @@
#include <stdint.h>
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);

View file

@ -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