Page 1 of 2

Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 4:37 am
by DeezRamChips
Sa, i successfully ploted a pixel on the screen with the right color !

But... I cant do this on all the screen, take a look:

Image

and the code to plot a pixel:

Code: Select all

char* screen = 0xA0000;

void setPixel(int x,int y, int r, int g, int b) {
    unsigned pos = x*3 + y*2400;
    screen[pos] = b;     // BLUE
    screen[pos + 1] = g; // GREEN
    screen[pos + 2] = r; // RED
}
here is the code to switch to the video mode:

Code: Select all

mov ax, 0x4F02
mov bx, 0x115
int 10h
On real hardware, teh computer simply crashes

Thank for your help :)

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 4:45 am
by BrightLight
You're not using a linear frame buffer; you're using bank switching. That is completely obsolete.
Try using mode 0x4115 instead of 0x0115, and also use function 0x4F01 with mode 0x0115 to get the linear frame buffer address.

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 4:55 am
by DeezRamChips
Well, I i just tried using mode 0x4115 but it didn't change anything :(

also, The probleme, is that i cant call int 10 in p_mode because i dont have a vm86 monitor setup :/

how could I pass the linear frame buffer address to the kernel from the bootloader ?

(Sorry for n00b questions :( )

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 5:05 am
by BrightLight
Pass a structure to your kernel. For example, in your boot loader:

Code: Select all

boot_information:
; whatever information your kernel needs
.bios_memory_map  dd 0   ; pointer to memory map
.vbe_framebuffer   dd 0    ; VBE framebuffer
; anything else
Then, right before you call your kernel:

Code: Select all

mov eax, 0x12345678    ; you can make up any magic number to tell your kernel that it was booted with your loader
mov ebx, boot_information     ; pass the boot information to the kernel
call 0x100000          ; if your kernel is loaded at 1 MB, for example

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 5:11 am
by DeezRamChips
Ok thank, I though it was reset when i jump to the kernel I'm so silly :roll:

and, now, how do I access it in the kernel ?

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 5:17 am
by BrightLight
Erm.. You're kidding right? :roll:
You already have a pointer to it. Access it from the pointer.

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 5:29 am
by DeezRamChips
Well I dont understand how pointers work in c and assembly: I just started OS developpement 3 weeks ago...

And my consol version works fine, but I want a better resolution so I would like to use VESA.

Could you show me an exemple of how i could get the info in the kernel and explain me how it works...


Sorry again for n00b question, i'm trying to get better

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 6:25 am
by Combuster
I dont understand how pointers work in c and assembly
Pointers is one of the fundamentals of C. If that's still magic to you, then possibly Required Knowledge applies to you. There are many resources out on the internet that can help you learn the things involved.

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 6:53 am
by DeezRamChips
You didn't understand i think... I mean:

I understand pointers in C alone

But i dont understand how you can use them with Assembly

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 7:38 am
by DeezRamChips
So, i read a little more about pointer !


but, I only manage to pass a single variable, how could a pass a structure ?

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 8:21 am
by osdever
DeezRamChips wrote:So, i read a little more about pointer !


but, I only manage to pass a single variable, how could a pass a structure ?
Exactly as a variable - pass pointer to the structure.

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 8:48 am
by DeezRamChips
To pass a pointer to a structure, how do you do?

like this ? :

Code: Select all

int addr; //stores the address
asm("\t movl %%ebx,%0" : "=r"(addr)); //get the address from EBX
addr = addr + 1; // Add 1

unsigned char *boot_information = addr; //Initialize the pointer

struct boot_info
{
    int a; //First info
    int b; //Second info
};

boot_info = boot_information;
I tried this but it gives me an error

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 10:02 am
by osdever
DeezRamChips wrote:To pass a pointer to a structure, how do you do?

like this ? :

Code: Select all

int addr; //stores the address
asm("\t movl %%ebx,%0" : "=r"(addr)); //get the address from EBX
addr = addr + 1; // Add 1

unsigned char *boot_information = addr; //Initialize the pointer

struct boot_info
{
    int a; //First info
    int b; //Second info
};

boot_info = boot_information;
I tried this but it gives me an error
First read Required Knowledge. You aren't declaring any copies of struct boot_info - instead you're trying to assign value to 1) invalid type in C (struct blablabla isn't creating new type in C), 2) type name in C++. Also, your assigning won't work even if you'll fix first your error - you need to swap boot_info and boot_information. You're assigning pointer to structure.
Some info: don't offend, I've been exactly like you when I started OSDev'ing.

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 10:21 am
by DeezRamChips
So, how could i fix the probleme ?

Re: Only portion of screen working in VESA

Posted: Sat Apr 09, 2016 10:57 am
by Schol-R-LEA
The use of

Code: Select all

addr = addr + 1; // Add 1
to increment the value here is troubling to me, for two reasons.

First, it implies that you don't know the increment operator (or just don't realize that it is a general operator rather than a part of the for() loop's control structure). The ++ operator is such a critical feature in C/C++ that not knowing it is a sign that you really don't understand the language as a whole as well as you think.

Second, I'm not sure just why you are incrementing that address in the first place. You already have the address of the boot map, why do you need to change it to map to a specific element in that map?

Third, since you are using an integer to hold the address rather than a pointer, incrementing the address gives it a value of address+1, but since you are working with a structure already (albeit one passed to you from the assembly code), you would only really need to increment it by address + sizeof(bootmap), if at all. By using a pointer, you could have the compiler do this part for you automatically.

If you had declared the boot_info structure first, then declared boot_information as a pointer to that type and implicitly cast the address to that type by passing boot_information as the inline assembly parameter, you wouldn't need any of this.

Code: Select all

typedef struct boot_info
{
    int a; //First info
    int b; //Second info
} BOOT_INFO;

BOOT_INFO* boot_information;

asm("\t movl %%ebx,%0" : "=r"(boot_information)); //get the address from EBX