注册 登录
编程论坛 C图形专区

关于NEO在486上运行的问题

beyondabcd 发布于 2007-06-09 18:51, 3816 次点击
我使用neo在pc104(相当于486),用tc编译不了呀,内存不够,在我的计算上编译过去了,也可运行,但放到pc104上运行没反应呀,这是怎么回事?
46 回复
#2
一笔苍穹2007-06-13 14:32
使用NEO,机器要满足一些基本条件:X86架构,640KB的常规内存,支持VESA的VBE标准(独立或集成)显卡。
#3
beyondabcd2007-06-13 19:11
我在问你一,我下载你的NEO后,为什么你那带的例子,在486上可以运行,而我把你的.c编译后的确在486上运行不了呢?(运行后没反应)
#4
beyondabcd2007-06-13 19:13
还有你那些现成的.exe例子,在486上有的能运行有的不能运行呀,有的运行后死机了
#5
beyondabcd2007-06-13 19:22
对了,你这些条件它都满足,只是在那个486运行下,总说 out of memory in funtion main(内存不够)的意思呀?
#6
一笔苍穹2007-06-15 11:10
恩,你可能没注意到,我提供的EXE文件比你编译出来的要小很多。
我编译的时候在#include<neo.h>之前用上了许多编译开关(宏),这些宏可以关闭编译器对你不需要的部分NEO功能,以减小程序体积。具体有哪些宏请参考NEO的用户文档。
#7
beyondabcd2007-06-16 18:23

我还有几个问题
1,我使用了编译开关,用了好多,有几个开关没有用,因为开启的几个开关是都是显示BMP文件用的,都是必须用到的,用486在TC2.0下(纯DOS),这把可以运行起来了,也很正常,但编译成exe文件后,运行后,退出就花屏了(出现蓝色字符,光标也没有了,打了几个dir后就按什么键也没反应了,除按num lock键除外),怎么解决退出后的花屏问题呢?
2,我计算机安装两个系统,在XP下运行编译的neo生成的exe,退出以后都很正常,但到98下运行编译的neo生成的exe,退出以后就花屏了,这是为什么?
3,我用neo显示bmp文件,也加了很多编译开关,再加的话就运行不起来了,已经到极点了,我一个个试的,但编译出来的exe文件也比我用一些程序写出来显示的BMP文件要大的多呢!一个是77K,一个是18K,但显示的速度要比我的快多了,怎么才能把编译出来的文件再减少呢?

#8
一笔苍穹2007-06-18 09:13
建议把编译时的大小优化开启
用WIN-TC编译的话可以很方便的从它的编译设置中开启大小优化,那样可以将产生的程序减小到30KB左右。
显示BMP的话可以将不要的色深屏蔽掉,比如你只需要显示256色图片时,可将NEO对高彩和真彩的支持屏蔽掉。

至于你所说的花屏现象,建议你将你使用的编译开关帖上来,我去试试,看能否重现。
#9
beyondabcd2007-06-18 18:51
"大小优化开启"怎么开呀,
“花屏现象”,我在我的电脑下,98就花屏(所有的编译开关都没用)
               XP下就不花屏(所有的编译开关都没用)
#10
beyondabcd2007-06-18 19:21
好的我回去试试,试完了给你一个信
#11
beyondabcd2007-06-19 18:28
我在DOS下挂上鼠标后,进入TC运行程序,又出 out of memory in funtion main
要是不挂上鼠标,进入TC运行程序,能运行起来,
我在纯DOS下,加载了Himem.sys
我只是写个小程序用一用呀,常规内存是600K,扩展内存15M,你说用扩展内存能弥补内存不够的问题吗?要是能的话,在程序中怎么扩展呀
#12
一笔苍穹2007-06-20 11:52
你写的程序可能是比较小,但TC集成编程环境本身就要占资源的。
再检查一下是否加载了其它的什么程序
#13
beyondabcd2007-06-20 18:24
先在DOS下挂上鼠标,就用三次show_bmp呀,
#14
一笔苍穹2007-06-23 08:42
你挂上鼠标,再直接运行你编译好的的EXE不行吗?为什么要先进TC再运行啊?
#15
beyondabcd2007-06-23 18:45
那也不行呀,没反映,和在纯DOS下打exit一样,没办法了,现在望着NEO也只能眼馋了。现在我也只能自己动手了,还有一件事请教一下。

              NEO 最佳匹配色插件如何使用
unsigned char npi_bestfit_col8(PALETTE pal, int r, int g, int b);
8 位模式下的最佳匹配:
从指定调色板pal中搜索与给出颜色分量r,g,b最匹配(相似)的颜色号并返回该颜色号;参数r,g,b范围为0~63。
       这个说明没看懂呀,能举个例子吗?
#16
一笔苍穹2007-06-25 08:48
那个插件不太好,在最新的NEO内测版中已经去掉了。
我还是不明白,不可能你的程序要先进TC环境才能RUN啊,在DOS命令行下输入你编译生成了的EXE名字回车之后不能运行?你确定吗?这两者没区别的啊
#17
beyondabcd2007-06-26 06:38

是呀,不能运行,根本就没反应,我试了好几次了

#18
beyondabcd2007-06-26 06:42
对了,忘说了,在RUN能运行的话,在dos的exe也能运行,要是RUN不行的话,那DOS的EXE也没反应
#19
beyondabcd2007-06-26 06:45
对了,在问一下,NEO中的鼠标是怎么能的,我在svga中,调用鼠标(用中断33H,和自己画鼠标),他们两好像不兼容呀,
#20
一笔苍穹2007-06-27 13:11
恩,我不知道你的具体函数是怎么写的,不过你可以看一下我的源码,底层鼠标那一块还是满简单的,就是几个中断的调用而已。
另,在RUN中没法运行的,在DOS下不能直接运行是正常的。不过请列举不能在RUN下运行的代码。
#21
beyondabcd2007-06-27 17:21
我用VESA,设置成101,设置成640X480X256是和<graphics.h>不兼有容吗?它们两分开就单个的就好使,合在一起时,屏幕就一闪就过去了,
如果是的话,那我画鼠标用什么画点(putpixel)函数呀,我看NEO没看明白呀,NEO是怎么画鼠标的呀?
我看有网上说,鼠标驱动程序一般不处理SVGA显示模式,是不是?
Svga256.bgi这个我也用了,是不是和<graphics.h>不兼有容呀?


如果要是举例的话,我手头一大堆这样的例子,只是我在单位的机器不能上网,家里能,我会从单位带会来的,麻烦你,在帮我看看
#22
一笔苍穹2007-06-27 22:42

是的,NEO和Graphics不兼容,你不能同时使用它们。NEO提供了一些函数名和Graphics一样的函数,但那些实际上还是NEO自己的函数,和后者无关,只是为了让习惯了Graphics的用户感到方便而已。你可以试试(基本绘图函数一节中有使用方法)。NEO话鼠标不难,example文件夹中有两个例子。你可以发你的代码给我,我给你改改看

#23
beyondabcd2007-06-28 18:39


#include <dos.h>
#include <stdio.h>
#include <mem.h>
#include <alloc.h>
#include <stdlib.h>
#include <conio.h>
#include <graphics.h>

#define VBE320X200X256 0X13
#define VBE640X480X256 0X101
#define VBE800X600X256 0X103
#define VBE1024X768X256 0X105
#define True 1
#define False 0
#define VARM_GRAPH_800(x,y) (((unsigned long)y<<9L)+((unsigned long)y<<7L)+((unsigned long)(x)))
#define WAITING 0xff00
#define LEFTPRESS 0xff01
#define LEFTCLICK 0xff10
#define LEFTDRAG 0xff19
#define RIGHTPRESS 0xff02
#define RIGHTCLICK 0xff20
#define RIGHTDRAG 0xff2a
#define MIDDLEPRESS 0xff04
#define MIDDLECLICK 0xff40
#define MIDDLEDRAG 0xff4c
#define MOUSEMOVE 0xff08int Keystate;

/************************************************mouse************************************/
int MouseExist;
int MouseButton;
int MouseX;
int MouseY;

int up[16][16],down[16][16],mouse_draw[16][16],pixel_save[16][16];
void MouseMath()/*计算鼠标的样子*/
{int i,j,jj,k;
long UpNum[16]={
0x3fff,0x1fff,0x0fff,0x07ff,
0x03ff,0x01ff,0x00ff,0x007f,
0x003f,0x00ff,0x01ff,0x10ff,
0x30ff,0xf87f,0xf87f,0xfc3f
};
long DownNum[16]={
0x0000,0x7c00,0x6000,0x7000,
0x7800,0x7c00,0x7e00,0x7f00,
0x7f80,0x7e00,0x7c00,0x4600,
0x0600,0x0300,0x0300,0x0180
};
for(i=0;i<16;i++)
{
j=jj=15;
while(UpNum[i]!=0)
{
up[i][j]=UpNum[i]%2;
j--;
UpNum[i]/=2;
}
while(DownNum[i]!=0)
{
down[i][jj--]=DownNum[i]%2;
DownNum[i]/=2;
}
for(k=j;k>=0;k--)
up[i][k]=0;
for(k=jj;k>=0;k--)
down[i][k]=0;
for(k=0;k<16;k++)/*四种组合方式*/
{
if(up[i][k]==0&&down[i][k]==0)
mouse_draw[i][k]=1;
else if(up[i][k]==0&&down[i][k]==1)
mouse_draw[i][k]=2;
else if(up[i][k]==1&&down[i][k]==0)
mouse_draw[i][k]=3;
else
mouse_draw[i][k]=4;
}
}
mouse_draw[1][2]=4;/*特殊点*/
}
/*鼠标光标显示*/
void MouseOn(int x,int y)
{
int i,j;
int color; for(i=0;i<16;i++)/*画鼠标*/
{
for(j=0;j<16;j++)
{
pixel_save[i][j]=getpixel(x+j,y+i);/*保存原来的颜色*/
if(mouse_draw[i][j]==1)
putpixel(x+j,y+i,0);
else if(mouse_draw[i][j]==2)
putpixel(x+j,y+i,15);
}
}
}
/*隐藏鼠标*/
void MouseOff()
{
int i,j,x,y,color;
x=MouseX;
y=MouseY;
for(i=0;i<16;i++)/*原位置异或消去*/
for(j=0;j<16;j++)
{
if(mouse_draw[i][j]==3||mouse_draw[i][j]==4)
continue;
color=getpixel(x+j,y+i);
putpixel(x+j,y+i,color^color);
putpixel(x+j,y+i,pixel_save[i][j]);
}
}
/*鼠标是否加载
MouseExist:1=加载
0=未加载
MouseButton:鼠标按键数目 */
void MouseLoad()
{
_AX=0x00;
geninterrupt(0x33);
MouseExist=_AX;
MouseButton=_BX;
}/*鼠标状态值初始化*/
void MouseReset()
{
_AX=0x00;
geninterrupt(0x33);
}/*设置鼠标左右边界
lx:左边界
gx:右边界 */
void MouseSetX(int lx,int rx)
{
_CX=lx;
_DX=rx;
_AX=0x07;
geninterrupt(0x33);
}/*设置鼠标上下边界
uy:上边界
dy:下边界 */
void MouseSetY(int uy,int dy)
{
_CX=uy;
_DX=dy;
_AX=0x08;
geninterrupt(0x33);
}/*设置鼠标当前位置
x:横向坐标
y:纵向坐标 */
void MouseSetXY(int x,int y)
{
_CX=x;
_DX=y;
_AX=0x04;
geninterrupt(0x33);
}/*设置鼠标速度(缺省值:vx=8,vy=1)
值越大速度越慢 */
void MouseSpeed(int vx,int vy)
{
_CX=vx;
_DX=vy;
_AX=0x0f;
geninterrupt(0x33);
}/*获取鼠标按下键的信息*/
/*是否按下左键
返回值: 1=按下 0=释放*/
int LeftPress()
{
_AX=0x03;
geninterrupt(0x33);
return(_BX&1);
}/*是否按下中键
返回值同上 */
int MiddlePress()
{
_AX=0x03;
geninterrupt(0x33);
return(_BX&4);
}/*是否按下右键
返回值同上 */
int RightPress()
{
_AX=0x03;
geninterrupt(0x33);
return(_BX&2);
}/*获取鼠标当前位置*/
void MouseGetXY()
{
_AX=0x03;
geninterrupt(0x33);
MouseX=_CX;
MouseY=_DX;
}int MouseStatus()/*鼠标按键情况*/
{
int x,y;
int status;
int press=0;int i,j,color;
status=0;/*默认鼠标没又移动*/
x=MouseX;
y=MouseY;
while(x==MouseX&&y==MouseY&&status==0&&press==0)
{
if(LeftPress()&&RightPress())
press=1;
else if(LeftPress())
press=2;
else if(RightPress())
press=3;
MouseGetXY();
if(MouseX!=x||MouseY!=y)
status=1;
}
if(status)/*移动情况才重新显示鼠标*/
{
for(i=0;i<16;i++)/*原位置异或消去*/
for(j=0;j<16;j++)
{
if(mouse_draw[i][j]==3||mouse_draw[i][j]==4)
continue;
color=getpixel(x+j,y+i);
putpixel(x+j,y+i,color^color);
putpixel(x+j,y+i,pixel_save[i][j]);
}
MouseOn(MouseX,MouseY);/*新位置显示*/
}
if(press!=0)/*有按键得情况*/
return press;
return 0;/*只移动得情况*/
}

/************************************************mouse************************************/


/************************************************BMP************************************/
typedef struct BIGIMAGE /*存图结构*/
{
char fill_name[16];
int height;
int width;
} BIGIMAGE; /*存图类型名*/

typedef struct tagRGBQUAD /*用于读取调色板信息*/
{
char r;
char g;
char b;
char reserved;
} RGBQUAD;
int g_cur_vbe_page = 0;

void _Cdecl InitGraph(void)
{
_AX = 0x4f02;
_BX = VBE640X480X256;
__int__(0x10);
if(_AH != 0)
{
puts("Can't Initialize the graphics mode!");
exit(1);
}
}

void _Cdecl CloseGraph(void)
{
_AX = 0x4f02;
_BX = 0x03;
__int__(0x10);
}


void selectpage(register char page) /*换页函数*/
{
union REGS r;

r.x.ax=0x4f05;
r.x.bx=0;
r.x.dx=page; /*选择页面*/
int86(0x10,&r,&r);
}

void _Cdecl set_vbe_page(int page)
{
if (g_cur_vbe_page != page)
{
_BX = 0;
_DX = g_cur_vbe_page = page;
_AX = 0x4F05;
__int__(0x10);
}
}

/*******************************************BMP图显示函数**********************************/
void show_bmp_256(char *File_Name, int x, int y) /*图片显示函数,不支持透明色*/
{
unsigned char buffer[9216];
unsigned int width, height, linebytes;
int i, j;
long addr;
int page;
char far *videoptr = (char far *)0xa0000000L;
RGBQUAD bmiColors[256];
FILE *fp;

/****************************读文件,判断是否符合条件*****************************/
if ((fp=fopen(File_Name,"rb"))==NULL) /*判断打开文件是否正确*/
{
printf("Can't open file: %s",File_Name);
bioskey(0);
exit(0);
}
fseek(fp,18L,SEEK_SET); width = getw(fp);/*图片宽度*/
fseek(fp,22L,SEEK_SET); height = getw(fp);/*图片高度*/
/********************************************************************************/
/* 设置当前图片的调色板 */
/********************************************************************************/
fseek(fp, 54L, SEEK_SET);
if (fread((char *)&bmiColors[0], 4, 256, fp) != 256) /* 读当前图片调色板数据 */
{
printf("Can't get palette !\n");
bioskey(0);
exit(0);
}
for (i = 0; i < 256; i++)
{
outportb(0x03C8, i);
outportb(0x03C9, bmiColors[i].b >> 2);
outportb(0x03C9, bmiColors[i].g >> 2);
outportb(0x03C9, bmiColors[i].r >> 2);
}
/*************************************************************************/
if(width%4 != 0)
linebytes = width+(4-width%4); /* 每行字节数--4的整数倍 */
else
linebytes = width;
fseek(fp,1078L,SEEK_SET); /* 跳到位图数据的起始位置 */
for(j = height-1; j >= 0; j--)
{
fread(buffer, linebytes, 1, fp);
for(i = 0; i < width; i++)
{
addr = VARM_GRAPH_800(i+x,j+y);
page = (int)(addr >> 16);
set_vbe_page(page);
if((i+x) > -1 && (i+x) < 640 && (j+y) > -1 && (j+y) < 480) /*在屏幕范围*/
*(videoptr+(unsigned int)(addr&0xffff))= buffer[i];
}
}
fclose(fp);
}

/*****************************************************************************************************/
void main(void)
{
InitGraph();
show_bmp_256("1-1.bmp",0,0);
MouseMath();/*计算鼠标形状,一开始必须使用,后面就不用了*/
MouseSetY(0,479);
MouseSetX(0,639);
MouseSetXY(100,100);
MouseOn(MouseX,MouseY);/*第一次显示鼠标*/
while(!kbhit())
{
switch(MouseStatus())
{/*双键按下画黄点*/
case 1:MouseOff();
putpixel(MouseX,MouseY,YELLOW);
MouseGetXY();
MouseOn(MouseX,MouseY);break;
/*左键按下画红点*/
case 2:
MouseOff();
show_bmp_256("2-1.bmp",0,0);
MouseGetXY();
MouseOn(MouseX,MouseY);break;
/*右键按下画绿点*/
case 3:
MouseOff();
putpixel(MouseX,MouseY,GREEN);
MouseGetXY();
MouseOn(MouseX,MouseY);break;
default:break;
} /* switch*/
} /*while*/
CloseGraph();
}

这个是640X480X256,为什么这个程序一闪就过呢?是不是与graphics.h不兼容呀?如果是的话,那么画鼠标不用putpixel,那用什么画呀?

还有能不能推荐两本书,我好上网上书店买两本,手头上什么也没有就靠上网找点东西也不行呀,还是不明白呀?

在NEO中用什么方法显示BMP的,为什么我显示没有你的那么快呢?你的也太快了,

费心了,帮忙看看


#24
一笔苍穹2007-06-28 21:25
NEO和Graphics的确不兼容,不论是色深还是函数接口。你只能使用其一,不过你可以试下陈凯的Graphics++,那是Graphics的加强版,用的是扩展BGI库。
书的话似乎不多,我当时做的时候主要是揣摩别人的源码再结合VESA文档慢慢弄的。
NEO显示BMP的速度其实还不够快,如果重写的话我可以让它快的更多(可能达到一倍)。
#25
beyondabcd2007-06-29 17:22
我上面的程序并没有用NEO呀,而是用svga的101H,好像是和Graphics不兼容,
你用什么方法显示BMP的能大概说一下吗?你那个NEO实在太复杂了,看不明白呀
#26
一笔苍穹2007-06-29 21:29

不好兼容哪
我就把BMP文件打开然后读出来显示到显存中啊,不过优化了一下而已。主步骤就是这样子的

#27
beyondabcd2007-06-30 07:31
怎么优化的,能大概说说吗?
#28
beyondabcd2007-07-04 20:23

班主,大概说说你是怎么优化的贝

#29
一笔苍穹2007-07-05 08:32
运算强度减弱,循环展开,空间换时间,充分利用CPU字长等等,这都是些常见简单的优化方法,
像内嵌汇编和更多的优化手段还没使用,如果全部用上,性能还能再提升一个档次。
#30
beyondabcd2007-07-06 18:43
这么复杂呀,就像这上一段程序

for(j = height-1; j >= 0; j--)
{
fread(buffer, linebytes, 1, fp);
for(i = 0; i < width; i++)
{
addr = VARM_GRAPH_800(i+x,j+y);
page = (int)(addr >> 16);
set_vbe_page(page);
if((i+x) > -1 && (i+x) < 640 && (j+y) > -1 && (j+y) < 480) /*在屏幕范围*/
*(videoptr+(unsigned int)(addr&0xffff))= buffer[i];
}
}
这个也没什么好方法优化了呀?
#31
一笔苍穹2007-07-07 12:52
set_vbe_page(page);
优化掉
if((i+x) > -1 && (i+x) < 640 && (j+y) > -1 && (j+y) < 480)想办法放在循环外面
就可以快一些了。
#32
beyondabcd2007-07-15 15:56

/***********************************图片显示*********************************/
int show_bmp(char *namea,int x0,int y0)
{
int width, height,i,j, fp;
unsigned char fix, *buffer, pix24b[4];
DacPalette256 dac256;
if((fp = open(namea, O_RDONLY | O_BINARY)) == -1)
{
puts("Can't find file ""xy_256.bmp"".");
return 1;
}
lseek(fp, 18, SEEK_SET);
read(fp, &width, 4);
read(fp, &height, 4);
fix = (width % 4) ? (4 - width % 4) : 0;
lseek(fp, 54, SEEK_SET);
for(i = 0; i < 256; i++) /* 按照该图片的DAC色表设置色彩寄存器 */
{
read(fp, pix24b, 4); /* 读取DAC分量信息 */
/* 设置调色板 */
dac256[i][0] = pix24b[2] >> 2;
dac256[i][1] = pix24b[1] >> 2;
dac256[i][2] = pix24b[0] >> 2;
}
setvgapalette256(&dac256); /* 应用调色板, 定义参见 Svga256.h */
buffer = (unsigned char *)malloc(width);
for(j = height - 1; j >= 0; j--)
{
read(fp, buffer, width);
lseek(fp, fix, SEEK_CUR);
for(i = 0; i < width; i++) putpixel(x0+i, y0+j, buffer[i]);
}
free(buffer);
close(fp);
}


这个显示图片的程序怎么优化一下,让快速显示呢?

#33
一笔苍穹2007-07-16 11:49
fix = (width % 4) ? (4 - width % 4) : 0;
把%优化掉

for(i = 0; i < width; i++) putpixel(x0+i, y0+j, buffer[i]);
不要直接用画点函数,这很重要。直接显存操作会快很多,块内在传输会更快
#34
beyondabcd2007-07-16 17:26
这个程序我也是不怎么才能看懂,什么是“块内”呀?
#35
一笔苍穹2007-07-16 21:32
应该是块内存传输会更快,比如datamove或memcpy
#36
beyondabcd2007-07-19 20:09

这两个程序运行的速度差不多呀(在486的机器上运行的),说明用Svga256.bgi和直接写屏的速度差不多呀?
----------------------------------------------------------------------------
/* Svga256.c */

#include "graphics.h"
#include "Svga256.h"
#include "stdio.h"
#include "fcntl.h"
#include "malloc.h"
#include "io.h"

int huge Return_SVGA256(void)
{
return(SVGA640x480x256); /* 返回各种分辨率的对应编号 0~6 宏定义参见 Svga256.h */
}

int main(void)
{
int width, height, i=DETECT, j=0, x0=0, y0=0, fp;
unsigned char fix, *buffer, pix24b[4];
DacPalette256 dac256;
installuserdriver("Svga256", Return_SVGA256); /* 对于svga256必需执行该函数以安装BGI驱动 */
initgraph(&i, &j, ""); /* 执行TC默认的BGI初始化函数 */

if((fp = open("main.bmp", O_RDONLY | O_BINARY)) == -1)
{
puts("Can't find file ""main.bmp"".");
return 1;
}
lseek(fp, 18, SEEK_SET);
read(fp, &width, 4);
read(fp, &height, 4);
fix = (width % 4) ? (4 - width % 4) : 0;

lseek(fp, 54, SEEK_SET);
for(i = 0; i < 256; i++) /* 按照该图片的DAC色表设置色彩寄存器 */
{
read(fp, pix24b, 4); /* 读取DAC分量信息 */
/* 设置调色板 */
dac256[i][0] = pix24b[2] >> 2;
dac256[i][1] = pix24b[1] >> 2;
dac256[i][2] = pix24b[0] >> 2;
}
setvgapalette256(&dac256); /* 应用调色板, 定义参见 Svga256.h */
buffer = (unsigned char *)malloc(width);
for(j = height - 1; j >= 0; j--)
{
read(fp, buffer, width);
lseek(fp, fix, SEEK_CUR);
for(i = 0; i < width; i++)
putpixel(x0+i, y0+j, buffer[i]);
}
free(buffer);
close(fp);
getch();
closegraph();
return 0;
}

---------------------------------------------------------------------------
/* bmp256.c */

#include "graphics.h"
#include "Svga256.h"
#include "stdio.h"
#include "fcntl.h"
#include "malloc.h"
#include "io.h"
#include "dos.h"
#define VARM_GRAPH_800(x,y) (((unsigned long)y<<9L)+((unsigned long)y<<7L)+((unsigned long)(x)))
int huge Return_SVGA256(void)
{
return(SVGA640x480x256); /* 返回各种分辨率的对应编号 0~6 宏定义参见 Svga256.h */
}

void selectpage(register char page) /*换页函数*/
{
union REGS r;

r.x.ax=0x4f05;
r.x.bx=0;
r.x.dx=page; /*选择页面*/
int86(0x10,&r,&r);
}


int g_cur_vbe_page = 0;
void _Cdecl set_vbe_page(int page)
{
if (g_cur_vbe_page != page)
{
_BX = 0;
_DX = g_cur_vbe_page = page;
_AX = 0x4F05;
__int__(0x10);
}
}


int main(void)
{
int width, height, i=DETECT, j=0, x0=0, y0=0, fp,page;
long addr;
unsigned char fix, *buffer, pix24b[4];
char far *videoptr = (char far *)0xa0000000L;
DacPalette256 dac256;
installuserdriver("Svga256", Return_SVGA256); /* 对于svga256必需执行该函数以安装BGI驱动 */
initgraph(&i, &j, ""); /* 执行TC默认的BGI初始化函数 */

if((fp = open("main.bmp", O_RDONLY | O_BINARY)) == -1)
{
puts("Can't find file ""xy_256.bmp"".");
return 1;
}
lseek(fp, 18, SEEK_SET);
read(fp, &width, 4);
read(fp, &height, 4);
fix = (width % 4) ? (4 - width % 4) : 0;
/*x0 = (320 - width) / 2;
y0 = (200 - height) / 2; */
lseek(fp, 54, SEEK_SET);
for(i = 0; i < 256; i++) /* 按照该图片的DAC色表设置色彩寄存器 */
{
read(fp, pix24b, 4); /* 读取DAC分量信息 */
/* 设置调色板 */
dac256[i][0] = pix24b[2] >> 2;
dac256[i][1] = pix24b[1] >> 2;
dac256[i][2] = pix24b[0] >> 2;
}

setvgapalette256(&dac256); /* 应用调色板, 定义参见 Svga256.h */
buffer = (unsigned char *)malloc(width);
for(j = height - 1; j >= 0; j--)
{
read(fp, buffer, width);
lseek(fp, fix, SEEK_CUR);
for(i = 0; i < width; i++)
{ addr = VARM_GRAPH_800(i+x0,j+y0);
page = (int)(addr >> 16);
set_vbe_page(page);
if((i+x0) > -1 && (i+x0) < 640 && (j+y0) > -1 && (j+y0) < 480) /*在屏幕范围*/
/* putpixel(x0+i, y0+j, buffer[i]);*/
*(videoptr+(unsigned int)(addr&0xffff))= buffer[i];
}
}
free(buffer);
close(fp);

getch();
closegraph();
return 0;
}


#37
一笔苍穹2007-07-19 20:27

不会,SVGA.BGI的速度要慢,只是可能因为你用的是486机器或是没优化到位的缘故

#38
beyondabcd2007-07-20 17:22
我想拿一个图片做按钮,可它的四周是白色的,而我的背景图不是白色的,
在程序中如何能够屏蔽掉白色呢?
#39
一笔苍穹2007-07-21 08:42
碰上白色不画出来
#40
beyondabcd2007-07-22 16:58
以下是引用一笔苍穹在2007-7-19 20:27:18的发言:

不会,SVGA.BGI的速度要慢,只是可能因为你用的是486机器或是没优化到位的缘故

还怎么优化呀,能不能提一个思路

#41
一笔苍穹2007-07-22 18:40
优化是没有公式可循的啊,实际情况实际处理。
#42
beyondabcd2007-07-24 17:18

就那下面的程序来说吧,这个算是直接写屏吧,也优化了吧,可和svga256那个速度一样慢呀?

#include <dos.h>
#include <stdio.h>
#include <mem.h>
#include <alloc.h>
#include <stdlib.h>
#include <conio.h>

#define VBE320X200X256 0X13
#define VBE640X480X256 0X101
#define VBE800X600X256 0X103
#define VBE1024X768X256 0X105
#define True 1
#define False 0
#define VARM_GRAPH_800(x,y) (((unsigned long)y<<9L)+((unsigned long)y<<7L)+((unsigned long)(x)))

typedef struct BIGIMAGE /*存图结构*/
{
char fill_name[16];
int height;
int width;
} BIGIMAGE; /*存图类型名*/

typedef struct tagRGBQUAD /*用于读取调色板信息*/
{
char r;
char g;
char b;
char reserved;
} RGBQUAD;
int g_cur_vbe_page = 0;

void _Cdecl InitGraph(void)
{
_AX = 0x4f02;
_BX = VBE640X480X256;
__int__(0x10);
if(_AH != 0)
{
puts("Can't Initialize the graphics mode!");
exit(1);
}
}

void _Cdecl CloseGraph(void)
{
_AX = 0x4f02;
_BX = 0x03;
__int__(0x10);
}


void selectpage(register char page) /*换页函数*/
{
union REGS r;

r.x.ax=0x4f05;
r.x.bx=0;
r.x.dx=page; /*选择页面*/
int86(0x10,&r,&r);
}

void _Cdecl set_vbe_page(int page)
{
if (g_cur_vbe_page != page)
{
_BX = 0;
_DX = g_cur_vbe_page = page;
_AX = 0x4F05;
__int__(0x10);
}
}

/*******************************************BMP图显示函数**********************************/
void show_bmp_256(char *File_Name, int x, int y) /*图片显示函数,不支持透明色*/
{
unsigned char buffer[9216];
unsigned int width, height, linebytes;
int i, j;
long addr;
int page;
char far *videoptr = (char far *)0xa0000000L;
RGBQUAD bmiColors[256];
FILE *fp;

/****************************读文件,判断是否符合条件*****************************/
if ((fp=fopen(File_Name,"rb"))==NULL) /*判断打开文件是否正确*/
{
printf("Can't open file: %s",File_Name);
bioskey(0);
exit(0);
}
fseek(fp,18L,SEEK_SET); width = getw(fp);/*图片宽度*/
fseek(fp,22L,SEEK_SET); height = getw(fp);/*图片高度*/
/********************************************************************************/
/* 设置当前图片的调色板 */
/********************************************************************************/
fseek(fp, 54L, SEEK_SET);
if (fread((char *)&bmiColors[0], 4, 256, fp) != 256) /* 读当前图片调色板数据 */
{
printf("Can't get palette !\n");
bioskey(0);
exit(0);
}
for (i = 0; i < 256; i++)
{
outportb(0x03C8, i);
outportb(0x03C9, bmiColors[i].b >> 2);
outportb(0x03C9, bmiColors[i].g >> 2);
outportb(0x03C9, bmiColors[i].r >> 2);
}
/*************************************************************************/
if(width%4 != 0)
linebytes = width+(4-width%4); /* 每行字节数--4的整数倍 */
else
linebytes = width;
fseek(fp,1078L,SEEK_SET); /* 跳到位图数据的起始位置 */
for(j = height-1; j >= 0; j--)
{
fread(buffer, linebytes, 1, fp);
for(i = 0; i < width; i++)
{
addr = VARM_GRAPH_800(i+x,j+y);
page = (int)(addr >> 16);
set_vbe_page(page);
if((i+x) > -1 && (i+x) < 640 && (j+y) > -1 && (j+y) < 480) /*在屏幕范围*/
*(videoptr+(unsigned int)(addr&0xffff))= buffer[i];
}
}
fclose(fp);
}

/*****************************************************************************************************/
void main(void)
{
InitGraph();
show_bmp_256("1.bmp",0,0);
getch();

CloseGraph();}

#43
一笔苍穹2007-07-24 21:36
if((i+x) > -1 && (i+x) < 640 && (j+y) > -1 && (j+y) < 480) /*在屏幕范围*/
提到循环外
*(videoptr+(unsigned int)(addr&0xffff))= buffer[i];
换成内存拷贝函数
#44
beyondabcd2007-07-28 19:40
在电脑(cpu 2.6G,内存512M)上用tc2.0运行程序时(XP系统),能通过,可拿到486(640k常规内存)上就运行时,出现Out of memory in function,程序中并没有使用EMS,XMS呀,在dos下对使用内存上应该是一样的吧?为什么在486上不能运行呢?
#45
一笔苍穹2007-07-29 11:02

不要总是用TC20打开你的代码再RUN,LINK了你的程序之后就可以得到一个EXE,它可以到处运行,当然,如果使用了SVGA.bgi的话还要带上这个文件。

#46
beyondabcd2007-08-04 20:03

在使svga256.bgi 时,与C语言中的graphics.h库中的setfillstyle,bar,setcolor等一些语句中,虽然兼容,但写到一定长度的程序时,有些不稳定呀(大多数时不行,但有极少数时好使);这是怎么回事,是我的程序不对吗?

当申请两次空间时,为什么不行(第一次申请malloc,不释放的情况下,申请第二次,为什么申请不下来呢?)

#47
一笔苍穹2007-08-05 11:56
应该还是你程序的问题,我很久以前有SVGA.bgi写了一个增强型图形库,也满大的,也没出什么问题。
如果你是小模式或中模式,用malloc能申请到的总量是64KB,如果你用的大模式或紧凑或巨模式,就是640KB,但这是理论值,你的程序本身还要占一部分内存。
1