Merge pull request #33 from sleepy-monax/master
The color scheme can be changed using the configuration file.
This commit is contained in:
commit
d192bb9101
|
@ -22,6 +22,8 @@ Some *local assignments* are shared between entries using any *protocol*, while
|
|||
*Globally assignable* keys are:
|
||||
* `TIMEOUT` - Specifies the timeout in seconds before the first *entry* is automatically booted.
|
||||
* `TEXTMODE` - If set to `on`, do not use graphical VESA framebuffer for the boot menu.
|
||||
* `THEME_BLACK`, `THEME_RED`, `THEME_GREEN`, `THEME_BROWN`, `THEME_BLUE`, `THEME_MAGENTA`, `THEME_CYAN`, `THEME_GREY`, `THEME_WHITE` - Specifies the colors used by the terminal (RRGGBB).
|
||||
* `THEME_MARGIN` - Set the amount of margin around the terminal.
|
||||
|
||||
*Locally assignable (non protocol specific)* keys are:
|
||||
* `PROTOCOL` - The boot protocol that will be used to boot the kernel. Valid protocols are: `linux`, `stivale`, `chainload`.
|
||||
|
|
BIN
limine.bin
BIN
limine.bin
Binary file not shown.
|
@ -28,22 +28,106 @@ static void vga_font_retrieve(void) {
|
|||
memcpy(vga_font, (void *)rm_desegment(r.es, r.ebp), VGA_FONT_MAX);
|
||||
}
|
||||
|
||||
static uint32_t ansi_colours[] = {
|
||||
0x00000000, // black
|
||||
0x00aa0000, // red
|
||||
0x0000aa00, // green
|
||||
0x00aa5500, // brown
|
||||
0x000000aa, // blue
|
||||
0x00aa00aa, // magenta
|
||||
0x0000aaaa, // cyan
|
||||
0x00aaaaaa, // grey
|
||||
0x00ffffff // white
|
||||
};
|
||||
|
||||
static uint32_t *vbe_framebuffer;
|
||||
static uint16_t vbe_pitch;
|
||||
static uint16_t vbe_width = 0;
|
||||
static uint16_t vbe_height = 0;
|
||||
static uint16_t vbe_bpp = 0;
|
||||
|
||||
static int frame_height, frame_width;
|
||||
static int frame_height;
|
||||
static int frame_width;
|
||||
static int frame_margin = 64;
|
||||
|
||||
static struct image *background;
|
||||
|
||||
#define A(rgb) (uint8_t)(rgb >> 24)
|
||||
#define R(rgb) (uint8_t)(rgb >> 16)
|
||||
#define G(rgb) (uint8_t)(rgb >> 8)
|
||||
#define B(rgb) (uint8_t)(rgb)
|
||||
#define ARGB(a, r, g, b) (a << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF)
|
||||
|
||||
static inline uint32_t color_blend(uint32_t fg, uint32_t bg)
|
||||
{
|
||||
uint8_t alpha = 255 - A(fg) ;
|
||||
uint8_t inv_alpha = A(fg) - 1;
|
||||
|
||||
uint8_t r = (uint8_t)((alpha * R(fg) + inv_alpha * R(bg)) / 255);
|
||||
uint8_t g = (uint8_t)((alpha * G(fg) + inv_alpha * G(bg)) / 255);
|
||||
uint8_t b = (uint8_t)((alpha * B(fg) + inv_alpha * B(bg)) / 255);
|
||||
|
||||
return ARGB(0, r, g, b);
|
||||
}
|
||||
|
||||
void vbe_plot_px(int x, int y, uint32_t hex) {
|
||||
size_t fb_i = x + (vbe_pitch / sizeof(uint32_t)) * y;
|
||||
|
||||
vbe_framebuffer[fb_i] = hex;
|
||||
}
|
||||
|
||||
void vbe_blend_px(int x, int y, uint32_t hex) {
|
||||
size_t fb_i = x + (vbe_pitch / sizeof(uint32_t)) * y;
|
||||
|
||||
vbe_framebuffer[fb_i] = color_blend(hex, vbe_framebuffer[fb_i]);
|
||||
}
|
||||
|
||||
void vbe_fill_rect(int x, int y, int width, int height, uint32_t hex)
|
||||
{
|
||||
for (int xx = 0; xx < width; xx++)
|
||||
for (int yy = 0; yy < height; yy++)
|
||||
vbe_plot_px(x + xx, y + yy, hex);
|
||||
}
|
||||
|
||||
void vbe_blend_rect(int x, int y, int width, int height, uint32_t hex)
|
||||
{
|
||||
for (int xx = 0; xx < width; xx++)
|
||||
for (int yy = 0; yy < height; yy++)
|
||||
vbe_blend_px(x + xx, y + yy, hex);
|
||||
}
|
||||
|
||||
void vbe_plot_background(int x, int y, int width, int height)
|
||||
{
|
||||
if (background) {
|
||||
for (int xx = 0; xx < width; xx++)
|
||||
for (int yy = 0; yy < height; yy++)
|
||||
vbe_plot_px(x + xx, y + yy, background->get_pixel(background, x + xx, y + yy));
|
||||
}
|
||||
else{
|
||||
for (int xx = 0; xx < width; xx++)
|
||||
for (int yy = 0; yy < height; yy++) {
|
||||
uint32_t pixel = color_blend(ansi_colours[0], 0x000000);
|
||||
vbe_plot_px(x + xx, y + yy, pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vbe_plot_background_colored(int x, int y, int width, int height, uint32_t hex){
|
||||
if (background) {
|
||||
for (int xx = 0; xx < width; xx++)
|
||||
for (int yy = 0; yy < height; yy++){
|
||||
uint32_t pixel = color_blend(hex, background->get_pixel(background, x + xx, y + yy));
|
||||
vbe_plot_px(x + xx, y + yy, pixel);
|
||||
}
|
||||
}else{
|
||||
for (int xx = 0; xx < width; xx++)
|
||||
for (int yy = 0; yy < height; yy++) {
|
||||
uint32_t pixel = color_blend(hex, 0x000000);
|
||||
vbe_plot_px(x + xx, y + yy, pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct vbe_char {
|
||||
char c;
|
||||
uint32_t fg;
|
||||
|
@ -51,15 +135,28 @@ struct vbe_char {
|
|||
};
|
||||
|
||||
void vbe_plot_char(struct vbe_char c, int x, int y) {
|
||||
int orig_x = x;
|
||||
uint8_t *glyph = &vga_font[c.c * VGA_FONT_HEIGHT];
|
||||
|
||||
for (int i = 0; i < VGA_FONT_HEIGHT; i++) {
|
||||
for (int j = VGA_FONT_WIDTH - 1; j >= 0; j--) {
|
||||
vbe_plot_px(x++, y, (glyph[i] & (1 << j)) ? c.fg : c.bg);
|
||||
if (A(c.bg)) {
|
||||
vbe_plot_background_colored(x, y, VGA_FONT_WIDTH, VGA_FONT_HEIGHT, c.bg);
|
||||
} else {
|
||||
vbe_fill_rect(x, y, VGA_FONT_WIDTH, VGA_FONT_HEIGHT, c.bg);
|
||||
}
|
||||
|
||||
if (A(c.fg)) {
|
||||
for (int i = 0; i < VGA_FONT_HEIGHT; i++) {
|
||||
for (int j = 0; j < VGA_FONT_WIDTH; j++) {
|
||||
if ((glyph[i] & (0x80 >> j)))
|
||||
vbe_blend_px(x + j, y + i, c.fg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < VGA_FONT_HEIGHT; i++) {
|
||||
for (int j = 0; j < VGA_FONT_WIDTH; j++) {
|
||||
if ((glyph[i] & (0x80 >> j)))
|
||||
vbe_plot_px(x + j, y + i, c.fg);
|
||||
}
|
||||
}
|
||||
y++;
|
||||
x = orig_x;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,11 +220,6 @@ static void scroll(void) {
|
|||
void vbe_clear(bool move) {
|
||||
clear_cursor();
|
||||
|
||||
if (background != NULL)
|
||||
for (int x = 0; x < vbe_width; x++)
|
||||
for (int y = 0; y < vbe_height; y++)
|
||||
vbe_plot_px(x, y, background->get_pixel(background, x, y));
|
||||
|
||||
struct vbe_char empty;
|
||||
empty.c = ' ';
|
||||
empty.fg = text_fg;
|
||||
|
@ -166,17 +258,6 @@ void vbe_get_cursor_pos(int *x, int *y) {
|
|||
*y = cursor_y;
|
||||
}
|
||||
|
||||
static uint32_t ansi_colours[] = {
|
||||
0x00000000, // black
|
||||
0x00aa0000, // red
|
||||
0x0000aa00, // green
|
||||
0x00aa5500, // brown
|
||||
0x000000aa, // blue
|
||||
0x00aa00aa, // magenta
|
||||
0x0000aaaa, // cyan
|
||||
0x00aaaaaa // grey
|
||||
};
|
||||
|
||||
void vbe_set_text_fg(int fg) {
|
||||
text_fg = ansi_colours[fg];
|
||||
}
|
||||
|
@ -185,6 +266,16 @@ void vbe_set_text_bg(int bg) {
|
|||
text_bg = ansi_colours[bg];
|
||||
}
|
||||
|
||||
void vbe_set_colors(uint32_t *colors){
|
||||
memcpy(ansi_colours, colors, sizeof(ansi_colours));
|
||||
text_bg = colors[0];
|
||||
text_fg = colors[7];
|
||||
}
|
||||
|
||||
void vbe_set_margin(int margin){
|
||||
frame_margin = margin;
|
||||
}
|
||||
|
||||
void vbe_putchar(char c) {
|
||||
switch (c) {
|
||||
case '\b':
|
||||
|
@ -234,14 +325,15 @@ void vbe_putchar(char c) {
|
|||
void vbe_tty_init(int *_rows, int *_cols, struct image *_background) {
|
||||
init_vbe(&vbe_framebuffer, &vbe_pitch, &vbe_width, &vbe_height, &vbe_bpp);
|
||||
vga_font_retrieve();
|
||||
*_cols = cols = 80;
|
||||
*_rows = rows = 25;
|
||||
*_cols = cols = (vbe_width - frame_margin * 2) / VGA_FONT_WIDTH;
|
||||
*_rows = rows = (vbe_height - frame_margin * 2) / VGA_FONT_HEIGHT;
|
||||
grid = ext_mem_alloc(rows * cols * sizeof(struct vbe_char));
|
||||
background = _background;
|
||||
|
||||
frame_height = vbe_height / 2 - (VGA_FONT_HEIGHT * rows) / 2;
|
||||
frame_width = vbe_width / 2 - (VGA_FONT_WIDTH * cols) / 2;
|
||||
|
||||
vbe_plot_background(0, 0, vbe_width, vbe_height);
|
||||
vbe_clear(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,5 +17,7 @@ void vbe_set_cursor_pos(int x, int y);
|
|||
void vbe_get_cursor_pos(int *x, int *y);
|
||||
void vbe_set_text_fg(int fg);
|
||||
void vbe_set_text_bg(int bg);
|
||||
void vbe_set_colors(uint32_t *colors);
|
||||
void vbe_set_margin(int margin);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -46,10 +46,31 @@ __attribute__((noreturn)) void panic(const char *fmt, ...) {
|
|||
}
|
||||
}
|
||||
|
||||
static int char_value(char c) {
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
return (c - 'a') + 10;
|
||||
}
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
return (c - 'A') + 10;
|
||||
}
|
||||
if (c >= '0' && c <= '9'){
|
||||
return c - '0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t strtoui(const char *s) {
|
||||
uint64_t n = 0;
|
||||
while (*s)
|
||||
n = n * 10 + ((*(s++)) - '0');
|
||||
n = n * 10 + char_value(*(s++));
|
||||
return n;
|
||||
}
|
||||
|
||||
uint64_t strtoui16(const char *s) {
|
||||
uint64_t n = 0;
|
||||
while (*s)
|
||||
n = n * 16 + char_value(*(s++));
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ int pit_sleep_and_quit_on_keypress(uint32_t pit_ticks);
|
|||
int getchar(void);
|
||||
void gets(const char *orig_str, char *buf, size_t limit);
|
||||
uint64_t strtoui(const char *s);
|
||||
uint64_t strtoui16(const char *s);
|
||||
|
||||
#define DIV_ROUNDUP(a, b) (((a) + ((b) - 1)) / (b))
|
||||
|
||||
|
|
|
@ -113,6 +113,12 @@ static void term_putchar(char c) {
|
|||
}
|
||||
|
||||
static void sgr(void) {
|
||||
if (esc_value0 == 0){
|
||||
set_text_bg(0);
|
||||
set_text_fg(7);
|
||||
return;
|
||||
}
|
||||
|
||||
if (esc_value0 >= 30 && esc_value0 <= 37) {
|
||||
set_text_fg(esc_value0 - 30);
|
||||
return;
|
||||
|
|
|
@ -9,12 +9,72 @@
|
|||
#include <lib/config.h>
|
||||
#include <lib/term.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <drivers/vbe.h>
|
||||
|
||||
static char *cmdline;
|
||||
#define CMDLINE_MAX 1024
|
||||
|
||||
static char config_entry_name[1024];
|
||||
|
||||
void load_theme_from_config(void) {
|
||||
char buf[16];
|
||||
|
||||
uint32_t colorsheme[9] = {
|
||||
0x00191919, // black
|
||||
0x00aa0000, // red
|
||||
0x0000aa00, // green
|
||||
0x00aa5500, // brown
|
||||
0x000000aa, // blue
|
||||
0x009076DE, // magenta
|
||||
0x0000aaaa, // cyan
|
||||
0x00aaaaaa, // grey
|
||||
0x00ffffff, // white
|
||||
};
|
||||
|
||||
|
||||
if (config_get_value(buf, 0, 16, "THEME_BLACK")) {
|
||||
colorsheme[0] = (int)strtoui16(buf);
|
||||
}
|
||||
|
||||
if (config_get_value(buf, 0, 16, "THEME_RED")) {
|
||||
colorsheme[1] = (int)strtoui16(buf);
|
||||
}
|
||||
|
||||
if (config_get_value(buf, 0, 16, "THEME_GREEN")) {
|
||||
colorsheme[2] = (int)strtoui16(buf);
|
||||
}
|
||||
|
||||
if (config_get_value(buf, 0, 16, "THEME_BROWN")) {
|
||||
colorsheme[3] = (int)strtoui16(buf);
|
||||
}
|
||||
|
||||
if (config_get_value(buf, 0, 16, "THEME_BLUE")) {
|
||||
colorsheme[4] = (int)strtoui16(buf);
|
||||
}
|
||||
|
||||
if (config_get_value(buf, 0, 16, "THEME_MAGENTA")) {
|
||||
colorsheme[5] = (int)strtoui16(buf);
|
||||
}
|
||||
|
||||
if (config_get_value(buf, 0, 16, "THEME_CYAN")) {
|
||||
colorsheme[6] = (int)strtoui16(buf);
|
||||
}
|
||||
|
||||
if (config_get_value(buf, 0, 16, "THEME_GREY")) {
|
||||
colorsheme[7] = (int)strtoui16(buf);
|
||||
}
|
||||
|
||||
if (config_get_value(buf, 0, 16, "THEME_WHITE")) {
|
||||
colorsheme[8] = (int)strtoui16(buf);
|
||||
}
|
||||
|
||||
if (config_get_value(buf, 0, 16, "THEME_MARGIN")) {
|
||||
vbe_set_margin((int)strtoui(buf));
|
||||
}
|
||||
|
||||
vbe_set_colors(colorsheme);
|
||||
}
|
||||
|
||||
char *menu(int boot_drive) {
|
||||
cmdline = conv_mem_alloc(CMDLINE_MAX);
|
||||
|
||||
|
@ -22,6 +82,8 @@ char *menu(int boot_drive) {
|
|||
|
||||
// If there is no TEXTMODE config key or the value is not "on", enable graphics
|
||||
if (config_get_value(buf, 0, 16, "TEXTMODE") == NULL || strcmp(buf, "on")) {
|
||||
load_theme_from_config();
|
||||
|
||||
int bg_drive;
|
||||
if (!config_get_value(buf, 0, 16, "BACKGROUND_DRIVE")) {
|
||||
bg_drive = boot_drive;
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
TIMEOUT=3
|
||||
|
||||
THEME_BLACK=33000000
|
||||
THEME_RED=aa0000
|
||||
THEME_GREEN=00aaff
|
||||
THEME_BROWN=aa5500
|
||||
THEME_BLUE=0000aa
|
||||
THEME_MAGENTA=aa00aa
|
||||
THEME_CYAN=9076DE
|
||||
THEME_GREY=aaaaaa
|
||||
THEME_WHITE=ffffff
|
||||
THEME_MARGIN=16
|
||||
|
||||
BACKGROUND_PARTITION=0
|
||||
BACKGROUND_PATH=bg.bmp
|
||||
|
||||
|
|
Loading…
Reference in New Issue