Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

rw_svgalib.c (6694B)


      1 /*
      2 ** RW_SVGALBI.C
      3 **
      4 ** This file contains ALL Linux specific stuff having to do with the
      5 ** software refresh.  When a port is being made the following functions
      6 ** must be implemented by the port:
      7 **
      8 ** SWimp_EndFrame
      9 ** SWimp_Init
     10 ** SWimp_InitGraphics
     11 ** SWimp_SetPalette
     12 ** SWimp_Shutdown
     13 ** SWimp_SwitchFullscreen
     14 */
     15 
     16 #include <termios.h>
     17 #include <sys/ioctl.h>
     18 #include <sys/stat.h>
     19 #include <sys/vt.h>
     20 #include <stdarg.h>
     21 #include <stdio.h>
     22 #include <signal.h>
     23 #include <sys/mman.h>
     24 
     25 #include <asm/io.h>
     26 
     27 #include "vga.h"
     28 #include "vgakeyboard.h"
     29 #include "vgamouse.h"
     30 
     31 #include "../ref_soft/r_local.h"
     32 #include "../client/keys.h"
     33 #include "../linux/rw_linux.h"
     34 
     35 /*****************************************************************************/
     36 
     37 int		VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
     38 byte	*VGA_pagebase;
     39 char	*framebuffer_ptr;
     40 
     41 void VGA_UpdatePlanarScreen (void *srcbuffer);
     42 
     43 int num_modes;
     44 vga_modeinfo *modes;
     45 int current_mode;
     46 
     47 // Console variables that we need to access from this module
     48 
     49 /*****************************************************************************/
     50 
     51 void VID_InitModes(void)
     52 {
     53 
     54 int i;
     55 
     56 	// get complete information on all modes
     57 
     58 	num_modes = vga_lastmodenumber()+1;
     59 	modes = malloc(num_modes * sizeof(vga_modeinfo));
     60 	for (i=0 ; i<num_modes ; i++)
     61 	{
     62 		if (vga_hasmode(i))
     63 			memcpy(&modes[i], vga_getmodeinfo(i), sizeof (vga_modeinfo));
     64 		else
     65 			modes[i].width = 0; // means not available
     66 	}
     67 
     68 	// filter for modes i don't support
     69 
     70 	for (i=0 ; i<num_modes ; i++)
     71 	{
     72 		if (modes[i].bytesperpixel != 1 && modes[i].colors != 256) 
     73 			modes[i].width = 0;
     74 	}
     75 
     76 	for (i = 0; i < num_modes; i++)
     77 		if (modes[i].width)
     78 			ri.Con_Printf(PRINT_ALL, "mode %d: %d %d\n", modes[i].width, modes[i].height);
     79 
     80 }
     81 
     82 /*
     83 ** SWimp_Init
     84 **
     85 ** This routine is responsible for initializing the implementation
     86 ** specific stuff in a software rendering subsystem.
     87 */
     88 int SWimp_Init( void *hInstance, void *wndProc )
     89 {
     90 	vga_init();
     91 
     92 	VID_InitModes();
     93 
     94 	return true;
     95 }
     96 
     97 int get_mode(int width, int height)
     98 {
     99 
    100 	int i;
    101 	int ok, match;
    102 
    103 	for (i=0 ; i<num_modes ; i++)
    104 		if (modes[i].width &&
    105 			modes[i].width == width && modes[i].height == height)
    106 				break;
    107 	if (i==num_modes)
    108 		return -1; // not found
    109 
    110 	return i;
    111 }
    112 
    113 /*
    114 ** SWimp_InitGraphics
    115 **
    116 ** This initializes the software refresh's implementation specific
    117 ** graphics subsystem.  In the case of Windows it creates DIB or
    118 ** DDRAW surfaces.
    119 **
    120 ** The necessary width and height parameters are grabbed from
    121 ** vid.width and vid.height.
    122 */
    123 static qboolean SWimp_InitGraphics( qboolean fullscreen )
    124 {
    125 	int bsize, zsize, tsize;
    126 
    127 	SWimp_Shutdown();
    128 
    129 	current_mode = get_mode(vid.width, vid.height);
    130 
    131 	if (current_mode < 0) {
    132 		ri.Con_Printf (PRINT_ALL, "Mode %d %d not found\n", vid.width, vid.height);
    133 		return false; // mode not found
    134 	}
    135 
    136 	// let the sound and input subsystems know about the new window
    137 	ri.Vid_NewWindow (vid.width, vid.height);
    138 
    139 	ri.Con_Printf (PRINT_ALL, "Setting VGAMode: %d\n", current_mode );
    140 
    141 //	Cvar_SetValue ("vid_mode", (float)modenum);
    142 	
    143 	VGA_width = modes[current_mode].width;
    144 	VGA_height = modes[current_mode].height;
    145 	VGA_planar = modes[current_mode].bytesperpixel == 0;
    146 	VGA_rowbytes = modes[current_mode].linewidth;
    147 
    148 	vid.rowbytes = modes[current_mode].linewidth;
    149 
    150 	if (VGA_planar) {
    151 		VGA_bufferrowbytes = modes[current_mode].linewidth * 4;
    152 		vid.rowbytes = modes[current_mode].linewidth*4;
    153 	}
    154 
    155 // get goin'
    156 
    157 	vga_setmode(current_mode);
    158 
    159 	VGA_pagebase = framebuffer_ptr = (char *) vga_getgraphmem();
    160 //		if (vga_setlinearaddressing()>0)
    161 //			framebuffer_ptr = (char *) vga_getgraphmem();
    162 	if (!framebuffer_ptr)
    163 		Sys_Error("This mode isn't hapnin'\n");
    164 
    165 	vga_setpage(0);
    166 
    167 	vid.buffer = malloc(vid.rowbytes * vid.height);
    168 	if (!vid.buffer)
    169 		Sys_Error("Unabled to alloc vid.buffer!\n");
    170 
    171 	return true;
    172 }
    173 
    174 /*
    175 ** SWimp_EndFrame
    176 **
    177 ** This does an implementation specific copy from the backbuffer to the
    178 ** front buffer.  In the Win32 case it uses BitBlt or BltFast depending
    179 ** on whether we're using DIB sections/GDI or DDRAW.
    180 */
    181 void SWimp_EndFrame (void)
    182 {
    183 	if (!vga_oktowrite())
    184 		return; // can't update screen if it's not active
    185 
    186 //	if (vid_waitforrefresh.value)
    187 //		vga_waitretrace();
    188 
    189 	if (VGA_planar)
    190 		VGA_UpdatePlanarScreen (vid.buffer);
    191 
    192 	else {
    193 		int total = vid.rowbytes * vid.height;
    194 		int offset;
    195 
    196 		for (offset=0;offset<total;offset+=0x10000) {
    197 			vga_setpage(offset/0x10000);
    198 			memcpy(framebuffer_ptr,
    199 					vid.buffer + offset,
    200 					((total-offset>0x10000)?0x10000:(total-offset)));
    201 		}
    202 	} 
    203 }
    204 
    205 /*
    206 ** SWimp_SetMode
    207 */
    208 rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
    209 {
    210 	rserr_t retval = rserr_ok;
    211 
    212 	ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode );
    213 
    214 	if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) )
    215 	{
    216 		ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
    217 		return rserr_invalid_mode;
    218 	}
    219 
    220 	ri.Con_Printf( PRINT_ALL, " %d %d\n", *pwidth, *pheight);
    221 
    222 	if ( !SWimp_InitGraphics( false ) ) {
    223 		// failed to set a valid mode in windowed mode
    224 		return rserr_invalid_mode;
    225 	}
    226 
    227 	R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
    228 
    229 	return retval;
    230 }
    231 
    232 /*
    233 ** SWimp_SetPalette
    234 **
    235 ** System specific palette setting routine.  A NULL palette means
    236 ** to use the existing palette.  The palette is expected to be in
    237 ** a padded 4-byte xRGB format.
    238 */
    239 void SWimp_SetPalette( const unsigned char *palette )
    240 {
    241 	static int tmppal[256*3];
    242 	const unsigned char *pal;
    243 	int *tp;
    244 	int i;
    245 
    246     if ( !palette )
    247         palette = ( const unsigned char * ) sw_state.currentpalette;
    248  
    249 	if (vga_getcolors() == 256)
    250 	{
    251 		tp = tmppal;
    252 		pal = palette;
    253 
    254 		for (i=0 ; i < 256 ; i++, pal += 4, tp += 3) {
    255 			tp[0] = pal[0] >> 2;
    256 			tp[1] = pal[1] >> 2;
    257 			tp[2] = pal[2] >> 2;
    258 		}
    259 
    260 		if (vga_oktowrite())
    261 			vga_setpalvec(0, 256, tmppal);
    262 	}
    263 }
    264 
    265 /*
    266 ** SWimp_Shutdown
    267 **
    268 ** System specific graphics subsystem shutdown routine.  Destroys
    269 ** DIBs or DDRAW surfaces as appropriate.
    270 */
    271 void SWimp_Shutdown( void )
    272 {
    273 	if (vid.buffer) {
    274 		free(vid.buffer);
    275 		vid.buffer = NULL;
    276 	}
    277 	vga_setmode(TEXT);
    278 }
    279 
    280 /*
    281 ** SWimp_AppActivate
    282 */
    283 void SWimp_AppActivate( qboolean active )
    284 {
    285 }
    286 
    287 //===============================================================================
    288 
    289 /*
    290 ================
    291 Sys_MakeCodeWriteable
    292 ================
    293 */
    294 void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
    295 {
    296 
    297 	int r;
    298 	unsigned long addr;
    299 	int psize = getpagesize();
    300 
    301 	addr = (startaddr & ~(psize-1)) - psize;
    302 
    303 //	fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
    304 //			addr, startaddr+length, length);
    305 
    306 	r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
    307 
    308 	if (r < 0)
    309     		Sys_Error("Protection change failed\n");
    310 }
    311