VGA in Pmode Not Working

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
purage
On Probation
Posts: 119
Joined: Wed Feb 11, 2009 1:04 am

VGA in Pmode Not Working

Post by purage »

Hi. I am attempting to create a basic GUI. In my boot loader (before I call main) I switch to VGA 320x200x8 (256 colors) and I test that it works by plotting several pixels (still before calling main) and it does work in real mode. It does not work in pmode. There is no error, I just do not see any change to the screen. I expect to see a single black pixel at (1,1). Here is what I am doing:

Once I am in main, I try to write a pixel to screen using (pmode --this does not work):

Code: Select all

char *vga = (char *) 0xA0000;
unsigned int i = (320*200);
char *buffer = (char *) kmalloc(320*200);
buffer[(1<<8) + (1<<6) + 1] = 0x00;
memcpy(vga, buffer, i); //draw one pixel
here is how I draw a line in my loader (real mode --this works):

Code: Select all

;Change the video mode to 13h
xor  ah, ah         ;VIDEO Function 00h: Change screen
mov  al, 13h        ;Put the desired graphics mode into AL
int  10h            ;Call VIDEO

;Prepare for writing to the video buffer
mov  di, 0a000h     ;Put the video segment into DI
mov  es, di         ; so it can easily be put into ES
xor  di, di         ;Start writing at coordinates (0,0)

;draw a vertical line
mov  ax, 320        ; Prepare for the multiplication
mov  di, ax         ; Put it into the pointer of the offset in ES
add  di, 320*187   	; x position
mov  al, 0x1A    	; Put the color to be written to the screen in AL
mov  cx, 320*1   	; Prepare for the loop
loopg:
    stosb               ; Write it to the screen!
    loop loopg			; loop till done
I have checked my non-working pmode code with other sources and I have no idea why it wouldn't work. Help to fix my mistake? Thank you.
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

Re: VGA in Pmode Not Working

Post by Love4Boobies »

Maybe you don't see anything because you're writing black pixels on a black screen? Anyway, your comment is wrong, you're not writing one pixel, you''re writing the whole screen.
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
eddyb
Member
Member
Posts: 248
Joined: Fri Aug 01, 2008 7:52 am

Re: VGA in Pmode Not Working

Post by eddyb »

purage wrote:

Code: Select all

char *vga = (char *) 0xA0000;
unsigned int i = (320*200);
char *buffer = (char *) kmalloc(320*200);
buffer[(1<<8) + (1<<6) + 1] = 0x00;
memcpy(vga, buffer, i); //draw one pixel
try this:

Code: Select all

char *vga = (char *) 0xA0000;
vga[123] = 25;//some numbers; here, it writes to pixel 123 the color 25
purage
On Probation
Posts: 119
Joined: Wed Feb 11, 2009 1:04 am

Re: VGA in Pmode Not Working

Post by purage »

That worked, but why does it write more than one pixel to screen and where does pixel location 123 represent? It appears to be near the lower right hand corner of the screen. Is what I place in the brackets the y value? How do I represent the x value? How do I prevent the code from writing the pixel more than once? thank you
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

Re: VGA in Pmode Not Working

Post by Love4Boobies »

It doesn't write more than one pixel, pixels are big (remember that your screen resolution is 320x200). Mode 13h is a 8bpp mode, probably the simplest one there is. You just have an array of consecutive pixels, their indexes ranging from 0 to 320x200-1. If you do a little math, it's only obvious that being 320 pixel per row the formula is INDEX = (Y * 320 + X) so just go ahead and write your desired colour there. You should really do more research on this (the OSDev wiki has some nice things on this).
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
eddyb
Member
Member
Posts: 248
Joined: Fri Aug 01, 2008 7:52 am

Re: VGA in Pmode Not Working

Post by eddyb »

purage wrote:That worked, but why does it write more than one pixel to screen and where does pixel location 123 represent? It appears to be near the lower right hand corner of the screen. Is what I place in the brackets the y value? How do I represent the x value? How do I prevent the code from writing the pixel more than once? thank you
well, i just gave you a random number.
to write a pixel (as Love4Boobies told you how to calculate the index) just use vga[y*width+x] = color;
purage
On Probation
Posts: 119
Joined: Wed Feb 11, 2009 1:04 am

Re: VGA in Pmode Not Working

Post by purage »

I'm sorry, it doesn't seem to work actually. If I do this:

Code: Select all

char *vga = (char *) 0xA0000;
vga[1 * 320 + 1] = 0x0C;
I see no change, and the background is not black or the same color as the color I have chosen above.

Yes, I know the pixels are bigger, I meant that when I did:

Code: Select all

vga[123]=0x0C;
I saw several other pixels (of the same size) written across the screen. I counted out 42 of them to be exact. Any idea?
User avatar
Love4Boobies
Member
Member
Posts: 2111
Joined: Fri Mar 07, 2008 5:36 pm
Location: Bucharest, Romania

Re: VGA in Pmode Not Working

Post by Love4Boobies »

First I would have thought there is something wrong with your kmalloc() implementation; however, this is not the case since you're not using it anymore for this. Can you tell me what you're testing on?
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
purage
On Probation
Posts: 119
Joined: Wed Feb 11, 2009 1:04 am

Re: VGA in Pmode Not Working

Post by purage »

I'm testing it in VPC. I know that the card (emulated or not) can support this mode since it works in real mode (on both real and emulated hardware). I just cannot seem to make it work in pmode. I was playing around with my loader the other day and I thought that might be why I am having memory issues, so I changed it all back to the original and I fixed the multiple pixel write issue, but now no matter what coordinate I choose, I still see nothing. Now I don't even see the stream of pixels I saw before.

EDIT: Even trying this gives me nothing at all and the screen is blue (set in rmode), so I expect it to go all black (with this code in pmode):

Code: Select all

char *vga = (char *) 0xA0000;
unsigned int i=0;
while(i < (320*200))
{
   vga[i]=0x00;
   i++;
}
But it doesn't change colors, it is as if the address 0xA0000 means absolutely nothing at all. If I try to write a color to that address I see no change on screen, it remains blue. Strange.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: VGA in Pmode Not Working

Post by Combuster »

Are you using paging? Using the GDT trick? have you checked where all the tables are actually pointing?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
purage
On Probation
Posts: 119
Joined: Wed Feb 11, 2009 1:04 am

Re: VGA in Pmode Not Working

Post by purage »

No to paging. What is the GDT trick? No I haven't checked that, how would I do that? Is that address write protected in pmode? Sorry, for all the newbie questions.
purage
On Probation
Posts: 119
Joined: Wed Feb 11, 2009 1:04 am

Re: VGA in Pmode Not Working

Post by purage »

Hi. After doing a lot of research on the GDT trick you mentioned, I finally found what you were talking about (vm86). It won't work for me. I do not link my loader with the kernel. The loader loads the kernel from disk. I assume it won't work but I may be wrong. What could I do to be able to use the vga graphics mode 0x13 in pmode without vm86 and paging? I think that I am causing a segmentation fault because if I do not write to the screen in my loader (as I was when testing from rmode), my pmode code makes the BIOS beep like crazy. I am using GCC so there is no way for far pointers and I am not sure how to build my own selector. I am a total newb. thank you.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: VGA in Pmode Not Working

Post by Combuster »

purage wrote:Hi. After doing a lot of research on the GDT trick you mentioned, I finally found what you were talking about (vm86).
First hit on google says differently. The GDT trick is a method of running a higher half kernel without paging enabled.

I thought of a few other causes:
- Weird selector values. Normal protected mode setups require all selectors to be set to base 0 and a limit of 4G. If that's not the case you'll end up writing somewhere different, which can also explain why you can see random noise on screen.
- You aren't in graphics mode. You need a VGA driver to change the video mode from protected mode. If you haven't set the correct mode before entering the kernel it won't do what you expect.
- Your kernel crashed and your code doesn't get executed.

If you could attach all the code you are trying to run (and fails) we have more of a reference to see where things go awry.
Sorry, for all the newbie questions.
Saying that only annoys people and makes you look like a total n00b.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
purage
On Probation
Posts: 119
Joined: Wed Feb 11, 2009 1:04 am

Re: VGA in Pmode Not Working

Post by purage »

Hi. Here is the code from my loader that sets the graphics mode (in loader --rmode):

Code: Select all

 xor  ah, ah         ;VIDEO Function 00h: Change screen
    mov  al, 13h        ;Put the desired graphics mode into AL
    int  10h            ;Call VIDEO

	;Prepare for writing to the video buffer
    mov  di, 0a000h     ;Put the video segment into DI
    mov  es, di         ; so it can easily be put into ES
    xor  di, di         ;Start writing at coordinates (0,0)

	;Write background
    mov  ax, 320        ; Prepare for the multiplication
    mov  di, ax         ; Put it into the pointer of the offset in ES
    add  di, 0       	; x position
    mov  al, 0x36    	; Put the color to be written to the screen in AL
    mov  cx, 320*200   	; Prepare for the loop
loopb:
    stosb               ; Write it to the screen!
    loop loopb			; loop till done
You see I test the mode and it works. Here is where I setup the call to main (in loader --pre-pmode).

Code: Select all

        mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov ss, ax
	mov fs, ax
	mov gs, ax

	mov esp, 0x200000 - 16

	mov esi, kernel	
	mov edi, 0x100000		
	mov ecx, (kernel_size/4) + 1  	
	rep movsd
			
	call 0x100000 					
	jmp $
Here is the code that now cause a series of sporadic beeps via the BIOS in VPC (in kernel --pmode).

Code: Select all

void main()
{
        char *vga = (char *) 0xa0000;
	unsigned int i = (320*200);
	vga[i++]=0x30;

for(;;);
}
As you can see I am trying to use the address 0xa0000 like 0xb8000, but it doesn't seem that easy. Please let me know if you need more code. I am not sure exactly what you would need to see. What I have posted above is pretty much everything involved ATM. thank you.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: VGA in Pmode Not Working

Post by Combuster »

- I miss the GDT
- I miss CS being set up (where did we get into 32 bit mode?)
- Have you checked main() is actually located at the very start of the kernel (and not somewhere else?)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Locked