📄 vesa.cpp
字号:
#include "vesa.h"
VIDEO_VESA::VIDEO_VESA(void)
{
addr = 0;
info_block.AllocateMem(512);
if(GetControllerInfo() == VESA_PASS)
{
if(GetVersion() >= 2.0)
vesa20_support = TRUE;
else
vesa20_support = FALSE;
ReadModeList();
VESA_MODE_INFO_BLOCK vmib;
for(int i=0; i<mode_list_length; i++)
{
GetModeInfo(mode_list[i].mode_number, &vmib);
mode_list[i].width = vmib.XResolution;
mode_list[i].height = vmib.YResolution;
mode_list[i].bpp = vmib.BitsPerPixel;
if(vmib.ModeAttributes & 0x80)
mode_list[i].mode_number |= 0x4000;
}
}
else
{
vesa20_support = FALSE;
mode_list_length = 0;
}
}
VIDEO_VESA::~VIDEO_VESA(void)
{
if(addr != 0)
free(addr);
}
int VIDEO_VESA::GetControllerInfo()
{
__dpmi_regs regs;
info_block.Set((DWORD)0x32454256);
#ifdef _DEBUG_
printf("DOS MEM = 0x%08X\n",info_block.GetAddress());
printf(" Offset = 0x%04X\n", info_block.GetOffset());
printf(" Segment = 0x%04X\n", info_block.GetSegment());
#endif
regs.d.eax = VESA_CONTROLLER_INFO;
regs.x.es = info_block.GetSegment();
regs.d.edi = info_block.GetOffset();
__dpmi_int(VIDEO_INT_NUM, ®s);
if(regs.h.al != 0x4f || regs.h.ah != 0 ||
info_block.GetDWORD() != 0x41534556)
return VESA_FAIL;
else
return VESA_PASS;
}
float VIDEO_VESA::GetVersion(void)
{
BYTE version_num;
BYTE rev_num;
rev_num = info_block.GetBYTE(4);
version_num = info_block.GetBYTE(5);
return ((float)(version_num) + ((float)(rev_num)/10.0));
}
void VIDEO_VESA::ReadModeList(void)
{
UWORD mode_num;
int i = 0;
mode_list_length = 0;
do
{
mode_num = info_block.GetDosMemWORD(info_block.GetWORD(0x10),
info_block.GetWORD(0xe) + i);
i += 2;
if(mode_num != 0xffff)
mode_list[mode_list_length++].mode_number = mode_num;
}while(mode_num != 0xffff && mode_list_length < MAX_VESA_MODES);
}
int VIDEO_VESA::GetModeInfo(int mode, VESA_MODE_INFO_BLOCK *vmib)
{
__dpmi_regs regs;
DOS_MEM dos_vmib(sizeof(VESA_MODE_INFO_BLOCK));
/* get mode info */
regs.d.eax = VESA_MODE_INFO;
regs.d.ecx = mode & 0x3fff;
regs.x.es = dos_vmib.GetSegment();
regs.d.edi = dos_vmib.GetOffset();
__dpmi_int(VIDEO_INT_NUM, ®s);
if(regs.h.al != 0x4f || regs.h.ah != 0x0)
return VESA_FAIL;
dosmemget(dos_vmib.GetAddress(), sizeof(VESA_MODE_INFO_BLOCK), vmib);
return VESA_PASS;
}
int VIDEO_VESA::GetMode(void)
{
__dpmi_regs regs;
/* get current mode */
regs.d.eax = VESA_GET_MODE;
__dpmi_int(VIDEO_INT_NUM, ®s);
if(regs.h.al != 0x4f || regs.h.ah != 0)
return -1;
return regs.x.bx;
}
int VIDEO_VESA::FindMode(int width, int height, int bpp)
{
int i;
UDWORD total_error = 65535;
int mode = 0;
for(i=0; i<mode_list_length; i++)
{
UDWORD error = abs(width - mode_list[i].width) +
abs(height - mode_list[i].height) +
abs(bpp - mode_list[i].bpp);
if(error <= total_error)
{
total_error = error;
mode = i;
}
}
return mode_list[mode].mode_number;
}
int VIDEO_VESA:: SetMode(int mode)
{
VESA_MODE_INFO_BLOCK vmib;
__dpmi_regs regs;
/* set video mode */
regs.d.eax = VESA_SET_MODE;
regs.x.bx = mode;
__dpmi_int(VIDEO_INT_NUM, ®s);
if(regs.h.al != 0x4f || regs.h.ah != 0)
return VESA_FAIL;
GetModeInfo(mode, &vmib);
DWORD LfbSize = LfbSize = vmib.XResolution * vmib.YResolution
* vmib.BitsPerPixel / 8;
DWORD len = (LfbSize + 0xfff) & 0xfffff000;
if(addr != 0) free(addr);
addr = (BYTE*)malloc(len + 0xfff);
virt_addr = (BYTE*)((DWORD)(addr + 0xfff) & 0xfffff000);
if(addr == 0)
{
printf("Error allocate memory for video!\n");
exit(10);
}
if(__djgpp_map_physical_memory(virt_addr, len,
vmib.PhysBasePtr) == -1)
{
printf("Failed map physical memory for video\n");
exit(10);
}
return VESA_PASS;
}
int VIDEO_VESA::SetMode(int width, int height, int bpp)
{
int mode = FindMode(width, height, bpp);
if(SetMode(mode) == VESA_FAIL)
return VESA_FAIL;
return VESA_PASS;
}
DWORD VIDEO_VESA::GetVideoBuffer(void)
{
return (DWORD)virt_addr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -