Drawing Lines
Drawing Lines
Hi. How do you draw lines in Pmode? I have a menu and would like to draw a box around it in C. Thanks.
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.
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.
You're not mistaken - I was just about to write that same reply.Pyrofan1 wrote:That code will not work at all, 0xb8000 is color text memory, graphic memory is located at 0xa0000 if i'm not mistaken.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;
}
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, but you could at least have used function and parameter names that actually describe what the function is intended to do.vst_0201 wrote:It works for me. I just wrote a routine that draws the box around my menu using that function.
Not trying to be fancy... =)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 }
(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?
I changed it, so here is the updated function and routine.
And, for those in need of this code, you would use it like so:
Of course you would need to change the x and y values to suit your own needs/design. Thanks
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;
}
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
}
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:
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 .
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;
}
}
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 .
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.