因为一些特殊的原因
需要在 DOS 环境下作些图形界面的应用
作图形界面当然没有问题
但是一直以来都没有能解决的问题就是:
在DOS中设置了屏幕的高分辨率图形模式后 怎样能调整显示器的刷新率避免画面的细小抖动现在最便宜的17"CRT也能上到85Hz左右  看起来没有闪烁  就是要这个效果以前也提过  没解决  看看现在有办法没有

解决方案 »

  1.   

    我刚见过这个问题,现在再回答一次,希望对你有所帮助。
    我在学习TC时也曾经寻求提高屏幕刷新率,但最后得出这样的结果:屏幕刷新率由操作系统控制。DOS操作系统没有该项功能,TC又不能调用WINDOWS的32位API函数,因此,TC不可能改变屏幕刷新率。建议你不要在这方面浪费太多时间。不过,DOS程序真的需要改变刷新率吗?如果你对屏幕界面感兴趣,你可以转入WINDOWS编程呀,这里有更多的界面等你学。
      

  2.   

    google: univbe vesahttp://www.gameprogrammer.com/1-vbe.html
      

  3.   

    Reply ggg82():感谢老兄的善意提醒不过我的确是需要在DOS下更改刷新率我想这个要求并不算过份老兄说这是由OS提供的功能在DOS下无法实现云云我想说句不礼貌的话其实是老兄你没搞清楚软件和硬件的真正关系很简单的一个道理:OS 也是一个软件系统  所以OS能提供的功能自己实际理论上是绝对可能的以前我曾通过I/O硬件端口来试过  在一些14" CRT上成功了  但通用性太差
    however 还是要感谢老兄关心  谢谢!
      

  4.   

    通过设置显卡的扫描寄存器时可以做到的。我上大学的时候做过,6、7年前了。我记得有一本叫显卡手册之类的工具书,暗红色硬质封面,大开本的。基本上参照当时的Trident 8900还是9600显卡(记不太清了),对SVGA显卡作了极为详尽的分析,其中就有设置场频和行频的寄存器,但那个时候的显示器最高的场频也就60,我还没资格见到,我的印象中好像那些寄存器也不能表示很高的频率。对于现在的显卡我不了解,就我遇到的,全部是向下兼容SVGA的。准确的情况还是需要查特定显卡的手册才行吧。
      

  5.   

    感谢各位关注本问题,现在我找到了些资料,大约知道该怎样做了:支持VBE2.0以上的显卡  在INT10 AX=4F02h 调用设置显示模式时
    能过设置BX中的D11=1可以使用自定义的CRTC设置
    在CRTC结构中可以设置Refresh-Rate
    我想这就是我要的但是现在又有个问题:
    我在DOS下面用的是WATCOM C++ 11.0
    我不知道该怎样把CRTC结构的地址传到 ES:DI 中
    用传统的FP_SEG和FP_OFF会失败这应该是个小问题  望大家帮忙!!
      

  6.   

    用嵌入式汇编好了,这不是什么问题吧?不知道你的WATCOM C++ 11.0支不支持嵌入式汇编?
      

  7.   

    当然支持  不过我不知道怎么把结构地址传入
    比如:struct CRTC info;//...设置info的内容// 设置显示模式的伪代码
    ax = 0x4F02
    bx = 0x800 + DevMode.ModeNum;这里 es:di 需要指向 &info  该怎么传过去呢
      

  8.   

    对于你的WATCOM C++ 11.0,我实在是一无所知。
    一般来说,只有16位的情况下,我们才考虑段寄存器,因为linux/UNIX 和Windows 32位操作系统都是线形编址的。首先,确定你的info所在的位置,是用DS,ES或是SS来定段的,假定是DS(反正可以通过自己写例子来判断)。可不可以这样写:
    push es;
    push ds;
    pop es;
    ...其他语句pop es;
    这里面要注意,别动乱了BP的值。
    8086下ES:DI实际上就是一个far pointer。TC下有个huge指针,千万不能用那样的指针,他会经常调整段地址。如果你的内存寻址被你设置成了32位,问题会比较复杂了。不过如果有人能够这么做,你可以问他,也不用我在这里罗里罗嗦了。
      

  9.   

    再给大家点提示:实模式中的VRAM指针为 0xA0000000
    即 A000:0000通过转换  在保护模式中应为 0xA0000但是我并不知道具体的计算方法:(知道计算方法的话  是不是就能把结构的地址转换为实模式中可用的地址呢?
    转换后  又怎样能把此地址分解为seg:off这样的方式以传入 es:di呢?(早知今日 当初就该学学ASM)
      

  10.   

    我在DOS下面用的是WATCOM C++ 11.0
    我不知道该怎样把CRTC结构的地址传到 ES:DI 中
    用传统的FP_SEG和FP_OFF会失败
    ???
    我觉得不要使用结构体传值,改为使用 char 数组来传值就行了
      

  11.   

    我的一段代码( BC3.1 控制 Mouse )
    unsigned int far part[]=
    {0xffff,0xffff,0xffff,0xffff,
     0xffff,0xffff,0xffff,0xffff,
     0xffff,0xffff,0xffff,0xffff,
     0xffff,0xffff,0xffff,0xffff,
     0x0000,0x4000,0x6000,0x7000,
     0x7800,0x7c00,0x7e00,0x7f00,
     0x7f80,0x7fc0,0x6c00,0x4600,
     0x0600,0x0300,0x0300,0x0180
    };
    void grpcursor(int x,int y)
    {
     union REGS ireg;
     struct SREGS isreg;
     ireg.x.ax=9;
     ireg.x.bx=x;
     ireg.x.cx=y;
     ireg.x.dx=FP_OFF(part);
     isreg.es=FP_OFF(part);
    }
      

  12.   

    哦,写错了
    改用 short int 数组来传值
      

  13.   

    Behard(我爱天安门) :那我试试看吧
    另:你用 BC3.1 做的这段是实模式还是保护模式?由于要用到 ES:DI
    而在 WATCOM C++ 里有 ES DI 的只有 union REGPACK
    而使用 RAGPACK 的函数只有 intr( int intno, union REGPACK regs );
    而我一调用 intr() 就会出错退出
    真是苦恼
    也试过 inline asm  还是没搞对
    头痛。。
    另另:
    关于设置刷新率我找到些资料  了解了大概的方法  不过是英文的
    如果哪位有兴趣愿意帮忙看看就太好了  不多  就一小段  可惜我看不明白 :([email protected]
      

  14.   

    我没有仔细看过
    不过 BC3.1 的例子是这样的
    #include <stdio.h>
    #include <string.h>
    #include <dir.h>
    #include <dos.h>#define CF 1  /* Carry flag */int main(void)
    {
       char directory[80];
       struct REGPACK reg;   printf("Enter directory to change to: ");
       gets(directory);
       reg.r_ax = 0x3B << 8;         /* shift 3Bh into  AH */
       reg.r_dx = FP_OFF(directory);
       reg.r_ds = FP_SEG(directory);
       intr(0x21, &reg);
       if (reg.r_flags & CF)
          printf("Directory change failed\n");
       getcwd(directory, 80);
       printf("The current directory is: %s\n", directory);
       return 0;
    }
      

  15.   

    参考 VBE 3.0(VESA's VBE Standard 3.0 )手册。可以通过调用BOIS中断设置所有的显卡(SVGA)支持的刷新率。下载地址:http://www.vesa.org/vbe3.pdf
      

  16.   

    AthlonxpX86(一滴水) :Ok 
     gavin1980x(远超):我早就有这个PDF文件了。也许你误解了我的意思我现在的麻烦是:怎样在保护模式里调用实模式实中断的问题。。因为调整refresh rate要用到 int 10h, AX=4F02h...这的确是VBE 3.0up才有的功能但是调用要求在 ES:DI 传入 CRTCInfoBlock 结构地址我不知道该怎样在保护模式中传入此地址或者说不知道怎样在保护模式中Call实模式中断也许要用到 INT 34H 的 DPMI 调用?请指教
      

  17.   

    用LES DI,xxx不就行了吗,这条指令就是用来在16位环境下加载一个地址的啊
      

  18.   

    ----------------------------------------------------------各位:关于传递地址的问题现已解决  是用到的DPMI调用
    我在另一贴中已经作了说明并已结贴此贴主要讨论内容是“怎样调整刷新率”现在调用没有问题了就剩下怎样确定刷新率了我说了关于调整的方法我有资料  下面我把核心部份贴出来
    希望大家帮忙弄明白:
      

  19.   

    Function 02h - Set VBE ModeInput: 
    AX = 4F02h Set VBE Mode
    BX = Desired Mode to setBX:
    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 structureOutput: AX = VBE Return StatusNote: All other registers are preserved.////This required function initializes the controller and sets a VBE mode. The format of VESA VBE
    mode numbers is described earlier in this document. If the mode cannot be set, the BIOS should
    leave the graphics environment unchanged and return a failure error code.
    If the requested mode number is not available, then the call will fail, returning AH=01h to indicate
    the failure to the application.
    If bit D11 is set, the mode will be using the CRTC parameters and pixel clock values passed in the
    CRTCInfoBlock structure, rather than using the default values that the BIOS is currently
    configured for. This allows the application program or operating system drivers to calculate a new
    set of CRTC values (preferably using the VESA Generalized Timing Formula (GTF)
    specification) for the mode, and allow the refresh rate to be set to any supported value for the
    hardware. If bit D11 is not set, the values passed in ES:DI will be ignored.
    If bit D14 is set, the mode will be initialized for use with a flat frame buffer model. The base
    address of the frame buffer can be determined from the extended mode information returned by
    VBE Function 01h. If D14 is set, and a linear frame buffer model is not available then the call will
    fail.
    If bit D15 is not set, all reported image pages, based on Function 00h returned information
    NumberOfImagePages, will be cleared to 00h in graphics mode, and 20 07 in text mode. Memory
    over and above the reported image pages will not be changed. If bit D15 is set, then the contents
    of the frame buffer after the mode change is undefined. Note, the 1-byte mode numbers used in
    Function 00h of an IBM VGA compatible BIOS use D7 to signify the same thing as D15 does in
    this function. If bit D7 is set and the application assumes it is similar to the IBM compatible mode
    set using VBE Function 02h, the implementation will fail. VBE aware applications must use the
    memory clear bit in D15.
      

  20.   

    算了  资料太多了没办法贴出来主要问题在于怎样确定并计算出新的刷新率与此相关的内容及公式如下:
    The PixelClock field defines the normalized pixel clock that will be programmed into the
    hardware. This value is represented in a 32 bit dword in units of Hz. For example to represent a
    pixel clock of 25.18Mhz one would code a value of 25,180,000. Note that this is the normalized
    pixel clock that will be programmed, not a physical pixel clock and does not include any scaling
    factors for the mode in question. If the hardware needs the pixel clock to be scaled from the
    normalized value this will be done by the VBE implementation internally. The normalized pixel
    clock is necessary in order to be able to calculate the refresh rate for the specific graphics mode
    using the following formula:refreshRate = PixelClock / HorizontalTotal * VerticalTotal  // 刷新率计算公式For example a 1024x768 mode with a HTotal of 1360, VTotal of 802, a normalized pixel clock of 75Mhz might be computed as follows:refreshRate Hz = 65 000 000 / 1360 * 802 = 59.59Hz  // 这里的三个参数不知道怎样算出来的
    The RefreshRate field defines the refresh rate that the CRTC table defines. This value may not
    actually be used by the BIOS but must be calculated by the application program using the above
    formulas before initializing the mode. This entry may be used by the BIOS to identify any special
    cases that may need to be handled when setting the mode for specific refresh rates. The value in
    this field should be represented in units if .01 Hz (ie: a value 7200 represents a refresh rate of
    72.00Hz).
      

  21.   

    刷新率的计算是这样的,显示器一般都有一个最大数据传输频带参数,一般是60-150MHz,现在17寸显示器一般都在110Mhz以上,如果显卡输出的信号频带超出这个最大值就会烧坏显示器,通频带=刷新率*水平扫描频率*垂直扫描频率,但有些扫描线是不可见的,所以1024x768实际上的扫描频率可能是1360 * 802 ,现在给出最大通频带比如110Mhz那么1024x768理论上最大刷新率就是110 000 000/1024x768=140HZ 但实际最大刷新率就是110 000 000/1360 * 802 =100.85Hz
      

  22.   


    AthlonxpX86(一滴水):那么要怎样才能确定显示器刷新率的合法上下限呢
    或者说要怎样才能计算出特定分辨率下的最大刷新率呢
      

  23.   

    AthlonxpX86(一滴水):“...所以1024x768实际上的扫描频率可能是1360 * 802 ,现在给出最大通频带比如110Mhz那么1024x768理论上最大刷新率就是110 000 000/1024x768=140HZ 但实际最大刷新率就是110 000 000/1360 * 802 =100.85Hz”这里的1360和802是怎么得来的?