рисовашк текст
This commit is contained in:
parent
e68f41f652
commit
94b03ee1f3
7 changed files with 185 additions and 37 deletions
|
|
@ -24,7 +24,7 @@ ZalupaCalc 2 - это инновационная операционная сис
|
||||||
- [x] Вывод на экран попиксельно
|
- [x] Вывод на экран попиксельно
|
||||||
- [x] Вывод на экран прямоугольников и прочих фигур
|
- [x] Вывод на экран прямоугольников и прочих фигур
|
||||||
- [x] Вывод на экран BMP
|
- [x] Вывод на экран BMP
|
||||||
- [ ] Вывод на экран текста
|
- [x] Вывод на экран текста
|
||||||
- [ ] Двойная буферизация
|
- [ ] Двойная буферизация
|
||||||
- [ ] Вывод курсора мыши на экран, движение
|
- [ ] Вывод курсора мыши на экран, движение
|
||||||
- [ ] Кнопки (touch zones, массив в памяти где будут координаты областей и действия при нажатии)
|
- [ ] Кнопки (touch zones, массив в памяти где будут координаты областей и действия при нажатии)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "multiboot.h"
|
#include "multiboot.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
#include "vmm.h" // Для маппинга
|
#include "vmm.h" // Для маппинга
|
||||||
|
#include "font.h"
|
||||||
#define TRANSPARENT_COLOR 0xFF00FF
|
#define TRANSPARENT_COLOR 0xFF00FF
|
||||||
|
|
||||||
uint32_t* fb_ptr = 0;
|
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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 clear_screen(uint32_t color);
|
||||||
void draw_bmp(uint8_t* data, int x, int y);
|
void draw_bmp(uint8_t* data, int x, int y);
|
||||||
void draw_cursor_sprite(uint8_t* bmp_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
|
#endif
|
||||||
|
|
|
||||||
99
src/font.c
Normal file
99
src/font.c
Normal 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
10
src/font.h
Normal 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
|
||||||
27
src/kmain.c
27
src/kmain.c
|
|
@ -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_bg_bmp_start[];
|
||||||
extern uint8_t _binary_assets_cursor_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
|
extern uint32_t _kernel_end; // Символ 'end' прописан в конце любого стандартного linker.ld
|
||||||
uint32_t kernel_end = (uint32_t)&_kernel_end;
|
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!");
|
log_info(LOG_NORMAL, "OK!");
|
||||||
int old_mouse_x = 0;
|
int old_mouse_x = 0;
|
||||||
int old_mouse_y = 0;
|
int old_mouse_y = 0;
|
||||||
|
char fpsbuf[4];
|
||||||
while (1) {
|
while (1) {
|
||||||
if (mouse_x != old_mouse_x || mouse_y != old_mouse_y) {
|
// 1. Всегда рисуем фон и элементы
|
||||||
// Стираем старый
|
draw_bmp(_binary_assets_bg_bmp_start, 0, 0);
|
||||||
draw_bmp(_binary_assets_bg_bmp_start, 0, 0);
|
draw_cursor_sprite(_binary_assets_cursor_bmp_start, mouse_x, mouse_y);
|
||||||
|
|
||||||
// Рисуем новый
|
// 2. Всегда рисуем FPS
|
||||||
draw_cursor_sprite(_binary_assets_cursor_bmp_start, mouse_x, mouse_y);
|
draw_string("FPS: ", 0, 0, color_white);
|
||||||
|
itoa(current_fps, fpsbuf, 10);
|
||||||
|
draw_string(fpsbuf, 40, 0, color_white);
|
||||||
|
|
||||||
old_mouse_x = mouse_x;
|
// 3. Считаем кадр
|
||||||
old_mouse_y = mouse_y;
|
frame_count++;
|
||||||
|
|
||||||
|
// 4. Логика обновления FPS (раз в секунду)
|
||||||
|
if (system_ticks - last_fps_ticks >= 100) {
|
||||||
|
current_fps = frame_count;
|
||||||
|
frame_count = 0;
|
||||||
|
last_fps_ticks = system_ticks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
45
src/string.c
45
src/string.c
|
|
@ -116,52 +116,43 @@ int atoi(const char* str) {
|
||||||
// Число в строку (поддерживает base = 10 и base = 2)
|
// Число в строку (поддерживает base = 10 и base = 2)
|
||||||
char* itoa(int value, char* str, int base) {
|
char* itoa(int value, char* str, int base) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
// Используем unsigned, чтобы безопасно обрабатывать MIN_INT
|
||||||
|
unsigned int n;
|
||||||
int is_negative = 0;
|
int is_negative = 0;
|
||||||
|
|
||||||
// Защита от дурака
|
if (base < 2 || base > 36) { str[0] = '\0'; return str; }
|
||||||
if (base < 2 || base > 36) {
|
|
||||||
str[0] = '\0';
|
if (value < 0 && base == 10) {
|
||||||
return str;
|
is_negative = 1;
|
||||||
|
n = (unsigned int)(-value); // Приводим к unsigned перед инверсией
|
||||||
|
} else {
|
||||||
|
n = (unsigned int)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обрабатываем 0
|
if (n == 0) {
|
||||||
if (value == 0) {
|
|
||||||
str[i++] = '0';
|
str[i++] = '0';
|
||||||
str[i] = '\0';
|
str[i] = '\0';
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Отрицательные числа обрабатываем только для десятичной системы
|
while (n != 0) {
|
||||||
if (value < 0 && base == 10) {
|
int rem = n % base;
|
||||||
is_negative = 1;
|
|
||||||
value = -value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Переводим число в строку (но она получится задом наперед)
|
|
||||||
while (value != 0) {
|
|
||||||
int rem = value % base;
|
|
||||||
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
|
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
|
||||||
value = value / base;
|
n /= base;
|
||||||
}
|
|
||||||
|
|
||||||
// Добавляем минус
|
|
||||||
if (is_negative) {
|
|
||||||
str[i++] = '-';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_negative) str[i++] = '-';
|
||||||
str[i] = '\0';
|
str[i] = '\0';
|
||||||
|
|
||||||
// Переворачиваем строку в нормальный вид
|
// Разворот (этот кусок у тебя верный)
|
||||||
int start = 0;
|
int start = 0, end = i - 1;
|
||||||
int end = i - 1;
|
|
||||||
while (start < end) {
|
while (start < end) {
|
||||||
char temp = str[start];
|
char temp = str[start];
|
||||||
str[start] = str[end];
|
str[start] = str[end];
|
||||||
str[end] = temp;
|
str[end] = temp;
|
||||||
start++;
|
start++; end--;
|
||||||
end--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue