存档在 ‘DOS’ 分类

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

2009年11月5日

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

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

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

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下的汇编程序是很难写的(其实不难,只不过写出来很长),所以我就偷懒不写了,反正以上四种方法也够用了。

XMS的使用

2009年11月5日

本来我是不准备写这篇文章的,但冷不妨有位同仁问起,也只好做个回答,顺便借此更新一下网页。

XMS,扩充内存管理规范。在16bit DOS系统下,为了使用640k以外的内存,XMS成了一种最好的手法。

在这里,我不想多讲XMS的实现,只对本文所提供的XMS类做一下使用讲解。

例子可以说明一切:

#include”XMS.H”
void main()
{
FILE *fp;
int i;
char *str;
XMS xms1(1024);                //为xms1指针分配1024k的内存
fp=fopen(“C:\\WIN\\WIN386.SWP”,”rb”);
str=(char *)malloc(1024);
for(i=0;i<1024;i++)
{
fread(str,1,1024,fp);
xms1.put((void *)str,(void *)(i*1024),1024);
//将内存指针str中的1024个字节的内容写到,xms1的第i*1024个字节处
}
fclose(fp);
fp=fopen(“WIN386.SWP”,”wb”);
for(i=0;i<1024;i++)
{
xms1.get((void *)str,(void *)(i*1024),1024);
//将扩充内存xms1中,从第i*1024个字节处开始的1024个字节的内容写到str中
fwrite(str,1,1024,fp);
}
fclose(fp);
}

XMS.H

#if !defined XMS_H
#define XMS_H

class XMS {
int handle;
int move(struct EMB *emb);
public:
XMS(int size);
~XMS();
static int OK;
static int init(void);
static unsigned freesize(void);
static unsigned largestblock(void);
int realloc(int size);
int put(void *dp,void *sp,long leng);
int get(void *dp,void *sp,long leng);
};

#endif

XMS.CPP

#include <dos.h>
#include <alloc.h>

#include “xms.h”

struct EMB {
long Leng;
unsigned SourceHandle;
long SourceOfs;
unsigned DestinHandle;
long DestinOfs;
};

int XMS::OK=0;
static void far *XMSaddr;

int XMS::init(void)
{
static struct REGPACK rg;

rg.r_ax=0x4300;
intr(0x2f,&rg);
if( (rg.r_ax&0x00ff) == 0x80 )
{
rg.r_ax=0x4310;
intr(0x2f,&rg);
XMSaddr=MK_FP(rg.r_es,rg.r_bx);
OK=1;
}
else
OK=0;
return(OK);
}

unsigned XMS::freesize(void)
{
if(OK==0)
return(0);
asm {
mov ah,8
call XMSaddr
}
return _DX;
}

unsigned XMS::largestblock(void)
{
if(OK==0)
return(0);
asm {
mov ah,8
call XMSaddr
}
return _AX;
}

XMS::XMS(int size)
{
if(OK==0)
{
handle=0;
return;
}

asm {
mov ah,9
mov dx,size
call XMSaddr
}
handle=_DX;
}

XMS::~XMS()
{
if(handle==0)
return;

int hd=handle;
asm {
mov ah,0ah
mov dx,hd
call XMSaddr
}
}

int XMS::realloc(int size)
{
if(handle==0)
return(0);

int hd=handle;
asm {
mov ah,0fh
mov bx,size
mov dx,hd
call XMSaddr
}
return _AX;
}

int XMS::move(struct EMB *emb)
{
asm {
push ds
mov ah,0bh
push ds
pop es
lds si,emb
call es:XMSaddr
pop ds
}
return _AX;
}

int XMS::put(void *sp,void *dp,long leng)
{
struct EMB emb;

if(leng&1L)
leng++;
emb.Leng=leng;
emb.SourceHandle=0;
emb.SourceOfs=(long)sp;
emb.DestinHandle=handle;
emb.DestinOfs=(long)dp;
return move(&emb);
}

int XMS::get(void *dp,void *sp,long leng)
{
int v;
struct EMB emb;

if(leng&1L)
{
char *p,*d;

leng–;
if( leng>0 )
{
emb.Leng=leng;
emb.SourceHandle=handle;
emb.SourceOfs=(long)sp;
emb.DestinHandle=0;
emb.DestinOfs=(long)dp;
move(&emb);
}

p=(char *)malloc(2);
emb.Leng=2L;
emb.SourceHandle=handle;
emb.SourceOfs=(long)sp+leng;
emb.DestinHandle=0;
emb.DestinOfs=(long)p;
v=move(&emb);
d=(char*)dp;
d[leng]=p[0];
free(p);
}
else
{
emb.Leng=leng;
emb.SourceHandle=handle;
emb.SourceOfs=(long)sp;
emb.DestinHandle=0;
emb.DestinOfs=(long)dp;
v=move(&emb);
}
return(v);
}