📄 vesa.c
字号:
#include "vesa.h"
#include "bmp.h"
/*****************************************************
* 数据声明部份 *
*****************************************************/
const int VESA_SCREEN_X_MAX = 800 ;
const int VESA_SCREEN_Y_MAX = 600 ;
static const int VESA_ADDR = 0x80001 ;
// 色调合成函数
unsigned short vesa_compond_rgb( unsigned char r , unsigned char g , unsigned char b )
{
union{
unsigned int color ;
struct{
unsigned char b : 5 ;
unsigned char g : 6 ;
unsigned char r : 5 ;
} ;
} u ;
u.r = r % 32 ;
u.g = g % 64 ;
u.b = b % 32 ;
return u.color ;
}
// 画点函数
void vesa_draw_point( unsigned int x , unsigned int y , unsigned short color )
{
unsigned int x_max = VESA_SCREEN_X_MAX - 1 ; // 每行像素数
unsigned int y_max = VESA_SCREEN_Y_MAX - 1 ; // 每列像素数
// 防止越界
if( x > x_max ){
return ;
}
if( y > y_max ){
return ;
}
// 取得显存线性地址
unsigned short *video = ( unsigned short * )( * ( ( unsigned int *)VESA_ADDR ) ) ;
// 计算点的偏移量
unsigned int offset = y * ( x_max + 1 ) + x ;
*( video + offset ) = color ;
}
// 取得指定点色彩
unsigned short vesa_get_point_color( unsigned int x , unsigned int y )
{
unsigned int x_max = VESA_SCREEN_X_MAX - 1 ; // 每行像素数
unsigned int y_max = VESA_SCREEN_Y_MAX - 1 ; // 每列像素数
// 防止越界
if( x > x_max ){
x = x_max ;
}
if( y > y_max ){
y = y_max ;
}
// 取得显存线性地址
unsigned short *video = ( unsigned short * )( * ( ( unsigned int *)VESA_ADDR ) ) ;
// 计算点的偏移量
unsigned int offset = y * ( x_max + 1 ) + x ;
return *( video + offset ) ;
}
// 矩形填充函数
void vesa_fill_rect( unsigned int x1 , unsigned int y1 , unsigned int x2 , unsigned int y2 , unsigned int color )
{
for( int x = x1 ; x < x2 + 1 ; ++x ){
for( int y = y1 ; y < y2 + 1 ; ++y ){
vesa_draw_point( x , y , color ) ;
}
}
}
// 清屏函数
void vesa_clean_screen( unsigned short color )
{
vesa_fill_rect( 0 , 0 , VESA_SCREEN_X_MAX - 1 , VESA_SCREEN_Y_MAX - 1 , color ) ;
}
// 图片拷贝函数
void vesa_copy_picture_from_screen( unsigned int x , unsigned int y , unsigned short *object_picture_addr , unsigned int picture_width , unsigned int picture_height )
{
for( int j = 0 ; j < picture_height ; ++j ){
for( int i = 0 ; i < picture_width ; ++i ){
*( object_picture_addr + j * picture_width + i ) = vesa_get_point_color( x + i , y + j ) ;
}
}
}
// 图片拷贝函数
void vesa_copy_picture_to_screen( unsigned int x , unsigned int y , unsigned short *source_picture_addr , unsigned int picture_width , unsigned int picture_height )
{
for( int j = 0 ; j < picture_height ; ++j ){
for( int i = 0 ; i < picture_width ; ++i ){
vesa_draw_point( x + i , y + j , *( source_picture_addr + j * picture_width + i ) ) ;
}
}
}
// 画横线函数
void vesa_draw_x_line( unsigned int y , unsigned int x1 , unsigned int x2 , unsigned short color )
{
for( int x = x1 ; x < x2 + 1 ; ++x ){
vesa_draw_point( x , y , color ) ;
}
}
// 画竖线函数
void vesa_draw_y_line( unsigned int x , unsigned int y1 , unsigned int y2 , unsigned short color )
{
for( int y = y1 ; y < y2 + 1 ; ++y ){
vesa_draw_point( x , y , color ) ;
}
}
// 画矩形函数
void vesa_draw_rect( unsigned int x1 , unsigned int y1 , unsigned int x2 , unsigned y2 , unsigned short color , int dose_fill_it )
{
vesa_draw_x_line( y1 , x1 , x2 , color ) ;
vesa_draw_x_line( y2 , x1 , x2 , color ) ;
vesa_draw_y_line( x1 , y1 , y2 , color ) ;
vesa_draw_y_line( x2 , y1 , y2 , color ) ;
if( dose_fill_it ){
vesa_fill_rect( x1 , y1 , x2 , y2 , color ) ;
}
}
// 显示英文
void vesa_print_english( unsigned int x , unsigned int y , unsigned int pos_in_font , unsigned short color )
{
unsigned char *english_font_addr = ( unsigned char * )0x30200 + pos_in_font * 16 ; // 一个英文 16 字节
union{
unsigned char ch ;
struct{
unsigned char ch0 : 1 ;
unsigned char ch1 : 1 ;
unsigned char ch2 : 1 ;
unsigned char ch3 : 1 ;
unsigned char ch4 : 1 ;
unsigned char ch5 : 1 ;
unsigned char ch6 : 1 ;
unsigned char ch7 : 1 ;
} ;
} u ;
for( int j = 0 ; j < 16 ; ++j ){ // 一个英文 16 行
u.ch = english_font_addr[ j ] ;
int offset = x ;
if( u.ch7 ){
vesa_draw_point( offset , y , color ) ;
}
if( u.ch6 ){
vesa_draw_point( offset + 1 , y , color ) ;
}
if( u.ch5 ){
vesa_draw_point( offset + 2 , y , color ) ;
}
if( u.ch4 ){
vesa_draw_point( offset + 3 , y , color ) ;
}
if( u.ch3 ){
vesa_draw_point( offset + 4 , y , color ) ;
}
if( u.ch2 ){
vesa_draw_point( offset + 5 , y , color ) ;
}
if( u.ch1 ){
vesa_draw_point( offset + 6 , y , color ) ;
}
if( u.ch0 ){
vesa_draw_point( offset + 7 , y , color ) ;
}
y++ ; // 显示下一行
}
}
// 显示汉字
void vesa_print_chinese( unsigned int x , unsigned int y , unsigned int pos_in_font , unsigned short color )
{
unsigned char *chinese_font_addr = ( unsigned char * )0x30000 + pos_in_font * 32 ; // 一个汉字 32 字节
union{
unsigned char ch ;
struct{
unsigned char ch0 : 1 ;
unsigned char ch1 : 1 ;
unsigned char ch2 : 1 ;
unsigned char ch3 : 1 ;
unsigned char ch4 : 1 ;
unsigned char ch5 : 1 ;
unsigned char ch6 : 1 ;
unsigned char ch7 : 1 ;
} ;
} u ;
for( int j = 0 ; j < 16 ; ++j ){ // 一个汉字 16 行
for( int i = 0 ; i < 2 ; ++i ){ // 每行 2 个字节 ( 16 位 )
u.ch = chinese_font_addr[ j * 2 + i ] ;
int offset = x + i * 8 ; // 一个字节 8 个像素
if( u.ch7 ){
vesa_draw_point( offset , y , color ) ;
}
if( u.ch6 ){
vesa_draw_point( offset + 1 , y , color ) ;
}
if( u.ch5 ){
vesa_draw_point( offset + 2 , y , color ) ;
}
if( u.ch4 ){
vesa_draw_point( offset + 3 , y , color ) ;
}
if( u.ch3 ){
vesa_draw_point( offset + 4 , y , color ) ;
}
if( u.ch2 ){
vesa_draw_point( offset + 5 , y , color ) ;
}
if( u.ch1 ){
vesa_draw_point( offset + 6 , y , color ) ;
}
if( u.ch0 ){
vesa_draw_point( offset + 7 , y , color ) ;
}
}
y++ ; // 显示下一行
}
}
// 显示 pbmp 格式的图片
void vesa_show_bmp_picture( unsigned int x , unsigned int y , void *bmp_addr , unsigned short mask_color , int dose_use_mask_color )
{
// 这里只支持 windows 标准 16 位 bmp 格式图片,(1:5:5:5)
struct bmp_bmp_head_struct *bmp_head = ( struct bmp_bmp_head_struct * )bmp_addr ;
int width = bmp_head->info_head.width ;
int height = bmp_head->info_head.height ;
// 下面记算存储每个点的色彩的信息所在的位置
unsigned short *color = ( unsigned short * )( ( unsigned int )bmp_addr + bmp_head->offset ) ;
// 由于一行的字节数比须是 4 的倍数,因此,这里先计算每行需要的填充数,除 2 是因为每个像素两个字节
int fill_length = width * 2 % 4 / 2 ;
// bmp 的存放顺序是从下到上,从左到右
for( int i = height - 1 ; i >= 0 ; --i ){
for( int j = 0 ; j < width ; ++j ){
// 取得每个点的色彩信息
// 由于 windows 默认的是 555 格式,而 pyos 用的是 565 格式,因此先进行一下转换
unsigned short temp_color = vesa_change_color_form_555_to_565( *color ) ;
if( !dose_use_mask_color || temp_color != mask_color ){
// 画出每个点
vesa_draw_point( x + j , y + i , temp_color ) ;
}
++color ;
}
// 填充
color += fill_length ;
}
}
// 显示字符在文本模式下
void vesa_print_char_under_text_model( char x )
{
static unsigned char *video = ( unsigned char * )0xb8000 ;
*video++ = x ;
*video++ = 0xf ;
}
// 色调转换函数,把 5:5:5 格式转换成标准的 5:6:5 格式
unsigned short vesa_change_color_form_555_to_565( unsigned short color_form_555 )
{
// 把 555 中间的色彩 * 2,为了掩色处理方便,如果不是 0,则末位恒置 1
union{
unsigned int color ;
struct{
unsigned char b : 5 ;
unsigned char g : 6 ;
unsigned char r : 5 ;
} ;
} u1 ;
union{
unsigned int color ;
struct{
unsigned char b : 5 ;
unsigned char g : 5 ;
unsigned char r : 5 ;
unsigned char alpha : 1 ; // alpha 通道,但这里不用
} ;
} u2 ;
u2.color = color_form_555 ;
u1.r = u2.r ;
if( u2.g ){
u1.g = ( int )u2.g * 2 + 1 ;
}
else{
u1.g = 0 ;
}
u1.b = u2.b ;
return u1.color ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -