r_draw.c (8137B)
1 /* 2 Copyright (C) 1997-2001 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 */ 20 21 // draw.c 22 23 #include "r_local.h" 24 25 26 image_t *draw_chars; // 8*8 graphic characters 27 28 //============================================================================= 29 30 /* 31 ================ 32 Draw_FindPic 33 ================ 34 */ 35 image_t *Draw_FindPic (char *name) 36 { 37 image_t *image; 38 char fullname[MAX_QPATH]; 39 40 if (name[0] != '/' && name[0] != '\\') 41 { 42 Com_sprintf (fullname, sizeof(fullname), "pics/%s.pcx", name); 43 image = R_FindImage (fullname, it_pic); 44 } 45 else 46 image = R_FindImage (name+1, it_pic); 47 48 return image; 49 } 50 51 52 53 /* 54 =============== 55 Draw_InitLocal 56 =============== 57 */ 58 void Draw_InitLocal (void) 59 { 60 draw_chars = Draw_FindPic ("conchars"); 61 } 62 63 64 65 /* 66 ================ 67 Draw_Char 68 69 Draws one 8*8 graphics character 70 It can be clipped to the top of the screen to allow the console to be 71 smoothly scrolled off. 72 ================ 73 */ 74 void Draw_Char (int x, int y, int num) 75 { 76 byte *dest; 77 byte *source; 78 int drawline; 79 int row, col; 80 81 num &= 255; 82 83 if (num == 32 || num == 32+128) 84 return; 85 86 if (y <= -8) 87 return; // totally off screen 88 89 // if ( ( y + 8 ) >= vid.height ) 90 if ( ( y + 8 ) > vid.height ) // PGM - status text was missing in sw... 91 return; 92 93 #ifdef PARANOID 94 if (y > vid.height - 8 || x < 0 || x > vid.width - 8) 95 ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: (%i, %i)", x, y); 96 if (num < 0 || num > 255) 97 ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: char %i", num); 98 #endif 99 100 row = num>>4; 101 col = num&15; 102 source = draw_chars->pixels[0] + (row<<10) + (col<<3); 103 104 if (y < 0) 105 { // clipped 106 drawline = 8 + y; 107 source -= 128*y; 108 y = 0; 109 } 110 else 111 drawline = 8; 112 113 114 dest = vid.buffer + y*vid.rowbytes + x; 115 116 while (drawline--) 117 { 118 if (source[0] != TRANSPARENT_COLOR) 119 dest[0] = source[0]; 120 if (source[1] != TRANSPARENT_COLOR) 121 dest[1] = source[1]; 122 if (source[2] != TRANSPARENT_COLOR) 123 dest[2] = source[2]; 124 if (source[3] != TRANSPARENT_COLOR) 125 dest[3] = source[3]; 126 if (source[4] != TRANSPARENT_COLOR) 127 dest[4] = source[4]; 128 if (source[5] != TRANSPARENT_COLOR) 129 dest[5] = source[5]; 130 if (source[6] != TRANSPARENT_COLOR) 131 dest[6] = source[6]; 132 if (source[7] != TRANSPARENT_COLOR) 133 dest[7] = source[7]; 134 source += 128; 135 dest += vid.rowbytes; 136 } 137 } 138 139 /* 140 ============= 141 Draw_GetPicSize 142 ============= 143 */ 144 void Draw_GetPicSize (int *w, int *h, char *pic) 145 { 146 image_t *gl; 147 148 gl = Draw_FindPic (pic); 149 if (!gl) 150 { 151 *w = *h = -1; 152 return; 153 } 154 *w = gl->width; 155 *h = gl->height; 156 } 157 158 /* 159 ============= 160 Draw_StretchPicImplementation 161 ============= 162 */ 163 void Draw_StretchPicImplementation (int x, int y, int w, int h, image_t *pic) 164 { 165 byte *dest, *source; 166 int v, u, sv; 167 int height; 168 int f, fstep; 169 int skip; 170 171 if ((x < 0) || 172 (x + w > vid.width) || 173 (y + h > vid.height)) 174 { 175 ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates"); 176 } 177 178 height = h; 179 if (y < 0) 180 { 181 skip = -y; 182 height += y; 183 y = 0; 184 } 185 else 186 skip = 0; 187 188 dest = vid.buffer + y * vid.rowbytes + x; 189 190 for (v=0 ; v<height ; v++, dest += vid.rowbytes) 191 { 192 sv = (skip + v)*pic->height/h; 193 source = pic->pixels[0] + sv*pic->width; 194 if (w == pic->width) 195 memcpy (dest, source, w); 196 else 197 { 198 f = 0; 199 fstep = pic->width*0x10000/w; 200 for (u=0 ; u<w ; u+=4) 201 { 202 dest[u] = source[f>>16]; 203 f += fstep; 204 dest[u+1] = source[f>>16]; 205 f += fstep; 206 dest[u+2] = source[f>>16]; 207 f += fstep; 208 dest[u+3] = source[f>>16]; 209 f += fstep; 210 } 211 } 212 } 213 } 214 215 /* 216 ============= 217 Draw_StretchPic 218 ============= 219 */ 220 void Draw_StretchPic (int x, int y, int w, int h, char *name) 221 { 222 image_t *pic; 223 224 pic = Draw_FindPic (name); 225 if (!pic) 226 { 227 ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name); 228 return; 229 } 230 Draw_StretchPicImplementation (x, y, w, h, pic); 231 } 232 233 /* 234 ============= 235 Draw_StretchRaw 236 ============= 237 */ 238 void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data) 239 { 240 image_t pic; 241 242 pic.pixels[0] = data; 243 pic.width = cols; 244 pic.height = rows; 245 Draw_StretchPicImplementation (x, y, w, h, &pic); 246 } 247 248 /* 249 ============= 250 Draw_Pic 251 ============= 252 */ 253 void Draw_Pic (int x, int y, char *name) 254 { 255 image_t *pic; 256 byte *dest, *source; 257 int v, u; 258 int tbyte; 259 int height; 260 261 pic = Draw_FindPic (name); 262 if (!pic) 263 { 264 ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name); 265 return; 266 } 267 268 if ((x < 0) || 269 (x + pic->width > vid.width) || 270 (y + pic->height > vid.height)) 271 return; // ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates"); 272 273 height = pic->height; 274 source = pic->pixels[0]; 275 if (y < 0) 276 { 277 height += y; 278 source += pic->width*-y; 279 y = 0; 280 } 281 282 dest = vid.buffer + y * vid.rowbytes + x; 283 284 if (!pic->transparent) 285 { 286 for (v=0 ; v<height ; v++) 287 { 288 memcpy (dest, source, pic->width); 289 dest += vid.rowbytes; 290 source += pic->width; 291 } 292 } 293 else 294 { 295 if (pic->width & 7) 296 { // general 297 for (v=0 ; v<height ; v++) 298 { 299 for (u=0 ; u<pic->width ; u++) 300 if ( (tbyte=source[u]) != TRANSPARENT_COLOR) 301 dest[u] = tbyte; 302 303 dest += vid.rowbytes; 304 source += pic->width; 305 } 306 } 307 else 308 { // unwound 309 for (v=0 ; v<height ; v++) 310 { 311 for (u=0 ; u<pic->width ; u+=8) 312 { 313 if ( (tbyte=source[u]) != TRANSPARENT_COLOR) 314 dest[u] = tbyte; 315 if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR) 316 dest[u+1] = tbyte; 317 if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR) 318 dest[u+2] = tbyte; 319 if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR) 320 dest[u+3] = tbyte; 321 if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR) 322 dest[u+4] = tbyte; 323 if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR) 324 dest[u+5] = tbyte; 325 if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR) 326 dest[u+6] = tbyte; 327 if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR) 328 dest[u+7] = tbyte; 329 } 330 dest += vid.rowbytes; 331 source += pic->width; 332 } 333 } 334 } 335 } 336 337 /* 338 ============= 339 Draw_TileClear 340 341 This repeats a 64*64 tile graphic to fill the screen around a sized down 342 refresh window. 343 ============= 344 */ 345 void Draw_TileClear (int x, int y, int w, int h, char *name) 346 { 347 int i, j; 348 byte *psrc; 349 byte *pdest; 350 image_t *pic; 351 int x2; 352 353 if (x < 0) 354 { 355 w += x; 356 x = 0; 357 } 358 if (y < 0) 359 { 360 h += y; 361 y = 0; 362 } 363 if (x + w > vid.width) 364 w = vid.width - x; 365 if (y + h > vid.height) 366 h = vid.height - y; 367 if (w <= 0 || h <= 0) 368 return; 369 370 pic = Draw_FindPic (name); 371 if (!pic) 372 { 373 ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name); 374 return; 375 } 376 x2 = x + w; 377 pdest = vid.buffer + y*vid.rowbytes; 378 for (i=0 ; i<h ; i++, pdest += vid.rowbytes) 379 { 380 psrc = pic->pixels[0] + pic->width * ((i+y)&63); 381 for (j=x ; j<x2 ; j++) 382 pdest[j] = psrc[j&63]; 383 } 384 } 385 386 387 /* 388 ============= 389 Draw_Fill 390 391 Fills a box of pixels with a single color 392 ============= 393 */ 394 void Draw_Fill (int x, int y, int w, int h, int c) 395 { 396 byte *dest; 397 int u, v; 398 399 if (x+w > vid.width) 400 w = vid.width - x; 401 if (y+h > vid.height) 402 h = vid.height - y; 403 if (x < 0) 404 { 405 w += x; 406 x = 0; 407 } 408 if (y < 0) 409 { 410 h += y; 411 y = 0; 412 } 413 if (w < 0 || h < 0) 414 return; 415 dest = vid.buffer + y*vid.rowbytes + x; 416 for (v=0 ; v<h ; v++, dest += vid.rowbytes) 417 for (u=0 ; u<w ; u++) 418 dest[u] = c; 419 } 420 //============================================================================= 421 422 /* 423 ================ 424 Draw_FadeScreen 425 426 ================ 427 */ 428 void Draw_FadeScreen (void) 429 { 430 int x,y; 431 byte *pbuf; 432 int t; 433 434 for (y=0 ; y<vid.height ; y++) 435 { 436 pbuf = (byte *)(vid.buffer + vid.rowbytes*y); 437 t = (y & 1) << 1; 438 439 for (x=0 ; x<vid.width ; x++) 440 { 441 if ((x & 3) != t) 442 pbuf[x] = 0; 443 } 444 } 445 }