阅读:2220回复:6
急救!哪位专家知道如何通过直接端口操作或VESA中断调用修改显示器刷新批率请不吝赐教,不胜感激!顷囊相增!
由于工作需要,我需要开发一个直接控制显示卡(符合VESA标准)绘图的图形库,万事具备就只差一个控制显示器刷新频率的功能未能实现,致使图形画面闪烁严重,虽然从VESA的官方网站上下载了一个VBE3.0标准,但是E文水平有限不能完全理解其精髓致使该功能一直无法实现,真是头疼!如果有那位仁兄有这方面的编程经验或能提供一些中文资料本人将不胜感激,若能实现本功能,本人将会把所有的可用分顷囊相增!拜托!拜托!
|
|
沙发#
发布于:2004-10-30 22:22
参考一下
《最新VESA SVGA 图形图像编程秘技》应该对你有帮助 |
|
|
板凳#
发布于:2004-10-31 02:09
先谢了,不过哪能找到这本书呢?最好是电子版的,我去过好几个大书店,都没有,麻烦帮忙找一下啦,非常感谢。
|
|
地板#
发布于:2004-11-10 20:52
先谢了,不过哪能找到这本书呢?最好是电子版的,我去过好几个大书店,都没有,麻烦帮忙找一下啦,非常感谢。 直接看VBE就好了。昨天发邮件给你了。摘抄一段: 今天抽空看了一下VESA BIOS EXTENSION (VBE) Core Functions Standard, 发现里面确实有设置Refresh rate的地方。我的笔记本没办法调试,把大致的想法和你说一下,你先看一下,有问题欢迎讨论。 1. 在Funciton 02h - Set VBE Mode的描述如下: Input: AX = 4F02h Set VBE Mode BX = Desired Mode to set D0-D8 = Mode number D9-D10 = Reserved (must be 0) D11 = 0 Use current default refresh rate = 1 Use user specified CRTC values for refresh rate D12-13 Reserved for VBE/AF (must be 0) D14 = 0 Use windowed frame buffer model = 1 Use linear/flat frame buffer model D15 = 0 Clear display memory = 1 Don't clear display memory ES:DI = Pointer to CRTCInfoBlock structure Output: AX = VBE Return Status 实际上如果在DOS下想得到高的图像品质,一定会调用这个Function的。比如我以前做的DOS下SVGA显示,800*600*16bit色的初始化程序片断如下: // Init to 800*600*16bit graphics mode: union REGS in, out; iMode=0x114; in.x.bx=iMode; in.x.ax=0x4F02; int86(0x10,&in,&out); 在这个程序片断中,bx=0x114 0000 0001 0001 0100 如果把D15改成1,就可以用ES:DI指向的结构里的一个元素来更改refresh rate了。 CRTCInfoBlock struc HorizontalTotal dw ? ; Horizontal total in pixels HorizontalSyncStart dw ? ; Horizontal sync start in pixels HorizontalSyncEnd dw ? ; Horizontal sync end in pixels VerticalTotal dw ? ; Vertical total in lines VerticalSyncStart dw ? ; Vertical sync start in lines VerticalSyncEnd dw ? ; Vertical sync end in lines Flags db ? ; Flags (Interlaced, Double Scan etc) PixelClock dd ? ; Pixel clock in units of Hz RefreshRate dw ? ; Refresh rate in units of 0.01 Hz Reserved db 40 dup (?) ; remainder of ModeInfoBlock CRTCInfoBlock ends Attatched please find the VBE pdf file, and the cpp file for example. I believe you'd already get these files, and maybe you should modify the initial graph part, then try it. |
|
|
地下室#
发布于:2004-11-12 14:50
搞定了。还真有点难,花了俺大概5个Hour...好久没编程了(最近都是让手下编),忽然自己编,有点累哦。 :D
问题的关键是,VBE上有些事没有说清楚。建议先去搞清楚屏幕上几种显示的关系(HTotal / HSyncStart / HSyncEnd / VTotal / VSyncStart / VSyncEnd), http://www.hut.fi/Misc/Electronics/faq/vga2rgb/timings.html 然后再去这里算一下你相应的分辩率与更新率下的相应数字, http://www.hut.fi/Misc/Electronics/faq/vga2rgb/calc.html 就可以开工了。 例子程序中的关键代码及注释: // SuperVGA CRTCInfoBlock structure struct { short HTotal; short HSyncStart; short HSyncEnd; short VTotal; short VSyncStart; short VSyncEnd; char Flags; long PixelClock; short RefreshRate; char Reserved[40]; } CRTCInfoBlock; 很简单,就是按VBE中所说的做了个结构。 void setVBEMode(int mode) { union REGS in,out; struct SREGS segs; char far *CRTCInfo; in.x.ax = 0x4F02; //in.x.bx = mode; in.x.bx = 0x905; // --------------------- Note 1 // 1024*768 @ 70Hz CRTCInfoBlock.HTotal=1328; CRTCInfoBlock.HSyncStart=1048; CRTCInfoBlock.HSyncEnd=1184; CRTCInfoBlock.VTotal=806; CRTCInfoBlock.VSyncStart=771; CRTCInfoBlock.VSyncEnd=777; CRTCInfoBlock.Flags=0xa; // -------------- Note 2 CRTCInfoBlock.PixelClock=75000000; CRTCInfoBlock.RefreshRate=70.07; CRTCInfo = (char far *)&CRTCInfoBlock; // ----------------------------------------- Note 3 in.x.di = FP_OFF(CRTCInfo); segs.es = FP_SEG(CRTCInfo); int86x(0x10, &in, &out, &segs); //int86(0x10,&in,&out); } Note 1: 我跟踪调试,如果不自己设置Refresh rate,这里imode=0x105 ==> 0000 0001 0000 0101 简单地将D11置1,变成: 0000 1001 0000 0101 ==> 0x905。实际上可以支持1024*768*16bit色的(0x917),但是这个例程中的显示会不正常。要直接改imode,懒得改了。你自己试吧。 Note 2: 网页版的计算工具无法设置Sync Polarity的+/-,一律用-的。 1100 ==> 0xa Note 3: 以上数据用网页版计算工具算得。 测试: HW: Pentium M 1.6G, 512MB RAM, Build-in display SW:DOS 6.22, Borland C++ 3.1 结果: 在我的测试机上,可以用到1024*768@60Hz, 1024*768@70Hz, 当设到1024*768@75Hz时,显示器报错:超出同步范围。 [编辑 - 11/12/04 by grant] [编辑 - 11/12/04 by grant] |
|
|
5楼#
发布于:2004-11-12 15:32
将例子程序传上来。
实际上就是VBE中附的例子,我改了初始化图形的部分。 |
|
|
6楼#
发布于:2004-11-12 15:36
再发一个计算GTF参数的C源程序。
原来是Linux下的,我改了一下,在DOS下也可以用。 已测试过它算的数据,是可以用的。 |
|
|