VESA编程介绍 (4):扩展的VGA BIOS续及应用举例
---------------------------------------------------------------------------------
相关章节:
(1): 标准VGA BIOS及超级VGA模式号
(2):CPU显存控制
(3):扩展的VGA BIOS
(4): 扩展的VGA BIOS(续)及应用举例
---------------------------------------------------------------------------------
6-6、04h-保存/恢复超级VGA状态
该函数提供了保存和恢复超级VGA显示状态的机制。该函数是标准VGA BIOS函数1Ch(保存/恢复显示状态)的三个子函数的超集。完整的超级VGA状态(除了显存)可通过设置请求状态遮盖(于CX寄存器)为000Fh来保存和恢复。
输入:AH = 4Fh 超级VGA支持
AL = 04h 保存/恢复超级VGA显示状态
DL = 00h 返回保存/恢复状态缓冲区大小
CX = 请求状态
D0 = 保存/恢复显示硬件状态
D1 = 保存/恢复显示BIOS数据状态
D2 = 保存/恢复显示DAC状态
D3 = 保存/恢复超级VGA状态
输出:AX = 状态
BX = 状态缓冲区内64字节块的块数
(其它寄存器保持不变)
输入:AH = 4Fh 超级VGA支持
AL = 04h 保存/恢复超级VGA显示状态
DL = 01h 保存超级VGA状态
CX = 请求状态(同上)
ES:BX = 缓冲区指针
输出:AX = 状态
(其它寄存器保持不变)
输入:AH = 4Fh 超级VGA支持
AL = 04h 保存/恢复超级VGA显示状态
DL = 02h 恢复超级VGA状态
CX = 请求状态(同上)
ES:BX = 缓冲区指针
输出:AX = 状态
(其它寄存器保持不变)
注意:
基于对VGA环境完全兼容的目标,标准VGA BIOS函数1Ch(保存/恢复VGA状态)没有被扩展为保存超级VGA显示状态。VGA BIOS兼容性需要函数1Ch返回一个有特定目录的特定缓冲区大小,其目录中以没有空间放下超级VGA状态了。
6-7、05h-超级VGA视频存储器窗口控制(设置BANK)
该函数设置或获得指定窗口在显存中的位置。函数允许对硬件页寄存器的直接访问。为了更好地使用此函数,程序应使用VESA BIOS函数01h(返回超级VGA模式信息)来决定窗口的大小、位置和间隔尺寸。
输入:AH = 4Fh 超级VGA支持
AL = 05h 超级VGA显存窗口控制
BH = 00h 选择超级VGA显存窗口
BL = 窗口号
0 = 窗口A
1 = 窗口B
DX = 窗口在显存中的位置(以窗口间隔尺寸为单位)
输出:AX = 状态
(见下面注释)
输入:AH = 4Fh 超级VGA支持
AL = 05h 超级VGA显存窗口控制
BH = 01h 返回超级VGA显存窗口
BL = 窗口号
0 = 窗口A
1 = 窗口B
输出:AX =状态
DX = 窗口在显存中的位置(以窗口间隔尺寸为单位)
(见如下注释)
注释:
该函数也能通过远程调用由程序直接访问。BIOS函数地址能通过VESA BIOS函数01h(返回超级VGA信息)获得。模式信息块中包含有此函数地址。注意在每一次BIOS执行时函数地址都会不同,所以应在每次设置模式后获取函数指针。
如果是远程调用的话,没有状态信息会被返回给程序。同时,AX和DX寄存器将遭破坏。因此,若AX、DX寄存器值需保留,应在远程调用前事先作准备。
若要作远程调用,程序必须在BH、BL和DX(对于设置窗口)中装入参数,但不必装入AH和AL。
6-8、06h-设置/获取逻辑扫描线长度
该函数设置或获得逻辑扫描线长度。函数允许程序建立大于显示区域的逻辑显存缓冲区。然后函数07h就能允许程序设置开始显示的位置。
输入:AH = 4Fh 超级VGA支持
AL = 06h 逻辑扫描线长度
BL = 00h 选择扫描线长度
CX = 想要的宽度(用像素表示)
输出:AX =状态
BX =每扫描线字节数
CX =每扫描线实际像素
DX =最大扫描线数
输入:AH = 4Fh 超级VGA支持
AL = 06h 逻辑扫描线长度
BL = 01h 返回扫描线长度
输出:AX =状态
BX =每扫描线字节数
CX =每扫描线实际像素
DX =最大扫描线数
注意:
所需要的按像素表示的宽度可能因为VGA硬件情况的原因而不能实现。下一个提供所需像素数的更大的值将被选中,而实际的像素数被返回到CX。当加到显存中的指针时,BX返回指向下一条扫描线的指针值。比如:在模式13,此值为320,但在模式12为80。DX返回基于新扫描线长度和装载的并在该模式下可用的总内存之上的逻辑扫描线数。此函数在文本方式下仍有效。在文本模式下,程序应通过BIOS函数找到当前字符单元宽度,并乘以每行想要的字符数,将结果送至CX寄存器。
6-9、07h-设置/获取显示起点
该函数从逻辑页中选出将在左上角显示的像素点。该函数能用来平移或卷动比显示屏幕更大的逻辑屏幕。它也能在两个不同的显示屏幕间快速切换从而获得双缓冲的动画效果。
输入:AH = 4Fh 超级VGA支持
AL = 07h 显示起点控制
BH = 00h 保留,必须为0
BL = 00h 选择显示起点
CX = 扫描线中第一像素点
DX = 第一根扫描线
输出:AX = 状态
输入:AH = 4Fh 超级VGA支持
AL = 07h 显示起点控制
BL = 01h 返回显示起点
输出:AX = 状态
BH = 00h 保留为0
CX = 扫描线中第一像素点
DX = 第一根扫描线
注意:
此函数在文本模式下仍有效。在文本模式中,程序可以通过BIOS函数获得当前字符单元宽度,再乘以希望开始的字符列数,并将此值送至CX寄存器。同样地,将字符高度乘以所需行数并送至DX寄存器。
6-10、08h-设置/获取DAC调色板控制
该函数查询并选择DAC调色板的操作模式。一些DAC提供可选择的6-位、8-位或是更多的RGB色彩成分定义。在标准或是VESA设置超级VGA模式(AX = 4F02h)调用时被默认地重设为每色6-位。
输入:AH = 4Fh 超级VGA支持
AL = 08h 设置/获取DAC调色板控制
BL = 00h 设置调色板宽度
BH = 所需的色彩位数(标准的VGA为6)
输出:AX = 状态
BH = 当前的色彩位数(标准的VGA为6)
输入:AH = 4Fh 超级VGA支持
AL = 08h 设置/获取DAC调色板控制
BL = 01h 获得DAC调色板宽度
输出:AX = 状态
BH = 当前的色彩位数(标准的VGA为6)
注意:
程序能通过查询由VESA返回超级VGA信息函数(AX
=
4F00h)所返回的VGA信息块中兼容性字段的D0位来获知DAC是否可变换。然后程序才能尝试将DAC调色板设置为所需的宽度。如果VGA不能使用请求的调色板宽度,则会选中低一点的超级VGA能使用的值。将最终的调色板宽度返回。
7、应用举例
以下依次说明程序如何与VESA BIOS扩展接口。假设程序已了解了VESA并调用了VESA BIOS函数。但程序并不是仅仅能支持VESA定义的显示模式。所以在设置显示模式之前先要查询有那些显示模式可用。
1、程序首先分配一个256字节的缓冲区。该区域用来存放由VESA BIOS返回的视频环境信息。一些程序需要静态分配空间,而另一些则可通过系统调用动态地获得临时缓冲。
2、程序然后调用VESA BIOS函数00h(返回超级VGA信息)。如果函数调用返回后AX寄存器的值不是004Fh,则程序可确定VESA BIOS不存在。若AX中没有任何错误码,则函数调用成功。缓冲区以被VESA BIOS扩展填满了各种各样的信息。程序能通过判断信息块首部的字符是否为‘VESA’来确定这是否为有效的VESA信息块。程序还可侦测VESA版本字段来了解VESA BIOS扩展是否有足够的函数。程序也可通过OEM串来定位OEM特定信息。
最后,程序能用显示模式指针来获得超级VGA所支持的显示模式列表。
3、然后程序创建一个新的缓冲区并调用VESA
BIOS函数01h(返回超级VGA模式信息)来获得所支持的显示模式的详细信息。利用第二步获得的显示模式指针,程序以新的模式号为参数调用此函数,直到找到一个合适的显示模式。如果没有合适的,则程序有权放弃。返回超级VGA模式信息的函数将一个程序指定的缓冲区填充为描述显示模式细节的信息。数据块包含了程序所能利用的显示模式的所有优点。程序应检查模式属性字段,来确定模式是否被支持。即检查D0位,如果D0位被清除,那么模式并不被硬件所支持。这种情况在需要一种特殊的显示器或是显示器不在的情况下可能发生。
4、程序选中一个显示模式后,下一步就是初始化。但是程序首先要保存现有的显示模式。只要程序还在,该模式就能被恢复。为获得现有的显示模式,可以使用VESA
BIOS函数03h(获得超级VGA模式)。如果当前模式并非VESA(标准VGA或OEM指定),则填充模式号的低字节而保留高字节。
5、要初始化显示模式,程序要使用VESA BIOS函数02h(设置超级VGA显示模式)。从此程序就能完全访问VGA硬件和显存了。
6、当程序要结束的时候,应恢复先前的显示状态。即利用第四步获得的先前的模式号,按第五步的方法设置显示模式。然后退出程序。