Page 1 of 1

VGA 320x200x256 - only getting a few colors

Posted: Sun Nov 30, 2008 5:49 am
by Jonanin
Hi

I've got a bare bones kernel that I have added VGA support to. It works great, except that all colors beyond ~30-40 dont work. I'm not sure what's wrong, so I was hoping someone could help me. Here is the relevant code:

Code: Select all

static __inline__ void outb(unsigned short port, unsigned char val)
{
   asm volatile("outb %0,%1"::"a"(val), "dN" (port));
}

static __inline__ unsigned char inb(unsigned short port)
{
   unsigned char ret;
   asm volatile ("inb %1,%0":"=a"(ret):"dN"(port));
   return ret;
}


void mode13h() {

	/*** CRT CONTROLLER REGISTERS ***/
	unsigned char  CRTCRegs[] = {
		0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F,
		0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
		0xFF
	};
	unsigned int CRTCRegsSize =  25;
	
	/*** ATTRIBUTE CONTROLLER REGISTERS ***/
	unsigned char ACRegs[] = {
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
		0x41, 0x00, 0x0F, 0x00, 0x00
	};
	unsigned int ACRegsSize = 21;
	
	/*** GRAPHICS CONTROLLER REGISTERS ***/
	unsigned char GCRegs[] = {
		0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
		0xFF
	};
	unsigned int GCRegsSize = 9;
	
	/*** SEQUENCER REGISTERS ***/
	unsigned char SEQRegs[] = {
		0x03, 0x01, 0x0F, 0x00, 0x0E
	};
	unsigned int SEQRegsSize = 5;
	
	/*** ******************* ***/
	/*** ******************* ***/
	
	unsigned int i, q;
	
	outb(0x3C2, 0x63);                  // Misc register
	
	for(i = 0; i < SEQRegsSize; i++) {
		outb(0x3C4, i);
		outb(0x3C5, SEQRegs[i]);
	}
	
	// Enable CRTC regs
	outb(0x3D4, 0x03);
	outb(0x3D5, inb(0x3D5) | 0x80);
	outb(0x3D4, 0x11);
	outb(0x3D5, inb(0x3D5) & ~0x80);

	// make sure they stay enabled
	CRTCRegs[0x03] |= 0x80;
	CRTCRegs[0x11] &= ~0x80;

	for(i = 0; i < CRTCRegsSize; i++) {
		outb(0x3D4, i);
		outb(0x3D5, CRTCRegs[i]);
	}
	for(i = 0; i < GCRegsSize; i++) {
		outb(0x3CE, i);
		outb(0x3CF, GCRegs[i]);
	}
	for(i = 0; i < ACRegsSize; i++) {
		q = inb(0x3DA); q = q;
		outb(0x3C0, i);
		outb(0x3C0, ACRegs[i]);
	}

	q = inb(0x3DA); q = q;
	outb(VGA_AC_INDEX, 0x20);

}

static inline void setp(int x, int y, unsigned char color) {
	static unsigned char * vga_mem = (unsigned char *) 0xA0000;
	if (x > 320 || x < 0 || y > 200 || y < 0) return;
	vga_mem[320 * y + x] = color;
}

void vga_clear()
{
	int x;
	int y;
	for(y=0;y<200;y++) {
		for(x=0;x<320;x++) {
			setp(x, y, 0);
		}
	}
}


void _kmain() {

	mode13h();
	
	vga_clear();
	
	int x = 0;
	int y = 0;

	unsigned char color = 0;
	
        // draw a simple line and go through each color.
	while (1) {
		color++;
		if (color > 254) color = 0;
		
		x += 1;
		y += 1;
		setp(x, y, color);
	}
	

}

As you can see in my main function, I draw a line which goes through each color starting at 0. However, after about 30 pixels drawn the line stops, its just black (the background)... I've tried and tried, I can't seem to get any colors beyond ~30

Here is a screenshot of what I get: http://i35.tinypic.com/258t9gy.png

I tried to make sure I was setting the right registers by referring to the VGA Hardware article on the wiki, and I'm pretty sure I am. Still, there is obviously an error somewhere.

Can anyone figure out what's wrong? (It's probably something really stupid I did <_<)

Re: VGA 320x200x256 - only getting a few colors

Posted: Sun Nov 30, 2008 6:11 am
by souradipm
Have you set the colours you want? I use this code for setting a colour to a value:

Code: Select all

//Set a colour to a certain colour combination. Takes effect immediately, so any pixels with that colour that have been drawn will change colour.
void vga_set_colour(int colour, int red, int green, int blue)
{
    outportb(0x3C8, colour);
    outportb(0x3C9, red);
    outportb(0x3C9, green);
    outportb(0x3C9, blue);
}
Take note of the comment - all colours will immediately change after changing the value of the colour. If you don't do this you will get random colours when you draw. Remember to loop it so that you can set all of the colours in one go!

Hope it helped,
souradipm

Re: VGA 320x200x256 - only getting a few colors

Posted: Sun Nov 30, 2008 1:37 pm
by Jonanin
Ahhh, thank you... that was it. I knew it would be something really stupid like that!

Thanks!

Re: VGA 320x200x256 - only getting a few colors

Posted: Mon Dec 01, 2008 7:14 am
by jal
Jonanin wrote:Ahhh, thank you... that was it. I knew it would be something really stupid like that!
For background information, Google on VGA palette registers. What happens is that each byte is looked up in the palette, which consists of 6-bit RGB values. It depends on your videocard BIOS what colours are set. At least the first 16 will be set to their normal values, for the others there's no way to be sure.


JAL