#include "quakedef.h" #ifdef SWQUAKE #include "sw.h" /* from http://www.delorie.com/djgpp/doc/ug/graphics/vesa.html */ typedef struct VESA_INFO { unsigned char VESASignature[4]; unsigned short VESAVersion __attribute__ ((packed)); unsigned long OEMStringPtr __attribute__ ((packed)); unsigned char Capabilities[4]; unsigned long VideoModePtr __attribute__ ((packed)); unsigned short TotalMemory __attribute__ ((packed)); unsigned short OemSoftwareRev __attribute__ ((packed)); unsigned long OemVendorNamePtr __attribute__ ((packed)); unsigned long OemProductNamePtr __attribute__ ((packed)); unsigned long OemProductRevPtr __attribute__ ((packed)); unsigned char Reserved[222]; unsigned char OemData[256]; } VESA_INFO; #include #include #include static VESA_INFO vesa_info; static int get_vesa_info() { __dpmi_regs r; long dosbuf; int c; /* use the conventional memory transfer buffer */ dosbuf = __tb & 0xFFFFF; /* initialize the buffer to zero */ for (c=0; c>4) & 0xFFFF; __dpmi_int(0x10, &r); /* quit if there was an error */ if (r.h.ah) return -1; /* copy the resulting data into our structure */ dosmemget(dosbuf, sizeof(VESA_INFO), &vesa_info); /* check that we got the right magic marker value */ if (strncmp(vesa_info.VESASignature, "VESA", 4) != 0) return -1; /* it worked! */ return 0; } typedef struct MODE_INFO { unsigned short ModeAttributes __attribute__ ((packed)); unsigned char WinAAttributes; unsigned char WinBAttributes; unsigned short WinGranularity __attribute__ ((packed)); unsigned short WinSize __attribute__ ((packed)); unsigned short WinASegment __attribute__ ((packed)); unsigned short WinBSegment __attribute__ ((packed)); unsigned long WinFuncPtr __attribute__ ((packed)); unsigned short BytesPerScanLine __attribute__ ((packed)); unsigned short XResolution __attribute__ ((packed)); unsigned short YResolution __attribute__ ((packed)); unsigned char XCharSize; unsigned char YCharSize; unsigned char NumberOfPlanes; unsigned char BitsPerPixel; unsigned char NumberOfBanks; unsigned char MemoryModel; unsigned char BankSize; unsigned char NumberOfImagePages; unsigned char Reserved_page; unsigned char RedMaskSize; unsigned char RedMaskPos; unsigned char GreenMaskSize; unsigned char GreenMaskPos; unsigned char BlueMaskSize; unsigned char BlueMaskPos; unsigned char ReservedMaskSize; unsigned char ReservedMaskPos; unsigned char DirectColorModeInfo; unsigned long PhysBasePtr __attribute__ ((packed)); unsigned long OffScreenMemOffset __attribute__ ((packed)); unsigned short OffScreenMemSize __attribute__ ((packed)); unsigned char Reserved[206]; } MODE_INFO; static MODE_INFO mode_info; static int get_mode_info(int mode) { __dpmi_regs r; long dosbuf; int c; /* use the conventional memory transfer buffer */ dosbuf = __tb & 0xFFFFF; /* initialize the buffer to zero */ for (c=0; c>4) & 0xFFFF; r.x.cx = mode; __dpmi_int(0x10, &r); /* quit if there was an error */ if (r.h.ah) return -1; /* copy the resulting data into our structure */ dosmemget(dosbuf, sizeof(MODE_INFO), &mode_info); /* it worked! */ return 0; } static int find_vesa_mode(int w, int h, int bpp) { int mode_list[256]; int number_of_modes; long mode_ptr; int c; /* check that the VESA driver exists, and get information about it */ if (get_vesa_info() != 0) return 0; /* convert the mode list pointer from seg:offset to a linear address */ mode_ptr = ((vesa_info.VideoModePtr & 0xFFFF0000) >> 12) + (vesa_info.VideoModePtr & 0xFFFF); number_of_modes = 0; /* read the list of available modes */ while (_farpeekw(_dos_ds, mode_ptr) != 0xFFFF) { mode_list[number_of_modes] = _farpeekw(_dos_ds, mode_ptr); number_of_modes++; mode_ptr += 2; } /* scan through the list of modes looking for the one that we want */ for (c=0; c 0) { /* select the appropriate bank */ set_vesa_bank(bank_number); /* how much can we copy in one go? */ if (todo > bank_size) copy_size = bank_size; else copy_size = todo; /* copy a bank of data to the screen */ dosmemput(memory_buffer, copy_size, 0xA0000); /* move on to the next bank of data */ todo -= copy_size; memory_buffer += copy_size; bank_number += bank_size/bank_granularity; } } extern int nostdout; //we flag with 0x800 to disable printfs while displaying stuff. static qboolean videoatexitregistered; static void videoatexit(void) { if (nostdout & 0x800) { nostdout &= ~0x800; __dpmi_regs r; r.x.ax = 0x0000 | 3; __dpmi_int(0x10, &r); } } static unsigned int *backbuffer; static unsigned int *depthbuffer; static unsigned int framenumber; //#define NORENDER qboolean SW_VID_Init(rendererstate_t *info, unsigned char *palette) { int bpp = info->bpp; vid.pixelwidth = info->width; vid.pixelheight = info->height; if (bpp != 32) bpp = 32; //sw renderer supports only this #ifndef NORENDER nostdout |= 0x800; if (set_vesa_mode(vid.pixelwidth, vid.pixelheight, bpp) < 0) return false; #endif if (!videoatexitregistered) { videoatexitregistered = true; atexit(videoatexit); } backbuffer = BZ_Malloc(vid.pixelwidth * vid.pixelheight * sizeof(*backbuffer)); if (!backbuffer) return false; depthbuffer = BZ_Malloc(vid.pixelwidth * vid.pixelheight * sizeof(*depthbuffer)); if (!depthbuffer) return false; return true; } void SW_VID_DeInit(void) { BZ_Free(backbuffer); backbuffer = NULL; BZ_Free(depthbuffer); depthbuffer = NULL; } qboolean SW_VID_ApplyGammaRamps (unsigned int rampcount, unsigned short *ramps) { //no gamma ramps with VESA. return false; } char *SW_VID_GetRGBInfo(int *bytestride, int *truevidwidth, int *truevidheight, enum uploadfmt *fmt) { void *ret = BZ_Malloc(vid.pixelwidth*vid.pixelheight*4); if (!ret) return NULL; memcpy(ret, backbuffer, vid.pixelwidth*vid.pixelheight*4); *bytestride = vid.pixelwidth*4; *truevidwidth = vid.pixelwidth; *truevidheight = vid.pixelheight; *fmt = TF_BGRX32; return ret; } void SW_VID_SetWindowCaption(const char *msg) { } void SW_VID_SwapBuffers(void) { #ifndef NORENDER copy_to_vesa_screen((char*)backbuffer, vid.pixelwidth*vid.pixelheight*4); #endif framenumber++; } void SW_VID_UpdateViewport(wqcom_t *com) { com->viewport.cbuf = backbuffer + vid.pixelwidth*(vid.pixelheight-1); com->viewport.dbuf = depthbuffer; com->viewport.width = vid.pixelwidth; com->viewport.height = vid.pixelheight; com->viewport.stride = -vid.pixelwidth; //this is in pixels. which is stupid. com->viewport.framenum = framenumber; } #endif