📄 xms.cpp
字号:
#include <alloc.h>
#include <graphics.h>
#include <dos.h>
#include <dir.h>
#include "xms.h"
int XMS::OK=0;
static void far *XMSaddr;
int XMS::Init(void)
{
static struct REGPACK rg; //{unsigned r_ax,r_bx,r_cx,r_dx;
//unsigned r_bp,r_si,r_di,r_es,r_flags;}
rg.r_ax=0x4300;
intr(0x2f,&rg); //改变软中断接口 intr(int IntNo,struct REGPACK *preg)
if((rg.r_ax & 0x00ff) == 0x80){
rg.r_ax=0x4310;
intr(0x2f,&rg);
XMSaddr=MK_FP(rg.r_es,rg.r_bx); //set a far pointer
OK=1; //seg and ofs
}
else
OK=0;
return OK;
}
unsigned XMS::FreeSize(void) //AH=08H查询自由扩展内存块
{ //返回参数AX!=0.成功.=0.失败
if(0 == OK) //AX中为最大自由扩展内存块的大小。
return 0; //DX中为自由扩展内存的总的大小。
asm mov ah,8
asm call XMSaddr
return _DX;
}
unsigned XMS::LargestBlock(void)
{
if(0 == OK)
return 0;
asm mov ah,8
asm call XMSaddr
return _AX;
}
XMS::XMS(int size) //AH=09H分配扩展内存块
{ //DX=请求的扩展内存的大小
if(0 ==OK) //返回参数.AX=1.成功.DX=分配块的句柄
{ // AX=0,分配失败,BL中为错误码
handle=0;
return;
}
asm mov ah,9
asm mov dx,size
asm call XMSaddr
handle=_DX;
}
XMS::~XMS() //AH=0AH释放扩展内存块
{ //调用参数:AH=0AH,DX=欲释放的扩展内存的句柄
if(0 == handle) //返回参数:AX=1,成功
return; // AX=0,失败.BL中为错误码
int hd=handle;
asm mov ah,0ah
asm mov dx,hd
asm call XMSaddr
}
int XMS::ReAlloc(int size) //AH=0FH重新分配扩展内存块
{ //调用参数:AH=0FH,BX=扩展内存块的新长度
if(0 == handle) // DX=EMB句柄
return 0; //返回参数:AX=1,成功BX=UMB段号
int hd=handle; //DX=已分配的节数.AX=0,失败.BL中为错误码
asm mov ah,0fh
asm mov bx,size
asm mov dx,hd
asm call XMSaddr
return _AX;
}
//AH=0BH:移动扩展内存块。
//本功能可在常规内存和扩展内存,扩展内存和扩展内存之间移动扩展内存块。
int XMS::Move(struct EMB *emb)
{ //调用参数:AH=0BH
//DS:SI指向扩展内存块移动参数表
char far *s=(char far *)emb;
if(0 != handle) //返回参数:AX=1,移动成功
{ // AX=0,失败,BL中为错误码
asm mov ah,0bh
asm push ds
asm push ds
asm pop es
asm lds si,s
asm call es:XMSaddr
asm pop ds
return _AX;
}
else
return 0;
}
int XMS::Put(long dp,void *sp,long leng)
{
struct EMB emb;
if(leng & 1L)
leng++;
emb.Leng=leng;
emb.SourceHandle=0;
emb.SourceOfs=(long)sp;
emb.DestinHandle=handle;
emb.DestinOfs=dp;
return Move(&emb);
}
int XMS::Get(void *dp,long sp,long leng)
{
struct EMB emb;
int v;
if(leng & 1L)
{
char *p,*d;
leng--;
if(leng>0)
{
emb.Leng=leng;
emb.SourceHandle=handle;
emb.SourceOfs=sp;
emb.DestinHandle=0;
emb.DestinOfs=(long)dp;
Move(&emb);
}
p=(char *)malloc(2);
emb.Leng=2L;
emb.SourceHandle=handle;
emb.SourceOfs=sp+leng;
emb.DestinHandle=0;
emb.DestinOfs=(long)p;
v=Move(&emb);
d=(char *)dp;
d[(unsigned)leng]=p[0];
free(p);
}
else
{
emb.Leng=leng;
emb.SourceHandle=handle;
emb.SourceOfs=sp;
emb.DestinHandle=0;
emb.DestinOfs=(long)dp;
v=Move(&emb);
}
return v;
}
int XMS::Transfer(long dp,long sp,long len)
{
struct EMB emb;
if(len & 1L)
return 0;
emb.Leng=len;
emb.SourceHandle=handle;
emb.SourceOfs=sp;
emb.DestinHandle=handle;
emb.DestinOfs=dp;
return Move(&emb);
}
//----------------------------------------------------------------------
/////////////////
//MEMORY CLASS///
/////////////////
void MEMORY :: PutBuf(void *buf,long length)
{
leng=length;
if(buf==NULL)
{
where=inNONE;
leng=0L;
OK=0;
return;
}
if(0 == XMS::OK) //如果扩充内存没有初始化
where=inHD;
else
{
long l=0;
l=(long)XMS::LargestBlock()-1L;
l *= 1024L;
if(leng >= l) // 是否有足够的扩充内存
where=inHD;
else where=inXMS;
}
if(inXMS == where) //将缓冲区的内容调入扩充内存
{
long ll;
ll = (leng+1023L)/1024L;
handle.xms = new XMS((int)ll);
handle.xms->Put(0L,buf,leng);
}
else{
where = inHD;
handle.file = tmpfile();
fwrite(buf,(size_t)leng,1,handle.file);
}
OK=1;
}
int MEMORY :: GetBuf(void *buf,long offset,int ll)
{
if(OK == 0)return 0;
long dl=leng-offset;
if(offset >= leng)
return 0;
if(dl < (long)ll)
ll=int(dl);
if(inXMS == where)
handle.xms->Get(buf,offset,ll);
else if(inHD == where)
{
fseek(handle.file,offset,SEEK_SET);
fread(buf,ll,1,handle.file);
}
return ll;
}
MEMORY :: ~MEMORY()
{
if(inXMS == where)
delete handle.xms;
else if(inHD == where)
fclose(handle.file);
}
//---------------------------------------------------------------------
FILETOXMS::FILETOXMS(char *name)
{
FILE *fp;
struct ffblk fblk;
if(-1 == findfirst(name,&fblk,0)) //如果没有这个文件
//查找第一个匹配文件
{
where=inNONE;
leng=0L;
OK=0;
return;
}
leng=fblk.ff_fsize; //文件大小
if(0 == XMS::OK) //如果扩充内存没有初始化
where=inHD;
else{
long l=0;
l=(long)XMS::LargestBlock()-1L;
l *= 1024L;
if(leng >= l) // 是否有足够的扩充内存
where=inHD;
else where=inXMS;
}
if(inXMS == where) //将文件调如扩充内存
{
long sagl = 0x4000L;
long left,offset,ll;
int n,i;
void *buf;
ll = (leng+1023L)/1024L;
handle.xms = new XMS((int)ll);
buf = malloc((unsigned)sagl);
n = (int)(leng/sagl);
left = leng-sagl*(long)n;
fp = fopen(name,"rb");
offset = 0L;
for(i=0;i<n;i++){
fread(buf,(unsigned)sagl,1,fp);
handle.xms->Put(offset,buf,sagl);
offset += sagl;
}
fread(buf,(unsigned)left,1,fp); //从流中读数据
handle.xms->Put(offset,buf,left);
free(buf);
fclose(fp);
}
else{
where = inHD;
handle.file=fopen(name,"rb");
}
OK=1;
}
//-----------------------------------------------------------------
////////////////
//IMAGE CLASS///
////////////////
void IMAGE :: GetImageMEM()
{
char far *cp;
register int y;
cp=(char far *)handle.mem;
for(y=y1;y<=y2;y++)
{
GetScanLine(x1,y,xn,cp);
cp += ssize;
}
}
void IMAGE :: PutImageMEM(int xx1,int yy1)
{
register int y;
char far *cp;
cp=(char far *)handle.mem;
for(y=0;y<yn;y++){
PutScanLine(xx1,yy1+y,xn,cp);
cp += ssize;
}
}
void IMAGE :: GetImageXMS()
{
register int y;
void *buf;
long offset=0L;
buf=malloc(ssize);
for(y=y1;y<=y2;y++)
{
GetScanLine(x1,y,xn,(char far *)buf);
handle.xms->Put(offset,buf,ssize);
offset += ssize;
}
free(buf);
}
void IMAGE :: PutImageXMS(int xx1,int yy1)
{
register int y;
void *buf;
long offset=0L;
buf=malloc(ssize);
for(y=0;y<yn;y++)
{
handle.xms->Get(buf,offset,ssize);
PutScanLine(xx1,y+yy1,xn,(char far *)buf);
offset += ssize;
}
free(buf);
}
void IMAGE :: GetImageHD()
{
register int y;
void *buf = malloc(ssize);
fseek(handle.file,0L,SEEK_SET);
for(y=y1;y<=y2;y++){
GetScanLine(x1,y,xn,(char far *)buf);
fwrite(buf,ssize,1,handle.file);
}
free(buf);
}
void IMAGE :: PutImageHD(int xx1,int yy1)
{
register int y;
void *buf = malloc(ssize);
fseek(handle.file,0L,SEEK_SET);
for(y=0;y<yn;y++){
fread(buf,ssize,1,handle.file);
PutScanLine(xx1,y+yy1,xn,(char far *)buf);
}
free(buf);
}
void IMAGE :: GetScanLine(int x1,int y,int n,char far *buf)
{
unsigned byte1,byte2,x2;
char pn=4;
asm{
mov ax,x1
add ax,n
dec ax
mov x2,ax // x2 = x1+n-1;
mov ax,y
mov bx,ax
mov cl,6
shl ax,cl
mov cl,4
shl bx,cl //mul scanleng=80
add ax,bx
push ax
mov bx,x1
shr bx,1
shr bx,1
shr bx,1
add ax,bx
mov byte1,ax // byte1 = y*80 + x1/8
pop ax
mov bx,x2
shr bx,1
shr bx,1
shr bx,1
add ax,bx
mov byte2,ax // byte2 = y*80 + x2/8
}
JEMP2:
asm{
mov dx,0x3ce // outportb(0x3ce,0x05);
mov ax,0x0005 // outportb(0x3cf,0);
out dx,ax
mov al,0x04
out dx,al // outportb(0x3ce,0x04);
inc dx
mov cx,x1
and cx,7
mov bl,cl
mov bh,8
sub bh,bl // bh = 8-(x1%8)
push ds
mov ax,0x0a000
mov ds,ax
les di,buf
mov ax,byte2
sub ax,byte1
add ax,2 // ax=byte2-byte1+2
mov es:[di],al
inc di
}
LOOP1:
asm{
dec pn
mov al,pn
out dx,al // outportb(0x3cf,al);
mov si,byte1
}
LOOP2:
asm{
mov ah,ds:[si]
inc si
mov al,ah
mov cl,bh
shr ah,cl
or es:[di],ah
inc di
mov cl,bl
shl al,cl
mov es:[di],al
cmp byte2,si
jae LOOP2 // if(byte2 >= si)
inc di
cmp pn,0
jne LOOP1 // if(pn != 0)
pop ds
}
}
void IMAGE :: PutScanLine(int x1,int y,int n,char far *buf)
{
unsigned byte1,byte2,x2;
unsigned char pn=4;
unsigned char pbn;
asm{
mov ax,x1
add ax,n
dec ax
mov x2,ax // x2 = x1+n-1;
mov ax,y
mov bx,ax
mov cl,6
shl ax,cl
mov cl,4
shl bx,cl //mul scanleng=80
add ax,bx
push ax
mov bx,x1
shr bx,1
shr bx,1
shr bx,1
add ax,bx
mov byte1,ax // byte1 = y*80+x1/8;
mov bx,x2
shr bx,1
shr bx,1
shr bx,1
pop ax
add ax,bx
mov byte2,ax // byte2 = y*80+x2/8;
}
JEMP2:
asm{
mov dx,0x3ce // outportb(0x3ce,0x05);
mov ax,0x0005 // outportb(0x3cf,0);
out dx,ax // 选择方式寄存器写方式0;
mov ax,0x0001 // outportb(0x3ce,0x01);
out dx,ax // outpotrb(0x3cf,0);
mov ax,0x0003 // outportb(0x3ce,0x03);
out dx,ax // outportb(0x3cf,0);
push ds
mov ax,0x0a000
mov es,ax
lds si,buf
mov al,ds:[si]
mov pbn,al
mov cx,x1
and cx,7
mov bl,cl
mov bh,8
sub bh,bl
}
LOOP1:
asm{
dec pn
lds si,buf
mov al,3
sub al,pn
mul pbn
add ax,2
add si,ax
mov di,byte1
mov dx,0x3c4
mov al,2
out dx,al // outportb(0x3c4,2);
inc dx
mov cl,pn
mov al,1
shl al,cl
out dx,al // outportb(0x3c5,al);(al = 1,2,4,8);
mov dx,0x3ce
mov al,0x08
out dx,al // outportb(0x3ce,0x08);
inc dx
mov ax,byte1
cmp ax,byte2
je INONEBYTE
}
asm{
mov al,0xff
mov cl,bl
shr al,cl
out dx,al // outportb(0x3cf,al);
mov al,ds:[si]
mov cl,bl
shr al,cl
mov ah,es:[di]
mov es:[di],al
mov al,0xff
out dx,al
}
MIDDLE_BYTE_LOOP:
asm{
inc di
cmp di,byte2
je WRITE_END_BYTE
mov al,ds:[si]
mov cl,bh
shl al,cl
inc si
mov ah,ds:[si]
mov cl,bl
shr ah,cl
or al,ah
mov es:[di],al
jmp MIDDLE_BYTE_LOOP
}
WRITE_END_BYTE:
asm{
mov cx,x2
not cx
and cx,7
mov al,0xff
shl al,cl
out dx,al
mov al,ds:[si]
mov cl,bh
shl al,cl
inc si
mov ah,ds:[si]
mov cl,bl
shr ah,cl
or al,ah
mov ah,es:[di]
mov es:[di],al
jmp JEMP3
}
INONEBYTE:
asm{
mov cx,x1
and cx,7
mov al,0xff
shr al,cl
mov cx,x2
not cx
and cx,7
mov ah,0xff
shl ah,cl
and al,ah
out dx,al
mov al,ds:[si]
mov cl,bl
shr al,cl
mov ah,es:[di]
mov es:[di],al
}
JEMP3:
if(pn>0)
goto LOOP1;
asm pop ds
}
// class MenuImage
IMAGE :: IMAGE(int xx1,int yy1,int xx2,int yy2,int whe)
{
where = whe;
if( xx1 > xx2 )
{ x1=xx2;x2=xx1; }
else
{ x1=xx1;x2=xx2; }
if( yy1 > yy2 )
{ y1=yy2;y2=yy1; }
else
{ y1=yy1;y2=yy2; }
xn=x2-x1+1;
yn=y2-y1+1;
ssize = (((x2-x1)>>3)+3)*4+2;
Isize=(long)ssize*yn;
if(inMEM == where)
{
long left;
left = coreleft();
if(Isize>=left || Isize >= 4000L )
where=inXMS;
else
handle.mem=malloc((unsigned)Isize);
}
if(inXMS == where)
{
if(0 == XMS::OK)
where=inHD;
else
{
long left=0;
left = (long)XMS::LargestBlock()-1L;
left *= 1024L;
if(Isize >= left)
where=inHD;
}
}
if(inXMS == where)
{
int ksize = (int)((Isize+1023L)/1024L);
handle.xms = new XMS(ksize);
}
else
{
where = inHD;
handle.file = tmpfile();
}
}
IMAGE :: ~IMAGE()
{
if(inMEM == where)
free(handle.mem);
else if(inXMS == where)
delete handle.xms;
else fclose(handle.file);
}
void IMAGE :: GetImage()
{
if(inMEM == where)
GetImageMEM();
else if(inXMS == where)
GetImageXMS();
else
GetImageHD();
/*
if(where==inXMS) outtextxy(400,400,"Inxms");
else if(where==inMEM) outtextxy(400,400,"Inmen");
else outtextxy(400,400,"Inhd");
if (XMS::OK==0) outtextxy(400,430,"sucess");
else outtextxy(400,430,"fail");
*/
}
void IMAGE :: PutImage(int xx1,int yy1)
{
if(inMEM == where)
PutImageMEM(xx1,yy1);
else if(inXMS == where)
PutImageXMS(xx1,yy1);
else if(inHD == where)
PutImageHD(xx1,yy1);
outport(0x3ce,0xff08);
outport(0x3c4,0x0f02);
}
/* void IMAGE :: GetImage(int xx1,int yy1,int xx2,int yy2,int whe)
{
where = whe;
if( xx1 > xx2 )
{ x1=xx2;x2=xx1; }
else
{ x1=xx1;x2=xx2; }
if( yy1 > yy2 )
{ y1=yy2;y2=yy1; }
else
{ y1=yy1;y2=yy2; }
xn=x2-x1+1;
yn=y2-y1+1;
ssize = (((x2-x1)>>3)+3)*4+2;
Isize=(long)ssize*yn;
if(inMEM == where)
{
long left;
left = coreleft();
if(Isize>=left || Isize >= 4000L )
where=inXMS;
else
{
handle.mem=malloc((unsigned)Isize);
GetImageMEM();
}
}
if(inXMS == where)
{
if(0 == XMS::OK)
where=inHD;
else
{
long left=0;
left = (long)XMS::LargestBlock()-1L;
left *= 1024L;
if(Isize >= left)
where=inHD;
}
}
if(inXMS == where)
{
int ksize = (int)((Isize+1023L)/1024L);
handle.xms = new XMS(ksize);
GetImageXMS();
}
else
{
where = inHD;
handle.file = tmpfile();
GetImageHD();
}
}
void IMAGE :: PutImage(int xx1,int yy1)
{
if(inMEM == where)
{
PutImageMEM(xx1,yy1);
free(handle.mem);
}
else if(inXMS == where)
{
PutImageXMS(xx1,yy1);
delete handle.xms;
}
else if(inHD == where)
{
PutImageHD(xx1,yy1);
fclose(handle.file);
}
outport(0x3ce,0xff08);
outport(0x3c4,0x0f02);
}
*/
/*---------------END-----------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -