/* ================ 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"); }
//============================================================================= // Programs the DMA controller to start DMAing in Auto-init mode //============================================================================= static void GUS_StartDMA(BYTE DmaChannel,short *dma_buffer,int count) { int mode; int RealAddr; RealAddr = ptr2real(dma_buffer); if (DmaChannel <= 3) { ModeReg = 0x0B; DisableReg = 0x0A; ClearReg = 0x0E; } else { ModeReg = 0xD6; DisableReg = 0xD4; ClearReg = 0xDC; } CountReg=CountRegs[DmaChannel]; AddrReg=AddrRegs[DmaChannel]; dos_outportb(DisableReg, DmaChannel | 4); // disable channel // set mode- see "undocumented pc", p.876 mode = (1<<6) // single-cycle +(0<<5) // address increment +(1<<4) // auto-init dma +(2<<2) // read +(DmaChannel & 0x03); // channel # dos_outportb(ModeReg, mode); // set page dos_outportb(PageRegs[DmaChannel], RealAddr >> 16); if (DmaChannel <= 3) { // address is in bytes dos_outportb(0x0C, 0); // prepare to send 16-bit value dos_outportb(AddrReg, RealAddr & 0xff); dos_outportb(AddrReg, (RealAddr>>8) & 0xff); dos_outportb(0x0C, 0); // prepare to send 16-bit value dos_outportb(CountReg, (count-1) & 0xff); dos_outportb(CountReg, (count-1) >> 8); }
/* ================ 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); }