c++graphicsx86osdevmultiboot

How to print pixels in 1024x768x32 resolution (OS Development)?


So, I recently got into operating system development a while ago, and I've made some good progress. I'm working in assembly language, C, and C++, with C++ as the language of my main kernel and drivers. Also, I'm using Grub2 as my bootloader.

I've begun writing my graphics driver now, and I can easily draw pixels in 320x200x8 resolution. Unfortunately, I'm unable to do so in 1024x768x32 resolution (which I definitely need to do for my operating system graphics to be at least be standard quality).

This is my grub.cfg file:

set timeout=0
set default=0

insmod normal
insmod multiboot2
insmod all_video

set background_image=/boot/res/background.jpg
set gfxpayload=1024x768x32

menuentry "Alaric OS" {
    multiboot2 /boot/kernel.bin
    set gfxmode=1024x768x32
    set gfxpayload=1024x768x32
    insmod all_video
    boot
}

This is my header.asm file:

section .multiboot_header
header_start:
    ; magic number used for multiboot2
    dd 0xe85250d6
    ; architecture
    dd 0 ; protected mode i386
    ; header length
    dd header_end - header_start
    ; checksum
    dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))
    ; ===
    dw 5
    dw 0
    dd 20
    dd 1024
    dd 768
    dd 32

    ; end tag
    ;dw 0
    ;dw 0
    ;dd 8
header_end:

This is part of my io.h file (my I/O and graphics driver file):

unsigned char *VIDEO_MEMORY = (unsigned char*) 0xa0000;
unsigned char *FRAMEBUFFER = (unsigned char*) 0xa0000;
        
const int SCREEN_WIDTH = 1024;
const int SCREEN_HEIGHT = 768;
        
const unsigned char BITS_PER_PIXEL = 32;
        
const unsigned char PIXEL_STRIDE = (BITS_PER_PIXEL | 7) >> 3;
const unsigned char BYTES_PER_PIXEL = (BITS_PER_PIXEL | 7) >> 3;
const unsigned char PIXEL_WIDTH = (BITS_PER_PIXEL | 7) >> 3;
        
const int PITCH = SCREEN_WIDTH * PIXEL_STRIDE;
const int BYTES_PER_SCAN_LINE = SCREEN_WIDTH * PIXEL_STRIDE;
        
void draw_pixel(unsigned int x, unsigned int y, unsigned char red, unsigned char green, unsigned char blue)
{
    unsigned char* framebuffer = (unsigned char*)FRAMEBUFFER; // Replace with your framebuffer address
        unsigned int bytes_per_pixel = SYSTEM::VIDEO::BYTES_PER_PIXEL; // Replace with your bytes per pixel
        unsigned int bytes_per_scanline = SYSTEM::VIDEO::SCREEN_WIDTH * bytes_per_pixel; // Replace with your bytes per scanline
        uint8_t* pixel_address = framebuffer + y * bytes_per_scanline + x * bytes_per_pixel;
        pixel_address[0] = blue; // blue
        pixel_address[1] = green; // Green
        pixel_address[2] = red; // red
        
}
        

The problem is, I can easily draw to coordinates (0,0) to (1024, 20), but anything beyond that doesn't print at all and most times causes the system to crash. Also, I know I could have assigned variables like FRAMEBUFFER with already existing variables like VIDEO_MEMORY, but my compiler started tripping lately and setting variables like such was the only thing that got the compiler to start working again. By the way, I'm using Netbeans as my IDE and I'm compiling using nasm (for assembly), gcc (for C), g++ (for C++), ld (for linking binaries) and grub-mkrescue (to bind everything into a bootable ISO image).

As for the error, this is the error I get when I try to run the operating system in VirtualBox. The error pops up after a second or two of the OS running, or when the screen is scrolled: error image

I've tried switching up the code as best I can, but nothing is working. Any help will be highly appreciated.


Solution

  • Simply enough, as was suggested, I just needed to get the address of the video memory from the GRUB bootloader...