📄 vga_controller.c
字号:
* Function: vga_draw_box
*
* Purpose: Draws a box on the screen with the specified corner
* points. The fill parameter tells the function whether or not
* to fill in the box. 1 = fill, 0 = do not fill.
*
******************************************************************/
int vga_draw_box (int horiz_start, int vert_start, int horiz_end, int vert_end, int color, int fill, vga_frame_buffer_struct* vga_frame_buffer)
{
// If we want to fill in our box
if (fill) {
vga_paint_block (horiz_start, vert_start, horiz_end, vert_end, color, vga_frame_buffer);
// If we're not filling in the box, just draw four lines.
} else {
vga_draw_line(horiz_start, vert_start, horiz_start, vert_end-1, 1, color, vga_frame_buffer);
vga_draw_line(horiz_end-1, vert_start, horiz_end-1, vert_end-1, 1, color, vga_frame_buffer);
vga_draw_horiz_line(horiz_start, horiz_end-1, vert_start, color, vga_frame_buffer);
vga_draw_horiz_line(horiz_start, horiz_end-1, vert_end-1, color, vga_frame_buffer);
}
return (0);
}
/******************************************************************
* Function: vga_print_char
*
* Purpose: Prints a character to the specified location of the
* screen using the specified font and color.
*
******************************************************************/
int vga_print_char (int horiz_offset, int vert_offset, int color, char character, char *font, vga_frame_buffer_struct* vga_frame_buffer)
{
int i, j;
char temp_char, char_row;
// Convert the ASCII value to an array offset
temp_char = (character - 0x20);
//Each character is 8 pixels wide and 11 tall.
for(i = 0; i < 11; i++) {
char_row = *(font + (temp_char * FONT_10PT_ROW) + i);
for (j = 0; j < 8; j++) {
//If the font table says the pixel in this location is on for this character, then set it.
if (char_row & (((unsigned char)0x80) >> j)) {
vga_set_pixel((horiz_offset + j), (vert_offset + i), color, vga_frame_buffer); // plot the pixel
}
}
}
return(0);
}
/******************************************************************
* Function: vga_set_pixel
*
* Purpose: Sets the specified pixel to the specified color.
* Sets one pixel although frame buffer consists of
* two-pixel words. Therefore this function is not
* efficient when painting large areas of the screen.
*
******************************************************************/
void vga_set_pixel(int horiz, int vert, unsigned int color, vga_frame_buffer_struct* vga_frame_buffer)
{
int addr;
if( vga_frame_buffer->color_depth == 24 )
{
addr = ( ( (int)(vga_frame_buffer->vga_frame1) )+ (vert * (vga_frame_buffer->width * 3)) + horiz * 3);
IOWR_8DIRECT( addr, 0, (unsigned char)(color));
IOWR_8DIRECT( addr+1, 0, (unsigned char)(color >> 8));
IOWR_8DIRECT( addr+2, 0, (unsigned char)(color >> 16));
}
else if( vga_frame_buffer->color_depth == 16 )
{
addr = ( ( (int)(vga_frame_buffer->vga_frame1) )+ (vert * (vga_frame_buffer->width * 2)) + horiz * 2);
IOWR_16DIRECT( addr, 0, (int)(color));
}
}
/******************************************************************
* Function: vga_get_pixel
*
* Purpose: Reads the color of the pixel at the given coordinates
*
******************************************************************/
short vga_get_pixel(int horiz, int vert, vga_frame_buffer_struct* vga_frame_buffer)
{
int addr;
addr = ( ( (int)(vga_frame_buffer->vga_frame1) )+ (vert * (vga_frame_buffer->width * 2)) + horiz * 2);
return(IORD_16DIRECT(addr, 0));
}
/******************************************************************
* Function: vga_clear_screen
*
* Purpose: Uses the fast memset routine to clear the entire frame
* buffer. User can specify black(0x00) or white(0xFF).
*
******************************************************************/
inline void vga_clear_screen (vga_frame_buffer_struct* vga_frame_buffer, char color)
{
memset( (void*)(vga_frame_buffer->vga_frame1), color, vga_frame_buffer->bytes_per_frame );
}
/******************************************************************
* Function: vga_paint_block
*
* Purpose: Paints a block of the screen the specified color.
* Note: works with two pixels at a time to maintain high
* bandwidth. Therefore, corner points must be even
* numbered coordinates. Use vga_draw_solid_box() for
* areas with odd-numbered corner points.
* The color parameter must contain two pixel's worth
* (32 bits).
*
******************************************************************/
void vga_paint_block (int Hstart,int Vstart, int Hend, int Vend, int color, vga_frame_buffer_struct* vga_frame_buffer)
{
int i;
int addr;
int bytes_per_line, bytes_per_pixel;
char* line;
bytes_per_pixel = (vga_frame_buffer->color_depth / 8);
bytes_per_line = ((Hend - Hstart) * bytes_per_pixel);
line = malloc(bytes_per_line + 12);
if(vga_frame_buffer->color_depth == 16)
{
for (i = 0; i < bytes_per_line; i+=2)
{
*(line + i) = (unsigned char)color;
*(line + i + 1) = (unsigned char)(color >> 8);
}
}
else if(vga_frame_buffer->color_depth == 24)
{
for (i = 0; i < bytes_per_line; i+=3)
{
*(line + i) = (unsigned char)color;
*(line + i + 1) = (unsigned char)(color >> 8);
*(line + i + 2) = (unsigned char)(color >> 16);
}
}
/* Initial Address */
addr = (int)(vga_frame_buffer->vga_frame1) + ((Vstart * (vga_frame_buffer->width * bytes_per_pixel)) + (Hstart * bytes_per_pixel));
for (i = Vstart; i < Vend; i++)
{
memcpy( (void*)addr, line, bytes_per_line );
addr += (vga_frame_buffer->width * bytes_per_pixel);
}
free (line);
}
/******************************************************************
* Function: vga_draw_horiz_line
*
* Purpose: Draws a horizontal line on the screen quickly.
* Good for filling stuff.
*
******************************************************************/
void vga_draw_horiz_line (int Hstart, int Hend, int V, int color, vga_frame_buffer_struct* vga_frame_buffer)
{
int i;
int addr;
int bytes_per_line;
// line = malloc(bytes_per_line + 12);
if(vga_frame_buffer->color_depth == 24)
{
addr = (int)(vga_frame_buffer->vga_frame1) + ((V * (vga_frame_buffer->width * 3)) + (Hstart * 3));
bytes_per_line = ((Hend - Hstart) * 3);
for (i = 0; i < bytes_per_line; i+=3)
{
*(fast_buffer + i) = (unsigned char)color;
*(fast_buffer + i + 1) = (unsigned char)(color >> 8);
*(fast_buffer + i + 2) = (unsigned char)(color >> 16);
}
memcpy( (void*)addr, fast_buffer, bytes_per_line );
}
else if(vga_frame_buffer->color_depth == 16)
{
addr = (int)(vga_frame_buffer->vga_frame1) + ((V * (vga_frame_buffer->width * 2)) + (Hstart * 2));
bytes_per_line = ((Hend - Hstart) * 2);
for (i = 0; i < bytes_per_line; i+=2)
{
*(fast_buffer + i) = (unsigned char)color;
*(fast_buffer + i + 1) = (unsigned char)(color >> 8);
}
memcpy( (void*)addr, fast_buffer, bytes_per_line );
}
}
/******************************************************************
* Function: vga_merge_colors
*
* Purpose: Takes 5-bit color values for each red, green, and blue
* and merges them into one 16-bit color value.
*
******************************************************************/
int vga_merge_colors(int red, int green, int blue)
{
// Green actually has 6-bits, but we'll make it's LSB 1 to be consistent.
return ((blue) | (((green << 1) | 0x1) << 5) | (red << 11));
}
/******************************************************************
* Function: vga_color_convert24_16
*
* Purpose: Takes a pointer to a 24-bit (3-byte) 24-bit RGB color
* sample and converts it to 16-bits, displayable by the
* VGA controller in 16-bit mode
*
******************************************************************/
unsigned short vga_color_convert24_16(char* color24)
{
unsigned char red, green, blue;
unsigned short output;
red = *(color24 + 0) & 0xF8;
green = *(color24 + 1) & 0xFC; // green is actualy 6 bits
blue = *(color24 + 2) & 0xF8;
output = ((blue >> 3) | (green << 3) | (red << 8));
return output;
}
/******************************************************************
* Function: vga_color_convert24_16
*
* Purpose: Takes a pointer to a 24-bit (3-byte) 24-bit RGB color
* sample and converts it to 16-bits, displayable by the
* VGA controller in 16-bit mode
*
******************************************************************/
int vga_color_convert16_24(unsigned short color16, char* color24)
{
*(color24 + 0) = color16 >> 11;
*(color24 + 1) = ((color16 & 0x3E) >> 5);
*(color24 + 2) = (color16 & 0x1F);
return (0);
}
/******************************************************************
* Function: vga_copy_line_to_frame_buffer
*
* Purpose: Copies a scanline from memory to the frame buffer at
* the specified coordinates. Converts color depth if
* necessary.
*
******************************************************************/
int vga_copy_line_to_frame_buffer( int x, int y, char* buffer, int num_pixels, int source_color_depth, vga_frame_buffer_struct* vga_frame_buffer )
{
unsigned short* temp_line;
int index_24 = 0;
int index_16 = 0;
unsigned int dest_addr;
unsigned int bytes_in_line;
dest_addr = (int)(vga_frame_buffer->vga_frame1) +
((y * (vga_frame_buffer->width * (vga_frame_buffer->bytes_per_pixel))) +
(x * (vga_frame_buffer->bytes_per_pixel)));
bytes_in_line = num_pixels * vga_frame_buffer->bytes_per_pixel;
if(source_color_depth == 24)
{
if(vga_frame_buffer->color_depth == 16)
{
temp_line = malloc(bytes_in_line);
while(index_24 < bytes_in_line)
{
*(temp_line + index_16) = vga_color_convert24_16_m((char*)(buffer + index_24));
index_16++;
index_24+=3;
}
memcpy( (void*)dest_addr, (void*)temp_line, bytes_in_line );
free(temp_line);
}
else if(vga_frame_buffer->color_depth == 24)
{
memcpy( (void*)dest_addr, (void*)buffer, bytes_in_line );
}
}
else if(source_color_depth == 16)
{
if(vga_frame_buffer->color_depth == 24)
{
temp_line = malloc(bytes_in_line);
while(index_16 < num_pixels )
{
vga_color_convert16_24((short)*(buffer + index_16), (char*)(temp_line + index_24));
index_16++;
index_24+=3;
}
memcpy( (void*)dest_addr, (void*)temp_line, bytes_in_line );
free(temp_line);
}
else if(vga_frame_buffer->color_depth == 16)
{
memcpy( (void*)dest_addr, (void*)buffer, bytes_in_line );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -