:: commit 7aa9d845e7b6cf8f75289df664432125c4e2dfad

mintsuki <mintsuki@protonmail.com> — 2020-09-21 22:18

parents: 5ee53fbe4d

Complete background infrastructure and fix some bmp bugs

diff --git a/limine.bin b/limine.bin
index 00ab4369..20c7cb73 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2/drivers/vbe.c b/stage2/drivers/vbe.c
index 0884990c..581aee80 100644
--- a/stage2/drivers/vbe.c
+++ b/stage2/drivers/vbe.c
@@ -6,6 +6,7 @@
 #include <lib/blib.h>
 #include <lib/real.h>
 #include <lib/print.h>
+#include <lib/image.h>
 #include <mm/pmm.h>
 
 #define VGA_FONT_WIDTH  8
@@ -33,6 +34,8 @@ static uint16_t  vbe_width = 0;
 static uint16_t  vbe_height = 0;
 static uint16_t  vbe_bpp = 0;
 
+static struct image *background;
+
 void vbe_plot_px(int x, int y, uint32_t hex) {
     size_t fb_i = x + (vbe_pitch / sizeof(uint32_t)) * y;
 
@@ -50,8 +53,11 @@ void vbe_plot_char(struct vbe_char c, int x, int y) {
     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);
+        for (int j = VGA_FONT_WIDTH - 1; j >= 0; j--) {
+            uint32_t bg_pixel = background == NULL ? c.bg :
+                background->get_pixel(background, x, y);
+            vbe_plot_px(x++, y, (glyph[i] & (1 << j)) ? c.fg : bg_pixel);
+        }
         y++;
         x = orig_x;
     }
@@ -217,12 +223,13 @@ void vbe_putchar(char c) {
     }
 }
 
-void vbe_tty_init(int *_rows, int *_cols) {
+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 = vbe_width / VGA_FONT_WIDTH;
     *_rows = rows = vbe_height / VGA_FONT_HEIGHT;
     grid = ext_mem_alloc(rows * cols * sizeof(struct vbe_char));
+    background = _background;
     vbe_clear(true);
 }
 
diff --git a/stage2/drivers/vbe.h b/stage2/drivers/vbe.h
index 03f6ac65..e1682df1 100644
--- a/stage2/drivers/vbe.h
+++ b/stage2/drivers/vbe.h
@@ -3,10 +3,11 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <lib/image.h>
 
 int init_vbe(uint32_t **framebuffer, uint16_t *pitch, uint16_t *target_width, uint16_t *target_height, uint16_t *target_bpp);
 
-void vbe_tty_init(int *rows, int *cols);
+void vbe_tty_init(int *rows, int *cols, struct image *background);
 
 void vbe_putchar(char c);
 void vbe_clear(bool move);
diff --git a/stage2/lib/bmp.c b/stage2/lib/bmp.c
index ae6907b4..5f101c9a 100644
--- a/stage2/lib/bmp.c
+++ b/stage2/lib/bmp.c
@@ -3,6 +3,7 @@
 #include <lib/image.h>
 #include <lib/bmp.h>
 #include <lib/libc.h>
+#include <lib/blib.h>
 #include <mm/pmm.h>
 
 struct bmp_header {
@@ -28,14 +29,25 @@ struct bmp_header {
 } __attribute__((packed));
 
 struct bmp_local {
-    uint32_t *image;
+    uint8_t  *image;
     uint32_t  pitch;
     struct bmp_header header;
 };
 
 static uint32_t get_pixel(struct image *this, int x, int y) {
     struct bmp_local *local = this->local;
-    return local->image[x + (local->pitch / local->header.bi_bpp) * y];
+    struct bmp_header *header = &local->header;
+
+    x %= header->bi_width;
+    y %= header->bi_height;
+
+    size_t pixel_offset = local->pitch * (header->bi_height - y - 1) + x * (header->bi_bpp / 8);
+
+    uint32_t composite = 0;
+    for (int i = 0; i < header->bi_bpp / 8; i++)
+        composite |= (uint32_t)local->image[pixel_offset + i] << (i * 8);
+
+    return composite;
 }
 
 int bmp_open_image(struct image *image, struct file_handle *file) {
@@ -45,12 +57,16 @@ int bmp_open_image(struct image *image, struct file_handle *file) {
     if (memcmp(&header.bf_signature, "BM", 2) != 0)
         return -1;
 
+    // We don't support bpp lower than 8
+    if (header.bi_bpp < 8)
+        return -1;
+
     struct bmp_local *local = ext_mem_alloc(sizeof(struct bmp_local));
 
     local->image = ext_mem_alloc(header.bf_size);
     fread(file, local->image, header.bf_offset, header.bf_size);
 
-    local->pitch  = header.bi_width * (header.bi_bpp / 8);
+    local->pitch  = ALIGN_UP(header.bi_width * header.bi_bpp, 32) / 8;
     local->header = header;
 
     image->x_size    = header.bi_width;
diff --git a/stage2/lib/term.c b/stage2/lib/term.c
index 2bb85da7..cf08ba44 100644
--- a/stage2/lib/term.c
+++ b/stage2/lib/term.c
@@ -3,6 +3,7 @@
 #include <stdbool.h>
 #include <lib/term.h>
 #include <lib/real.h>
+#include <lib/image.h>
 #include <drivers/vga_textmode.h>
 #include <drivers/vbe.h>
 
@@ -23,9 +24,9 @@ void (*set_text_bg)(int bg);
 
 static int rows, cols;
 
-void term_vbe(void) {
+void term_vbe(struct image *background) {
     term_deinit();
-    vbe_tty_init(&rows, &cols);
+    vbe_tty_init(&rows, &cols, background);
 
     raw_putchar    = vbe_putchar;
     clear          = vbe_clear;
diff --git a/stage2/lib/term.h b/stage2/lib/term.h
index 4a4be458..97480a41 100644
--- a/stage2/lib/term.h
+++ b/stage2/lib/term.h
@@ -3,6 +3,7 @@
 
 #include <stddef.h>
 #include <stdbool.h>
+#include <lib/image.h>
 
 extern void (*raw_putchar)(char c);
 extern void (*clear)(bool move);
@@ -13,7 +14,7 @@ extern void (*get_cursor_pos)(int *x, int *y);
 extern void (*set_text_fg)(int fg);
 extern void (*set_text_bg)(int bg);
 
-void term_vbe(void);
+void term_vbe(struct image *background);
 void term_textmode(void);
 void term_deinit(void);
 void term_write(const char *buf, size_t count);
diff --git a/stage2/main.c b/stage2/main.c
index 2a8a8f14..5c7ec2a9 100644
--- a/stage2/main.c
+++ b/stage2/main.c
@@ -46,7 +46,7 @@ void entry(int boot_drive) {
     init_e820();
     init_memmap();
 
-    char *cmdline = menu();
+    char *cmdline = menu(boot_drive);
 
     char proto[32];
     if (!config_get_value(proto, 0, 32, "KERNEL_PROTO")) {
diff --git a/stage2/menu.c b/stage2/menu.c
index 390867ed..4b5d2e3e 100644
--- a/stage2/menu.c
+++ b/stage2/menu.c
@@ -15,14 +15,43 @@ static char *cmdline;
 
 static char config_entry_name[1024];
 
-char *menu(void) {
+char *menu(int boot_drive) {
     cmdline = conv_mem_alloc(CMDLINE_MAX);
 
     char buf[16];
 
     // 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")) {
-        term_vbe();
+        int bg_drive;
+        if (!config_get_value(buf, 0, 16, "BACKGROUND_DRIVE")) {
+            bg_drive = boot_drive;
+        } else {
+            bg_drive = (int)strtoui(buf);
+        }
+        int bg_part;
+        if (!config_get_value(buf, 0, 16, "BACKGROUND_PARTITION")) {
+            goto nobg;
+        } else {
+            bg_part = (int)strtoui(buf);
+        }
+        if (!config_get_value(cmdline, 0, CMDLINE_MAX, "BACKGROUND_PATH"))
+            goto nobg;
+
+        struct file_handle *bg_file = conv_mem_alloc(sizeof(struct file_handle));
+        if (fopen(bg_file, bg_drive, bg_part, cmdline))
+            goto nobg;
+
+        struct image *bg = conv_mem_alloc(sizeof(struct image));
+        if (open_image(bg, bg_file))
+            goto nobg;
+
+        term_vbe(bg);
+        goto yesbg;
+
+    nobg:
+        term_vbe(NULL);
+
+    yesbg:;
     }
 
     int timeout;
diff --git a/stage2/menu.h b/stage2/menu.h
index 8d04432f..b6e8c901 100644
--- a/stage2/menu.h
+++ b/stage2/menu.h
@@ -1,6 +1,6 @@
 #ifndef __MENU_H__
 #define __MENU_H__
 
-char *menu(void);
+char *menu(int boot_drive);
 
 #endif
diff --git a/test/limine.cfg b/test/limine.cfg
index 690e7bdb..775a29a4 100644
--- a/test/limine.cfg
+++ b/test/limine.cfg
@@ -1,6 +1,5 @@
 TIMEOUT=3
 
-BACKGROUND_DRIVE=0
 BACKGROUND_PARTITION=0
 BACKGROUND_PATH=bg.bmp
 
tab: 248 wrap: offon