怎样在DOS平台下置取调色板


  说实话,在DOS平台下置取调色板可要比在Windows平台下简单多了,而且置了之后决对正确,不会出现象DirectDraw那样置了还未必起作用的情况。

  好了,言归正传,我来详细讲述一下置调色板的办法。对于读调色板就不再介绍了,因为每一个优秀的C/C++程序员都不会笨到去读取调色板。调色板是什么样的,随时都掌握在他们的程序中,要什么调色板就设置成什么样的,从来不去读调色板。

  在编程前,我想请您最好去读一下《在任意平台下读取BMP文件》,里面讲解了uvar8、uvar16这些变量类型的由来,否则你会很难看懂我的程序的。

  假设我们对调色板的定义如下:

uvar8 Palette[256][3];

  uvar8表示8位无符号变量,表示范围是0-255。Palette变量中有256种颜色,以Palette[颜色号]来表示。每个颜色中均保存红、绿、蓝三原色的值。Palette[0][0]就表示第0种颜色的红色值,同样Palette[0][1]就表示第0种颜色的绿色值。

  在DOS平台下,设置调色板的办法是多种多样的,以下我将逐一介绍:


方法一:16位DOS平台下,调用中断进行设置

  由于16位DOS平台下,主流编程工具Borland C/C++与Turbo C/C++只支持16色,所以显得很无用。所以我们只好自己调用中断进行设置了,源程序如下:

void SetPalette(uvar8 pal[256][3])
{
 union REGS r;
 struct SREGS s;
 r.h.ah=0x10;
 r.h.al=0x12;
 r.x.bx=0;
 r.x.cx=256;
 s.es=FP_SEG(pal);
 r.x.dx=FP_OFF(pal);
 int86x(0x10,&r,&r,&s);
}


方法二:16位DOS平台下,直接写DAC进行设置

  相比之下,在16位DOS平台下,置调色板最快的手法莫过于直接写DAC了,源程序如下:

void SetDac(uvar8 idx,uvar8 red,uvar8 green,uvar8 blue)
{
asm {
    mov dx,3c8h
    mov al,idx
    out dx,al

    mov cl,2
    inc dx
    mov al,red
    shr al,cl
    out dx,al
    mov al,green
    shr al,cl
    out dx,al
    mov al,blue
    shr al,cl
    out dx,al
    }
}

void SetPalette(uvar8 pal[256][3])
{
 for(uvar16 i=0;i<256;i++)SetDac(i,pal[i][0],pal[i][1],pal[i][2]);
}

  不要问我那倒数第二行为什么要用uvar16来定义i,而不用uvar8,您自己试一下就知道了。


方法三:32位DOS平台下,使用Watcom C/C++编程时直接使用其图形函数进行设置

  Watcom C/C++不愧为优秀的32位DOS平台开发工具,它的图形函数直接用来编游戏都没问题,所以速度上也绝对慢不了。源程序如下:

void SetPalette(uvar8 pal[256][3])
{
 uvar32 pal256[256];
 uvar16 i;
 for(i=0;i<256;i++)pal256[i]=pal[i][2]/4*0x10000+pal[i][1]/4*0x100+pal[i][0]/4;
 _remapallpalette(&pal256);
}
  当然,这个程序还未做过优化,留着您自己优化吧!这里我只讲怎么设置调色板。


方法四:32位DOS平台下,调用中断进行设置

  不过是方法一的16位转32位吧了,没什么大的变化,源程序如下:

void SetPalette(uvar8 pal[256][3])
{
 union REGS r;
 struct SREGS s;
 r.h.ah=0x10;
 r.h.al=0x12;
 r.w.bx=0;
 r.w.cx=256;
 s.es=FP_SEG(pal);
 r.x.dx=FP_OFF(pal);
 int386x(0x10,&r,&r,&s);
}


  当然,32位DOS环境也可以直接写DAC以便取得最快的速度,但是32位DOS下的汇编程序是很难写的(其实不难,只不过写出来很长),所以我就偷懒不写了,反正以上四种方法也够用了。