Vesa Problems

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
z4ck
Member
Member
Posts: 28
Joined: Thu Oct 21, 2004 11:00 pm
Location: swiss
Contact:

Vesa Problems

Post by z4ck »

Hy

i have a lot of trouble whit my vesa 2.0 driver.

the problem is, that in a real pc the colour are different as those from bochs.

if i try to draw a pixel whit the colour 0x0011A8C6 bochs put the 0x00C6A8 colour out. ... :(

here is the code:

Code: Select all

/*
;
;---------------------------------------------------------------+
;       .__               __                          			?
;______ |__|___________ _/  |_            ____  ______			?
;\____ \|  \_  __ \__  \\   __\  ______  /  _ \/  ___/			?
;|  |_> >  ||  | \// __ \|  |   /_____/ (  <_> )___ \ 			?
;|   __/|__||__|  (____  /__|            \____/____  >			?
;|__|                  \/                          \/ 			?
;---------------------------------------------------------------+
;
;[1] Informations
;
; Last Modified: 	25. Januar 2005
; Begin: 			15. Juni 2004
; Version: 			0.000
; Coder: 			z4ck
;
;
;[2] Tasks
;
;	Task									Done		Coder
;----------------------------------------------------------------
; -                  						[  0%]		z4ck
;----------------------------------------------------------------
; TOTAL										[  0%]		z4ck
;================================================================
*/

#include <video.h>

#define VesaMode 0x118



/********************************************/
/* VbeModeInfoBlock Struktur                */
/********************************************/
typedef struct {
	unsigned short 	VbeModeModeAttributes;
	unsigned char 		VbeModeWinAAttributes;
	unsigned char 		VbeModeWinBAttributes;
	unsigned short 	VbeModeWinGranularity;
	unsigned short 	VbeModeWinSize;
	unsigned short 	VbeModeWinASegment;
	unsigned short 	VbeModeWinBSegment;
	unsigned long 		VbeModeWinFuncPtr;
	unsigned short 	VbeModeBytesPerScanLine;
	unsigned short 	VbeModeXResolution;
	unsigned short 	VbeModeYResolution;
	unsigned char 		VbeModeXCharSize;
	unsigned char 		VbeModeYCharSize;
	unsigned char 		VbeModeNumberOfPlanes;
	unsigned char 		VbeModeBitsPerPixel;
	unsigned char 		VbeModeNumberOfBanks;
	unsigned char 		VbeModeMemoryModel;
	unsigned char 		VbeModeBankSize;
	unsigned char 		VbeModeNumberOfImagePages;
	unsigned char 		VbeModeReserved_page;
	unsigned char 		VbeModeRedMaskSize;
	unsigned char 		VbeModeRedMaskPos;
	unsigned char 		VbeModeGreenMaskSize;
	unsigned char 		VbeModeGreenMaskPos;
	unsigned char 		VbeModeBlueMaskSize;
	unsigned char 		VbeModeBlueMaskPos;
	unsigned char 		VbeModeReservedMaskSize;
	unsigned char 		VbeModeReservedMaskPos;
	unsigned char 		VbeModeDirectColorModeInfo;
	unsigned long 		VbeModePhysBasePtr;
	unsigned long 		VbeModeOffScreenMemOffset;
	unsigned short 	VbeModeOffScreenMemSize;
	unsigned short 	VbeModeLinBytesPerScanLine;
	unsigned char 		VbeModeBnkNumberOfPages;
	unsigned char 		VbeModeLinNumberOfPages;
	unsigned char 		VbeModeLinRedMaskSize;
	unsigned char 		VbeModeLinRedFieldPos;
	unsigned char 		VbeModeLinGreenMaskSize;
	unsigned char 		VbeModeLinGreenFieldPos;
	unsigned char 		VbeModeLinBlueMaskSize;
	unsigned char 		VbeModeLinBlueFieldPos;
	unsigned char 		VbeModeLinRsvdMaskSize;
	unsigned char 		VbeModeLinRsvdFieldPos;
	unsigned char 		VbeModeMaxPixelClock;
	unsigned char 		VbeModeReserved[190];

} __attribute__ ((packed)) VbeModeInfoBlock;



/********************************************/
/* Global Vars                              */
/********************************************/
VbeModeInfoBlock *VbeMIB = (VbeModeInfoBlock *) 0x7e00;			// This one ist set in kernel16.asm @ setvesa...
unsigned char *VideoMem;										// saved in the VbeModeInfoBlock

/********************************************/
/* Screen Settings                          */
/********************************************/
unsigned long ScrWidth, ScrHeight;
unsigned char BitsPerPixel;


/********************************************/
/* COLORS                                   */
/********************************************/
unsigned long BGColor 			= 0x0011A8C6;
unsigned long FontColor 		= 0x00FFFFFF;
unsigned long FontShadowColor	= 0x00EEEEEE;


/********************************************/
/* Init the video                           */
/********************************************/
void SetupVideo()
{
	ScrWidth	  =  VbeMIB->VbeModeXResolution; 				
	ScrHeight	  =  VbeMIB->VbeModeYResolution;
	BitsPerPixel  =  VbeMIB->VbeModeBitsPerPixel;
	
	VideoMem 	  = (unsigned char *)(VbeMIB->VbeModePhysBasePtr);
	
	ClearScreen();												//Result: Color 0x00c6a8
	
	DrawPixel(0, 0, 0x202020);									//Result: Color 0x002020
	VideoMem[(1*BitsPerPixel/8)]=0x11;							//Result: COlor 0xc6a811
	VideoMem[(1*BitsPerPixel/8)+1]=0xA8;
	VideoMem[(1*BitsPerPixel/8)+2]=0xc6;
};


/********************************************/
/* Clear Screen whit BGColor                */
/********************************************/
void ClearScreen ()
{
	unsigned long i = 0;
	for (;i < ScrHeight; i++)
	{
		unsigned long u = 0;
		for (; u < ScrWidth; u++)
			DrawPixel(u, i, BGColor);
	};	
	
};


void printf (char *_string, long _color)
{

};

void printc (char _character, long _color)
{
	
};

void Num2String(int _number)
{
	
};


/********************************************/
/* Draw a Pixel                             */
/********************************************/
void DrawPixel (unsigned long _x, unsigned long _y, unsigned long _RGB)
{
	unsigned char A   =  _RGB 				 >> 0x18;			//Alpha 
	unsigned char R   = (_RGB & 0x00FF0000) >> 0x10;			//Red
	unsigned char G   = (_RGB & 0x0000FF00) >> 0x08;			//Green
	unsigned char B   = (_RGB & 0x000000FF);					//Blue
	unsigned long pos = ((_y*ScrWidth)+_x)*(BitsPerPixel/8);
	
	if (pos > (ScrWidth*ScrHeight*BitsPerPixel/8)) return;
	
	switch(BitsPerPixel)
		{
			case 8:
			case 16:
				break;
				
			case 24:
				VideoMem[pos]   = R;
				VideoMem[pos++] = G;
				VideoMem[pos++] = B;
				break;
				
			case 32:
				VideoMem[pos]	= A;
				VideoMem[pos++] = R;
				VideoMem[pos++] = G;
				VideoMem[pos++] = B;
				break;
		};
};


/*
void DrawBMP (File *_file, int _x, int _y)
{

};

*/

thx 4 helping
char *autor="I don't know english!! :(";
Anton
Member
Member
Posts: 30
Joined: Thu Oct 21, 2004 11:00 pm
Location: Moscow, Russian Federation

Re: Vesa Problems

Post by Anton »

First of all, you are not calculating the pos correctlly:
unsigned long pos = ((_y*ScrWidth)+_x)*(BitsPerPixel/8);
but it should be
unsigned long pos = _y*VbeModeBytesPerScanLine+_x*BitsPerPixel/8;

Anton
z4ck
Member
Member
Posts: 28
Joined: Thu Oct 21, 2004 11:00 pm
Location: swiss
Contact:

Re: Vesa Problems

Post by z4ck »

thx anton

but
unsigned long pos = _y*VbeModeBytesPerScanLine+_x*BitsPerPixel/8;
means
unsigned long pos = (_y*VbeModeBytesPerScanLine)+(_x*BitsPerPixel/8);

is that correct??

my second problem was that i wrote:
....videomem[pos++] = ...

that means
...videomem[pos] = ... ; pos++;....
it should be
....videomem[++pos]=...
that means
....pos++;..videomem[pos]...
char *autor="I don't know english!! :(";
z4ck
Member
Member
Posts: 28
Joined: Thu Oct 21, 2004 11:00 pm
Location: swiss
Contact:

Re: Vesa Problems

Post by z4ck »

thats my courrent code.
it works fine on bochs. but on my real pc the screen move in a way together that a black part is in the center of the screen..

Code: Select all

/*
;
;---------------------------------------------------------------+
;       .__               __                          			?
;______ |__|___________ _/  |_            ____  ______			?
;\____ \|  \_  __ \__  \\   __\  ______  /  _ \/  ___/			?
;|  |_> >  ||  | \// __ \|  |   /_____/ (  <_> )___ \ 			?
;|   __/|__||__|  (____  /__|            \____/____  >			?
;|__|                  \/                          \/ 			?
;---------------------------------------------------------------+
;
;[1] Informations
;
; Last Modified: 	25. Januar 2005
; Begin: 			15. Juni 2004
; Version: 			0.000
; Coder: 			z4ck
;
;
;[2] Tasks
;
;	Task									Done		Coder
;----------------------------------------------------------------
; -                  						[  0%]		z4ck
;----------------------------------------------------------------
; TOTAL										[  0%]		z4ck
;================================================================
*/

#include <video.h>
#include <font.h>

#define VesaMode 0x118

/********************************************/
/* VbeModeInfoBlock Struktur                */
/********************************************/
typedef struct {
	unsigned short 	VbeModeModeAttributes;
	unsigned char 		VbeModeWinAAttributes;
	unsigned char 		VbeModeWinBAttributes;
	unsigned short 	VbeModeWinGranularity;
	unsigned short 	VbeModeWinSize;
	unsigned short 	VbeModeWinASegment;
	unsigned short 	VbeModeWinBSegment;
	unsigned long 		VbeModeWinFuncPtr;
	unsigned short 	VbeModeBytesPerScanLine;
	unsigned short 	VbeModeXResolution;
	unsigned short 	VbeModeYResolution;
	unsigned char 		VbeModeXCharSize;
	unsigned char 		VbeModeYCharSize;
	unsigned char 		VbeModeNumberOfPlanes;
	unsigned char 		VbeModeBitsPerPixel;
	unsigned char 		VbeModeNumberOfBanks;
	unsigned char 		VbeModeMemoryModel;
	unsigned char 		VbeModeBankSize;
	unsigned char 		VbeModeNumberOfImagePages;
	unsigned char 		VbeModeReserved_page;
	unsigned char 		VbeModeRedMaskSize;
	unsigned char 		VbeModeRedMaskPos;
	unsigned char 		VbeModeGreenMaskSize;
	unsigned char 		VbeModeGreenMaskPos;
	unsigned char 		VbeModeBlueMaskSize;
	unsigned char 		VbeModeBlueMaskPos;
	unsigned char 		VbeModeReservedMaskSize;
	unsigned char 		VbeModeReservedMaskPos;
	unsigned char 		VbeModeDirectColorModeInfo;
	unsigned long 		VbeModePhysBasePtr;
	unsigned long 		VbeModeOffScreenMemOffset;
	unsigned short 	VbeModeOffScreenMemSize;
	unsigned short 	VbeModeLinBytesPerScanLine;
	unsigned char 		VbeModeBnkNumberOfPages;
	unsigned char 		VbeModeLinNumberOfPages;
	unsigned char 		VbeModeLinRedMaskSize;
	unsigned char 		VbeModeLinRedFieldPos;
	unsigned char 		VbeModeLinGreenMaskSize;
	unsigned char 		VbeModeLinGreenFieldPos;
	unsigned char 		VbeModeLinBlueMaskSize;
	unsigned char 		VbeModeLinBlueFieldPos;
	unsigned char 		VbeModeLinRsvdMaskSize;
	unsigned char 		VbeModeLinRsvdFieldPos;
	unsigned char 		VbeModeMaxPixelClock;
	unsigned char 		VbeModeReserved[190];

} __attribute__ ((packed)) VbeModeInfoBlock;

/********************************************/
/* Global Vars                              */
/********************************************/
VbeModeInfoBlock *VbeMIB = (VbeModeInfoBlock *) 0x7e00;			// This one ist set in kernel16.asm @ setvesa...
unsigned char *VideoMem;										// saved in the VbeModeInfoBlock
unsigned char ChX = 5, ChY=9;


/********************************************/
/* Screen Settings                          */
/********************************************/
unsigned long ScrWidth, ScrHeight;
unsigned char BitsPerPixel;


/********************************************/
/* COLORS                                   */
/********************************************/
unsigned long BGColor 			= 0x0011A8C6;
unsigned long FontColor 		= 0x00FFFFFF;
unsigned long FontShadowColor	= 0x00EEEEEE;
unsigned long WindowColor		= 0x00A2C8D0;
unsigned long WindowBorder		= 0x00136E80;


/********************************************/
/* Init the video                           */
/********************************************/
void SetupVideo()
{
	ScrWidth	  =  VbeMIB->VbeModeXResolution; 				
	ScrHeight	  =  VbeMIB->VbeModeYResolution;
	BitsPerPixel  =  VbeMIB->VbeModeBitsPerPixel;
	
	VideoMem 	  = (unsigned char *)(VbeMIB->VbeModePhysBasePtr);
	
	ClearScreen();
	
};


/********************************************/
/* Clear Screen whit BGColor                */
/********************************************/
void ClearScreen ()
{
	unsigned long i = 0, u = 0;
	for (;i < ScrHeight; i++)
	{
		for (u = 0; u < ScrWidth; u++)
			DrawPixel(u, i, BGColor);
	};	
	
};


void printf (char *_string, unsigned long _x, unsigned long _y, unsigned long _color)
{
	unsigned tmpX = 0, tmpY = 0;
	int i;
	for (i=0; _string[i] != '\0'; i++)
	{
		switch (_string[i])
		{
			case '\t':
				break;
				
			case '\n':
				tmpY+=10;
				tmpX=0;
				break;
				
			case '\b':
				break;
				
			default:
				tmpX += printc(_string[i], _x+tmpX, _y+tmpY, _color);
				break;
		};	
	};	
};

unsigned char printc (char _character,unsigned long _x, unsigned long _y, unsigned long _color)
{
	unsigned char *tmp;
	unsigned char u, i, width; 
	
		switch (_character)
		{
			case '0': tmp = PxCh_0; width =  6; break;
			case '1': tmp = PxCh_1; width =  4; break;
			case '2': tmp = PxCh_2; width =  6; break;
			case '3': tmp = PxCh_3; width =  6; break;
			case '4': tmp = PxCh_4; width =  7; break;
			case '5': tmp = PxCh_5; width =  6; break;
			case '6': tmp = PxCh_6; width =  6; break;
			case '7': tmp = PxCh_7; width =  6; break;
			case '8': tmp = PxCh_8; width =  6; break;
			case '9': tmp = PxCh_9; width =  6; break;
			
			case 'A': tmp = PxCh_A; width =  9; break;
			case 'B': tmp = PxCh_B; width =  6; break;
			case 'C': tmp = PxCh_C; width =  7; break;
			case 'D': tmp = PxCh_D; width =  7; break;
			case 'E': tmp = PxCh_E; width =  7; break;				
			case 'F': tmp = PxCh_F; width =  6; break;
			case 'G': tmp = PxCh_G; width =  7; break;
			case 'H': tmp = PxCh_H; width =  7; break;				
			case 'I': tmp = PxCh_I; width =  3; break;
			case 'J': tmp = PxCh_J; width =  6; break;				
			case 'K': tmp = PxCh_K; width =  7; break;		
			case 'L': tmp = PxCh_L; width =  6; break;
			case 'M': tmp = PxCh_M; width =  9; break;
			case 'N': tmp = PxCh_N; width =  7; break;
			case 'O': tmp = PxCh_O; width =  7; break;
			case 'P': tmp = PxCh_P; width =  6; break;
			case 'Q': tmp = PxCh_Q; width =  7; break;
			case 'R': tmp = PxCh_R; width =  7; break;
			case 'S': tmp = PxCh_S; width =  6; break;
			case 'T': tmp = PxCh_T; width =  7; break;
			case 'U': tmp = PxCh_U; width =  7; break;
			case 'V': tmp = PxCh_V; width =  9; break;
			case 'W': tmp = PxCh_W; width = 11; break;
			case 'X': tmp = PxCh_X; width =  7; break;
			case 'Y': tmp = PxCh_Y; width =  7; break;
			case 'Z': tmp = PxCh_Z; width =  8; break;	
			
			case 'a': tmp = PxCh_a; width =  6; break;
			case 'b': tmp = PxCh_b; width =  6; break;
			case 'c': tmp = PxCh_c; width =  6; break;
			case 'd': tmp = PxCh_d; width =  6; break;
			case 'e': tmp = PxCh_e; width =  6; break;
			case 'f': tmp = PxCh_f; width =  5; break;
			case 'g': tmp = PxCh_g; width =  6; break;
			case 'h': tmp = PxCh_h; width =  6; break;
			case 'i': tmp = PxCh_i; width =  3; break;
			case 'j': tmp = PxCh_j; width =  4; break;
			case 'k': tmp = PxCh_k; width =  6; break;
			case 'l': tmp = PxCh_l; width =  3; break;
			case 'm': tmp = PxCh_m; width =  9; break;
			case 'n': tmp = PxCh_n; width =  6; break;
			case 'o': tmp = PxCh_o; width =  6; break;
			case 'p': tmp = PxCh_p; width =  6; break;
			case 'q': tmp = PxCh_q; width =  6; break;
			case 'r': tmp = PxCh_r; width =  5; break;
			case 's': tmp = PxCh_s; width =  6; break;
			case 't': tmp = PxCh_t; width =  5; break;
			case 'u': tmp = PxCh_u; width =  6; break;
			case 'v': tmp = PxCh_v; width =  7; break;
			case 'w': tmp = PxCh_w; width =  7; break;
			case 'x': tmp = PxCh_x; width =  6; break;
			case 'y': tmp = PxCh_y; width =  7; break;
			case 'z': tmp = PxCh_z; width =  5; break;
			
			case '.': tmp = PxCh_Dot;    width =  3; break;
			case ',': tmp = PxCh_Komma;  width =  3; break;
			case '-': tmp = PxCh_Score;  width =  4; break;
			case ';': tmp = PxCh_SKolon; width =  3; break;
			case ':': tmp = PxCh_DDot;   width =  3; break;
			case '_': tmp = PxCh_UScore; width =  7; break;
			
			default:
				return 4;
		};
		
	for (u=0; u < ChY; u++)
	{
		for (i=0; i < width; i++)
		{
			if (tmp[(width*u)+i] == 1) DrawPixel(_x+i, _y+u, _color);
		};
	};
	return width;
};

void Num2String(int _number)
{
	
};


/********************************************/
/* Draw a Pixel                             */
/********************************************/
void DrawPixel (unsigned long _x, unsigned long _y, unsigned long _RGB)
{
	unsigned char A   =  _RGB 				 >> 0x18;			//Alpha 
	unsigned char R   = (_RGB & 0x00FF0000) >> 0x10;			//Red
	unsigned char G   = (_RGB & 0x0000FF00) >> 0x08;			//Green
	unsigned char B   = (_RGB & 0x000000FF);					//Blue
	unsigned long pos = _y*VbeMIB->VbeModeBytesPerScanLine+_x*BitsPerPixel/8; //((_y*ScrWidth)+_x)*(BitsPerPixel/8);
	
	if (pos > (ScrWidth*ScrHeight*BitsPerPixel/8)) return;
	
	switch(BitsPerPixel)
		{
			case 8:
			case 16:
				break;
				
			case 24:
				VideoMem[pos]   = B;
				VideoMem[++pos] = G;
				VideoMem[++pos] = R;
				break;
				
			case 32:
				VideoMem[pos]	= A;
				VideoMem[++pos] = B;
				VideoMem[++pos] = G;
				VideoMem[++pos] = R;
				break;
		};
};


/********************************************/
/* Draw a Line                              */
/********************************************/
void DrawLine (unsigned long _x1, unsigned long _y1, unsigned long _x2, unsigned long _y2, unsigned long _RGB)
{
	unsigned long tmpWidth		=	(_x2 > _x1)?(_x2 - _x1):(_x1 - _x2);
	unsigned long tmpHeight	=	(_y2 > _y1)?(_y2 - _y1):(_y1 - _y2);
	unsigned long i	=	0;
	
	if (tmpHeight == 0)
	{
		for (;i<=tmpWidth; i++)
		{
			DrawPixel(_x1+i, _y1, _RGB);
		}
		return;
	}
	
	if (tmpWidth == 0)
	{
		for (;i<=tmpHeight; i++)
		{
			DrawPixel(_x1, _y1+i, _RGB);
		}
		return;
	}
};


/********************************************/
/* Draw a Rectangle                         */
/********************************************/
void DrawRectangle (unsigned long _x1, unsigned long _y1, unsigned long _x2, unsigned long _y2, unsigned long _LineRGB, unsigned long _FillRGB)
{
	
	DrawLine(_x1, _y1, _x2, _y1, _LineRGB);	//left to right; up
	DrawLine(_x1, _y2, _x2, _y2, _LineRGB);	//left to right; down
	DrawLine(_x1, _y1, _x1, _y2, _LineRGB);	//up to down; left
	DrawLine(_x2, _y1, _x2, _y2, _LineRGB);	//up to down; right
	
	unsigned tmpHeight = _y2-_y1;
	unsigned tmpWidth  = _x2-_x1;
	unsigned i = 1, u = 1;
	
	for (;i < tmpHeight; i++)
	{
		for (u = 1; u < tmpWidth; u++)
		{
			DrawPixel (_x1+u, _y1+i, _FillRGB);
		}	
	}
	
	
};


/********************************************/
/* Draw a Window                            */
/********************************************/
void DrawWindow (GUIWindow *_Wnd) 
{
	switch (_Wnd->WindowStyle)
	{
		case 0:
			DrawRectangle(_Wnd->WindowXPosition, _Wnd->WindowYPosition, _Wnd->WindowXPosition+_Wnd->WindowWidth, _Wnd->WindowYPosition+_Wnd->WindowHeight, WindowColor, WindowBorder);
			DrawRectangle(_Wnd->WindowXPosition + 3, _Wnd->WindowYPosition + 15, _Wnd->WindowXPosition+_Wnd->WindowWidth - 3, _Wnd->WindowYPosition+_Wnd->WindowHeight - 3, WindowColor, WindowBorder);
			printf(_Wnd->WindowTitle, _Wnd->WindowXPosition + 4, _Wnd->WindowYPosition + 5, FontColor);
			break;
		default:
		case 1:
			DrawRectangle(_Wnd->WindowXPosition, _Wnd->WindowYPosition, _Wnd->WindowXPosition+_Wnd->WindowWidth, _Wnd->WindowYPosition+_Wnd->WindowHeight, WindowColor, WindowBorder);
			DrawRectangle(_Wnd->WindowXPosition + 3, _Wnd->WindowYPosition + 15, _Wnd->WindowXPosition+_Wnd->WindowWidth - 3, _Wnd->WindowYPosition+_Wnd->WindowHeight - 3, WindowColor, WindowBorder);
			DrawRectangle(_Wnd->WindowXPosition + _Wnd->WindowWidth - 13, _Wnd->WindowYPosition + 3, _Wnd->WindowXPosition + _Wnd->WindowWidth - 3, _Wnd->WindowYPosition + 13, WindowColor, WindowBorder);
			printf(_Wnd->WindowTitle, _Wnd->WindowXPosition + 4, _Wnd->WindowYPosition + 5, FontColor);
			break;
	};
};


/********************************************/
/* Draw a Bitmap-Area                       */
/********************************************/
void DrawArea (unsigned long *_area, unsigned long _x, unsigned long _y, unsigned long _width, unsigned long _height)
{
	unsigned long u, i;
	
	for (i=0; i < _height; i++)
	{
		for (u=0; u < _width; u++)
		{
			DrawPixel(_x+u, _y+i, _area[i*_height+u]);
		};
	
	};

};
/*
void DrawBMP (File *_file, int _x, int _y)
{

};

*/

char *autor="I don't know english!! :(";
User avatar
carbonBased
Member
Member
Posts: 382
Joined: Sat Nov 20, 2004 12:00 am
Location: Wellesley, Ontario, Canada
Contact:

Re: Vesa Problems

Post by carbonBased »

This isn't an answer, unfortunately, but a question... I'm curious as to the current state of your kernel (ie, why did you decide to implement graphics at this point)?

Have you implemented mutexes, semaphores, multitasking, IPC, etc?

This isn't an attempt to discourage, I'm just curious (although I do think these things should preclude graphics driver development).

Cheers,
Jeff
Post Reply