diff --git a/include/bochs.h b/include/bochs.h new file mode 100644 index 0000000..4aa933e --- /dev/null +++ b/include/bochs.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +/** + * Loads the framebuffer + * @param width - the width of the screen + * @param height - the height of the screen + */ +uint32_t *bochs_init(uint16_t w, uint16_t h, uint8_t b); diff --git a/include/fb.h b/include/fb.h deleted file mode 100644 index 2c5ea13..0000000 --- a/include/fb.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -int fb_init(uint16_t res_x, uint16_t res_y); diff --git a/include/screen.h b/include/screen.h new file mode 100644 index 0000000..296be31 --- /dev/null +++ b/include/screen.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +/** + * Initalizes the screen and framebuffer + */ +void screen_init(void); + +/** + * Redraws the screen + */ +void screen_redraw(void); diff --git a/include/shim.h b/include/shim.h index 498de92..e445765 100644 --- a/include/shim.h +++ b/include/shim.h @@ -15,16 +15,17 @@ struct memory_map { struct memory_segment entries[MMAP_MAX_ENTRY]; }; -//struct framebuffer { -// uint64_t addr; -// uint32_t pitch; -// uint32_t width; -// uint32_t height; -// uint8_t bit_depth; -//}; +struct framebuffer { + uint64_t addr; + uint32_t pitch; + uint32_t width; + uint32_t height; + uint8_t bit_depth; +}; struct boot_info { struct memory_map map; + struct framebuffer fb; void *symbol_table; void *acpi_table; char cmdline[CMDLINE_MAX]; diff --git a/src/arch/amd64/acpi.c b/src/arch/amd64/acpi.c index e262a99..eb38f73 100644 --- a/src/arch/amd64/acpi.c +++ b/src/arch/amd64/acpi.c @@ -1,14 +1,12 @@ #include #include - +#include #include #include +#include +#include #include "bindings.h" -#include "memory.h" - -/* global state, idk a better way rn */ -struct acpi_state state; struct acpi_header { char signature[4]; @@ -20,7 +18,7 @@ struct acpi_header { uint32_t oem_revision; uint32_t creator_id; uint32_t creator_revision; -}; +} __attribute__((packed)); // root system descriptor pointer // ACPI 1.0 @@ -30,7 +28,7 @@ struct rsdp { char oemid[6]; uint8_t revision; uint32_t rsdt_addr; -}; +} __attribute__((packed)); // eXtended system descriptor pointer // ACPI 2.0 @@ -45,7 +43,7 @@ struct xsdp { uint64_t xsdt_addr; uint8_t extendeid_checksum; uint8_t reserved[3]; -}; +} __attribute__((packed)); // root system descriptor table // ACPI 1.0 @@ -152,6 +150,9 @@ struct acpi_state { uint16_t SCI_EN; }; +/* global state, idk a better way rn */ +static struct acpi_state state; + static bool checksum(uint8_t *data, size_t len) { unsigned char sum = 0; for (size_t i = 0; i < len; i++) @@ -230,6 +231,9 @@ static void *acpi_find_table_xsdt(struct xsdt *xsdt, const char *identifier, int } int acpi_init_rsdt(struct rsdt *rsdt) { + + kprintf("RSDT: %#016lx\n", (size_t)rsdt); + rsdt = mmap(rsdt, sizeof(struct rsdt)); state.dst.rsdt = rsdt; @@ -278,23 +282,35 @@ int acpi_init(void *rootsdp) { if (!checksum((uint8_t *)rsdp, sizeof(struct rsdp))) return -1; + if (strncmp(rsdp->signature, "RSD PTR ", 8) != 0) { + panic("invalid acpi rsdp signature: %.*s\n", 8, rsdp->signature); + } + int res; if (rsdp->revision == 0) { + kprintf("ACPI 1.0\n"); + kprintf("RSDP: %#016lx\n", (size_t)rsdp); res = acpi_init_rsdt( (struct rsdt *) (uintptr_t) rsdp->rsdt_addr ); } else if (rsdp->revision == 2) { struct xsdp *xsdp = (struct xsdp *) rsdp; + kprintf("ACPI 2.0\n"); + kprintf("XSDP: %#016lx\n", (size_t)xsdp); res = acpi_init_xsdt( (struct xsdt *) (uintptr_t) xsdp->xsdt_addr ); } else { - return -1; + panic("invalid acpi rev: %d\n", rsdp->revision); } - if (res) + if (res) { + kprintf("...acpi failed to load\n\n"); return res; + } + + kprintf("\n\n"); int ret = read_s5_addr(&state); if (!ret) diff --git a/src/arch/amd64/backtrace.c b/src/arch/amd64/cpu/backtrace.c similarity index 100% rename from src/arch/amd64/backtrace.c rename to src/arch/amd64/cpu/backtrace.c diff --git a/src/arch/amd64/debugger.c b/src/arch/amd64/cpu/debugger.c similarity index 99% rename from src/arch/amd64/debugger.c rename to src/arch/amd64/cpu/debugger.c index a1fa968..4d9d3c3 100644 --- a/src/arch/amd64/debugger.c +++ b/src/arch/amd64/cpu/debugger.c @@ -2,6 +2,7 @@ #include #include #include + #include "debugger.h" struct dr6 { @@ -195,8 +196,8 @@ static int debugger_handle_bkp_cmd(char *msg) { const char *lenstrs[] = {"1", "2", "8", "4"}; const char *rwstrs[] = {"x ", "w ", "io", "rw"}; kprintf( - "breakpoint %d: %#016lx len=%s trigger=%s instrlen=%01d %s\n", - i, + "breakpoint %d: %#016lx len=%s trigger=%s instrlen=%01d %s\n", + i, bkp.addr, lenstrs[bkp.len], rwstrs[bkp.rw], diff --git a/src/arch/amd64/debugger.h b/src/arch/amd64/cpu/debugger.h similarity index 83% rename from src/arch/amd64/debugger.h rename to src/arch/amd64/cpu/debugger.h index e679c07..14f73bf 100644 --- a/src/arch/amd64/debugger.h +++ b/src/arch/amd64/cpu/debugger.h @@ -3,7 +3,7 @@ #include "idt.h" #define DEBUG_INT3 0x00 -#define DEBUG_DBG 0x01 +#define DEBUG_DBG 0x01 #define DEBUG_FAULT 0x02 void debugger(struct isr_regs *state, int cause); diff --git a/src/arch/amd64/idt.S b/src/arch/amd64/cpu/idt.S similarity index 100% rename from src/arch/amd64/idt.S rename to src/arch/amd64/cpu/idt.S diff --git a/src/arch/amd64/idt.c b/src/arch/amd64/cpu/idt.c similarity index 97% rename from src/arch/amd64/idt.c rename to src/arch/amd64/cpu/idt.c index d33c795..053f614 100644 --- a/src/arch/amd64/idt.c +++ b/src/arch/amd64/cpu/idt.c @@ -2,10 +2,10 @@ #include #include #include - -#include "debugger.h" #include "idt.h" -#include "pic.h" +#include "debugger.h" +#include "../paging.h" +#include "../drivers/pic.h" #define IDT_SIZE 256 @@ -148,7 +148,7 @@ void idt_pic_timer(void) { // print a message once we know the timer works // but avoid spamming the logs if (counter == 3) { - kputs("pic timer!\n"); + //kputs("pic timer!\n"); } if (counter <= 3) { counter++; @@ -158,4 +158,3 @@ void idt_pic_timer(void) { void idt_pic_keyboard(void) {} void idt_pic_mouse(void) {} - diff --git a/src/arch/amd64/idt.h b/src/arch/amd64/cpu/idt.h similarity index 100% rename from src/arch/amd64/idt.h rename to src/arch/amd64/cpu/idt.h diff --git a/src/arch/amd64/fb.c b/src/arch/amd64/drivers/bochs.c similarity index 65% rename from src/arch/amd64/fb.c rename to src/arch/amd64/drivers/bochs.c index 8560166..5383213 100644 --- a/src/arch/amd64/fb.c +++ b/src/arch/amd64/drivers/bochs.c @@ -3,8 +3,9 @@ #include #include #include +#include -#include "bindings.h" +#include "../bindings.h" #define INDEX 0x1CE #define DATA 0x1CF @@ -52,38 +53,21 @@ static void set_mode(uint16_t width, uint16_t height, uint16_t bit_depth, int lf (clear ? 0 : DATA_NO_CLEAR_MEM)); } -//static void set_bank(uint16_t bank) { -// write(INDEX_BANK, bank); -//} +uint32_t* bochs_init(uint16_t width, uint16_t height, uint8_t bit_depth) { -int fb_init(uint16_t width, uint16_t height) { - - set_mode(width, height, 32, true, true); + set_mode(width, height, bit_depth, true, true); if (!is_available()) - panic("bochs framebuffer not avaliable"); + return NULL; struct pci_device bochs = {0}; bool found = pci_findby_id(&bochs, BOCHS_PCI_DEVICE, BOCHS_PCI_VENDOR, NULL); if (!found) - panic("bochs pci device not avaliable"); + return NULL; uint32_t bar0 = pci_rcfg_d(bochs, PCI_BAR0_D); - uint32_t *fb = (uint32_t*) (uintptr_t) bar0; - fb = mmap(fb, width * height * 4); + uint32_t *addr = (uint32_t*) (uintptr_t) bar0; + addr = mmap(addr, width * height * bit_depth); - for (uint16_t y = 0; y < height; y++) { - for (uint16_t x = 0; x < width; x++) { - double dx = x / (double) width, - dy = y / (double) height, - dz = (2 - dx - dy) / 2; - uint32_t r = (uint32_t)(dx * 255), - g = (uint32_t)(dy * 255), - b = (uint32_t)(dz * 255); - fb[x + y * width] = (b << 0) | (g << 8) | (r << 16); - } - } - - - return 0; + return addr; } diff --git a/src/arch/amd64/pci.c b/src/arch/amd64/drivers/pci.c similarity index 99% rename from src/arch/amd64/pci.c rename to src/arch/amd64/drivers/pci.c index 7b30f0e..410eb7e 100644 --- a/src/arch/amd64/pci.c +++ b/src/arch/amd64/drivers/pci.c @@ -3,7 +3,7 @@ #include #include -#include "bindings.h" +#include "../bindings.h" #define CONF_ADDR 0xCF8 #define CONF_DATA 0xCFC diff --git a/src/arch/amd64/pic.c b/src/arch/amd64/drivers/pic.c similarity index 99% rename from src/arch/amd64/pic.c rename to src/arch/amd64/drivers/pic.c index c25856b..be7716f 100644 --- a/src/arch/amd64/pic.c +++ b/src/arch/amd64/drivers/pic.c @@ -1,4 +1,4 @@ -#include "bindings.h" +#include "../bindings.h" #include "pic.h" #define PIC1 0x20 /* IO base address for master PIC */ diff --git a/src/arch/amd64/pic.h b/src/arch/amd64/drivers/pic.h similarity index 100% rename from src/arch/amd64/pic.h rename to src/arch/amd64/drivers/pic.h diff --git a/src/arch/amd64/serial.c b/src/arch/amd64/drivers/serial.c similarity index 98% rename from src/arch/amd64/serial.c rename to src/arch/amd64/drivers/serial.c index fe21629..b9e351e 100644 --- a/src/arch/amd64/serial.c +++ b/src/arch/amd64/drivers/serial.c @@ -1,5 +1,6 @@ #include -#include "bindings.h" + +#include "../bindings.h" #define PORT 0x3F8 diff --git a/src/arch/amd64/fpu.c b/src/arch/amd64/fpu.c index 551485e..43fc653 100644 --- a/src/arch/amd64/fpu.c +++ b/src/arch/amd64/fpu.c @@ -1,6 +1,7 @@ #include #include #include +#include void enable_fpu() { size_t cr4; diff --git a/src/arch/amd64/linker.ld b/src/arch/amd64/linker.ld deleted file mode 100644 index 0032765..0000000 --- a/src/arch/amd64/linker.ld +++ /dev/null @@ -1,38 +0,0 @@ -ENTRY(start) - -SECTIONS { - . = 1M; - - kernel_start = .; - - .boot BLOCK(4K) : ALIGN(4K) - { - *(.multiboot) - } - - .rodata BLOCK(4K) : ALIGN(4K) - { - *(.rodata) - } - - .data BLOCK(4K) : ALIGN(4K) - { - *(.data) - } - - text_start = .; - - .text BLOCK(4K) : ALIGN(4K) - { - *(.text) - } - - text_end = .; - - .bss BLOCK(4K) : ALIGN(4K) - { - *(.bss) - } - - kernel_end = .; -} diff --git a/src/arch/amd64/mboot.c b/src/arch/amd64/mboot.c index 315747e..34424a0 100644 --- a/src/arch/amd64/mboot.c +++ b/src/arch/amd64/mboot.c @@ -9,6 +9,7 @@ #define MBOOT_CMDLINE 1 #define MBOOT_MEMORY_MAP 6 +#define MBOOT_FRAMEBUFFER 8 #define MBOOT_ELF_SYMBOLS 9 #define MBOOT_OLD_RSDP 14 #define MBOOT_NEW_RSDP 15 @@ -82,6 +83,18 @@ struct mboot_tag_cmdline { uint8_t cmdline[]; }; +struct mboot_tag_framebuffer { + uint32_t type; + uint32_t size; + uint64_t framebuffer_addr; + uint32_t framebuffer_pitch; + uint32_t framebuffer_width; + uint32_t framebuffer_height; + uint8_t framebuffer_bpp; + uint8_t framebuffer_type; + uint16_t reserved; +}; + static void read_symbols( struct boot_info *shim_info, struct mboot_tag_elf_sections *sections @@ -133,6 +146,17 @@ static void read_cmdline( shim_info->cmdline[size] = '\0'; } +static void read_framebuffer( + struct boot_info *shim_info, + struct mboot_tag_framebuffer *framebuffer +) { + shim_info->fb.addr = framebuffer->framebuffer_addr; + shim_info->fb.width = framebuffer->framebuffer_width; + shim_info->fb.height = framebuffer->framebuffer_height; + shim_info->fb.pitch = framebuffer->framebuffer_pitch; + shim_info->fb.bit_depth = framebuffer->framebuffer_bpp; +} + static const char *segment_type[] = { "Reserved", "Free", @@ -217,6 +241,12 @@ void mboot_load_info( (struct mboot_tag_cmdline *) tag ); break; + case MBOOT_FRAMEBUFFER: + read_framebuffer( + shim_info, + (struct mboot_tag_framebuffer *) tag + ); + break; case MBOOT_MEMORY_MAP: read_memory_map( shim_info, diff --git a/src/arch/amd64/paging.c b/src/arch/amd64/paging.c index 604e0a0..1c1c56c 100644 --- a/src/arch/amd64/paging.c +++ b/src/arch/amd64/paging.c @@ -45,7 +45,8 @@ struct pde { // PAGE TABLE ENTRY struct pte { uint64_t flags : 9; - uint64_t : 3; + uint64_t loaded : 1; + uint64_t : 2; uint64_t address : 40; uint64_t : 7; uint64_t protection_key : 4; @@ -69,7 +70,7 @@ static struct pde *pd_mapped = (void *) (uintptr_t) 0x202000; static struct pte *pt_mapped = (void *) (uintptr_t) 0x203000; static inline void invlpg(void *addr) { - __asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); + __asm__ volatile("invlpg (%0)" ::"r" (addr) : "memory"); } static void load_addr(void *phys_addr) { @@ -297,6 +298,7 @@ static void unmap_page( page->address = 0; page->flags = 0; + page->loaded = 0; try_unmap_pt(); @@ -360,6 +362,7 @@ static void unmap_pages( page->address = 0; page->flags = 0; + page->loaded = 0; } @@ -369,6 +372,31 @@ static void unmap_pages( return; } +static struct pte *get_page( + struct pml4e *root, + void *virt +) { + struct pdpte *pdpt; + struct pde *pd; + struct pte *pt; + struct pte *page; + + unsigned int df = 0; + + if (select_pdpt(virt, df, root, &pdpt, false)) + return NULL; + + if (select_pd(virt, df, pdpt, &pd, false)) + return NULL; + + if (select_pt(virt, df, pd, &pt, false)) + return NULL; + + select_page(virt, pt, &page); + + return page; +} + static int map_page( struct pml4e *root, void *virt, @@ -382,6 +410,9 @@ static int map_page( unsigned int df = F_WRITEABLE; + if (phys == NULL) + df = 0; // alloc page on fault + if (select_pdpt(virt, df, root, &pdpt, true)) return 1; @@ -393,9 +424,16 @@ static int map_page( select_page(virt, pt, &page); - page->address = (uint64_t)phys >> 12; - page->flags = F_PRESENT | flags; - invlpg(virt); + if (phys) { + page->flags = F_PRESENT | flags; + page->address = (uint64_t)phys >> 12; + page->loaded = 1; + invlpg(virt); + } else { + page->flags = flags; + page->address = 0; + page->loaded = 0; + } return 0; } @@ -424,6 +462,9 @@ static int map_pages( unsigned int df = F_WRITEABLE; + if (phys_start == NULL) + df = 0; // alloc page on fault + long i; for (i = 0; i < page_count; i++) { @@ -454,15 +495,22 @@ static int map_pages( select_page(virt, pt, &page); - page->address = (uint64_t)phys >> 12; - page->flags = F_PRESENT | flags; + if (phys_start) { + page->flags = F_PRESENT | flags; + page->address = (uint64_t)phys >> 12; + page->loaded = 1; + } else { + page->flags = flags; + page->address = 0; + page->loaded = 0; + } if (flags & F_GLOBAL) invlpg(virt); } - __asm volatile("mov %cr3, %rax; mov %rax, %cr3;"); + __asm__ volatile("mov %cr3, %rax; mov %rax, %cr3;"); return 0; @@ -575,3 +623,21 @@ int kunmap_page(void *virt_addr) { unmap_page(kernel_pml4, virt_addr); return 0; } + +int kload_page(void *virt_addr) { + struct pte *page = get_page(kernel_pml4, virt_addr); + if (page == NULL) + return -1; + if (page->loaded) + return -1; + void *phys = alloc_phys_page(); + kprintf("0x%p\n", phys); + if (phys == NULL) + return -2; + page->loaded = 1; + page->address = (uint64_t)phys >> 12; + page->flags |= F_PRESENT | F_WRITEABLE; + invlpg(virt_addr); + __asm__ volatile ("movq %cr3, %rax; movq %rax, %cr3;"); + return 0; +} diff --git a/src/arch/amd64/paging.h b/src/arch/amd64/paging.h index a76a172..9e1352c 100644 --- a/src/arch/amd64/paging.h +++ b/src/arch/amd64/paging.h @@ -13,3 +13,4 @@ void paging_init(void); int kmap_page(void *virt_addr, void *phys_addr, unsigned int flags); int kunmap_page(void *virt_addr); +int kload_page(void *virt_addr); diff --git a/src/arch/amd64/shim.c b/src/arch/amd64/shim.c index c161c88..b84167c 100644 --- a/src/arch/amd64/shim.c +++ b/src/arch/amd64/shim.c @@ -6,8 +6,8 @@ #include "paging.h" #include "mboot.h" -#include "idt.h" -#include "pic.h" +#include "cpu/idt.h" +#include "drivers/pic.h" static struct boot_info boot_info; diff --git a/src/kmain.c b/src/kmain.c index 7ae9d01..249dd84 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -1,28 +1,27 @@ -#include "fpu.h" +#include #include #include #include -#include +#include #include #include #include +#include void kmain(struct boot_info *info) { enable_fpu(); memory_init(&info->map); pci_init(); - fb_init(1024, 768); - //acpi_init(info->acpi_table); + screen_init(); + acpi_init(info->acpi_table); kprintf("enterd kmain\n"); - *(char *)(0xB8000 + 0x144) = 'h'; - *(char *)(0xB8000 + 0x146) = 'i'; + char *test = kalloc(5); + *test = 1; while (1) { - __asm__("hlt;"); - // loop so we dont halt - // this allows interrupts to fire + screen_redraw(); } } diff --git a/src/lib.c b/src/lib.c index d2708c8..bd8e335 100644 --- a/src/lib.c +++ b/src/lib.c @@ -32,7 +32,9 @@ void *memmove(void *dest, const void *src, unsigned long n) { void *memset(void *restrict dest, int c, unsigned long n) { unsigned char *d = dest; - for (; n; n--) *d++ = c; + for (; n; n--) { + *d++ = c; + }; return dest; } diff --git a/src/memory/memory.c b/src/memory/memory.c index d1a163f..1e69d8a 100644 --- a/src/memory/memory.c +++ b/src/memory/memory.c @@ -51,7 +51,7 @@ void *kalloc_new(size_t size) { node = 0; } - memset(addr, 0, pages * PAGE_SIZE); + memcpy(addr, 0, pages * PAGE_SIZE); struct page_header *header = addr; header->magic = 0xBEEFCAFE; header->used = size; diff --git a/src/print.c b/src/print.c index 4adfcf7..fa16bab 100644 --- a/src/print.c +++ b/src/print.c @@ -138,6 +138,7 @@ static struct format_precision read_precision(const char *format, const char **e if (c == '*' && precision.defined == false) { precision.defined = true; precision.varys = true; + format++; break; } @@ -336,7 +337,7 @@ static void print_unum( char buf[1024]; char *str = get_decimal( num, - buf, + buf + 1023, sign, radix, base @@ -457,11 +458,21 @@ void kvprintf(const char *format, va_list args) { char c; const char *str; void *ptr; - } data; + } data = {0}; int radix = 0; char base = 0; + if (width.varys) { + int len = va_arg(args, int); + width.value = len; + } + + if (precision.varys) { + int len = va_arg(args, int); + precision.value = len; + } + switch (conversion) { case FMT_INT: if (modifier == MOD_NONE) @@ -475,7 +486,15 @@ void kvprintf(const char *format, va_list args) { else if (modifier == MOD_LONG_LONG) data.l = va_arg(args, long long); radix = 10; - goto printnum; + print_num( + data.l, + flag, + width, + precision, + radix, + base + ); + break; case FMT_UINT: case FMT_OCT: case FMT_HEX_UPPER: @@ -503,6 +522,7 @@ void kvprintf(const char *format, va_list args) { base = 'A'; } goto printunum; + break; case FMT_PTR: case FMT_PTR_UPPER: flag |= FLG_ZERO; @@ -513,15 +533,6 @@ void kvprintf(const char *format, va_list args) { else base = 'A'; goto printunum; - printnum: - print_num( - data.l, - flag, - width, - precision, - radix, - base - ); break; printunum: print_unum( diff --git a/src/screen.c b/src/screen.c new file mode 100644 index 0000000..6f682ae --- /dev/null +++ b/src/screen.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include + +#define SCREEN_WIDTH 1024 +#define SCREEN_HEIGHT 768 +#define SCREEN_BIT_DEPTH 32 + +struct rgb { + uint8_t r; + uint8_t g; + uint8_t b; +}; + +struct hsv { + uint16_t h; + uint16_t s; + uint16_t v; +}; + +static uint32_t *buffer = NULL; +static uint32_t width, height; +static uint8_t bit_depth; + +static uint16_t angle; + +static void set_pixel(struct rgb color, uint16_t x, uint16_t y) { + uint32_t offset = y * width + x; + buffer[offset] = (color.b << 0) | (color.g << 8) | (color.r << 16); +} + +static float fmod(float f, float m) { + return f - (int)(f / m) * m; +} + +static float fabs(float f) { + return f > 0 ? f : -f; +} + +static struct rgb htor(struct hsv hsv) { + struct rgb rgb; + float s = hsv.s / 100.0; + float v = hsv.v / 100.0; + float c = s * v; + float x = c * (1-fabs(fmod(hsv.h/60.0, 2) - 1)); + float m = v - c; + float r,g,b; + + if (hsv.h < 60) { + r = c; g = x; b = 0; + } else if (hsv.h >= 60 && hsv.h < 120) { + r = x; g = c; b = 0; + } else if (hsv.h >= 120 && hsv.h < 180) { + r = 0; g = c; b = x; + } else if (hsv.h >= 180 && hsv.h < 240) { + r = 0; g = x; b = c; + } else if (hsv.h >= 240 && hsv.h < 300) { + r = x; g = 0; b = c; + } else { + r = c; g = 0; b = x; + } + + rgb.r = (r + m) * 255; + rgb.g = (g + m) * 255; + rgb.b = (b + m) * 255; + + return rgb; +} + +static struct rgb get_color(uint16_t a, uint16_t x, uint16_t y) { + struct hsv hsv = { + .h = a, + .s = x * 100.0 / width, + .v = y * 100.0 / height, + }; + return htor(hsv); +} + +void screen_init(void) { + angle = 0; + width = SCREEN_WIDTH; + height = SCREEN_HEIGHT; + bit_depth = SCREEN_BIT_DEPTH; + buffer = bochs_init(width, height, bit_depth); +} + +void screen_redraw(void) { + for (uint16_t y = 0; y < height; y++) { + for (uint16_t x = 0; x < width; x++) { + struct rgb color = get_color(angle, x, height - y); + set_pixel(color, x, y); + } + } + angle++; + angle %= 360; +}