2021-11-26 07:18:08 +03:00
|
|
|
/**
|
|
|
|
* @brief Abstractions for text output.
|
|
|
|
*
|
|
|
|
* Tries to provide a common interface to text output for
|
|
|
|
* EFI framebuffer, BIOS VESA framebuffer, and BIOS VGA text mode.
|
|
|
|
*
|
|
|
|
* I don't know why I haven't added a full printf to this.
|
|
|
|
*
|
|
|
|
* A lot of this could be rewritten...
|
|
|
|
*
|
|
|
|
* @copyright
|
|
|
|
* This file is part of ToaruOS and is released under the terms
|
|
|
|
* of the NCSA / University of Illinois License - see LICENSE.md
|
|
|
|
* Copyright (C) 2018-2021 K. Lange
|
|
|
|
*/
|
2021-06-14 05:11:37 +03:00
|
|
|
#include "text.h"
|
2021-09-07 05:45:58 +03:00
|
|
|
#include "util.h"
|
2021-06-14 05:11:37 +03:00
|
|
|
int txt_debug = 0;
|
|
|
|
|
2021-09-07 05:45:58 +03:00
|
|
|
#ifdef EFI_PLATFORM
|
|
|
|
#include <efi.h>
|
|
|
|
extern EFI_SYSTEM_TABLE *ST;
|
2021-10-19 14:29:44 +03:00
|
|
|
#else
|
|
|
|
#include <stdint.h>
|
|
|
|
#endif
|
2021-09-07 05:45:58 +03:00
|
|
|
|
|
|
|
#include "../apps/terminal-font.h"
|
|
|
|
#define char_height LARGE_FONT_CELL_HEIGHT
|
|
|
|
#define char_width LARGE_FONT_CELL_WIDTH
|
|
|
|
|
|
|
|
static int offset_x = 0;
|
|
|
|
static int offset_y = 0;
|
2021-10-26 10:13:50 +03:00
|
|
|
static int center_x = 0;
|
|
|
|
static int center_y = 0;
|
2021-09-07 05:45:58 +03:00
|
|
|
|
2021-10-19 14:29:44 +03:00
|
|
|
static void write_char(int x, int y, int val, int attr);
|
|
|
|
|
|
|
|
#ifdef EFI_PLATFORM
|
|
|
|
|
2021-10-26 10:13:50 +03:00
|
|
|
int in_graphics_mode = 1;
|
|
|
|
|
2021-10-19 14:29:44 +03:00
|
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL * GOP;
|
|
|
|
|
2021-09-07 05:45:58 +03:00
|
|
|
static EFI_GUID efi_graphics_output_protocol_guid =
|
|
|
|
{0x9042a9de,0x23dc,0x4a38, {0x96,0xfb,0x7a,0xde,0xd0,0x80,0x51,0x6a}};
|
|
|
|
|
|
|
|
int init_graphics() {
|
|
|
|
UINTN count;
|
|
|
|
EFI_HANDLE * handles;
|
|
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL * gfx;
|
|
|
|
EFI_STATUS status;
|
|
|
|
|
|
|
|
status = uefi_call_wrapper(ST->BootServices->LocateHandleBuffer,
|
|
|
|
5, ByProtocol, &efi_graphics_output_protocol_guid, NULL, &count, &handles);
|
|
|
|
if (EFI_ERROR(status)) goto no_graphics;
|
|
|
|
status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
|
|
|
|
3, handles[0], &efi_graphics_output_protocol_guid, (void **)&gfx);
|
|
|
|
if (EFI_ERROR(status)) goto no_graphics;
|
|
|
|
|
|
|
|
GOP = gfx;
|
|
|
|
|
|
|
|
int total_width = GOP->Mode->Info->HorizontalResolution;
|
|
|
|
int total_height = GOP->Mode->Info->VerticalResolution;
|
|
|
|
|
|
|
|
offset_x = (total_width - 80 * char_width) / 2;
|
|
|
|
offset_y = (total_height - 24 * char_height) / 2;
|
|
|
|
|
2021-10-26 10:13:50 +03:00
|
|
|
center_x = total_width / 2;
|
|
|
|
center_y = total_height / 2;
|
|
|
|
|
2021-09-07 05:45:58 +03:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
no_graphics:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-10-19 14:29:44 +03:00
|
|
|
static void set_point(int x, int y, uint32_t color) {
|
|
|
|
((uint32_t *)GOP->Mode->FrameBufferBase)[(x + offset_x) + (y + offset_y) * GOP->Mode->Info->PixelsPerScanLine] = color;
|
|
|
|
}
|
|
|
|
void clear_() {
|
|
|
|
x = 0;
|
|
|
|
y = 0;
|
|
|
|
memset((void*)GOP->Mode->FrameBufferBase,0,GOP->Mode->FrameBufferSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void placech(unsigned char c, int x, int y, int attr) {
|
|
|
|
write_char(x * char_width, y * char_height, c, attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
extern uint32_t *vbe_info_fbaddr;
|
|
|
|
extern uint16_t vbe_info_pitch;
|
|
|
|
extern uint16_t vbe_info_width;
|
|
|
|
extern uint16_t vbe_info_height;
|
|
|
|
extern uint8_t vbe_info_bpp;
|
|
|
|
|
|
|
|
int in_graphics_mode = 0;
|
|
|
|
|
|
|
|
void init_graphics(void) {
|
|
|
|
if (!vbe_info_width) return;
|
|
|
|
in_graphics_mode = 1;
|
|
|
|
offset_x = (vbe_info_width - 80 * char_width) / 2;
|
|
|
|
offset_y = (vbe_info_height - 24 * char_height) / 2;
|
2021-10-26 10:13:50 +03:00
|
|
|
|
|
|
|
center_x = vbe_info_width / 2;
|
|
|
|
center_y = vbe_info_height / 2;
|
2021-10-19 14:29:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void set_point(int x, int y, uint32_t color) {
|
|
|
|
if (vbe_info_bpp == 24) {
|
|
|
|
*((uint8_t*)vbe_info_fbaddr + (x + offset_x) * 3 + (y + offset_y) * (vbe_info_pitch)) = (color >> 0) & 0xFF;
|
|
|
|
*((uint8_t*)vbe_info_fbaddr + (x + offset_x) * 3 + (y + offset_y) * (vbe_info_pitch) + 1) = (color >> 8) & 0xFF;
|
|
|
|
*((uint8_t*)vbe_info_fbaddr + (x + offset_x) * 3 + (y + offset_y) * (vbe_info_pitch) + 2) = (color >> 16) & 0xFF;
|
|
|
|
} else if (vbe_info_bpp == 32) {
|
2021-10-26 12:32:32 +03:00
|
|
|
vbe_info_fbaddr[(x + offset_x) + (y + offset_y) * (vbe_info_pitch >> 2)] = color;
|
2021-10-19 14:29:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned short * textmemptr = (unsigned short *)0xB8000;
|
|
|
|
|
|
|
|
static void placech_vga(unsigned char c, int x, int y, int attr) {
|
|
|
|
unsigned short *where;
|
|
|
|
unsigned att = attr << 8;
|
|
|
|
where = textmemptr + (y * 80 + x);
|
|
|
|
*where = c | att;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void placech(unsigned char c, int x, int y, int attr) {
|
|
|
|
in_graphics_mode ? write_char(x * char_width, y * char_height, c, attr) : placech_vga(c,x,y,attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear_() {
|
|
|
|
x = 0;
|
|
|
|
y = 0;
|
|
|
|
if (in_graphics_mode) {
|
|
|
|
memset(vbe_info_fbaddr, 0, vbe_info_pitch * vbe_info_height);
|
|
|
|
} else {
|
|
|
|
for (int y = 0; y < 24; ++y) {
|
|
|
|
for (int x = 0; x < 80; ++x) {
|
|
|
|
placech_vga(' ', x, y, 0x00);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-09-07 05:45:58 +03:00
|
|
|
static uint32_t term_colors[] = {
|
|
|
|
0xFF000000,
|
|
|
|
0xFFCC0000,
|
|
|
|
0xFF4E9A06,
|
|
|
|
0xFFC4A000,
|
|
|
|
0xFF3465A4,
|
|
|
|
0xFF75507B,
|
|
|
|
0xFF06989A,
|
|
|
|
0xFFD3D7CF,
|
|
|
|
|
|
|
|
0xFF555753,
|
|
|
|
0xFFEF2929,
|
|
|
|
0xFF8AE234,
|
|
|
|
0xFFFCE94F,
|
|
|
|
0xFF729FCF,
|
|
|
|
0xFFAD7FA8,
|
|
|
|
0xFF34E2E2,
|
|
|
|
0xFFEEEEEC,
|
|
|
|
};
|
|
|
|
|
|
|
|
char vga_to_ansi[] = {
|
|
|
|
0, 4, 2, 6, 1, 5, 3, 7,
|
|
|
|
8,12,10,14, 9,13,11,15
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void write_char(int x, int y, int val, int attr) {
|
|
|
|
if (val > 128) {
|
|
|
|
val = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t fg_color = term_colors[vga_to_ansi[attr & 0xF]];
|
|
|
|
uint32_t bg_color = term_colors[vga_to_ansi[(attr >> 4) & 0xF]];
|
|
|
|
|
2021-10-26 12:32:32 +03:00
|
|
|
uint32_t colors[] = {bg_color, fg_color};
|
|
|
|
|
2021-09-07 05:45:58 +03:00
|
|
|
uint16_t * c = large_font[val];
|
|
|
|
for (uint8_t i = 0; i < char_height; ++i) {
|
|
|
|
for (uint8_t j = 0; j < char_width; ++j) {
|
2021-10-26 12:32:32 +03:00
|
|
|
set_point(x+j,y+i,colors[!!(c[i] & (1 << LARGE_FONT_MASK-j))]);
|
2021-09-07 05:45:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-06-14 05:11:37 +03:00
|
|
|
int x = 0;
|
|
|
|
int y = 0;
|
|
|
|
int attr = 0x07;
|
|
|
|
|
|
|
|
void print_(char * str) {
|
|
|
|
while (*str) {
|
|
|
|
if (*str == '\n') {
|
|
|
|
for (; x < 80; ++x) {
|
|
|
|
placech(' ', x, y, attr);
|
|
|
|
}
|
|
|
|
x = 0;
|
|
|
|
y += 1;
|
|
|
|
if (y == 24) {
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
placech(*str, x, y, attr);
|
|
|
|
x++;
|
|
|
|
if (x == 80) {
|
|
|
|
x = 0;
|
|
|
|
y += 1;
|
|
|
|
if (y == 24) {
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void move_cursor(int _x, int _y) {
|
|
|
|
x = _x;
|
|
|
|
y = _y;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_attr(int _attr) {
|
|
|
|
attr = _attr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void print_banner(char * str) {
|
|
|
|
if (!str) {
|
|
|
|
for (int i = 0; i < 80; ++i) {
|
|
|
|
placech(' ', i, y, attr);
|
|
|
|
}
|
|
|
|
y++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int len = 0;
|
|
|
|
char *c = str;
|
|
|
|
while (*c) {
|
|
|
|
len++;
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
int off = (80 - len) / 2;
|
|
|
|
|
|
|
|
for (int i = 0; i < 80; ++i) {
|
2021-10-26 12:32:32 +03:00
|
|
|
placech((i >= off && i - off < len) ? str[i-off] : ' ', i, y, attr);
|
2021-06-14 05:11:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
y++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void print_hex_(unsigned int value) {
|
|
|
|
char out[9] = {0};
|
|
|
|
for (int i = 7; i > -1; i--) {
|
|
|
|
out[i] = "0123456789abcdef"[(value >> (4 * (7 - i))) & 0xF];
|
|
|
|
}
|
|
|
|
print_(out);
|
|
|
|
}
|
|
|
|
|
2021-10-19 14:29:44 +03:00
|
|
|
void print_int_(unsigned int value) {
|
|
|
|
if (value == 0) {
|
|
|
|
print_("0");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
unsigned int n_width = 1;
|
|
|
|
char tmp[32] = {0};
|
|
|
|
unsigned int val = value;
|
|
|
|
while (val >= 10UL) {
|
|
|
|
val /= 10UL;
|
|
|
|
n_width++;
|
|
|
|
}
|
|
|
|
int i = n_width;
|
|
|
|
while (i > 0) {
|
|
|
|
tmp[i-1] = (value % 10UL) + '0';
|
|
|
|
value /= 10UL;
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
while (i < n_width) {
|
|
|
|
char t[2] = {tmp[i],'\0'};
|
|
|
|
print_(t);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
2021-10-26 10:13:50 +03:00
|
|
|
|
|
|
|
static void draw_square(int x, int y, int stage) {
|
|
|
|
for (int _y = 0; _y < 7; ++_y) {
|
|
|
|
unsigned int color_green = 0xB2 - (y * 8 + _y) * 2;
|
|
|
|
unsigned int color_blue = 0xFF;
|
|
|
|
|
|
|
|
if (stage > 0 && y + 1 != stage) {
|
|
|
|
color_green /= 2;
|
|
|
|
color_blue /= 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int color = 0xFF000000 | (color_green << 8) | color_blue;
|
|
|
|
|
|
|
|
for (int _x = 0; _x < 7; ++_x) {
|
|
|
|
set_point(center_x - 32 - offset_x + x * 8 + _x, center_y - 32 - offset_y + y * 8 + _y, color);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void draw_logo(int stage) {
|
|
|
|
if (!in_graphics_mode) return;
|
|
|
|
uint64_t logo_squares = 0x981818181818FFFFUL;
|
|
|
|
for (int y = 0; y < 8; ++y) {
|
|
|
|
for (int x = 0; x < 8; ++x) {
|
|
|
|
if (logo_squares & (1 << x)) {
|
|
|
|
draw_square(x,y,stage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
logo_squares >>= 8;
|
|
|
|
}
|
|
|
|
}
|