[SOLVED] VESA and Bochs

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
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

[SOLVED] VESA and Bochs

Post by AlfaOmega08 »

Hi, I finally got a Virtual 8086 monitor working, and now I'm trying to switch to a graphic mode. I want higher resolution than VGA so I'm working on VESA. After the kernel initialization, I check for the presence of VESA on the system with INT 0x10 AX = 0x4F00. Then I try to detect the best resolution available on the system between modes 0x113, 0x115, 0x116, 0x118, 0x119, 0x11B (800x600, 1024x768, 1280x1024 at 16bpp or 32bpp), using INT 0x10 AX = 0x4F01 and checking for the bits 0, 4 and 5 of the mode attribute to see if it can be used. Found the mode I switch to it using INT 0x10 AX = 0x4F02. This works well on my desktop hardware and on virtualbox but it doesn't on bochs or my eeePC. Bochs gives always attribute = 0 for any of the modes but if I try to force the switch it change the mode but won't let me writing pixels.

May I have misconfigured bochs? Or is a code problem?
Last edited by AlfaOmega08 on Thu Aug 13, 2009 4:04 pm, edited 2 times in total.
Please, correct my English...
Motherboard: ASUS Rampage II Extreme
CPU: Core i7 950 @ 3.06 GHz OC at 3.6 GHz
RAM: 4 GB 1600 MHz DDR3
Video: nVidia GeForce 210 GTS... it sucks...
User avatar
f2
Member
Member
Posts: 311
Joined: Mon Jun 15, 2009 10:01 am
Location: France

Re: VESA and Bochs

Post by f2 »

I never had any problems with Bochs with VESA modes. If Bochs was misconfigured, INT 0x10 says that there is no VESA support.
I think there's an error in your code.
"Open source seems to embrace the dark side of human nature." - Ville Turjanmaa
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Re: VESA and Bochs

Post by AlfaOmega08 »

Uhm... now it doesn't work neither on real hardware... Here is my code :mrgreen:

Code: Select all

struct VESAHeader {
	char signature[4];
	short version;
	short oemString[2];
	unsigned char capabilities[4];
	short videomodes[2];
	short totalMemory;
};

struct VESAModeInfo {
	word attributes;
	byte winA,winB;
	word granularity;
	word winsize;
	word segmentA, segmentB;
	dword realFctPtr;
	word pitch;

	word Xres, Yres;
	byte Wchar, Ychar, planes, bpp, banks;
	byte memory_model, bank_size, image_pages;
	byte reserved0;

	byte red_mask, red_position;
	byte green_mask, green_position;
	byte blue_mask, blue_position;
	byte rsv_mask, rsv_position;
	byte directcolor_attributes;

	dword physbase;
} __attribute__ ((packed));

void setbank(int n) {
	struct regs regs;
	regs.eax = 0x4F05;
	regs.ebx = 0;
	regs.edx = n;
	v86_int(0x10, &regs);
}

int curBank = 0;
void PutPixel(int x, int y, dword color, dword gran, dword max, dword bpp) {
	int addr = y * max + x;
	int banksize = gran * max;
	int bnum = addr / banksize;
	int boff = addr % banksize;
	
	if (bnum != curBank) {
		setbank(bnum);
		curBank = bnum;
	}
	
	if (bpp == 16) {
		word *ptr = (word *) (0xC00A0000 + boff * 2);
		*ptr = color & 0xFFFFFF;
	} else if (bpp == 24) {
		byte *ptr = (byte *) (0xC00A0000 + boff * 3);
		ptr[0] = color & 0xFF;
		ptr[1] = color >> 8 & 0xFF;
		ptr[2] = color >> 16 & 0xFF;
	} else if (bpp == 32) {
		dword *ptr = (dword *) (0xC00A0000 + boff * 4);
		*ptr = color;
	}		    	
}

void vesa_init() {
	struct regs regs;

	// Read the vesa header
	regs.eax = 0x4F00;
	regs.es = 0;
	regs.edi = 0x2000;
	v86_int(0x10, &regs);
	
	if (regs.eax != 0x004F) {
		panic("VESA is not present on this system\n");
	}
	
	struct VESAHeader *vbe = (struct VESAHeader *) 0xC0002000;
	if (strncmp(vbe->signature, "VESA", 4)) {
		panic("Wrong VESA signature\n");
	}

	word Modes[6] = { 0x113, 0x115, 0x116, 0x118, 0x119, 0x11B };

	int i, best = -1;
	for (i = 0; i < 6; i++) {
		// Get Mode informations
		regs.eax = 0x4F01;
		regs.ebx = Modes[i];
		regs.es = 0;
		regs.edi = 0x3000;
		v86_int(0x10, &regs);
		
		struct VESAModeInfo *tmp = (struct VESAModeInfo *) 0xC0003000;
		if (tmp->attributes & 0x19 == 0x19) {
			kprintf("Mode %04X, %dx%dx%d detected\n", Modes[i], tmp->Xres, tmp->Yres, tmp->bpp);
			best = Modes[i];
		} else {
			kprintf("Bad mode %04X attr %d\n", Modes[i], tmp->attributes);
		}
	}
	
	if (best == -1) {
		panic("Unable to find an available VESA mode");
	}
	
	kprintf("Best mode found: %04X", Modes[best]);
	
	struct VESAModeInfo *tmp = (struct VESAModeInfo *) 0xC0003000;
	
	// Set video mode
	regs.eax = 0x4F02;
	regs.ebx = Modes[best];
	v86_int(0x10, &regs);

	int gran = tmp->granularity;
	int maxX = tmp->Xres;
	int maxY = tmp->Yres;
	int bpp = tmp->bpp;

	for (i = 0; i < maxX; i++) {
		int j;
		for (j = 0; j < maxY; j++) {
			PutPixel(i, j, 0xFFFFFFFF, gran, maxX, bpp);
		}
	}
}
please help me [-o<
Last edited by AlfaOmega08 on Tue Aug 11, 2009 3:44 am, edited 1 time in total.
Please, correct my English...
Motherboard: ASUS Rampage II Extreme
CPU: Core i7 950 @ 3.06 GHz OC at 3.6 GHz
RAM: 4 GB 1600 MHz DDR3
Video: nVidia GeForce 210 GTS... it sucks...
giszo
Member
Member
Posts: 124
Joined: Tue Nov 06, 2007 2:37 pm
Location: Hungary

Re: VESA and Bochs

Post by giszo »

AlfaOmega08 wrote:please help me [-o<
What about using packed attribute on the VESA structs? :roll:
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Re: VESA and Bochs

Post by AlfaOmega08 »

well, the packed attribute, may be one of the causes, but it hasn't solved the problem.
thanks for the trying
Please, correct my English...
Motherboard: ASUS Rampage II Extreme
CPU: Core i7 950 @ 3.06 GHz OC at 3.6 GHz
RAM: 4 GB 1600 MHz DDR3
Video: nVidia GeForce 210 GTS... it sucks...
User avatar
f2
Member
Member
Posts: 311
Joined: Mon Jun 15, 2009 10:01 am
Location: France

Re: VESA and Bochs

Post by f2 »

Code: Select all

best = Modes[i];

...

regs.ebx = Modes[best];
Perhaps the problem is here...
Should be:

Code: Select all

regs.ebx = best;
Another thing:
AlfaOmega08 wrote:and checking for the bits 0, 4 and 5
0x19 -> 11001 -> bit 0, 3 and 4 are set here.
Note: if you use banks, you shouldn't check if bit 5 is set.
"Open source seems to embrace the dark side of human nature." - Ville Turjanmaa
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Re: VESA and Bochs

Post by AlfaOmega08 »

thank you tommy the first error was the cause for witch the code didn't work anymore on real hardware. However I still have problems anywhere else...

I prefer to use lfb instead of banks so as suggested on the wiki I check for bits 0x90 of the attribute instead of 0x19. I noticed that Bochs returns as resolutions for any of the modes 0x0 at 0 bpp with attribute 0. Isn't that nice?

However now the code is:

Code: Select all

struct VESAHeader {
	char signature[4];
	short version;
	short oemString[2];
	unsigned char capabilities[4];
	short videomodes[2];
	short totalMemory;
} __attribute__ ((packed));

struct VESAModeInfo {
	word attributes;
	byte winA,winB;
	word granularity;
	word winsize;
	word segmentA, segmentB;
	dword realFctPtr;
	word pitch;

	word Xres, Yres;
	byte Wchar, Ychar, planes, bpp, banks;
	byte memory_model, bank_size, image_pages;
	byte reserved0;

	byte red_mask, red_position;
	byte green_mask, green_position;
	byte blue_mask, blue_position;
	byte rsv_mask, rsv_position;
	byte directcolor_attributes;

	dword physbase;
} __attribute__ ((packed));

void PutPixel(int x, int y, dword color, dword max, dword bpp, dword buff) {
	int addr = y * max + x;

	if (bpp == 16) {
		word *ptr = (word *) (0xC00A0000 + addr * 2);
		*ptr = color & 0xFFFFFF;
	} else if (bpp == 24) {
		byte *ptr = (byte *) (0xC00A0000 + addr * 3);
		ptr[0] = color & 0xFF;
		ptr[1] = color >> 8 & 0xFF;
		ptr[2] = color >> 16 & 0xFF;
	} else if (bpp == 32) {
		dword *ptr = (dword *) (0xC00A0000 + addr * 4);
		*ptr = color;
	}		    	
}

void vesa_init() {
	struct regs regs;

	// Read the vesa header
	regs.eax = 0x4F00;
	regs.es = 0;
	regs.edi = 0x2000;
	v86_int(0x10, &regs);
	
	if (regs.eax != 0x004F) {
		panic("VESA is not present on this system\n");
	}
	
	struct VESAHeader *vbe = (struct VESAHeader *) 0xC0002000;
	if (strncmp(vbe->signature, "VESA", 4)) {
		panic("Wrong VESA signature\n");
	}

	word Modes[6] = { 0x113, 0x115, 0x116, 0x118, 0x119, 0x11B };

	int i, best = -1;
	for (i = 0; i < 6; i++) {
		// Get Mode informations
		regs.eax = 0x4F01;
		regs.ebx = Modes[i];
		regs.es = 0;
		regs.edi = 0x3000;
		v86_int(0x10, &regs);
		
		struct VESAModeInfo *tmp = (struct VESAModeInfo *) 0xC0003000;
		if (tmp->attributes & 0x90 == 0x90) {
			kprintf("Mode %04X, %dx%dx%d detected\n", Modes[i], tmp->Xres, tmp->Yres, tmp->bpp);
			best = Modes[i];
		} else {
			kprintf("Bad mode %04X attr %d, %dx%d\n", Modes[i], tmp->attributes, tmp->Xres, tmp->Yres);
		}
	}
	
	if (best == -1) {
		panic("Unable to find an available VESA mode");
	}
	
	kprintf("Best mode found: %04X", best);
	
	struct VESAModeInfo *tmp = (struct VESAModeInfo *) 0xC0003000;
	
	// Set video mode
	regs.eax = 0x4F02;
	regs.ebx = best;
	v86_int(0x10, &regs);

	int buff = tmp->physbase;
	int maxX = tmp->Xres;
	int maxY = tmp->Yres;
	int bpp = tmp->bpp;

	for (i = 0; i < maxX; i++) {
		int j;
		for (j = 0; j < maxY; j++) {
			PutPixel(i, j, 0xFFFFFFFF, maxX, bpp, buff);
		}
	}
}
Please, correct my English...
Motherboard: ASUS Rampage II Extreme
CPU: Core i7 950 @ 3.06 GHz OC at 3.6 GHz
RAM: 4 GB 1600 MHz DDR3
Video: nVidia GeForce 210 GTS... it sucks...
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Re: VESA and Bochs

Post by AlfaOmega08 »

OK, while JamesM is on the road of 2D Graphic acceleration :shock: , I am still unable to use VESA. Something strange is happenin in my code. I changed all the extensions from .c to .cpp and did the needed changes to the code to be compiled as c++ (casting void * for maths and for mallocs, changing char * to const char * etc...) and the code shown before just does its work. On bochs as well as on real hardware. The strange thing is that if I put a "while (1);" just before the mode switch interrupt, the code doesn't find any good VESA mode on bochs anymore. If I remove that while (1) the mode is found and switched :shock: :shock: :shock: . May this be a G++/GCC bug?
Please, correct my English...
Motherboard: ASUS Rampage II Extreme
CPU: Core i7 950 @ 3.06 GHz OC at 3.6 GHz
RAM: 4 GB 1600 MHz DDR3
Video: nVidia GeForce 210 GTS... it sucks...
tantrikwizard
Member
Member
Posts: 153
Joined: Sun Jan 07, 2007 9:40 am
Contact:

Re: VESA and Bochs

Post by tantrikwizard »

AlfaOmega08 wrote:May this be a G++/GCC bug?
highly unlikely. VESA works fine on my bochs build. Make sure you have vga: extension=vbe in the bochsrc It might not be related to your problem but I think it's required to use VBE. Bochs does not fully implement all the VBE extensions but it does implement the stuff you're trying to use.
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Re: VESA and Bochs

Post by AlfaOmega08 »

Bochs has VBE extension enabled. I have vga: extension=vbe in bochsrc.txt. As I said the code works until I insert a while(1) after the mode search. If I insert a "while(1)" line the code stops working
Please, correct my English...
Motherboard: ASUS Rampage II Extreme
CPU: Core i7 950 @ 3.06 GHz OC at 3.6 GHz
RAM: 4 GB 1600 MHz DDR3
Video: nVidia GeForce 210 GTS... it sucks...
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Re: VESA and Bochs

Post by AlfaOmega08 »

Got it!!!

// Get Mode informations
regs.eax = 0x4F01;
regs.ebx = Modes;
regs.es = 0;
regs.edi = 0x3000;
v86_int(0x10, &regs);

Reading the RBIL I discovered that the mode have to be set in ecx, not in ebx... Now I have to understand why did I use ebx :mrgreen:
Please, correct my English...
Motherboard: ASUS Rampage II Extreme
CPU: Core i7 950 @ 3.06 GHz OC at 3.6 GHz
RAM: 4 GB 1600 MHz DDR3
Video: nVidia GeForce 210 GTS... it sucks...
tantrikwizard
Member
Member
Posts: 153
Joined: Sun Jan 07, 2007 9:40 am
Contact:

Re: VESA and Bochs

Post by tantrikwizard »

AlfaOmega08 wrote:Got it!!!
Why not read the docs? The spec fully outlines the register formats and interrupts.
Post Reply