Page 1 of 1

320X200 resolution works but 640X480 does not ???

Posted: Sun Feb 22, 2009 11:59 pm
by schwin
hi ! first of all thank you to all the people on this forum, for guiding me previously on switching to VGA graphics mode, even when it was asked zillionth time.

I am stuck again and not able to move ahead ... I have the following code:


#include <kernel.h>

//define the ports , taken from //http://files.osdev.org/mirrors/geezer/o ... cs/modes.c
#define VGA_AC_INDEX 0x3C0
#define VGA_AC_WRITE 0x3C0
#define VGA_AC_READ 0x3C1
#define VGA_MISC_WRITE 0x3C2
#define VGA_SEQ_INDEX 0x3C4
#define VGA_SEQ_DATA 0x3C5
#define VGA_DAC_READ_INDEX 0x3C7
#define VGA_DAC_WRITE_INDEX 0x3C8
#define VGA_DAC_DATA 0x3C9
#define VGA_MISC_READ 0x3CC
#define VGA_GC_INDEX 0x3CE
#define VGA_GC_DATA 0x3CF
#define VGA_CRTC_INDEX 0x3D4 /* 0x3B4 */
#define VGA_CRTC_DATA 0x3D5 /* 0x3B5 */
#define VGA_INSTAT_READ 0x3DA
#define VGA_NUM_SEQ_REGS 5
#define VGA_NUM_CRTC_REGS 25
#define VGA_NUM_GC_REGS 9
#define VGA_NUM_AC_REGS 21
#define VGA_NUM_REGS (1+VGA_NUM_SEQ_REGS+VGA_NUM_CRTC_REGS+VGA_NUM_GC_REGS+VGA_NUM_AC_REGS)

//the vga identifiers
unsigned int VGA_width;
unsigned int VGA_height;
unsigned int VGA_bpp;
unsigned char *VGA_address;

void VGA_init(int width, int height, int bpp);
void write_registers(unsigned char *regs);
void VGA_clear_screen();


void vga_mode()
{
VGA_init(640,480,16);
}

/**
* CREATE THE REGISTER ARRAY TAKEN FROM http://wiki.osdev.org/VGA_Hardware
*/

unsigned char g_640x480x16[] =
{
/* MISC */
0xE3,
/* SEQ */
0x03, 0x01, 0x08, 0x00, 0x06,
/* CRTC */
0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xEA, 0x0C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
0xFF,
/* GC */
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F,
0xFF,
/* AC */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x01, 0x00, 0x0F, 0x00, 0x00
};


void write_registers(unsigned char *regs){
unsigned i;

/* write MISCELLANEOUS reg */
outportb(VGA_MISC_WRITE, *regs);
regs++;
/* write SEQUENCER regs */
for(i = 0; i < VGA_NUM_SEQ_REGS; i++)
{
outportb(VGA_SEQ_INDEX, i);
outportb(VGA_SEQ_DATA, *regs);
regs++;
}
/* unlock CRTC registers */
outportb(VGA_CRTC_INDEX, 0x03);
outportb(VGA_CRTC_DATA, inportb(VGA_CRTC_DATA) | 0x80);
outportb(VGA_CRTC_INDEX, 0x11);
outportb(VGA_CRTC_DATA, inportb(VGA_CRTC_DATA) & ~0x80);
/* make sure they remain unlocked */
regs[0x03] |= 0x80;
regs[0x11] &= ~0x80;
/* write CRTC regs */
for(i = 0; i < VGA_NUM_CRTC_REGS; i++)
{
outportb(VGA_CRTC_INDEX, i);
outportb(VGA_CRTC_DATA, *regs);
regs++;
}
/* write GRAPHICS CONTROLLER regs */
for(i = 0; i < VGA_NUM_GC_REGS; i++)
{
outportb(VGA_GC_INDEX, i);
outportb(VGA_GC_DATA, *regs);
regs++;
}
/* write ATTRIBUTE CONTROLLER regs */
for(i = 0; i < VGA_NUM_AC_REGS; i++)
{
(void)inportb(VGA_INSTAT_READ);
outportb(VGA_AC_INDEX, i);
outportb(VGA_AC_WRITE, *regs);
regs++;
}

/* lock 16-color palette and unblank display */
(void)inportb(VGA_INSTAT_READ);
outportb(VGA_AC_INDEX, 0x20);

outportb(0x3c8,0x00);
outportb(0x3c9,0x3f);
outportb(0x3c9,0x3f);
outportb(0x3c9,0x3f);
}

/**
* Clears the VGA screen
*/
void VGA_clear_screen(){
unsigned int x=0;
unsigned int y=0;

for(y=0; y<VGA_height; y++){
for(x=0; x<VGA_width; x++){
// Address 0xA0000 is (0,0)
VGA_address[VGA_width*y+x]=0x0f; // 8 bit/pixel
}
}
}

/**
* Note here the vga struct must have the width 320 and height of 200
* color mode is 256
*/
void VGA_init(int width, int height, int bpp){
//setup the vga struct
VGA_width=(unsigned int)width;
VGA_height=(unsigned int)height;
VGA_bpp=bpp; // Bit per pixel 8 bits to color 1 pixel.
VGA_address=0xA0000;

write_registers(g_640x480x16);


//clears the screen
VGA_clear_screen();
}

which i found through this forum itself. I am trying to switch to graphics mode in Protected mode with 640X480X16 resolution. It does switch to graphics mode but the VGA_clear_screen() is not able to clear the screen, the screen is still blurred, it has all junk appearance. It does not color the whole screen to one color as desired. It works when I pass an array with 320X200X256 register values, but not with 640X480X16. Am I still missing something in the code above.

I have read the documentation VGA_hardware and the Register properties in Wiki VGA_Resources but as a beginner I am not able to figure out the bug.

Please guide me on the error and how to rectify it.

Re: 320X200 resolution works but 640X480 does not ???

Posted: Mon Feb 23, 2009 12:19 am
by gzaloprgm
Remember that in 640x480x16colors you have 4 planes that define the color of each pixel, so to "clear" the video you'll need to clear each plane.

Cheers,
Gonzalo

Re: 320X200 resolution works but 640X480 does not ???

Posted: Mon Feb 23, 2009 1:01 am
by schwin
Oh yes ! you are right...

But

what does this code do ?
/* lock 16-color palette and unblank display */
(void)inportb(VGA_INSTAT_READ);
outportb(VGA_AC_INDEX, 0x20);

and if the following code clears only 1 plane how do I move to the next one ?

outportb(0x3c8,0x00);
outportb(0x3c9,0x3f);
outportb(0x3c9,0x3f);
outportb(0x3c9,0x3f);

Sorry for being so elementry but i am still trying to get an understanding of the VGA Registers.

Re: 320X200 resolution works but 640X480 does not ???

Posted: Mon Feb 23, 2009 4:51 am
by jal
schwin wrote:Sorry for being so elementry but i am still trying to get an understanding of the VGA Registers.
Try searching the web for this, no doubt there are good tutorials. Clearing all four plains at the same time is possible to do really quick, but it involves setting up the right plane mask, and all these other masks I don't know by heart and have no time to check right now. But iirc, enable all four planes, select the right write mode, and write the desired attribute value. Thus you can set 8 pixels at a time.


JAL

Re: 320X200 resolution works but 640X480 does not ???

Posted: Mon Feb 23, 2009 5:15 am
by djmauretto
Hello,

Code: Select all

	MOV	DX,3C4H		; Sequencer
	MOV	AX,0F02H	; Enable ALL Planes 
	OUT	DX,AX   				
	
				
	MOV	BX,0A000H			
	MOV	ES,BX				
	XOR	DI,DI				
	MOV	CX,(640*480/8)/2		
	XOR	AX,AX			
	CLD	
	REP	STOSW

Re: 320X200 resolution works but 640X480 does not ???

Posted: Mon Feb 23, 2009 6:51 am
by jal
djmauretto wrote:Hello,

Code: Select all

	MOV	DX,3C4H		; Sequencer
	MOV	AX,0F02H	; Enable ALL Planes 
	OUT	DX,AX   				
	
				
	MOV	BX,0A000H			
	MOV	ES,BX				
	XOR	DI,DI				
	MOV	CX,(640*480/8)/2		
	XOR	AX,AX			
	CLD	
	REP	STOSW
Indeed, that seems to be it :). However, when in (32-bits) protected mode, I'd do a /4 and a stosd (and xor or mov of eax instead of ax).


JAL

Re: 320X200 resolution works but 640X480 does not ???

Posted: Mon Feb 23, 2009 10:19 am
by djmauretto
Indeed, that seems to be it :). However, when in (32-bits) protected mode, I'd do a /4 and a stosd (and xor or mov of eax instead of ax).
OOPS :oops:
Yes , usually i use VGA in real mode 16bit and VESA VBE in protect mode ,
anyway it's easy to extend to 32bit :)

Code: Select all

   
  XOR  EAX,EAX
  XOR  EDX,EDX

  MOV   DX,3C4H      ; Sequencer
  MOV   AX,0F02H     ; Enable ALL Planes
  OUT   DX,AX               
          
  XOR   EDI,EDI          
  MOV   ECX,9600     
  XOR   EAX,EAX         
  CLD   
  REP   STOSD
in this case you must have in ES a selector with base address of A0000
and limit 64KB

Re: 320X200 resolution works but 640X480 does not ???

Posted: Mon Feb 23, 2009 4:59 pm
by schwin
jal wrote:Thus you can set 8 pixels at a time.
JAL
Thanks a lots sir !
I got from the code that you posted that Map Mask Register of Sequencer was to be set to 0000 1111 or 0x0F hex...
And that enabled all the planes 3-0 that Mode12h is using and my whole screen was painted in one color...

As you said in your posts 8 pixels can be set at a time. how are we doing that ? If I need to plot a pixel at (1,1) location how do I set the colors ? I understand that the 6 least significant bits are to be set for each plane. but can you please guide me as to how do they work together? and also, it is written on Wiki that DAC Data Register has to be written three times , once for red , once for blue and once for green, do we use the same index address all the time? or do it as shown below:

outportb(0x3c8,0x00);
outportb(0x3c9,0x3f);
outportb(0x3c9,0x3f);
outportb(0x3c9,0x3f);


outportb(0x3c8,0x01);
outportb(0x3c9,0x3f);
outportb(0x3c9,0x3f);
outportb(0x3c9,0x3f);


outportb(0x3c8,0x02);
outportb(0x3c9,0x3f);
outportb(0x3c9,0x3f);
outportb(0x3c9,0x3f);

Thanks

Re: 320X200 resolution works but 640X480 does not ???

Posted: Tue Feb 24, 2009 3:13 am
by jal
schwin wrote:As you said in your posts 8 pixels can be set at a time. how are we doing that?
In 16 colour mode, the EGA/VGA uses four planes. Each plane contributes one bit to each pixel, hence 2^4 = 16 colours. The planes reside in the same memory space. For each plane, a byte contains a bit for 8 consecutive pixels. When you write a byte, you write 8 pixels at the same time. To which planes you are writing depends on the plane mask. The plane mask register contains 4 bits, 1 for each plane. If the bit is set, the plane is written to, otherwise it's skipped. Since the colour of a pixel is determined by the bits in the planes, if at first the colour is black, you can set any colour by setting the colour (actually attribute, see below) in the plane mask. Note however that when the current colour is not 0, the results are naturally different (masked planes are not affected, so if theres already a 1 in the plane, it stays there, effectively ORing the old and new value).

If I need to plot a pixel at (1,1) location how do I set the colors?
To address individual pixels, there's another mask (I think it's called pixel mask or something), that determines (together with the write mode, see below) which bits are affected. So if you want to plot the very first pixel, you'd have to set 1000.0000b (0x80) to that register before writing your colour value.

Note that the EGA/VGA is far more complex, it has colour don't care registers, read and write modes, and much more. Please Google to find a goof EGA/VGA reference and read it thoroughly. I don't know it all by heart, and this space is far too limited to explain. Also check the Wiki, it has probably all the info you need.

As for attributes vs. colours, the original EGA had 64 different colours, and the 16 different colours on screen could each refer to one of these 64 colours (they were an index into a table, as it were). Then VGA came along, having 18-bit colours (6 bits for R, G and B each). So for VGA, each of the 16 attributes can be one of those 2^18 colours (although it is still compatible with the 64 colours, to keep it simple :)).

it is written on Wiki that DAC Data Register has to be written three times , once for red , once for blue and once for green, do we use the same index address all the time? or do it as shown below:

Code: Select all

outportb(0x3c8,0x00); 
outportb(0x3c9,0x3f); 
outportb(0x3c9,0x3f); 
outportb(0x3c9,0x3f);
The DAC is the thing that determines the final colour (as explained above). And yes, you write first the index, then three times the values for R, G and B. The DAC registers have 256 entries (for each of the 256 VGA attributes), but since the 16 attributes of 4 colour mode are also mapped themselves, there's double mapping.


JAL