VGA 320x200x256 - only getting a few colors

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.
Post Reply
Jonanin
Posts: 2
Joined: Sat Nov 29, 2008 11:54 pm

VGA 320x200x256 - only getting a few colors

Post 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 <_<)
souradipm
Posts: 22
Joined: Fri Aug 15, 2008 10:08 am

Re: VGA 320x200x256 - only getting a few colors

Post 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
Jonanin
Posts: 2
Joined: Sat Nov 29, 2008 11:54 pm

Re: VGA 320x200x256 - only getting a few colors

Post by Jonanin »

Ahhh, thank you... that was it. I knew it would be something really stupid like that!

Thanks!
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: VGA 320x200x256 - only getting a few colors

Post 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
Post Reply