📄 vesa.h
字号:
#include<io.h>
#include<time.h>
#include<dos.h>
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
#include<bios.h>
#include<stdarg.h>
#include<stddef.h>
#include"timer.h"
#include"draw.h"
#include"hzk.h"
RMInfo RMI;
VBEHardWare HardWareInfo;
VBEModeInfo VesaModeInfo;
long VideoPhysBasePtr,
screen_videomem;
PCXHEAD pcx;
unsigned char ColorTable[256][3];
BITMAP *_Screen=NULL,*_Display;
struct LineWriteMode
{unsigned char StyLine;
}LineWriteMode;
char DpmiRealMalloc(unsigned short Size, unsigned short *Segment, unsigned short *Selector)
{ union REGS regs;
memset(®s, 0, sizeof(regs));
regs.x.eax = 0x0100; // DPMI 分配DOS内存
regs.x.ebx = Size; // Size * 16
int386 (0x31, ®s, ®s); // 分配DOS内存块
if (regs.x.cflag) // 失败
{
printf("\nError: Allocate DOS memory: %dunsigned char", Size*16);
return FALSE;
}
*Selector = regs.w.dx;
*Segment = regs.w.ax;
return TRUE;
}
char DpmiRealFree(unsigned short Selector)
{ union REGS regs;
memset(®s, 0, sizeof(regs));
regs.x.eax = 0x0101;
regs.x.edx = Selector; // 块的选择符
int386 (0x31, ®s, ®s); // 释放DOS内存块
if (regs.x.cflag) // 失败
{
printf("\nError: Free DOS memory: Selector = %d", Selector);
return FALSE;
}
return TRUE;
}
char DpmiRealInt386x(unsigned char IntNO, RMInfo *RealRegs)
{ union REGS regs;
struct SREGS sregs;
memset(®s, 0, sizeof(regs));
memset(&sregs, 0, sizeof(sregs));
regs.w.ax = 0x0300;
regs.h.bl = IntNO;
regs.h.bh = 0;
regs.w.cx = 0;
sregs.es = FP_SEG(RealRegs);
regs.x.edi = FP_OFF(RealRegs);
int386x(0x31, ®s, ®s, &sregs);
if (regs.x.cflag) // 失败
{
printf("\nError: Issue the DOS interrupt: %dh", IntNO);
return FALSE;
}
return TRUE;
}
unsigned long DPMIPhysicalToLinear(unsigned long physAddr, unsigned long limit)
{ union REGS regs;
regs.w.ax = 0x800; // 物理地址 -> 线形地址
regs.w.bx = physAddr >> 16;
regs.w.cx = physAddr & 0xFFFF;
regs.w.si = limit >> 16;
regs.w.di = limit & 0xFFFF;
int386(0x31, ®s, ®s);
if (regs.w.cflag) return FALSE;
return ((unsigned long)regs.w.bx << 16) + regs.w.cx;
}
unsigned long DPMIGetSelectorBase(unsigned short Selector)
{ union REGS regs;
regs.w.ax = 6; // 取描述符的基地址
regs.w.bx = Selector;
int386(0x31, ®s, ®s);
return ((unsigned long)regs.w.cx << 16) + regs.w.dx;
}
char DPMISetSelectorLimit(unsigned short Selector, unsigned long limit)
{ union REGS regs;
regs.w.ax = 8; // 设置描述符的访问范围
regs.w.bx = Selector;
regs.w.cx = limit >> 16;
regs.w.dx = limit & 0xFFFF;
int386(0x31, ®s, ®s);
if (regs.w.cflag) return FALSE;
return TRUE;
}
void *DPMIPhysicalAddr(unsigned long base, unsigned long limit)
{
struct SREGS sregs;
unsigned long linAddr;
unsigned long DSBaseAddr;
segread(&sregs);
DSBaseAddr = DPMIGetSelectorBase(sregs.ds);
if((linAddr = DPMIPhysicalToLinear(base, limit))==FALSE)
return NULL;
if(DPMISetSelectorLimit(sregs.ds, 0xFFFFFFFFUL)==FALSE)
return NULL;
return (void*)(linAddr - DSBaseAddr);
}
char GetVesaInfo(void) // 取VESA显示卡信息
{
unsigned short segment, selector;
unsigned char *vesalist;
DpmiRealMalloc(0x0010, &segment, &selector);
if(segment == NULL)
{
printf("Error: Malloc DOS memory error !\n");
return FALSE;
}
memset(&RMI, 0, sizeof(RMI));
RMI.EAX = VESA_FUNC + VESA_VGA_INFO;
RMI.ES = segment;
RMI.EDI = 0;
DpmiRealInt386x(0x10, &RMI);
if(RMI.EAX == VESA_SUCCESS)
{
vesalist = (unsigned char *)(segment<<4);
memcpy(&HardWareInfo, vesalist, 256);
if(strncmp((char*)HardWareInfo.VESASignature, "VESA", 4) == 0)
{
unsigned char *OEMStr, *VideoPtr;
OEMStr = (unsigned char *)((unsigned long)(HardWareInfo.OEMStringSeg<<4)
+HardWareInfo.OEMStringOff);
VideoPtr = (unsigned char *)((unsigned long)(HardWareInfo.VideoModePtrSeg<<4)
+HardWareInfo.VideoModePtrOff);
DpmiRealFree(selector);
if( VESA_VERSION_MAJOR(HardWareInfo.VESAVersion) < 2)
{
printf("Error: Requirement VESA V2.0 !!!\n");
return FALSE;
}
return TRUE;
}
printf("Error: VESA ID not found !\n");
return FALSE;
}
DpmiRealFree(selector);
printf("Error: INT 10h 4F00 Call failed !\n");
return FALSE;
}
char GetVesaModeInfo(unsigned short mode) // 取VESA显示卡指定模式信息
{
unsigned short segment, selector;
unsigned char *vesalist;
DpmiRealMalloc(0x0010, &segment, &selector);
if(segment == NULL)
{
printf("Error: Malloc DOS memory error !\n");
return FALSE;
}
memset(&RMI, 0, sizeof(RMI));
RMI.EAX = VESA_FUNC + VESA_MODE_INFO;
RMI.ES = segment;
RMI.ECX = mode;
RMI.EDI = 0;
DpmiRealInt386x(0x10, &RMI);
if(RMI.EAX == VESA_SUCCESS)
{
vesalist = (unsigned char *)(segment<<4);
memcpy(&VesaModeInfo, vesalist, 256);
if((VesaModeInfo.ModeAttributes & MODE_SUPPORTED) == 1)
{
VideoPhysBasePtr = VesaModeInfo.PhysBasePtr;
DpmiRealFree(selector);
return TRUE;
}
printf("Error: VESA %xh Mode no supported !\n", mode);
return FALSE;
}
DpmiRealFree(selector);
printf("Error: INT 10h 4F01 Call failed !\n");
return FALSE;
}
char vesa_2l_init(short mode) // 初始化显示卡
{
if(GetVesaInfo()==TRUE)
{
if(GetVesaModeInfo(mode)==TRUE)
{
if(SetVesaMode(mode)==FALSE)
{ grp_exit();
printf("Error: VESA %xh Mode set Error !\n", mode);
return FALSE;
}
}
else
{grp_exit();
printf("Error: Get VESA %xh mode Information Error !\n", mode);
return FALSE;
}
screen->w=VesaModeInfo.XResolution;
screen->h=VesaModeInfo.YResolution;
_Display=create_bitmap(screen->w,screen->h);
delete []_Display->dat;
_Display->dat=(unsigned char *)DPMIPhysicalAddr(VideoPhysBasePtr,
VesaModeInfo.XResolution*VesaModeInfo.YResolution);
_Display->line[0]=_Display->dat;
for(int i=1;i<screen->h;i++)
_Display->line[i]=_Display->line[i-1]+screen->w;
return TRUE;
}
return FALSE;
}
char SetVesaMode(short mode) // 设置显示模式
{
union REGS regs;
memset(®s, 0, sizeof(regs));
regs.x.eax = VESA_FUNC+VESA_SET_MODE;
regs.x.ebx = mode;
regs.x.ebx |= 0xc000; // VESA 2.0 新定义了bit14
int386 (0x10, ®s, ®s);
if(regs.w.ax == VESA_SUCCESS){
return TRUE;
}
else
{
printf("Error: Set VESA Mode: %x\n", mode);
return FALSE;
}
}
unsigned short GetVesaMode(void) // 取当前的显示模式
{
union REGS regs;
memset(®s, 0, sizeof(regs));
regs.x.eax = VESA_FUNC+VESA_GET_MODE;
int386 (0x10, ®s, ®s);
return (regs.w.bx&0xfff);
}
void setwritemode(char mode)
{if(mode){screen=_Display;screen_write=0;}
else
if(_Screen!=NULL)
{screen=_Screen;screen_write=1;}
}
/* 真正的显卡初始化
mode 显示模式,在vesa.h中有定义
*/
char grp_init(int mode)
{
LineWriteMode.StyLine=0xff;//画线模式
if(mode>=0x100)
{ if(vesa_2l_init(mode)==FALSE){
grp_exit();
printf("Error: Can't Set VESA Liner Mode: %x\n", mode);
exit(0);
}
}
else
{union REGS r;
r.w.ax=mode;
int386(0x10,&r,&r);
screen->w=320;
screen->h=200;
_Display=create_bitmap(320,200);
delete [] _Display->dat;
_Display->dat=(unsigned char *)0xa0000;
_Display->line[0]=_Display->dat;
for(unsigned char i=1;i<200;i++)
_Display->line[i]=_Display->line[i-1]+320;
screen_videomem=64000;
}
screen_videomem=screen->w*screen->h;
// _Screen=create_bitmap(screen->w,screen->h);
timer_init();
setwritemode(TRUE);
clear(screen);
grp_mem_lock(screen->dat,screen_videomem);
atexit(grp_exit);
return TRUE;
}
//退出图形模式
void grp_exit()
{ grp_mem_unlock(screen->dat,screen_videomem);
union REGS r;
r.w.ax=3;
int386(0x10,&r,&r);
if(_Screen->dat!=NULL)destroy_bitmap(_Screen);
}
void Disappear(int time)
{ register int i,j,k;
unsigned char Source[256][3];
for(j=0;j<3;j++)
for(i=0;i<256;i++)
Source[i][j]=ColorTable[i][j];
for(j=0;j<64;j++)
{delay(time);
for(i=0;i<256;i++)
{
outp(0x3c8,i);
for(k=0;k<3;k++)
{if(Source[i][k]>0)Source[i][k]--;
outp(0x3c9,Source[i][k]);
}
}
}
}
//渐显
void Appear(int time)
{ register int i,j,k;
unsigned char Source[256][3];
for(i=0;i<3;i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -