рисовашк текст

This commit is contained in:
msh356 2026-07-19 16:52:45 +03:00
parent e68f41f652
commit 94b03ee1f3
7 changed files with 185 additions and 37 deletions

View file

@ -24,7 +24,7 @@ ZalupaCalc 2 - это инновационная операционная сис
- [x] Вывод на экран попиксельно
- [x] Вывод на экран прямоугольников и прочих фигур
- [x] Вывод на экран BMP
- [ ] Вывод на экран текста
- [x] Вывод на экран текста
- [ ] Двойная буферизация
- [ ] Вывод курсора мыши на экран, движение
- [ ] Кнопки (touch zones, массив в памяти где будут координаты областей и действия при нажатии)

View file

@ -2,6 +2,7 @@
#include "multiboot.h"
#include "serial.h"
#include "vmm.h" // Для маппинга
#include "font.h"
#define TRANSPARENT_COLOR 0xFF00FF
uint32_t* fb_ptr = 0;
@ -132,3 +133,35 @@ void draw_cursor_sprite(uint8_t* bmp_data, int x, int y) {
}
}
}
void put_char(char c, int x, int y, uint32_t color) {
if (c < 32 || c > 126) c = 32; // Если символ вне диапазона — рисуем пробел
const uint8_t* glyph = font8x8[c - 32];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
// Если бит в строке установлен — рисуем пиксель
if (glyph[i] & (1 << (7 - j))) {
put_pixel(x + j, y + i, color);
}
}
}
}
void draw_string(const char* str, int x, int y, uint32_t color) {
int cursor_x = x;
int cursor_y = y;
while (*str != '\0') {
// Если встретили символ переноса строки
if (*str == '\n') {
cursor_x = x;
cursor_y += 10; // 8 пикселей высота буквы + 2 пикселя отступ
} else {
put_char(*str, cursor_x, cursor_y, color);
cursor_x += 9; // 8 пикселей ширина буквы + 1 пиксель пробел между ними
}
str++;
}
}

View file

@ -15,5 +15,7 @@ void draw_rect(int x, int y, int w, int h, uint32_t color);
void clear_screen(uint32_t color);
void draw_bmp(uint8_t* data, int x, int y);
void draw_cursor_sprite(uint8_t* bmp_data, int x, int y);
void put_char(char c, int x, int y, uint32_t color);
void draw_string(const char* str, int x, int y, uint32_t color);
#endif

99
src/font.c Normal file
View file

@ -0,0 +1,99 @@
#include <stdint.h>
const uint8_t font8x8[95][8] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 32
{0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00}, // 33 !
{0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00}, // 34 "
{0x66, 0x66, 0xFF, 0x66, 0xFF, 0x66, 0x66, 0x00}, // 35 #
{0x18, 0x7E, 0xFF, 0x1B, 0x1B, 0x1B, 0x1B, 0x00}, // 36 $
{0x63, 0x66, 0x0C, 0x18, 0x30, 0x66, 0x63, 0x00}, // 37 %
{0x3C, 0x66, 0x3C, 0x6B, 0x33, 0x66, 0x3C, 0x00}, // 38 &
{0x06, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00}, // 39 '
{0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00}, // 40 (
{0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00}, // 41 )
{0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00}, // 42 *
{0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00}, // 43 +
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30}, // 44 ,
{0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00}, // 45 -
{0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00}, // 46 .
{0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00}, // 47 /
{0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // 48 0
{0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00}, // 49 1
{0x3C, 0x66, 0x06, 0x1C, 0x30, 0x66, 0x7E, 0x00}, // 50 2
{0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0x00}, // 51 3
{0x0C, 0x1C, 0x3C, 0x6C, 0x7E, 0x0C, 0x0C, 0x00}, // 52 4
{0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0x00}, // 53 5
{0x3C, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x3C, 0x00}, // 54 6
{0x7E, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00}, // 55 7
{0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00}, // 56 8
{0x3C, 0x66, 0x66, 0x7C, 0x06, 0x66, 0x3C, 0x00}, // 57 9
{0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00}, // 58 :
{0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30}, // 59 ;
{0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00}, // 60 <
{0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00}, // 61 =
{0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00}, // 62 >
{0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00}, // 63 ?
{0x3C, 0x66, 0x76, 0x76, 0x76, 0x60, 0x3C, 0x00}, // 64 @
{0x18, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00}, // 65 A
{0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00}, // 66 B
{0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00}, // 67 C
{0x78, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00}, // 68 D
{0x7E, 0x60, 0x60, 0x78, 0x60, 0x60, 0x7E, 0x00}, // 69 E
{0x7E, 0x60, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00}, // 70 F
{0x3C, 0x66, 0x60, 0x6E, 0x66, 0x66, 0x3C, 0x00}, // 71 G
{0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00}, // 72 H
{0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00}, // 73 I
{0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x00}, // 74 J
{0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66, 0x00}, // 75 K
{0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00}, // 76 L
{0x63, 0x77, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x00}, // 77 M
{0x63, 0x73, 0x7B, 0x6F, 0x67, 0x63, 0x63, 0x00}, // 78 N
{0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // 79 O
{0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00}, // 80 P
{0x3C, 0x66, 0x66, 0x66, 0x76, 0x3C, 0x0E, 0x00}, // 81 Q
{0x7C, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x00}, // 82 R
{0x3C, 0x66, 0x60, 0x3C, 0x06, 0x66, 0x3C, 0x00}, // 83 S
{0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00}, // 84 T
{0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00}, // 85 U
{0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00}, // 86 V
{0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // 87 W
{0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00}, // 88 X
{0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00}, // 89 Y
{0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00}, // 90 Z
{0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00}, // 91 [
{0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // 92 \
{0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00}, // 93 ]
{0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00}, // 94 ^
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF}, // 95 _
{0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}, // 96 `
{0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0x00}, // 97 a
{0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00}, // 98 b
{0x00, 0x00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0x00}, // 99 c
{0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3B, 0x00}, // 100 d
{0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00}, // 101 e
{0x1C, 0x36, 0x30, 0x78, 0x30, 0x30, 0x30, 0x00}, // 102 f
{0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x3C}, // 103 g
{0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00}, // 104 h
{0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00}, // 105 i
{0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38}, // 106 j
{0x60, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0x00}, // 107 k
{0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00}, // 108 l
{0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xD6, 0xC6, 0x00}, // 109 m
{0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00}, // 110 n
{0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00}, // 111 o
{0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60}, // 112 p
{0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x06}, // 113 q
{0x00, 0x00, 0x6E, 0x76, 0x60, 0x60, 0x60, 0x00}, // 114 r
{0x00, 0x00, 0x3C, 0x60, 0x3C, 0x06, 0x3C, 0x00}, // 115 s
{0x30, 0x30, 0x7C, 0x30, 0x30, 0x36, 0x1C, 0x00}, // 116 t
{0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3B, 0x00}, // 117 u
{0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00}, // 118 v
{0x00, 0x00, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00}, // 119 w
{0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00}, // 120 x
{0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x3C}, // 121 y
{0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00}, // 122 z
{0x0E, 0x18, 0x18, 0x18, 0x3C, 0x18, 0x18, 0x0E}, // 123 {
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, // 124 |
{0x70, 0x18, 0x18, 0x18, 0x3C, 0x18, 0x18, 0x70}, // 125 }
{0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // 126 ~
};

10
src/font.h Normal file
View file

@ -0,0 +1,10 @@
// font.h
#ifndef FONT_H
#define FONT_H
#include <stdint.h>
// Массив содержит 95 символов (от пробела до '~'), каждый по 8 байт
extern const uint8_t font8x8[95][8];
#endif

View file

@ -22,6 +22,10 @@ extern uint8_t _binary_assets_logo_bmp_start[];
extern uint8_t _binary_assets_bg_bmp_start[];
extern uint8_t _binary_assets_cursor_bmp_start[];
uint32_t frame_count = 0; // Сколько раз отрисовали за секунду
uint32_t last_fps_ticks = 0; // Когда последний раз обновляли FPS
uint32_t current_fps = 0; // Результат (число FPS)
extern uint32_t _kernel_end; // Символ 'end' прописан в конце любого стандартного linker.ld
uint32_t kernel_end = (uint32_t)&_kernel_end;
@ -199,16 +203,25 @@ void kernel_main(uint32_t mboot_addr, uint32_t magic) {
log_info(LOG_NORMAL, "OK!");
int old_mouse_x = 0;
int old_mouse_y = 0;
char fpsbuf[4];
while (1) {
if (mouse_x != old_mouse_x || mouse_y != old_mouse_y) {
// Стираем старый
draw_bmp(_binary_assets_bg_bmp_start, 0, 0);
// Рисуем новый
draw_cursor_sprite(_binary_assets_cursor_bmp_start, mouse_x, mouse_y);
old_mouse_x = mouse_x;
old_mouse_y = mouse_y;
// 1. Всегда рисуем фон и элементы
draw_bmp(_binary_assets_bg_bmp_start, 0, 0);
draw_cursor_sprite(_binary_assets_cursor_bmp_start, mouse_x, mouse_y);
// 2. Всегда рисуем FPS
draw_string("FPS: ", 0, 0, color_white);
itoa(current_fps, fpsbuf, 10);
draw_string(fpsbuf, 40, 0, color_white);
// 3. Считаем кадр
frame_count++;
// 4. Логика обновления FPS (раз в секунду)
if (system_ticks - last_fps_ticks >= 100) {
current_fps = frame_count;
frame_count = 0;
last_fps_ticks = system_ticks;
}
}
}

View file

@ -116,52 +116,43 @@ int atoi(const char* str) {
// Число в строку (поддерживает base = 10 и base = 2)
char* itoa(int value, char* str, int base) {
int i = 0;
// Используем unsigned, чтобы безопасно обрабатывать MIN_INT
unsigned int n;
int is_negative = 0;
// Защита от дурака
if (base < 2 || base > 36) {
str[0] = '\0';
return str;
if (base < 2 || base > 36) { str[0] = '\0'; return str; }
if (value < 0 && base == 10) {
is_negative = 1;
n = (unsigned int)(-value); // Приводим к unsigned перед инверсией
} else {
n = (unsigned int)value;
}
// Обрабатываем 0
if (value == 0) {
if (n == 0) {
str[i++] = '0';
str[i] = '\0';
return str;
}
// Отрицательные числа обрабатываем только для десятичной системы
if (value < 0 && base == 10) {
is_negative = 1;
value = -value;
}
// Переводим число в строку (но она получится задом наперед)
while (value != 0) {
int rem = value % base;
while (n != 0) {
int rem = n % base;
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
value = value / base;
}
// Добавляем минус
if (is_negative) {
str[i++] = '-';
n /= base;
}
if (is_negative) str[i++] = '-';
str[i] = '\0';
// Переворачиваем строку в нормальный вид
int start = 0;
int end = i - 1;
// Разворот (этот кусок у тебя верный)
int start = 0, end = i - 1;
while (start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
start++; end--;
}
return str;
}