From 00cc8736f10098dedf6b856b9ad8bd0094211263 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Thu, 18 Feb 2021 11:56:08 -0500 Subject: vbe support, truecolor window manager pixbufs --- doc/internal/mem.txt | 6 +- doc/ints.txt | 2 + src/boot.asm | 119 ++++++++++++++++++++++++++++++++-- src/kernel/log.c | 10 ++- src/kernel/main.c | 28 ++++++++ src/kernel/vbe.h | 71 ++++++++++++++++++++ src/kernel/window.c | 126 +++++++++++++++++++++--------------- src/kernel/window.h | 13 +++- src/user/highway/line.c | 31 ++++++--- src/user/highway/main.c | 1 - src/user/highway/vars.c | 44 +++++++++++-- src/user/include/libfont/fonts.h | 5 +- src/user/include/libterm/command.h | 4 +- src/user/include/libterm/terminal.h | 2 +- src/user/include/pland/syscall.h | 13 +++- src/user/include/popups/info.h | 6 +- src/user/include/popups/popup.h | 2 +- src/user/libfont/fonts.c | 3 +- src/user/libterm/terminal.c | 2 +- src/user/meminfo/meminfo.c | 3 +- src/user/mkpopup/main.c | 2 +- src/user/popups/info.c | 8 +-- src/user/terminal/main.c | 48 ++++++++------ 23 files changed, 433 insertions(+), 116 deletions(-) create mode 100644 src/kernel/vbe.h diff --git a/doc/internal/mem.txt b/doc/internal/mem.txt index 1606ca1..72b72ec 100644 --- a/doc/internal/mem.txt +++ b/doc/internal/mem.txt @@ -6,8 +6,12 @@ 0x2 byte: PCI minor 0x3 byte: PCI major 0x4 byte: last PCI bus - + ;0x5 byte 0x6 word: BIOS memory map length + 0x8 word: active VBE mode + +0x0000.4200 - 0x0000.43ff (512): VBE2 info block +0x0000.4400 - 0x0000.44ff (256): active VBE mode info 0x0000.4f98 - 0x0000.4fff (104): TSS 0x0000.5000 - 0x0000.5fff (4k): kernel page directory diff --git a/doc/ints.txt b/doc/ints.txt index f3e89cc..631ed52 100644 --- a/doc/ints.txt +++ b/doc/ints.txt @@ -24,6 +24,8 @@ the edx register of "start task" is a pointer to a null-terminated string. the new task receives its own handle in ecx. ipc operations return 0xffffffff if the specified task doesn't exist. "find unread ipc" system call returns 0 if there is no unread ipc. +pixbufs are arrays of four-byte pixels, from left to right, then top to bottom. + pixels are a red byte, a green byte, a blue byte, and a padding byte. invalid system call numbers change eax to -1, and have no other effect. diff --git a/src/boot.asm b/src/boot.asm index 08b2834..c19534e 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -8,6 +8,11 @@ support_flags equ 0x4000 pci_hw_char equ 0x4001 pci_ver equ 0x4002 last_pci_bus equ 0x4004 +bios_mmap_len equ 0x4006 +vbe_mode equ 0x4008 + +vbe_block equ 0x4200 +vbe_mode_info equ 0x4400 pci_support equ 0x80 pae_support equ 0x40 @@ -18,10 +23,7 @@ pae_support equ 0x40 xor ax, ax mov ss, ax - mov sp, 0x7ffc - - mov ax, 0x0013 - int 0x10 + mov sp, 0x8000 mov ax, kernel_segment mov es, ax @@ -72,7 +74,95 @@ mmap_loop: test ebx, ebx jnz mmap_loop mmap_end: - mov word [0x4006], di + mov word [bios_mmap_len], di + + xor ax, ax + mov es, ax + mov di, vbe_block + mov ah, 0x4f + + mov dword [di], 0x32454256;'VBE2' + + int 0x10 + + cmp dword [di], 0x41534556;'VESA' + jne no_vbe + + mov bx, word [di + 0x0e] + mov ax, word [di + 0x10] + mov fs, ax + xor esi, esi + mov bp, 0xffff + mov di, 0x5000 + +vbe_loop: + max_height equ 800 + ;fs:bx is mode pointer + ;esi is highest resolution yet (width * height) + ;bp is that mode's number + ;uses 0x5000 - 0x50ff as mode info buffer + ;skips those without byte-aligned pixels + + mov cx, word [fs:bx] + cmp cx, 0xffff + je got_highest_vbe + + add bx, 4 + + mov ax, 0x4f01 + int 0x10 + + mov al, byte [di] + + test al, 0x01 + jz vbe_loop + + test al, 0x10 + jz vbe_loop + + test al, 0x80 + jz vbe_loop + + mov dx, word [di + 0x14];height + cmp dx, max_height + jg vbe_loop + + mov ax, word [di + 0x12];width + mul dx + + shl edx, 16 + mov dx, ax + + xor eax, eax + + mov al, byte [di + 0x19];bpp + test al, 0x07 + jnz vbe_loop + + mul edx + + cmp eax, esi + jle vbe_loop + + mov esi, eax + mov bp, cx + jmp vbe_loop + +got_highest_vbe: + cmp bp, 0xffff + je no_vbe + + mov cx, bp + mov ax, 0x4f01 + mov di, vbe_mode_info + int 0x10 + + or ch, 0x40 + mov word [vbe_mode], cx + + mov ax, 0x4f02 + mov bx, cx + int 0x10 cli @@ -84,6 +174,25 @@ mmap_end: jmp 0x10:pmode +no_vbe: + xor ax, ax + mov es, ax + + mov ax, 0x1300 + mov bx, 0x004f + mov cx, no_vbe_str.len + xor dx, dx + mov bp, no_vbe_str + int 0x10 + +real_halt: + hlt + jmp real_halt + +no_vbe_str: + db "NO VBE2!" +.len equ $ - no_vbe_str + bits 32 pmode: diff --git a/src/kernel/log.c b/src/kernel/log.c index 6bad1cc..2819a2e 100644 --- a/src/kernel/log.c +++ b/src/kernel/log.c @@ -52,8 +52,16 @@ void logf(enum log_level level, const char *format, ...) { while (*s) logch(*(s++)); break; + case 'n':; + uint32_t d = va_arg(args, uint32_t); + if (d >= 0x80000000) { + logch('-'); + d = -d; + } + goto put_dec; case 'd':; - const uint32_t d = va_arg(args, uint32_t); + d = va_arg(args, uint32_t); + put_dec: if (d == 0) { logch('0'); break; diff --git a/src/kernel/main.c b/src/kernel/main.c index 92315ce..43778d4 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -15,6 +15,7 @@ #include "kbd.h" #include "log.h" #include "pci.h" +#include "vbe.h" void _start_user_mode() __attribute__ ((noreturn)); @@ -46,12 +47,16 @@ void main() { logf(LOG_INFO, "Available kernel memory: %dk", kernel_pages_left * 4); logf(LOG_INFO, "Available user memory: %dk", user_pages_left * 4); + logf(LOG_INFO, ""); + logf(LOG_INFO, "PCI devices:"); for (uint16_t i = 0; i < n_pci_devices; ++i) { const struct pci_device *dev = nth_pci_device(i); logf(LOG_INFO, " %hw:%hw (%hb:%hb)", dev->id_vendor, dev->id_device, dev->class, dev->subclass); } + logf(LOG_INFO, ""); + logf(LOG_INFO, "Drives:"); for (uint8_t i = 0; i < n_drives; ++i) { const struct drive *d = &drives[i]; @@ -59,6 +64,29 @@ void main() { logf(LOG_INFO, " %s: %d%sk, %s (%d%sk free)", d->drive_type, d->n_sectors / 2, d->n_sectors % 2 ? ".5" : "", d->fs_type, free / 2, free % 2 ? ".5" : ""); } + logf(LOG_INFO, ""); + + logf(LOG_INFO, "VBE info:"); + logf(LOG_INFO, " Implemention: %s", RM_PTR(char, VBE_INFO->oem_name)); + logf(LOG_INFO, " Video memory: %dk", VBE_INFO->total_memory * 64); + logf(LOG_INFO, " Standard: %d.%d.%d", VBE_INFO->major_version, VBE_INFO->minor_version, VBE_INFO->version_rev); + logf(LOG_INFO, " Vendor: %s", RM_PTR(char, VBE_INFO->vendor_name)); + logf(LOG_INFO, " Product: %s", RM_PTR(char, VBE_INFO->product_name)); + logf(LOG_INFO, " Version: %s", RM_PTR(char, VBE_INFO->product_rev_name)); + + logf(LOG_INFO, ""); + + #define MASK(offset, length) ((~((1 << offset) - 1)) - (offset + length == 32 ? 0 : (~((1 << (offset + length)) - 1)))) + logf(LOG_INFO, "Active video mode:"); + logf(LOG_INFO, " Resolution: %dx%dx%d", VBE_MODE_INFO->width, VBE_MODE_INFO->height, VBE_MODE_INFO->bpp); + logf(LOG_INFO, " Red mask: 0x%h", MASK(VBE_MODE_INFO->red_off, VBE_MODE_INFO->red_len)); + logf(LOG_INFO, " Green mask: 0x%h", MASK(VBE_MODE_INFO->green_off, VBE_MODE_INFO->green_len)); + logf(LOG_INFO, " Blue mask: 0x%h", MASK(VBE_MODE_INFO->blue_off, VBE_MODE_INFO->blue_len)); + logf(LOG_INFO, " Alpha mask: 0x%h", MASK(VBE_MODE_INFO->alpha_off, VBE_MODE_INFO->alpha_len)); + logf(LOG_INFO, " Framebuffer address: 0x%h", VBE_MODE_INFO->frame_buf); + + logf(LOG_INFO, ""); + logf(LOG_INFO, "Loading init program."); if (!try_elf_run(drives, "bin/init", "", 0)) diff --git a/src/kernel/vbe.h b/src/kernel/vbe.h new file mode 100644 index 0000000..6fcdb56 --- /dev/null +++ b/src/kernel/vbe.h @@ -0,0 +1,71 @@ +#ifndef VBE_H +#define VBE_H + +#include + +struct segoff { + uint16_t offset; + uint16_t segment; +} __attribute__ ((__packed__)); + +#define RM_PTR(type, segoff) ((type *)((segoff).segment * 16 + (segoff).offset)) + +enum vbe_capabilities { + VBE_CAP_SWITCHABLE_DAC = 0x1, + VBE_CAP_NON_VGA = 0x2, + VBE_CAP_WEIRD_RAMDAC = 0x4 +}; + +#define VBE_INFO \ + ((struct { \ + uint8_t signature[4]; \ + uint8_t minor_version; \ + uint8_t major_version; \ + struct segoff oem_name; \ + uint32_t capabilities; \ + struct segoff mode_list; \ + /*in units of 64kiB*/ \ + uint16_t total_memory; \ + uint16_t version_rev; \ + struct segoff vendor_name; \ + struct segoff product_name; \ + struct segoff product_rev_name; \ + } __attribute__ ((__packed__)) *)0x4200) + +#define VBE_MODE_INFO \ + ((struct { \ + uint16_t attribs; \ + uint8_t wina_attribs; \ + uint8_t winb_attribs; \ + uint16_t win_gran; \ + uint16_t win_size; \ + uint16_t wina_seg; \ + uint16_t winb_seg; \ + struct segoff win_func; \ + uint16_t pitch;/*in bytes*/ \ + uint16_t width; \ + uint16_t height; \ + uint8_t char_width; \ + uint8_t char_height; \ + uint8_t n_planes; \ + uint8_t bpp; \ + uint8_t n_banks; \ + uint8_t mem_model; \ + uint8_t bank_size;/*in kiB*/\ + uint8_t image_pages; \ + uint8_t reserved; \ + uint8_t red_len; \ + uint8_t red_off; \ + uint8_t green_len; \ + uint8_t green_off; \ + uint8_t blue_len; \ + uint8_t blue_off; \ + uint8_t alpha_len; \ + uint8_t alpha_off; \ + uint8_t color_attribs; \ + void *frame_buf; \ + void *off_screen; \ + uint16_t off_screen_length; \ + } __attribute__ ((__packed__)) *)0x4400) + +#endif \ No newline at end of file diff --git a/src/kernel/window.c b/src/kernel/window.c index 74273fb..10c573f 100644 --- a/src/kernel/window.c +++ b/src/kernel/window.c @@ -7,18 +7,21 @@ #include "pmap.h" #include "elf.h" #include "log.h" +#include "vbe.h" #define MAX_WINDOWS 64 #define ACTION_BUFFER_PAGES 1 #define AB_END(buf) (buf + (ACTION_BUFFER_PAGES * 4096) / sizeof(struct window_action)) -#define BACKGROUND(x, y) ((x / 16 + y / 16) % 2 ? 0x14 : 0x07) +#define GSC(x, y) (x / 4 + y / 4 >= 256 ? 255 : x / 4 + y / 4) +#define BACKGROUND(x, y) ((struct pixel){.r = GSC(x / 2, y / 3), .g = GSC(x, y), .b = GSC(x, y / 2)}) -#define BORDER_LIGHT 0x1c -#define BORDER_DARK 0x08 +#define BORDER_COLOR ((struct pixel){.r = 0x11, .g = 0x11, .b = 0x11}) + +#define MOVE_BY 5 static struct window { - const volatile void *pixel_buffer_pma; + const volatile struct pixel *pixel_buffer_pma; uint16_t width; uint16_t height; @@ -38,65 +41,74 @@ static struct window { static struct window *bottom_window = 0; static struct window *top_window = 0; -#define SCREEN_HEIGHT 200 -#define SCREEN_WIDTH 320 -#define VGA_MEMORY ((uint8_t *)0xa0000) +uint32_t pix_clear_mask; + +static inline void put_pix(uint16_t y, uint16_t x, struct pixel px) { + uint32_t *const fbp = VBE_MODE_INFO->frame_buf + y * VBE_MODE_INFO->pitch + x * VBE_MODE_INFO->bpp / 8; +//logf(LOG_INFO, "-- fbp = 0x%h", fbp); +//logf(LOG_INFO, "-- *fbp -> 0x%h", *fbp); + *fbp &= pix_clear_mask; + *fbp |= (px.r >> (8 - VBE_MODE_INFO->red_len)) << VBE_MODE_INFO->red_off; + *fbp |= (px.g >> (8 - VBE_MODE_INFO->green_len)) << VBE_MODE_INFO->green_off; + *fbp |= (px.b >> (8 - VBE_MODE_INFO->blue_len)) << VBE_MODE_INFO->blue_off; +//logf(LOG_INFO, "-- *fbp <- 0x%h", *fbp); +} -static inline void draw_hz_line(uint16_t y, uint16_t xs, uint16_t xm, uint8_t color) { - if (y >= SCREEN_HEIGHT) +static inline void draw_hz_line(uint16_t y, uint16_t xs, uint16_t xm, struct pixel color) { + if (y >= VBE_MODE_INFO->height) return; - if (xs >= SCREEN_WIDTH) + if (xs >= VBE_MODE_INFO->width) xs = 0; - if (xm > SCREEN_WIDTH) - xm = SCREEN_WIDTH; - uint8_t *const line_start = VGA_MEMORY + y * SCREEN_WIDTH; - for (uint8_t *p = line_start + xs; p < line_start + xm; ++p) - *p = color; + if (xm > VBE_MODE_INFO->width) + xm = VBE_MODE_INFO->width; + for (uint16_t x = xs; x < xm; ++x) + put_pix(y, x, color); } -static inline void draw_vt_line(uint16_t x, uint16_t ys, uint16_t ym, uint8_t color) { - if (x >= SCREEN_WIDTH) +static inline void draw_vt_line(uint16_t x, uint16_t ys, uint16_t ym, struct pixel color) { + if (x >= VBE_MODE_INFO->width) return; - if (ys >= SCREEN_HEIGHT) + if (ys >= VBE_MODE_INFO->height) ys = 0; - if (ym > SCREEN_HEIGHT) - ym = SCREEN_HEIGHT; - uint8_t *const line_start = VGA_MEMORY + x; - for (uint8_t *p = line_start + ys * SCREEN_WIDTH; p < line_start + ym * SCREEN_WIDTH; p += SCREEN_WIDTH) - *p = color; + if (ym > VBE_MODE_INFO->height) + ym = VBE_MODE_INFO->height; + for (uint16_t y = ys; y < ym; ++y) + put_pix(y, x, color); } static void paint_and_above(const struct window *w) { switch_to_kernel_cr3(); for (const struct window *i = w; i; i = i->above) { - const uint16_t ys = i->ypos < SCREEN_HEIGHT ? 0 : -i->ypos; - const uint16_t xs = i->xpos < SCREEN_WIDTH ? 0 : -i->xpos; - const uint16_t ym = i->ypos + i->height <= SCREEN_HEIGHT ? i->height : SCREEN_HEIGHT - i->ypos; - const uint16_t xm = i->xpos + i->width <= SCREEN_WIDTH ? i->width : SCREEN_WIDTH - i->xpos; + const uint16_t ys = i->ypos < VBE_MODE_INFO->height ? 0 : -i->ypos; + const uint16_t xs = i->xpos < VBE_MODE_INFO->width ? 0 : -i->xpos; + const uint16_t ym = ((i->ypos + i->height) & 0xffff) <= VBE_MODE_INFO->height ? i->height : VBE_MODE_INFO->height - i->ypos; + const uint16_t xm = ((i->xpos + i->width) & 0xffff) <= VBE_MODE_INFO->width ? i->width : VBE_MODE_INFO->width - i->xpos; - for (uint16_t y = ys; y < ym; ++y) - for (uint16_t x = xs; x < xm; ++x) { - const uint8_t pixel = ((uint8_t *)i->pixel_buffer_pma)[y * i->width + x]; - if (pixel) - VGA_MEMORY[(y + i->ypos) * SCREEN_WIDTH + x + i->xpos] = pixel; - } + //logf(LOG_INFO, "y: %n .. %n", ys, ym - 1); + //logf(LOG_INFO, "x: %n .. %n", xs, xm - 1); - draw_hz_line(i->ypos - 2, i->xpos - 2, i->xpos + i->width + 2, BORDER_LIGHT); - draw_vt_line(i->xpos - 2, i->ypos - 1, i->ypos + i->height + 2, BORDER_LIGHT); - draw_hz_line(i->ypos - 1, i->xpos - 1, i->xpos + i->width + 2, BORDER_DARK); - draw_vt_line(i->xpos - 1, i->ypos, i->ypos + i->height + 2, BORDER_DARK); - draw_hz_line(i->ypos + i->height, i->xpos, i->xpos + i->width + 1, BORDER_LIGHT); - draw_vt_line(i->xpos + i->width, i->ypos, i->ypos + i->height, BORDER_LIGHT); - draw_hz_line(i->ypos + i->height + 1, i->xpos, i->xpos + i->width + 2, BORDER_DARK); - draw_vt_line(i->xpos + i->width + 1, i->ypos, i->ypos + i->height + 1, BORDER_DARK); + for (uint16_t y = ys; y < ym; ++y) + for (uint16_t x = xs; x < xm; ++x) + put_pix(y + i->ypos, x + i->xpos, i->pixel_buffer_pma[y * i->width + x]); + + draw_hz_line(i->ypos - 2, i->xpos - 2, i->xpos + i->width + 2, BORDER_COLOR); + draw_hz_line(i->ypos - 1, i->xpos - 2, i->xpos + i->width + 2, BORDER_COLOR); + draw_hz_line(i->ypos + i->height, i->xpos - 2, i->xpos + i->width + 2, BORDER_COLOR); + draw_hz_line(i->ypos + i->height + 1, i->xpos - 2, i->xpos + i->width + 2, BORDER_COLOR); + draw_vt_line(i->xpos - 2, i->ypos, i->ypos + i->height, BORDER_COLOR); + draw_vt_line(i->xpos - 1, i->ypos, i->ypos + i->height, BORDER_COLOR); + draw_vt_line(i->xpos + i->width, i->ypos, i->ypos + i->height, BORDER_COLOR); + draw_vt_line(i->xpos + i->width + 1, i->ypos, i->ypos + i->height, BORDER_COLOR); } switch_to_task_cr3(); } static void paint_bg() { - for (uint16_t y = 0; y < SCREEN_HEIGHT; ++y) - for (uint16_t x = 0; x < SCREEN_WIDTH; ++x) - VGA_MEMORY[y * SCREEN_WIDTH + x] = BACKGROUND(x, y); + switch_to_kernel_cr3(); + for (uint16_t y = 0; y < VBE_MODE_INFO->height; ++y) + for (uint16_t x = 0; x < VBE_MODE_INFO->width; ++x) + put_pix(y, x, BACKGROUND(x, y)); + switch_to_task_cr3(); } static void paint_all() { @@ -104,7 +116,7 @@ static void paint_all() { paint_and_above(bottom_window); } -struct window *new_window(uint16_t width, uint16_t height, const void *pixel_buffer) { +struct window *new_window(uint16_t width, uint16_t height, const struct pixel *pixel_buffer) { if (!pixel_buffer) { logf(LOG_WARN, "Refusing to create window with null pixel buffer for task %s.", active_task->name); return 0; @@ -122,8 +134,8 @@ got_window: w->pixel_buffer_pma = vma_to_pma(active_task->page_directory, pixel_buffer); w->width = width; w->height = height; - w->xpos = 10; - w->ypos = 10; + w->xpos = (VBE_MODE_INFO->width / 2) - (width / 2); + w->ypos = (VBE_MODE_INFO->height / 2) - (height / 2); struct window_action *const ab = allocate_kernel_pages(ACTION_BUFFER_PAGES); w->action_buffer = ab; @@ -174,7 +186,7 @@ void delete_any_windows_from(struct task_state *tstate) { paint_all(); } -void resize_window(struct window *w, uint16_t width, uint16_t height, const void *pixel_buffer) { +void resize_window(struct window *w, uint16_t width, uint16_t height, const struct pixel *pixel_buffer) { const bool smaller = (width < w->width) || (height < w->height); w->width = width; @@ -187,7 +199,7 @@ void resize_window(struct window *w, uint16_t width, uint16_t height, const void paint_and_above(w); } -void reassign_pixel_buffer(struct window *w, const void *pixel_buffer) { +void reassign_pixel_buffer(struct window *w, const struct pixel *pixel_buffer) { w->pixel_buffer_pma = vma_to_pma(active_task->page_directory, pixel_buffer); } @@ -259,6 +271,14 @@ static char *run_command; static char *run_command_pass = ""; void init_win() { + #define MASK(offset, length) ((~((1 << offset) - 1)) - (offset + length == 32 ? 0 : (~((1 << (offset + length)) - 1)))) + pix_clear_mask = ~( + MASK(VBE_MODE_INFO->red_off, VBE_MODE_INFO->red_len) | + MASK(VBE_MODE_INFO->green_off, VBE_MODE_INFO->green_len) | + MASK(VBE_MODE_INFO->blue_off, VBE_MODE_INFO->blue_len) | + MASK(VBE_MODE_INFO->alpha_off, VBE_MODE_INFO->alpha_len) + ); + paint_bg(); const file_id_t fid = drives->get_file(drives, RUN_COMMAND_FILE); @@ -323,25 +343,25 @@ void on_action(struct window_action packet) { break; case WM_MOVE_LEFT: if (top_window) { - --top_window->xpos; + top_window->xpos -= MOVE_BY; paint_all(); } break; case WM_MOVE_RIGHT: if (top_window) { - ++top_window->xpos; + top_window->xpos += MOVE_BY; paint_all(); } break; case WM_MOVE_UP: if (top_window) { - --top_window->ypos; + top_window->ypos -= MOVE_BY; paint_all(); } break; case WM_MOVE_DOWN: if (top_window) { - ++top_window->ypos; + top_window->ypos += MOVE_BY; paint_all(); } break; diff --git a/src/kernel/window.h b/src/kernel/window.h index a226c11..ebd0496 100644 --- a/src/kernel/window.h +++ b/src/kernel/window.h @@ -9,13 +9,20 @@ struct window; +struct pixel { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t pad; +} __attribute__ ((__packed__)); + void init_win(); -struct window *new_window(uint16_t width, uint16_t height, const void *pixel_buffer); +struct window *new_window(uint16_t width, uint16_t height, const struct pixel *pixel_buffer); void del_window(struct window *w); -void resize_window(struct window *w, uint16_t width, uint16_t height, const void *pixel_buffer); -void reassign_pixel_buffer(struct window *w, const void *pixel_buffer); +void resize_window(struct window *w, uint16_t width, uint16_t height, const struct pixel *pixel_buffer); +void reassign_pixel_buffer(struct window *w, const struct pixel *pixel_buffer); void push_window_paint(const struct window *w); struct window_action next_window_action(struct window *w); void wait_window_action(); diff --git a/src/user/highway/line.c b/src/user/highway/line.c index 5d1e543..3bc3bf2 100644 --- a/src/user/highway/line.c +++ b/src/user/highway/line.c @@ -12,18 +12,33 @@ #define LINE_SIZE 4096 static char line[LINE_SIZE]; -static inline uint8_t hex_to_int(char ch) { +static inline uint8_t hex_digit_to_int(char ch) { return ch - (ch <= '9' ? '0' : 'a' - 10); } +static inline uint8_t hex_byte_to_int(const char *ch) { + return (hex_digit_to_int(ch[0]) << 4) | hex_digit_to_int(ch[1]); +} + +static inline _pixel_t hex_to_pixel(const char *ch) { + return (_pixel_t){ + .r = hex_byte_to_int(ch), + .g = hex_byte_to_int(ch + 2), + .b = hex_byte_to_int(ch + 4) + }; +} + void ensure_color() { - const struct no_null_sn *color = get_var((struct no_null_sn){.data = "_color", .length = 6}); - //fgbg - if (color) - term_set_color( - (hex_to_int(color->data[0]) << 4) | hex_to_int(color->data[1]), - (hex_to_int(color->data[2]) << 4) | hex_to_int(color->data[3]) - ); + const struct no_null_sn *color; +get_color: + color = get_var((struct no_null_sn){.data = "_color", .length = 6}); + if (color && (color->length == 12)) + //rgb, fgbg + term_set_color(hex_to_pixel(color->data), hex_to_pixel(color->data + 6)); + else { + new_color(); + goto get_color; + } } static void line_replace(const char *from) { diff --git a/src/user/highway/main.c b/src/user/highway/main.c index 59586c1..47f3985 100644 --- a/src/user/highway/main.c +++ b/src/user/highway/main.c @@ -8,7 +8,6 @@ #include "vars.h" void main(const char *arg) { - new_color(); source(*arg ? arg : "user/default.rc"); ensure_color(); diff --git a/src/user/highway/vars.c b/src/user/highway/vars.c index ed9fa3a..2d53c3a 100644 --- a/src/user/highway/vars.c +++ b/src/user/highway/vars.c @@ -84,7 +84,7 @@ void dump_vars() { } static const char hex_digits[] = "0123456789abcdef"; -static char color[] = {'1', '0', '.', '.'}; +static char color[12] = "000000......"; static const struct no_null_sn color_name = { .data = "_color", @@ -93,12 +93,46 @@ static const struct no_null_sn color_name = { static const struct no_null_sn color_value = { .data = color, - .length = 4 + .length = 12 }; void new_color() { - const uint8_t bg = gen_rand() % 0x30 + 0x38; - color[2] = hex_digits[bg >> 4]; - color[3] = hex_digits[bg & 0xf]; + const uint16_t hue = gen_rand() % (0x33 * 6); + _pixel_t bg = {.r = 0xff, .g = 0xcc, .b = 0xcc}; + if (hue <= 0x33) { + bg.b += hue; + goto got_bg; + } + bg.b += 0x33; + if (hue <= 0x33 * 2) { + bg.r -= hue - 0x33; + goto got_bg; + } + bg.r -= 0x33; + if (hue <= 0x33 * 3) { + bg.g += hue - 0x33 * 2; + goto got_bg; + } + bg.g += 0x33; + if (hue <= 0x33 * 4) { + bg.b -= hue - 0x33 * 3; + goto got_bg; + } + bg.b -= 0x33; + if (hue <= 0x33 * 5) { + bg.r += hue - 0x33 * 4; + goto got_bg; + } + bg.r += 0x33; + bg.g -= hue - 0x33 * 5; + +got_bg: + color[ 6] = hex_digits[bg.r / 16]; + color[ 7] = hex_digits[bg.r % 16]; + color[ 8] = hex_digits[bg.g / 16]; + color[ 9] = hex_digits[bg.g % 16]; + color[10] = hex_digits[bg.b / 16]; + color[11] = hex_digits[bg.b % 16]; + set_var(color_name, color_value); } \ No newline at end of file diff --git a/src/user/include/libfont/fonts.h b/src/user/include/libfont/fonts.h index b66659f..f7ed3e1 100644 --- a/src/user/include/libfont/fonts.h +++ b/src/user/include/libfont/fonts.h @@ -1,6 +1,8 @@ #ifndef LIBFONT_FONTS_H #define LIBFONT_FONTS_H +#include + #include #include @@ -16,6 +18,7 @@ struct font_info { struct font_info *get_font(const char *name); -void put_char(const struct font_info *font, char ch, uint8_t *pb_ptr, uint32_t pb_pitch, uint8_t bg, uint8_t fg); +//pitch is in pixels +void put_char(const struct font_info *font, char ch, _pixel_t *pb_ptr, uint32_t pb_pitch, _pixel_t bg, _pixel_t fg); #endif \ No newline at end of file diff --git a/src/user/include/libterm/command.h b/src/user/include/libterm/command.h index 7587306..ca9e00d 100644 --- a/src/user/include/libterm/command.h +++ b/src/user/include/libterm/command.h @@ -37,8 +37,8 @@ struct terminal_command { uint32_t x; } as_coords; struct { - uint8_t fg; - uint8_t bg; + _pixel_t fg; + _pixel_t bg; } as_color; char as_char; uint32_t as_uint; diff --git a/src/user/include/libterm/terminal.h b/src/user/include/libterm/terminal.h index 19bd517..40536e0 100644 --- a/src/user/include/libterm/terminal.h +++ b/src/user/include/libterm/terminal.h @@ -12,7 +12,7 @@ void term_get_dimensions(uint32_t *width, uint32_t *height); void term_paint(); void term_clear(); -void term_set_color(uint8_t fg, uint8_t bg); +void term_set_color(_pixel_t fg, _pixel_t bg); void term_set_cursor(uint32_t new_y, uint32_t new_x); void term_cursor_left(); diff --git a/src/user/include/pland/syscall.h b/src/user/include/pland/syscall.h index fd0b416..9518d09 100644 --- a/src/user/include/pland/syscall.h +++ b/src/user/include/pland/syscall.h @@ -18,6 +18,13 @@ typedef struct __attribute__ ((packed)) { uint8_t pad[23]; } _dir_info_entry_t; +typedef struct __attribute__ ((packed)) { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t pad; +} _pixel_t; + enum _scn { _SCN_OPEN_FILE, _SCN_CLOSE_FILE, @@ -177,7 +184,7 @@ static inline uint32_t _count_of_dir(uint8_t drive_number, const char *path) { return _sc2(_SCN_COUNT_OF_DIR, drive_number, (uint32_t)path); } -static inline _window_handle_t _new_window(uint16_t width, uint16_t height, void *pixel_buffer) { +static inline _window_handle_t _new_window(uint16_t width, uint16_t height, _pixel_t *pixel_buffer) { return (_window_handle_t)_sc3(_SCN_NEW_WINDOW, width, height, (uint32_t)pixel_buffer); } @@ -185,11 +192,11 @@ static inline void _delete_window(_window_handle_t window) { _sc1(_SCN_DELETE_WINDOW, (uint32_t)window); } -static inline void _resize_window(_window_handle_t window, uint16_t width, uint16_t height, const void *pixel_buffer) { +static inline void _resize_window(_window_handle_t window, uint16_t width, uint16_t height, const _pixel_t *pixel_buffer) { _sc4(_SCN_RESIZE_WINDOW, (uint32_t)window, width, height, (uint32_t)pixel_buffer); } -static inline void _reassign_pixbuf(_window_handle_t window, const void *pixel_buffer) { +static inline void _reassign_pixbuf(_window_handle_t window, const _pixel_t *pixel_buffer) { _sc2(_SCN_REASSIGN_PIXBUF, (uint32_t)window, (uint32_t)pixel_buffer); } diff --git a/src/user/include/popups/info.h b/src/user/include/popups/info.h index 2c4e83f..36d557a 100644 --- a/src/user/include/popups/info.h +++ b/src/user/include/popups/info.h @@ -7,8 +7,8 @@ #include -void info_popup(struct popup *into, const char *text, uint8_t fg, uint8_t bg); -void info_popupf(struct popup *into, const char *text, uint8_t fg, uint8_t bg, ...); -void info_popupf_v(struct popup *into, const char *text, uint8_t fg, uint8_t bg, va_list args); +void info_popup(struct popup *into, const char *text, _pixel_t fg, _pixel_t bg); +void info_popupf(struct popup *into, const char *text, _pixel_t fg, _pixel_t bg, ...); +void info_popupf_v(struct popup *into, const char *text, _pixel_t fg, _pixel_t bg, va_list args); #endif \ No newline at end of file diff --git a/src/user/include/popups/popup.h b/src/user/include/popups/popup.h index 9a39997..cf4315b 100644 --- a/src/user/include/popups/popup.h +++ b/src/user/include/popups/popup.h @@ -5,7 +5,7 @@ struct popup { _window_handle_t handle; - uint8_t *pixbuf; + _pixel_t *pixbuf; bool has_quit; struct key_packet quit_as; diff --git a/src/user/libfont/fonts.c b/src/user/libfont/fonts.c index c085604..51e127b 100644 --- a/src/user/libfont/fonts.c +++ b/src/user/libfont/fonts.c @@ -56,7 +56,8 @@ struct font_info *get_font(const char *name) { return 0; } -void put_char(const struct font_info *font, char ch, uint8_t *pb_ptr, uint32_t pb_pitch, uint8_t bg, uint8_t fg) { +//pitch is in pixels +void put_char(const struct font_info *font, char ch, _pixel_t *pb_ptr, uint32_t pb_pitch, _pixel_t bg, _pixel_t fg) { //char *const msg = format("put_char(font = 0x%x, ch = '%c', pb_ptr = 0x%x, pb_pitch = %u, bg = 0x%2x, fg = 0x%2x);", font, ch, pb_ptr, pb_pitch, bg, fg); //_system_log(msg); //free_block(msg); diff --git a/src/user/libterm/terminal.c b/src/user/libterm/terminal.c index 387d63f..549194f 100644 --- a/src/user/libterm/terminal.c +++ b/src/user/libterm/terminal.c @@ -48,7 +48,7 @@ void term_clear() { try_send_command(&cmd); } -void term_set_color(uint8_t fg, uint8_t bg) { +void term_set_color(_pixel_t fg, _pixel_t bg) { struct terminal_command cmd = { .kind = SET_COLOR, .as_color = { diff --git a/src/user/meminfo/meminfo.c b/src/user/meminfo/meminfo.c index 4dbd6bf..3c3c45b 100644 --- a/src/user/meminfo/meminfo.c +++ b/src/user/meminfo/meminfo.c @@ -15,7 +15,8 @@ redo: "kernel memory free: %uk\n" "userspace memory free: %uk / %uk\n" "Escape to quit, F5 to refresh.", - 0x10, 0x07, + (_pixel_t){.r = 0, .g = 0, .b = 0}, + (_pixel_t){.r = 0xbf, .g = 0xbf, .b = 0xbf}, _kernel_dynamic_area_left() * 4, _total_userspace_left() * 4, _total_userspace_size() * 4 diff --git a/src/user/mkpopup/main.c b/src/user/mkpopup/main.c index 5b56889..05ea4e3 100644 --- a/src/user/mkpopup/main.c +++ b/src/user/mkpopup/main.c @@ -31,6 +31,6 @@ void main(const char *text) { } struct popup p; - info_popup(&p, text, 0x10, 0x07); + info_popup(&p, text, (_pixel_t){.r = 0, .g = 0, .b = 0}, (_pixel_t){.r = 0xbf, .g = 0xbf, .b = 0xbf}); make_modal(&p); } \ No newline at end of file diff --git a/src/user/popups/info.c b/src/user/popups/info.c index 667d440..eac155b 100644 --- a/src/user/popups/info.c +++ b/src/user/popups/info.c @@ -18,7 +18,7 @@ static const struct key_packet info_quits[] = { { .key_id = 0 } }; -void info_popup(struct popup *into, const char *msg, uint8_t fg, uint8_t bg) { +void info_popup(struct popup *into, const char *msg, _pixel_t fg, _pixel_t bg) { if (!info_font) info_font = get_font(FONT); @@ -41,7 +41,7 @@ void info_popup(struct popup *into, const char *msg, uint8_t fg, uint8_t bg) { const uint32_t pitch = info_font->space_width * w + 2 * PADDING; const uint32_t height = info_font->space_height * h + 2 * PADDING; - uint8_t *const pixbuf = get_block(pitch * height); + _pixel_t *const pixbuf = get_block(pitch * height * 4); for (uint32_t y = 0; y < height; ++y) for (uint32_t x = 0; x < pitch; ++x) @@ -63,13 +63,13 @@ void info_popup(struct popup *into, const char *msg, uint8_t fg, uint8_t bg) { into->handle = _new_window(pitch, height, pixbuf); } -void info_popupf_v(struct popup *into, const char *text, uint8_t fg, uint8_t bg, va_list args) { +void info_popupf_v(struct popup *into, const char *text, _pixel_t fg, _pixel_t bg, va_list args) { char *const msg = format_v(text, args); info_popup(into, msg, fg, bg); free_block(msg); } -void info_popupf(struct popup *into, const char *text, uint8_t fg, uint8_t bg, ...) { +void info_popupf(struct popup *into, const char *text, _pixel_t fg, _pixel_t bg, ...) { va_list args; va_start(args, bg); info_popupf_v(into, text, fg, bg, args); diff --git a/src/user/terminal/main.c b/src/user/terminal/main.c index 3c9eb04..b3e1d9f 100644 --- a/src/user/terminal/main.c +++ b/src/user/terminal/main.c @@ -11,22 +11,23 @@ #include #define FONT_HARDCODE "fixed-10" +#define PADDING 2 _window_handle_t window; -uint8_t *pixbuf; +_pixel_t *pixbuf; char *termbuf; struct font_info *font; uint32_t width; uint32_t height; -uint32_t cols = 50; -uint32_t rows = 15; +uint32_t cols = 100; +uint32_t rows = 30; uint32_t cursor_y = 0; uint32_t cursor_x = 0; -uint8_t bg_color = 0x10; -uint8_t fg_color = 0x07; +_pixel_t bg_color = (_pixel_t){.r = 0, .g = 0, .b = 0}; +_pixel_t fg_color = (_pixel_t){.r = 0xff, .g = 0xff, .b = 0xff}; struct waiting_for_key_record { _task_handle_t task; @@ -35,7 +36,7 @@ struct waiting_for_key_record { static void draw_char(uint32_t y, uint32_t x, bool inverted) { //syslogf("drawing 0x%2h%s at %u, %u", termbuf[y * cols + x], inverted ? " inverted" : "", y, x); - put_char(font, termbuf[y * cols + x], pixbuf + y * font->space_height * width + x * font->space_width, width, inverted ? fg_color : bg_color, inverted ? bg_color : fg_color); + put_char(font, termbuf[y * cols + x], pixbuf + (y * font->space_height + PADDING) * width + (x * font->space_width + PADDING), width, inverted ? fg_color : bg_color, inverted ? bg_color : fg_color); } static void clear() { @@ -52,9 +53,9 @@ static void scroll_fw() { for (; i < cols * rows; ++i) termbuf[i] = ' '; const uint32_t row_height = font->space_height; - for (i = 0; i < width * (height - row_height); ++i) + for (i = width * PADDING; i < width * (height - PADDING - row_height); ++i) pixbuf[i] = pixbuf[i + width * row_height]; - for (; i < width * height; ++i) + for (; i < width * (height - PADDING); ++i) pixbuf[i] = bg_color; } @@ -187,9 +188,9 @@ static void set_dimensions(uint32_t new_rows, uint32_t new_cols) { cols = new_cols; termbuf = get_block(rows * cols); - width = cols * font->space_width; - height = cols * font->space_height; - pixbuf = get_block(width * height); + width = cols * font->space_width + PADDING * 2; + height = cols * font->space_height + PADDING * 2; + pixbuf = get_block(width * height * 4); cursor_y = 0; cursor_x = 0; @@ -199,27 +200,34 @@ static void set_dimensions(uint32_t new_rows, uint32_t new_cols) { } void draw_all() { + for (uint32_t y = 0; y < PADDING; ++y) + for (uint32_t x = 0; x < width; ++x) + pixbuf[y * width + x] = bg_color; + for (uint32_t y = height - PADDING; y < height; ++y) + for (uint32_t x = 0; x < width; ++x) + pixbuf[y * width + x] = bg_color; + for (uint32_t x = 0; x < PADDING; ++x) + for (uint32_t y = PADDING; y < height - PADDING; ++y) + pixbuf[y * width + x] = bg_color; + for (uint32_t x = width - PADDING; x < width; ++x) + for (uint32_t y = PADDING; y < height - PADDING; ++y) + pixbuf[y * width + x] = bg_color; + for (uint32_t y = 0; y < rows; ++y) for (uint32_t x = 0; x < cols; ++x) draw_char(y, x, false); draw_char(cursor_y, cursor_x, true); } -//#include - void main(const char *cmd) { -//syslogf(" this task: 0x%2h", this_task); -//syslogf(" stdio task: 0x%2h", stdio_task); -//syslogf("calling task: 0x%2h", calling_task); - font = get_font(FONT_HARDCODE); if (!font) return; termbuf = get_block(cols * rows); - width = cols * font->space_width; - height = rows * font->space_height; - pixbuf = get_block(width * height); + width = cols * font->space_width + PADDING * 2; + height = rows * font->space_height + PADDING * 2; + pixbuf = get_block(width * height * 4); clear(); add_sz_ww("Portland Terminal\n"); window = _new_window(width, height, pixbuf); -- cgit v1.2.3