VGA图形控制器直接编程技术.docx

上传人:b****8 文档编号:29987040 上传时间:2023-08-04 格式:DOCX 页数:16 大小:23.01KB
下载 相关 举报
VGA图形控制器直接编程技术.docx_第1页
第1页 / 共16页
VGA图形控制器直接编程技术.docx_第2页
第2页 / 共16页
VGA图形控制器直接编程技术.docx_第3页
第3页 / 共16页
VGA图形控制器直接编程技术.docx_第4页
第4页 / 共16页
VGA图形控制器直接编程技术.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

VGA图形控制器直接编程技术.docx

《VGA图形控制器直接编程技术.docx》由会员分享,可在线阅读,更多相关《VGA图形控制器直接编程技术.docx(16页珍藏版)》请在冰豆网上搜索。

VGA图形控制器直接编程技术.docx

VGA图形控制器直接编程技术

VGA图形控制器直接编程技术

使用VGA图形控制器直接编程,可以突破C语言提供的图形函数只能实现16色的限制,还可以在同一屏幕中控制图像的灰度,做出许多特技效果。

学习目标

●VGA卡的结构原理

●调用BIOS中断设置图形方式

●灰度级别的应用

VGA卡的概念

VGA图形控制器位于CPU和VideoRAM(视频存储器)的通路之间,主要用来对CPU写入VideoRAM的数据进行各种操作和处理。

它由算术逻辑部件(ALU)、位平面读出暂存器及一些控制寄存器组成。

在初始状态下它是透明的。

即CPU向VideoRAM读出时它对数据不作任何修改。

当直接对图形控制器进行控制时,它能协助我们完成一些原来要由CPU执行的任务。

在图形模式下,它对于绘图算法的快速实现提供了一定的硬件支持。

特别是在对像素操作时,直接使用图形控制器是最快捷的方法。

在VGA卡上,是不能直接对VideoRAM的内容进行读写的,必须通过特殊硬件作界面。

VGA的VideoRAM被分成四个独立的位平面(Bitplane)的形式。

在图形方式下的位平面地址方式是水平的,各位平面具有相同的空间地址,其首地址入口为A000:

000H。

每个位平面的读写操作均可独立地进行。

通常,屏幕上第五个像素的颜色用4个二进制位表示,它的像素值被划分到4个位平面上,分别占用4个位平面的一位。

所以,当CPU要读写VideoRAM地址时,并不是只用到一个字节,而是同时用到4个字节,分别在每一个位平面上。

图形控制器有四个读出数据暂存器(Latch),从VideoRAM的4个位平面读出的数据都同时暂存在其中,直到下一次再更新它们的内容。

每一个Latch对应于一个位平面,当CPU要用到VideoRAM的地址时,读取操作会更新Latch中的值,写入操作会更新位平面的值。

由于VGA与CPU之间的数据通路是单字节宽,只有8个Bit,但内部却有32位的数据通路,因此,从CPU送来的一个字节,在一个写周期内,可以同时向4个位平面写入。

图形控制器的逻辑运算部件主要对CPU与入VideoRAM的数据执行与、或、异或、循环等操作,由于可以对像素的颜色进行逻辑运算,可以大大简化绘图操作,获得一些特殊的效果。

在VGA卡中,与图形控制器工作状态相关的另一个物理器件是操作定序控制器,它是VGA各种寄存器操作和数据传送操作的顺序控制器,起着控制VideoRAM或图形控制器到属性控制器之间的数据流动的作用。

在下面所涉及的各种位平面写入操作中,最终对哪些平面有效,还要受到操作定序控制器中的位平面屏蔽寄存储的影响。

图形控制寄存器访问

对图形控制器的访问必须通过寄存器的读写操作来完成。

图形控制器有9个可定址的寄存器,这些寄存器均为一个字节宽。

由于系统分配给显示器端口地址的数量有限,在访问寄存器时采用了间址选择的方法,即预先将这些寄存器编号(称之为索引号),并添加一个索引寄存器和一个数据寄存器。

它们的存取操作均须通过地址索引寄存器(输出地址为3CEH)和数据寄存器(输入/输出地址为3CFH),前者存放索引号,后者存放索SI号所指定的寄存器写入或读出的数据。

索引寄存器的内容起着控制数据寄存器的功能,所以可将地址为3CFH的数据寄存器看作9个不同的寄存器来使用。

为了访问图形控制器的功能,对图形控制器寄存器的存取操作均须分两步进行:

首先应当把索引号(即功能号)作为寄存器的内容输出到索引寄存器端口3CEH中,然后再对数据寄存器进行读写操作。

图形控制器寄存器的参数及功能

为了实现对图形控制器的直接编程,必须掌握各个寄存器的含义及其用法。

在VGABIDS中,这些寄存器都有其初值,当然,这些值都是可以修改的。

下表列出这9个寄存器的名称和系统初始值。

ROMBIOS中VGA图形控制器所设置的初始值

功能索引号

寄存器名称及作用

系统初值

0

Set/Reset(置位/复位寄存器)

0

1

EnableSet(置位/复位允许寄存器)

0

2

ColorCompare<颜色比较寄存器)

0

3

DataRotate(数据移位寄存OS)

0

4

ReadMapSelect(位平面选择寄存器)

0

5

Mode(模式寄存器)

D0-D3为0

6

Miscellaneous(辅助寄存器)

取决视频模式

7

ColorDon'tCare(颜色忽略寄存器)

0FH或01H

8

BitMask(位屏蔽寄存器)

FFH

下面对这9个图形控制器寄存器进行逐一介绍。

1.置位/复位寄存器(功能号0)

S/R寄存器用来定义区域填充时向显示RAM写入的颜色。

S/R寄存器的D0~D3位分别与4个位平面相对应。

若D2=l,则向位平面2中写入的数据就全为1。

若D1:

0,则向位平面1中写入的数据就全为00

2.置位/复位允许寄存器(功能号1)

通常与S/R寄存器配合使用,启动对应于该寄存器D0~D3位的位平面,用来决定置位/复位操作在哪几个位子面进行。

如果关闭某位平面,则不能修改被关闭平面的颜色,也不能改变由功能0选取的颜色。

通常将OFH输出到ESR寄存器后,便可对0,-3位平面进行操作。

注意:

功能0与功能1仅用于由功能5设定的模式0写操作

3.颜色比较寄存器(功能2)与颜色忽略寄存器(功能7)

这一功能使用寄存器的D0~D3位存储从位平面读入的数据,当CPU向图形控制器指定一个参考色之后,颜色比较器每次都把从4个位平面中同时读出的数据与参考颜色作比较,指出是否与参考颜色相同。

若相同,则结果寄存器相应位置1,否则置o。

颜色忽略寄存器则用来控制哪些位平面参加比较,不参加比较的位平面无论其内容如何,总认为与参考颜色的相应位相等。

此功能仅用于模式寄存器(功能5)中读模式为1时。

4.数据移位寄存器(功能3)

这个寄存器用来控制以下功能:

写入数据的循环位移的逻辑操作。

寄存器在功能5模式。

情况下,该寄存器的D0~D2位表示的数值为向右循环移位的数据位数目。

逻辑运算用来实现显示RAM的读一改一写操作,对于实现光标或图符在屏幕上的移动特别有用。

5.位平面读出选择寄存器(功能4)

用来选取位平面在读模式0时进行读取。

当CPU对VideoRAM进行读出操作时,4个位平面的数据总是同时读出到暂存器中,由于一次只能向CPU送出一个字节,通过设置RMS的D0~D2位的数值可选择哪一个位平面的读出数据字节被送到CPU中去。

例如,当RMS:

01H时,送到CPU去的是从位平面1中读出的一个字节。

6,模式寄存器(功能5)

这里仅介绍功能5的读写模式。

在图形控制器中,无论按字节方式处理还是按像素方式处理,都要选择写入模式或读取模式。

MODE寄存器的DO~D1位值按以下方式确定:

写入模式0:

这是最基本的一种方式。

在CPU执行写入动作时,结合了字节方式和像素方式的操作,CPU所写入的数据可以更新任何一个或是全部的位平面,也可以更新暂存器的2个像素或是其中的一个。

在此模式下,可使用功能3提供的数值对处理器数据进行循环移位和逻辑操作,可使用功能。

和功能1启动位平面并设置像素颜色,可使用功能8来设置所有的位平面对应位等。

写入模式1:

此时向VideoRAM写入的仅仅是从Latch读出的数据,而与CPU送来的数据无关。

这时的移位、逻辑运算、置位/复位等操作均不起作用。

在此模式下,可实现对VGA表面上的一个彩色区域从一个位置拷贝到屏幕的另一个位置。

写入模式2:

此模式可将由CPU送来的数据字节的D0~D3位的数值按位分别写入0~3个位平面的所有8位中去。

例如该字节第。

位为1,则位平面。

中则为全l字节。

写入模式3:

它把置位/复位寄存器中的数据写到相应的位平面中去,例如DO=O时,位平面0中写入为全1字节。

功能5的读取模式共有两种,分别由MODE寄存器的第三位设置读模式(o,1两种状态)。

读模式0:

将读取由功能4选取的位平面中之一的一个字节的内容送到CPU中去。

读模式1:

使CPU获得4个位平面在指定地址处像素颜色与参考颜色的比较结果。

7.辅助寄存器(功能6)

该寄存器的D1~D2用来决定VGA的VideoRAM在CPU可寻址的主存储空间的入口地址及范围。

它的值在系统确定显示模式时已设定,一般不再改变。

例如D3和D2的值分别为0时,这时显存地址被设定为A000~BFFFH之间。

8.位屏蔽寄存器(功能8)

位屏蔽寄存器用来控制写入VideoRAM去的数据字节中,哪些位应该修改,哪些位应该保持不变,从而实现对VideoRAM的读一改一写操作,这对于以像素为单位画图时特别有用。

VGA图形控制器编程实例

我们所讨论的只是VGA的图形控制器一些最基本的内容,要想熟练掌握和灵活使用好图形控制器是要付出许多努力的。

为帮助读者理解和掌握VGA图形控制器的直接编程方法,这里我们给出一个用TURBOC实现的程序实例,供读者参考。

#include"graphics.h"

#include"dos.h"

#include"stdio.h"

#defineENABLE0x0F

#defineINDEXREG0x3CE

/*定义索引寄存器端口地址*/

#defineVALREG0x3CF

/*定义数据寄存器端口地址*/

#defineVGABASE0xA0000000L

#defineWIDTH80L

#defineXMAX639

#defineYMAX479

#defineXMIX0

#defineYMIN0

#defineOUTINDEX(index,val)outport(INDEXREG,index);outport(VALREG,val);

charfar*vgabase;

voidputpoint(intx,inty,intcolor,inthow);

main()

{

intgmode=VGAHI,gdriver=VGA;

intcolor=1,x,y;

initgraph(&gdriver,&gmode,"");

/*绘制各种颜色的直线段*/

for(y=1;y<=479;++y){

for(x=1;x<=639;++x)

putpoint(x,y,color,0);

color++;}

getch();

/*用异或方式擦除各条直线*/

color=1;

for(y=1;y<=479;++y){

for(x=1;x<=639;++x)

putpoint(x,y,color,0x18);

color++;}

getch();

closegraph();

}

/*利用图形控制寄存器功能写像素函数*/

voidputpoint(intx,inty,intcolor,inthow)

{

registerunsignedcharmask=0x80;

registercharfar*base;

unsigneddummy;

vgabase=(charfar*)MK_FP(0xA000,0);

base=(charfar*)(vgabase+((long)y*

WIDTH+(long)x/8L));

mask>>=x%8;

dummy=*base;

OUTINDEX(0,color);/*设定额色*/

OUTINDEX(1,ENABLE);/*启动位平面*/

OUTINDEX(3,how);/*确定逻辑操作方式*/

OUTINDEX(8,mask);/*设置屏蔽位*/

*base=1;

OUTINDEX(0,0);/*寄存器复位*/

OUTINDEX(1,0);

OUTINDEX(3,0);

OUTINDEX(8,0xff);

}

TVGA显示原理

SuperVGA是目前微机上显示方式极为普遍的配置,但SuperVGA并无统一标准,各种高级语言不支持SuperVGA方式的显示。

要实现高分辨多色彩图形显示,必须清楚SuperVGA的显示原理。

Windows是目前受人们欢迎的操作系统,位图(.BMP)文件是它图形文件的标准格式,但用户在用TurboC开发图形图像程序时,不能直接取用.BMP位图文件,这不能不说是一件遗憾之事。

下面就针对以上问题提出解决的方法。

这里只讨论256色下的图形显示技术。

1.内存映射关系

TVGA8900卡有512KB和1024KB显示缓冲区1种(512KBVRAM不支持1034X768的256色模式)。

DOS环境从A0000H~BFYFFH共有128KB的存储空间留给显示器,分为64KB的A0000H—久1TFPH和128KB的页方式映射到TVGA的VRAM来实现显示的。

2.寻址技术

要实现SuperVGA的显示,首先是将图形缓冲区中数据送到CPURAM,然后映射到TVGAVRAM中实现。

对于256色模式来说,屏幕上的一点占8位(28=256)1字节,VRAM中的数据从0KBdl024KB,每个字节顺序在对应屏幕中按行逐点对应。

CPURAM只有64KB,而VRAM有1024KB,要使图形数据缓冲区中的数据通过CPURAM和TVGAVRAM建立一一对应关系实现显示,关键是CPURAM如何映射到VRAM。

分析TVGA结构可以得到,TVGA(1024KB)VRAM被分成16个段,每段64KB,通过访问3C4H定序器地址寄存器来实现A0000H~AFFFFH64KB对应于TVGAVRAM不同的段,这样就得到了屏幕上一点(x,y)与CPURAM和TVGAVRAM的寻址关系:

xy=x+y*MAXX(MAXX为每行的最大值)

其中,xy为点(x,y)在VRAM中的线性地址

SEG:

xy/10000H=xy/65536=xy>>16

其中,SEG为点(x,y)在VRAM中的段号。

OFF:

xy&FFFFH

OFF是点(x,y)在VRAM段中的偏移量,即CPURAM中的线性地址

3.设置显示模式

SupervGA的扩充显示模式不像标准vGA只需设置相应的视频方式,它还需要设置页映射方式以及切换视频内存。

(1)设置视频方式

MOVAH,0

MOVAI,MODE;MODE=显示模式

INTl0H

(2)设置页方式,如下为选择64KB方式

MOVDX,3C4H

MOVAL,OBH

OUTDX,AL

INAL,DX

MOVDX,3CEH

MOVAX,506H

OUTDX,AX

(3)切换视频内存

MOVDX,3C4H

MOVAL,0EH

OUTDX,AL

MOVDX,3C5H

INAL,DX

XORAL,2

OUTDX,AL

4.点(x,y)在屏幕上显示

依据前面的分析,可以得到点(x,y)在屏幕上显示过程:

设置显示模式——计算点的线性地址——计算在VRAM中的段号——计算在RAM中的地址及偏移量——建立CPURAM与点在VRAM段的映射——向CPURAM中地址写点(x,y)的颜色值。

TVGA方式下灰度的实现

1.位图BMP文件格式分析

Paintbrush的.BMP位图共有1位、4位、8位、24位(即单色、1

彩色)4种位映像,结构都基本相同,现仅以256色为例说明。

256色.BMP位图文件格式分为三部分:

文件头、调色板和图形数据

①文件头的结构分析

文件头占用位图的前54个字节

1~2字节文件类型标志

4~7字节文件的长度

8~21字节图形的宽度

22~25字节图形的高度

②调色板的结构分析

从55到1078的1024个字节为调色板值,每4个字节为一种颜色的RGB值,依次分别存放B,G,R(O<二B,G,R<二255)的值,

③图形数据结构分析

从1079起为图形数据,每字节存放屏幕上的一个点的颜色值,有两点与屏幕显示不同。

第一、屏幕上图形的第一行对应于位图存储时的最后一行数据,以此类推:

第二、实际存放的每行数据是按16倍数存储的,当图形列数不是16的倍数时,存储时会自动补充为16的倍数存储。

2.灰度在IVGA卡上的实现

有了前面的TVGA显示原理和位图的结构分析,就能实现位图的显示。

有兴趣的读者可以参照上一讲的相关内容去编程实现,这里就不多讲了。

下面给出一个在TVGA卡上实现灰度显示的程序实例。

#include"stdio.h"

#include"dos.h"

#include

#include

#include

#include

unsignedlongpre_cale_y2[480];

typedefunsignedcharbyte;

unionREGSreg;

structSREGSinreg;

typedefstruct

{

bytered;

bytegrn;

byteblu;

}

rgb;

typedefrgbpalette_Register[256];

voidset_palette(palette_Registerhue)

{

reg.x.ax=0x1012;

segread(&inreg);

inreg.es=inreg.ds;

reg.x.bx=0;

reg.x.cx=256;

reg.x.dx=(int)&hue[0];

int86x(0x10,®,®,&inreg);

}

voidinit_palette_2(palette_Registercolor)

{

inti;

for(i=0;i<36;i++)

{

color[i].red=0;

color[i].grn=0;

color[i].blu=(int)(1.8*i+0.5);

}

for(i=36;i<72;i++)

{

color[i].red=0;

color[i].grn=(int)(1.8*(i-36)+0.5);

color[i].blu=0;

}

for(i=72;i<108;i++)

{

color[i].red=0;

color[i].grn=(int)(1.8*(i-72)+0.5);

color[i].blu=(int)(1.8*(i-72)+0.5);

}

for(i=108;i<144;i++)

{

color[i].red=(int)(1.8*(i-108)+0.5);

color[i].grn=0;

color[i].blu=0;

}

for(i=144;i<180;i++)

{

color[i].red=(int)(1.8*(i-144)+0.5);

color[i].grn=0;

color[i].blu=(int)(1.8*(i-144)+0.5);

}

for(i=180;i<216;i++)

{

color[i].red=(int)(1.8*(i-180)+0.5);

color[i].grn=(int)(1.8*(i-180)+0.5);

color[i].blu=0;

}

for(i=216;i<252;i++)

{

color[i].red=(int)(1.8*(i-216)+0.5);

color[i].grn=(int)(1.8*(i-216)+0.5);

color[i].blu=(int)(1.8*(i-216)+0.5);

}

}

voidprecale()

{

unsignedintj;

for(j=0;j<480;j++)

{

pre_cale_y2[j]=640*j;

}

}

voidplot(intx,inty,charcolor)

{

longL_offset;

intoffset,page;

charfar*address;

precale();

if((x<640)&&(y<480))

{

L_offset=pre_cale_y2[y]+x;

page=(L_offset>>16);

offset=L_offset&65535;

outportb(0x3c4,0xe);

outportb(0x3c5,(page&0xf)^0x2);

address=(charfar*)(0xa0000000L+offset);

*address=color;

}

}

voidput_pix(intx,inty,charcolor,charinten)

{

charcol;

col=((35+1)*(color-1)+inten)&255;

plot(x,y,col);

}

main()

{

inti,j;

palette_Registercolor;

precale();

reg.h.ah=0;

reg.h.al=0x13;

int86(0x10,®,®);

init_palette_2(color);

set_palette(color);

for(i=0;i<300;i++)

for(j=0;j<35;j++)

put_pix(i,j,3,j);

getchar();

closegraph();

}

小结

这一讲首先对VGA卡的结构原理作了介绍,然后分析了BIOS中断调用来设置图形方式的方法,最后给出了一个完整的调整图像灰度的程序,这些知识在图像处理编程中是有很大作用的。

讲座到这里,我们对于程序外壳编写的讨论就要告一段落了,我们的后继课程将讨论一些编程技术,主要包括:

中断调用、底层编程技术、鼠标的使用、程序的内存驻留与释放、软件加密算法等。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1