/* ================ VID_SetVESAPalette ================ */ void VID_SetVESAPalette (viddef_t *lvid, vmode_t *pcurrentmode, unsigned char *pal) { int i; byte *pp; UNUSED(lvid); UNUSED(pcurrentmode); pp = ppal; for (i=0 ; i<256 ; i++) { pp[2] = pal[0] >> 2; pp[1] = pal[1] >> 2; pp[0] = pal[2] >> 2; pp += 4; pal += 3; } regs.x.ax = 0x4F09; regs.x.bx = 0; regs.x.cx = 256; regs.x.dx = 0; regs.x.es = ptr2real(ppal) >> 4; regs.x.di = ptr2real(ppal) & 0xf; dos_int86(0x10); if (regs.x.ax != 0x4f) Sys_Error ("Unable to load VESA palette\n"); }
/* ================ VGA_BankedEndDirectRect ================ */ void VGA_BankedEndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x, int y, int width, int height) { regs.x.ax = 0x4f05; regs.x.bx = 0; regs.x.dx = VID_displayedpage; dos_int86(0x10); VGA_EndDirectRect (lvid, pcurrentmode, x, y, width, height); regs.x.ax = 0x4f05; regs.x.bx = 0; regs.x.dx = VID_currentpage; dos_int86(0x10); }
/* ================ VID_Shutdown ================ */ void VID_Shutdown (void) { regs.h.ah = 0; regs.h.al = 0x3; dos_int86(0x10); vid_testingmode = 0; }
void Sys_Quit (void) { byte screen[80*25*2]; // byte *d; // 2001-09-12 Returning information about loaded file by Maddes char ver[6]; int i; loadedfile_t *fileinfo; // 2001-09-12 Returning information about loaded file by Maddes // load the sell screen before shuting everything down if (registered->value) // 2001-09-12 Returning information about loaded file by Maddes start // d = COM_LoadHunkFile ("end2.bin"); fileinfo = COM_LoadHunkFile ("end2.bin"); // 2001-09-12 Returning information about loaded file by Maddes end else // 2001-09-12 Returning information about loaded file by Maddes start // d = COM_LoadHunkFile ("end1.bin"); fileinfo = COM_LoadHunkFile ("end1.bin"); // 2001-09-12 Returning information about loaded file by Maddes end // 2001-09-12 Returning information about loaded file by Maddes start /* if (d) memcpy (screen, d, sizeof(screen)); */ if (fileinfo) memcpy (screen, fileinfo->data, sizeof(screen)); // 2001-09-12 Returning information about loaded file by Maddes end // write the version number directly to the end screen sprintf (ver, " v%4.2f", VERSION); for (i=0 ; i<6 ; i++) screen[0*80*2 + 72*2 + i*2] = ver[i]; Host_Shutdown(); // do the text mode sell screen // 2001-09-12 Returning information about loaded file by Maddes start // if (d) if (fileinfo) // 2001-09-12 Returning information about loaded file by Maddes end { memcpy ((void *)real2ptr(0xb8000), screen,80*25*2); // set text pos regs.x.ax = 0x0200; regs.h.bh = 0; regs.h.dl = 0; regs.h.dh = 22; dos_int86 (0x10); } else printf ("couldn't load endscreen.\n"); exit(0); }
/* ================ VGA_BankedBeginDirectRect ================ */ void VGA_BankedBeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x, int y, byte *pbitmap, int width, int height) { if (!lvid->direct) return; regs.x.ax = 0x4f05; regs.x.bx = 0; regs.x.dx = VID_displayedpage; dos_int86(0x10); VGA_BeginDirectRect (lvid, pcurrentmode, x, y, pbitmap, width, height); regs.x.ax = 0x4f05; regs.x.bx = 0; regs.x.dx = VID_currentpage; dos_int86(0x10); }
void Sys_Quit(void) { byte screen[80*25*2]; byte *d; char ver[6]; int i; // load the sell screen before shuting everything down if (registered.value) { d = COM_LoadHunkFile("end2.bin"); } else { d = COM_LoadHunkFile("end1.bin"); } if (d) { memcpy(screen, d, sizeof(screen)); } // write the version number directly to the end screen sprintf(ver, " v%4.2f", VERSION); for (i=0 ; i<6 ; i++) { screen[0*80*2 + 72*2 + i*2] = ver[i]; } Host_Shutdown(); // do the text mode sell screen if (d) { memcpy((void *)real2ptr(0xb8000), screen,80*25*2); // set text pos regs.x.ax = 0x0200; regs.h.bh = 0; regs.h.dl = 0; regs.h.dh = 22; dos_int86(0x10); } else { printf("couldn't load endscreen.\n"); } exit(0); }
/* ================ 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; } } }
/* ================ 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_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_InitExtra ================ */ void VID_InitExtra (void) { int nummodes; short *pmodenums; vbeinfoblock_t *pinfoblock; __dpmi_meminfo phys_mem_info; pinfoblock = dos_getmemory(sizeof(vbeinfoblock_t)); *(long *)pinfoblock->VbeSignature = 'V' + ('B'<<8) + ('E'<<16) + ('2'<<24); // see if VESA support is available regs.x.ax = 0x4f00; regs.x.es = ptr2real(pinfoblock) >> 4; regs.x.di = ptr2real(pinfoblock) & 0xf; dos_int86(0x10); if (regs.x.ax != 0x4f) return; // no VESA support if (pinfoblock->VbeVersion[1] < 0x02) return; // not VESA 2.0 or greater Con_Printf ("VESA 2.0 compliant adapter:\n%s\n", VID_ExtraFarToLinear (*(byte **)&pinfoblock->OemStringPtr[0])); totalvidmem = *(unsigned short *)&pinfoblock->TotalMemory[0] << 16; pmodenums = (short *) VID_ExtraFarToLinear (*(byte **)&pinfoblock->VideoModePtr[0]); // find 8 bit modes until we either run out of space or run out of modes nummodes = 0; while ((*pmodenums != -1) && (nummodes < MAX_VESA_MODES)) { if (VID_ExtraGetModeInfo (*pmodenums)) { vesa_modes[nummodes].pnext = &vesa_modes[nummodes+1]; if (modeinfo.width > 999) { if (modeinfo.height > 999) { sprintf (&names[nummodes][0], "%4dx%4d", modeinfo.width, modeinfo.height); names[nummodes][9] = 0; } else { sprintf (&names[nummodes][0], "%4dx%3d", modeinfo.width, modeinfo.height); names[nummodes][8] = 0; } } else { if (modeinfo.height > 999) { sprintf (&names[nummodes][0], "%3dx%4d", modeinfo.width, modeinfo.height); names[nummodes][8] = 0; } else { sprintf (&names[nummodes][0], "%3dx%3d", modeinfo.width, modeinfo.height); names[nummodes][7] = 0; } } vesa_modes[nummodes].name = &names[nummodes][0]; vesa_modes[nummodes].width = modeinfo.width; vesa_modes[nummodes].height = modeinfo.height; vesa_modes[nummodes].aspect = ((float)modeinfo.height / (float)modeinfo.width) * (320.0 / 240.0); vesa_modes[nummodes].rowbytes = modeinfo.bytes_per_scanline; vesa_modes[nummodes].planar = 0; vesa_modes[nummodes].pextradata = &vesa_extra[nummodes]; vesa_modes[nummodes].setmode = VID_ExtraInitMode; vesa_modes[nummodes].swapbuffers = VID_ExtraSwapBuffers; vesa_modes[nummodes].setpalette = VID_SetVESAPalette; if (modeinfo.mode_attributes & LINEAR_FRAME_BUFFER) { // add linear bit to mode for linear modes vesa_extra[nummodes].vesamode = modeinfo.modenum | LINEAR_MODE; vesa_extra[nummodes].pages[0] = 0; vesa_extra[nummodes].pages[1] = modeinfo.pagesize; vesa_extra[nummodes].pages[2] = modeinfo.pagesize * 2; vesa_modes[nummodes].numpages = modeinfo.numpages; vesa_modes[nummodes].begindirectrect = VGA_BeginDirectRect; vesa_modes[nummodes].enddirectrect = VGA_EndDirectRect; phys_mem_info.address = (int)modeinfo.pptr; phys_mem_info.size = 0x400000; if (__dpmi_physical_address_mapping(&phys_mem_info)) goto NextMode; 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); }