syscalls needed for doom (tell/eof/draw_fb) + minor fixes, compiler shut up etc

This commit is contained in:
2026-05-10 21:25:41 +02:00
parent 22f20d47ad
commit 18ab2c7628
12 changed files with 507 additions and 169 deletions
+105
View File
@@ -0,0 +1,105 @@
/*
* @author xamidev <xamidev@riseup.net>
* @brief Screen/framebuffer system calls
* @license GPL-3.0-only
*/
// This is not part of POSIX or anything btw
#include <stdint.h>
#include <kernel.h>
extern struct boot_context boot_ctx;
/*
* pack_rbga_to_fb - Convert rgb values to rgba pixel for framebuffer
* @r: red value
* @g: green value
* @b: blue value
*
* This function uses the mask sizes and shifts of the Limine
* framebuffer to convert raw rgb values into usable pixels.
*
* Return:
* <pixel> - usable pixel
*/
static uint32_t pack_rgba_to_fb(uint8_t r, uint8_t g, uint8_t b)
{
uint32_t pixel = 0;
if (boot_ctx.fb->red_mask_size) {
pixel |= ((uint32_t)(r >> (8 - boot_ctx.fb->red_mask_size)) << boot_ctx.fb->red_mask_shift);
}
if (boot_ctx.fb->green_mask_size) {
pixel |= ((uint32_t)(g >> (8 - boot_ctx.fb->green_mask_size)) << boot_ctx.fb->green_mask_shift);
}
if (boot_ctx.fb->blue_mask_size) {
pixel |= ((uint32_t)(b >> (8 - boot_ctx.fb->blue_mask_size)) << boot_ctx.fb->blue_mask_shift);
}
return pixel;
}
/*
* sys_draw_fb - Draw a framebuffer subset
* @src: Source frame
* @width: width of the frame
* @height: height of the frame
* @channels: how many channels (RGB, RGBA)
*
* This system call draws the frame @src, having some
* @width and @height, in the top right of the Limine
* framebuffer. (Used for DOOM)
*
* Return:
* %0 - on success
* On error, a negative value with an error code is returned.
*/
int sys_draw_fb(const uint8_t* src, int width, int height, int channels)
{
if (!boot_ctx.fb || !src) {
return -EINVAL;
}
if (channels != 4 || width <= 0 || height <= 0) {
return -EINVAL;
}
if (boot_ctx.fb->bpp < 24) {
return -EIO;
}
uint32_t* dst = (uint32_t*)boot_ctx.fb->address;
uint64_t dst_w = boot_ctx.fb->width;
uint64_t dst_h = boot_ctx.fb->height;
uint64_t dst_pitch_px = boot_ctx.fb->pitch / 4;
uint64_t scale = 2;
uint64_t scaled_w = (uint64_t)width * scale;
uint64_t scaled_h = (uint64_t)height * scale;
if (scaled_w > dst_w || scaled_h > dst_h) {
return -EINVAL;
}
uint64_t dst_x = dst_w - scaled_w;
uint64_t dst_y = 0;
for (uint64_t y = 0; y < (uint64_t)height; ++y) {
const uint8_t* src_row = src + y * (uint64_t)width * 4ULL;
uint32_t* dst_row0 = dst + (dst_y + y * scale) * dst_pitch_px + dst_x;
uint32_t* dst_row1 = dst_row0 + dst_pitch_px;
for (uint64_t x = 0; x < (uint64_t)width; ++x) {
const uint8_t* p = src_row + x * 4ULL;
uint32_t pixel = pack_rgba_to_fb(p[0], p[1], p[2]);
uint64_t dx = x * scale;
// Write 2x2 block. This is because source DOOM frame (320x200)
// is quite small.
dst_row0[dx + 0] = pixel;
dst_row0[dx + 1] = pixel;
dst_row1[dx + 0] = pixel;
dst_row1[dx + 1] = pixel;
}
}
return 0;
}