Drawing Lines

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
Omega
Member
Member
Posts: 250
Joined: Sun May 25, 2008 2:04 am
Location: United States
Contact:

Drawing Lines

Post by Omega »

Hi. How do you draw lines in Pmode? I have a menu and would like to draw a box around it in C. Thanks.
Pyrofan1
Member
Member
Posts: 234
Joined: Sun Apr 29, 2007 1:13 am

Post by Pyrofan1 »

Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

Well, you are a bit cryptic on your description. So, you have a menu, I am assuming this is in text mode? if that's the case, you can draw lines using special ascii codes, look up the ascii character map. Here are the ones of interest:

196 is a horizontal section
179 is vertical section
218 = top left corner
217 = bottom right corner
191 = top right
192 = bottom left

So, you simply draw your horizontal and vertical lines around the menu, then and fill in the 4 corners with the above ascii values. I have a nice text based window drawing routine, using this, there is also a double thick line, useful in some other cases, take a peek at the standard ascii map though, should give you an idea.
User avatar
Omega
Member
Member
Posts: 250
Joined: Sun May 25, 2008 2:04 am
Location: United States
Contact:

Post by Omega »

Thanks, that was going to be my next question.
void plot_pixel(int x,int y,unsigned char color)
{
char *vga = (char *) 0xb8000;
unsigned int i = 160*y + 2*x;
i = 160*y + 2*x;
vga[i++] = color;
}
Example Usage wrote: plot_pixel(1, 1, 0xDA);
Now the fun is writing my own drawing routine. =)
Pyrofan1
Member
Member
Posts: 234
Joined: Sun Apr 29, 2007 1:13 am

Post by Pyrofan1 »

void plot_pixel(int x,int y,unsigned char color)
{
char *vga = (char *) 0xb8000;
unsigned int i = 160*y + 2*x;
i = 160*y + 2*x;
vga[i++] = color;
}
That code will not work at all, 0xb8000 is color text memory, graphic memory is located at 0xa0000 if i'm not mistaken.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

Pyrofan1 wrote:
void plot_pixel(int x,int y,unsigned char color)
{
char *vga = (char *) 0xb8000;
unsigned int i = 160*y + 2*x;
i = 160*y + 2*x;
vga[i++] = color;
}
That code will not work at all, 0xb8000 is color text memory, graphic memory is located at 0xa0000 if i'm not mistaken.
You're not mistaken - I was just about to write that same reply.
User avatar
Omega
Member
Member
Posts: 250
Joined: Sun May 25, 2008 2:04 am
Location: United States
Contact:

Post by Omega »

It works for me. I just wrote a routine that draws the box around my menu using that function.

Code: Select all

void draw_box(void)
{
	int y=0;
	plot_pixel((13/2)-1,7,0xDA); //left corner
	for(y=0;y<37;y++) { plot_pixel((13/2)+y,7,0xC4); } //top line
	plot_pixel((13/2)+37,7,0xBF); //right corner
	//*******************
	int u=0;
	for(u=8;u<14;u++) { plot_pixel((13/2)-1,u,0xB3); } //left side
	//*******************
	int s=0;
	for(s=8;s<14;s++) { plot_pixel((13/2)+37,s,0xB3); } //right side
	//*******************
	int r=0;
	plot_pixel((13/2)-1,14,0xC0); //left corner
	for(r=0;r<37;r++) { plot_pixel((13/2)+r,14,0xC4); } //bottom line
	plot_pixel((13/2)+37,14,0xD9); //right corner
}
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

vst_0201 wrote:It works for me. I just wrote a routine that draws the box around my menu using that function.

Code: Select all

void draw_box(void)
{
	int y=0;
	plot_pixel((13/2)-1,7,0xDA); //left corner
	for(y=0;y<37;y++) { plot_pixel((13/2)+y,7,0xC4); } //top line
	plot_pixel((13/2)+37,7,0xBF); //right corner
	//*******************
	int u=0;
	for(u=8;u<14;u++) { plot_pixel((13/2)-1,u,0xB3); } //left side
	//*******************
	int s=0;
	for(s=8;s<14;s++) { plot_pixel((13/2)+37,s,0xB3); } //right side
	//*******************
	int r=0;
	plot_pixel((13/2)-1,14,0xC0); //left corner
	for(r=0;r<37;r++) { plot_pixel((13/2)+r,14,0xC4); } //bottom line
	plot_pixel((13/2)+37,14,0xD9); //right corner
}
Not trying to be fancy... =)
Not trying to be fancy, but you could at least have used function and parameter names that actually describe what the function is intended to do.

(1) plot_pixel doesn't really plot a pixel, does it? it puts a character at a certain place on the screen.
(2) the "color" parameter isn't a colour, is it? it's an ASCII character code.

Can you see why we were confused?
User avatar
Omega
Member
Member
Posts: 250
Joined: Sun May 25, 2008 2:04 am
Location: United States
Contact:

Post by Omega »

Right, my mistake. No problem, I can fix it. thanks =)
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

Glad it's working, not to difficult. I agree though, I would fix up your function naming, will confuse yourself later when you look back at it.
User avatar
Omega
Member
Member
Posts: 250
Joined: Sun May 25, 2008 2:04 am
Location: United States
Contact:

Post by Omega »

I changed it, so here is the updated function and routine.

Code: Select all

void plot_ascii(int x,int y,unsigned char ascii)
{
	char *vga = (char *) 0xb8000;
	unsigned int i = 160*y + 2*x;
	i = 160*y + 2*x;
	vga[i++] = ascii;
}
And, for those in need of this code, you would use it like so:

Code: Select all

void draw_box(void)
{
   int y=0;
   plot_ascii((13/2)-1,7,0xDA); //left corner
   for(y=0;y<37;y++) { plot_ascii((13/2)+y,7,0xC4); } //top line
   plot_ascii((13/2)+37,7,0xBF); //right corner
   //*******************
   int u=0;
   for(u=8;u<14;u++) { plot_ascii((13/2)-1,u,0xB3); } //left side
   //*******************
   int s=0;
   for(s=8;s<14;s++) { plot_ascii((13/2)+37,s,0xB3); } //right side
   //*******************
   int r=0;
   plot_ascii((13/2)-1,14,0xC0); //left corner
   for(r=0;r<37;r++) { plot_ascii((13/2)+r,14,0xC4); } //bottom line
   plot_ascii((13/2)+37,14,0xD9); //right corner
}
Of course you would need to change the x and y values to suit your own needs/design. Thanks
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

I wrote mine a bit differently to be more efficient, plus to have variable sized boxes. I can use this for text based windows, or messages, etc. Here is my function for comparison:

Code: Select all


typedef unsiged long u32;
typedef unsigned short u16;

u16 *ScreenPtr16 = (u16*)0xB8000;

struct Rect_S
{
	u32	x1,y1,x2,y2;
};

//Used to display windows/menus
u16	Pieces[11] =
{
	218,		//Top Left
	192,		//Bottom Left
	191,		//Top Right
	217,		//Bottom Right
	196,		//Straight Horizontal
	179,		//Straight Vertical
	194,		//Split Vertical Down
	193,		//Split Vertical Up
	195,		//Split Horizontal Right
	180,		//Split Horizontal Left
	197		//Cross
};

void DrawBox(struct Rect_S *rect, u32 Color)	//Draws a box :)
{
	u32 Ctr, Off1, Off2;
	Off1 = rect->y1*80+rect->x1;
	Off2 = rect->y2*80+rect->x1;

	ScreenPtr16[Off1] = Pieces[0]+Color;
	ScreenPtr16[Off2] = Pieces[1]+Color;

	++Off1;
	++Off2;
	for (Ctr=0;Ctr!=rect->x2-rect->x1-1;++Ctr)
	{
		ScreenPtr16[Off1] = Pieces[4]+Color;
		ScreenPtr16[Off2] = Pieces[4]+Color;
		++Off1;
		++Off2;
	}
	ScreenPtr16[Off1] = Pieces[2]+Color;
	ScreenPtr16[Off2] = Pieces[3]+Color;

	Off1 = rect->y1*80+rect->x1;
	Off2 = rect->y1*80+rect->x2;
	for (Ctr=0;Ctr!=rect->y2-rect->y1-1;++Ctr)
	{
		Off1+=80;
		Off2+=80;
		ScreenPtr16[Off1] = Pieces[5]+Color;
		ScreenPtr16[Off2] = Pieces[5]+Color;
	}
}
This will draw a box using a color, however for the color it goes like this:

Color = (Background << 12 ) + (Foreground << 8 );

Each one can be 4-bits wide, so 16 colors each. This is so I can draw windows, menu's, etc in any color comination as well as any location and size. I also have a window structure that holds the position, size and name, and draws a window with title. Pretty useless since I have VESA support, and have never used this code beyond testing, but hopefully it gets some use to help others. It's pretty well optimized, so it should be plenty fast for text mode ;).
User avatar
Omega
Member
Member
Posts: 250
Joined: Sun May 25, 2008 2:04 am
Location: United States
Contact:

Post by Omega »

Yours is much better and more useful as mine has hard-coded x and y values and is much too custom to present itself as a useful snippet to the masses. I am storing this one in my dev folder just in case I decide to start fencing in my content. Nice work, thanks a lot
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post by Ready4Dis »

Well, hopefully it's useful for someone. I also have the scan-code in my list of pieces for splitting the box (like breaks between menu's, or seperating a window into multiple sections), so it can be pretty useful for a text-based GUI, menu system, IDE or Shell of sorts. Hope it goes to some use, wrote it and never used it beyond testing to make sure it worked, haha.
Post Reply