📄 vid_ext.c
字号:
vesa_extra[nummodes].plinearmem =
real2ptr (phys_mem_info.address);
}
else
{
// banked at 0xA0000
vesa_extra[nummodes].vesamode = modeinfo.modenum;
vesa_extra[nummodes].pages[0] = 0;
vesa_extra[nummodes].plinearmem =
real2ptr(modeinfo.winasegment<<4);
vesa_modes[nummodes].begindirectrect =
VGA_BankedBeginDirectRect;
vesa_modes[nummodes].enddirectrect = VGA_BankedEndDirectRect;
vesa_extra[nummodes].pages[1] = modeinfo.pagesize;
vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2;
vesa_modes[nummodes].numpages = modeinfo.numpages;
}
vesa_extra[nummodes].vga_incompatible =
modeinfo.mode_attributes & VGA_INCOMPATIBLE;
nummodes++;
}
NextMode:
pmodenums++;
}
// add the VESA modes at the start of the mode list (if there are any)
if (nummodes)
{
vesa_modes[nummodes-1].pnext = pvidmodes;
pvidmodes = &vesa_modes[0];
numvidmodes += nummodes;
ppal = dos_getmemory(256*4);
}
dos_freememory(pinfoblock);
}
/*
================
VID_ExtraGetModeInfo
================
*/
qboolean VID_ExtraGetModeInfo(int modenum)
{
char *infobuf;
int numimagepages;
infobuf = dos_getmemory(256);
regs.x.ax = 0x4f01;
regs.x.cx = modenum;
regs.x.es = ptr2real(infobuf) >> 4;
regs.x.di = ptr2real(infobuf) & 0xf;
dos_int86(0x10);
if (regs.x.ax != 0x4f)
{
return false;
}
else
{
modeinfo.modenum = modenum;
modeinfo.bits_per_pixel = *(char*)(infobuf+25);
modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8;
modeinfo.width = *(short*)(infobuf+18);
modeinfo.height = *(short*)(infobuf+20);
// we do only 8-bpp in software
if ((modeinfo.bits_per_pixel != 8) ||
(modeinfo.bytes_per_pixel != 1) ||
(modeinfo.width > MAXWIDTH) ||
(modeinfo.height > MAXHEIGHT))
{
return false;
}
modeinfo.mode_attributes = *(short*)infobuf;
// we only want color graphics modes that are supported by the hardware
if ((modeinfo.mode_attributes &
(MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) !=
(MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE))
{
return false;
}
// we only work with linear frame buffers, except for 320x200, which can
// effectively be linear when banked at 0xA000
if (!(modeinfo.mode_attributes & LINEAR_FRAME_BUFFER))
{
if ((modeinfo.width != 320) || (modeinfo.height != 200))
return false;
}
modeinfo.bytes_per_scanline = *(short*)(infobuf+16);
modeinfo.pagesize = modeinfo.bytes_per_scanline * modeinfo.height;
if (modeinfo.pagesize > totalvidmem)
return false;
// force to one page if the adapter reports it doesn't support more pages
// than that, no matter how much memory it has--it may not have hardware
// support for page flipping
numimagepages = *(unsigned char *)(infobuf+29);
if (numimagepages <= 0)
{
// wrong, but there seems to be an ATI VESA driver that reports 0
modeinfo.numpages = 1;
}
else if (numimagepages < 3)
{
modeinfo.numpages = numimagepages;
}
else
{
modeinfo.numpages = 3;
}
if (*(char*)(infobuf+2) & 5)
{
modeinfo.winasegment = *(unsigned short*)(infobuf+8);
modeinfo.win = 0;
}
else if (*(char*)(infobuf+3) & 5)
{
modeinfo.winbsegment = *(unsigned short*)(infobuf+8);
modeinfo.win = 1;
}
modeinfo.granularity = *(short*)(infobuf+4) * 1024;
modeinfo.win_size = *(short*)(infobuf+6) * 1024;
modeinfo.bits_per_pixel = *(char*)(infobuf+25);
modeinfo.bytes_per_pixel = (modeinfo.bits_per_pixel+1)/8;
modeinfo.memory_model = *(unsigned char*)(infobuf+27);
modeinfo.num_pages = *(char*)(infobuf+29) + 1;
modeinfo.red_width = *(char*)(infobuf+31);
modeinfo.red_pos = *(char*)(infobuf+32);
modeinfo.green_width = *(char*)(infobuf+33);
modeinfo.green_pos = *(char*)(infobuf+34);
modeinfo.blue_width = *(char*)(infobuf+35);
modeinfo.blue_pos = *(char*)(infobuf+36);
modeinfo.pptr = *(long *)(infobuf+40);
#if 0
printf("VID: (VESA) info for mode 0x%x\n", modeinfo.modenum);
printf(" mode attrib = 0x%0x\n", modeinfo.mode_attributes);
printf(" win a attrib = 0x%0x\n", *(unsigned char*)(infobuf+2));
printf(" win b attrib = 0x%0x\n", *(unsigned char*)(infobuf+3));
printf(" win a seg 0x%0x\n", (int) modeinfo.winasegment);
printf(" win b seg 0x%0x\n", (int) modeinfo.winbsegment);
printf(" bytes per scanline = %d\n",
modeinfo.bytes_per_scanline);
printf(" width = %d, height = %d\n", modeinfo.width,
modeinfo.height);
printf(" win = %c\n", 'A' + modeinfo.win);
printf(" win granularity = %d\n", modeinfo.granularity);
printf(" win size = %d\n", modeinfo.win_size);
printf(" bits per pixel = %d\n", modeinfo.bits_per_pixel);
printf(" bytes per pixel = %d\n", modeinfo.bytes_per_pixel);
printf(" memory model = 0x%x\n", modeinfo.memory_model);
printf(" num pages = %d\n", modeinfo.num_pages);
printf(" red width = %d\n", modeinfo.red_width);
printf(" red pos = %d\n", modeinfo.red_pos);
printf(" green width = %d\n", modeinfo.green_width);
printf(" green pos = %d\n", modeinfo.green_pos);
printf(" blue width = %d\n", modeinfo.blue_width);
printf(" blue pos = %d\n", modeinfo.blue_pos);
printf(" phys mem = %x\n", modeinfo.pptr);
#endif
}
dos_freememory(infobuf);
return true;
}
/*
================
VID_ExtraInitMode
================
*/
int VID_ExtraInitMode (viddef_t *lvid, vmode_t *pcurrentmode)
{
vesa_extra_t *pextra;
int pageoffset;
pextra = pcurrentmode->pextradata;
if (vid_nopageflip->value)
lvid->numpages = 1;
else
lvid->numpages = pcurrentmode->numpages;
// clean up any old vid buffer lying around, alloc new if needed
if (!VGA_FreeAndAllocVidbuffer (lvid, lvid->numpages == 1))
return -1; // memory alloc failed
// clear the screen and wait for the next frame. VGA_pcurmode, which
// VGA_ClearVideoMem relies on, is guaranteed to be set because mode 0 is
// always the first mode set in a session
if (VGA_pcurmode)
VGA_ClearVideoMem (VGA_pcurmode->planar);
// set the mode
regs.x.ax = 0x4f02;
regs.x.bx = pextra->vesamode;
dos_int86(0x10);
if (regs.x.ax != 0x4f)
return 0;
VID_banked = !(pextra->vesamode & LINEAR_MODE);
VID_membase = pextra->plinearmem;
VGA_width = lvid->width;
VGA_height = lvid->height;
VGA_rowbytes = lvid->rowbytes;
lvid->colormap = host_colormap;
VID_pagelist = &pextra->pages[0];
// wait for display enable by default only when triple-buffering on a VGA-
// compatible machine that actually has a functioning display enable status
vsync_exists = VID_ExtraStateFound (0x08);
de_exists = VID_ExtraStateFound (0x01);
if (!pextra->vga_incompatible &&
(lvid->numpages == 3) &&
de_exists &&
(_vid_wait_override->value == 0.0))
{
Cvar_SetValue (vid_wait, (float)VID_WAIT_DISPLAY_ENABLE);
VID_displayedpage = 0;
VID_currentpage = 1;
}
else
{
if ((lvid->numpages == 1) && (_vid_wait_override->value == 0.0))
{
Cvar_SetValue (vid_wait, (float)VID_WAIT_NONE);
VID_displayedpage = VID_currentpage = 0;
}
else
{
Cvar_SetValue (vid_wait, (float)VID_WAIT_VSYNC);
VID_displayedpage = 0;
if (lvid->numpages > 1)
VID_currentpage = 1;
else
VID_currentpage = 0;
}
}
// TODO: really should be a call to a function
pageoffset = VID_pagelist[VID_displayedpage];
regs.x.ax = 0x4f07;
regs.x.bx = 0x80; // wait for vsync so we know page 0 is visible
regs.x.cx = pageoffset % VGA_rowbytes;
regs.x.dx = pageoffset / VGA_rowbytes;
dos_int86(0x10);
if (VID_banked)
{
regs.x.ax = 0x4f05;
regs.x.bx = 0;
regs.x.dx = VID_currentpage;
dos_int86(0x10);
VGA_pagebase = VID_membase;
}
else
{
VGA_pagebase = VID_membase + VID_pagelist[VID_currentpage];
}
if (lvid->numpages > 1)
{
lvid->buffer = VGA_pagebase;
lvid->conbuffer = lvid->buffer;
}
else
{
lvid->rowbytes = lvid->width;
}
lvid->direct = VGA_pagebase;
lvid->conrowbytes = lvid->rowbytes;
lvid->conwidth = lvid->width;
lvid->conheight = lvid->height;
lvid->maxwarpwidth = WARP_WIDTH;
lvid->maxwarpheight = WARP_HEIGHT;
VGA_pcurmode = pcurrentmode;
D_InitCaches (vid_surfcache, vid_surfcachesize);
return 1;
}
/*
================
VID_ExtraSwapBuffers
================
*/
void VID_ExtraSwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode,
vrect_t *rects)
{
int pageoffset;
UNUSED(rects);
UNUSED(pcurrentmode);
pageoffset = VID_pagelist[VID_currentpage];
// display the newly finished page
if (lvid->numpages > 1)
{
// page flipped
regs.x.ax = 0x4f07;
if (vid_wait->value != VID_WAIT_VSYNC)
{
if ((vid_wait->value == VID_WAIT_DISPLAY_ENABLE) && de_exists)
VID_ExtraWaitDisplayEnable ();
regs.x.bx = VESA_DONT_WAIT_VSYNC;
}
else
{
regs.x.bx = VESA_WAIT_VSYNC; // double buffered has to wait
}
regs.x.cx = pageoffset % VGA_rowbytes;
regs.x.dx = pageoffset / VGA_rowbytes;
dos_int86(0x10);
VID_displayedpage = VID_currentpage;
if (++VID_currentpage >= lvid->numpages)
VID_currentpage = 0;
//
// set the new write window if this is a banked mode; otherwise, set the
// new address to which to write
//
if (VID_banked)
{
regs.x.ax = 0x4f05;
regs.x.bx = 0;
regs.x.dx = VID_currentpage;
dos_int86(0x10);
}
else
{
lvid->direct = lvid->buffer; // direct drawing goes to the
// currently displayed page
lvid->buffer = VID_membase + VID_pagelist[VID_currentpage];
lvid->conbuffer = lvid->buffer;
}
VGA_pagebase = lvid->buffer;
}
else
{
// non-page-flipped
if (vsync_exists && (vid_wait->value == VID_WAIT_VSYNC))
{
VGA_WaitVsync ();
}
while (rects)
{
VGA_UpdateLinearScreen (
lvid->buffer + rects->x + (rects->y * lvid->rowbytes),
VGA_pagebase + rects->x + (rects->y * VGA_rowbytes),
rects->width,
rects->height,
lvid->rowbytes,
VGA_rowbytes);
rects = rects->pnext;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -