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