1 //
2 // Copyright(C) 1993-1996 Id Software, Inc.
3 // Copyright(C) 1993-2008 Raven Software
4 // Copyright(C) 2005-2014 Simon Howard
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16
17
18 #include "h2def.h"
19 #include "i_system.h"
20 #include "i_video.h"
21 #include "r_local.h"
22 #include "v_video.h"
23
24 /*
25
26 All drawing to the view buffer is accomplished in this file. The other refresh
27 files only know about ccordinates, not the architecture of the frame buffer.
28
29 */
30
31 byte *viewimage;
32 int viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy;
33 byte *ylookup[MAXHEIGHT];
34 int columnofs[MAXWIDTH];
35 //byte translations[3][256]; // color tables for different players
36
37 /*
38 ==================
39 =
40 = R_DrawColumn
41 =
42 = Source is the top of the column to scale
43 =
44 ==================
45 */
46
47 lighttable_t *dc_colormap;
48 int dc_x;
49 int dc_yl;
50 int dc_yh;
51 fixed_t dc_iscale;
52 fixed_t dc_texturemid;
53 byte *dc_source; // first pixel in a column (possibly virtual)
54
55 int dccount; // just for profiling
56
R_DrawColumn(void)57 void R_DrawColumn(void)
58 {
59 int count;
60 byte *dest;
61 fixed_t frac, fracstep;
62
63 count = dc_yh - dc_yl;
64 if (count < 0)
65 return;
66
67 #ifdef RANGECHECK
68 if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
69 I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
70 #endif
71
72 dest = ylookup[dc_yl] + columnofs[dc_x];
73
74 fracstep = dc_iscale;
75 frac = dc_texturemid + (dc_yl - centery) * fracstep;
76
77 do
78 {
79 *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]];
80 dest += SCREENWIDTH;
81 frac += fracstep;
82 }
83 while (count--);
84 }
85
R_DrawColumnLow(void)86 void R_DrawColumnLow(void)
87 {
88 int count;
89 byte *dest;
90 fixed_t frac, fracstep;
91
92 count = dc_yh - dc_yl;
93 if (count < 0)
94 return;
95
96 #ifdef RANGECHECK
97 if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
98 I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
99 // dccount++;
100 #endif
101
102 dest = ylookup[dc_yl] + columnofs[dc_x];
103
104 fracstep = dc_iscale;
105 frac = dc_texturemid + (dc_yl - centery) * fracstep;
106
107 do
108 {
109 *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]];
110 dest += SCREENWIDTH;
111 frac += fracstep;
112 }
113 while (count--);
114 }
115
R_DrawTLColumn(void)116 void R_DrawTLColumn(void)
117 {
118 int count;
119 byte *dest;
120 fixed_t frac, fracstep;
121
122 if (!dc_yl)
123 dc_yl = 1;
124 if (dc_yh == viewheight - 1)
125 dc_yh = viewheight - 2;
126
127 count = dc_yh - dc_yl;
128 if (count < 0)
129 return;
130
131 #ifdef RANGECHECK
132 if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
133 I_Error("R_DrawTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
134 #endif
135
136 dest = ylookup[dc_yl] + columnofs[dc_x];
137
138 fracstep = dc_iscale;
139 frac = dc_texturemid + (dc_yl - centery) * fracstep;
140
141 do
142 {
143 *dest = tinttable[*dest +
144 (dc_colormap[dc_source[(frac >> FRACBITS) & 127]] <<
145 8)];
146 dest += SCREENWIDTH;
147 frac += fracstep;
148 }
149 while (count--);
150 }
151
152 //============================================================================
153 //
154 // R_DrawAltTLColumn
155 //
156 //============================================================================
157
R_DrawAltTLColumn(void)158 void R_DrawAltTLColumn(void)
159 {
160 int count;
161 byte *dest;
162 fixed_t frac, fracstep;
163
164 if (!dc_yl)
165 dc_yl = 1;
166 if (dc_yh == viewheight - 1)
167 dc_yh = viewheight - 2;
168
169 count = dc_yh - dc_yl;
170 if (count < 0)
171 return;
172
173 #ifdef RANGECHECK
174 if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
175 I_Error("R_DrawAltTLColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
176 #endif
177
178 dest = ylookup[dc_yl] + columnofs[dc_x];
179
180 fracstep = dc_iscale;
181 frac = dc_texturemid + (dc_yl - centery) * fracstep;
182
183 do
184 {
185 *dest = tinttable[((*dest) << 8)
186 + dc_colormap[dc_source[(frac >> FRACBITS) & 127]]];
187 dest += SCREENWIDTH;
188 frac += fracstep;
189 }
190 while (count--);
191 }
192
193 /*
194 ========================
195 =
196 = R_DrawTranslatedColumn
197 =
198 ========================
199 */
200
201 byte *dc_translation;
202 byte *translationtables;
203
R_DrawTranslatedColumn(void)204 void R_DrawTranslatedColumn(void)
205 {
206 int count;
207 byte *dest;
208 fixed_t frac, fracstep;
209
210 count = dc_yh - dc_yl;
211 if (count < 0)
212 return;
213
214 #ifdef RANGECHECK
215 if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
216 I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
217 #endif
218
219 dest = ylookup[dc_yl] + columnofs[dc_x];
220
221 fracstep = dc_iscale;
222 frac = dc_texturemid + (dc_yl - centery) * fracstep;
223
224 do
225 {
226 *dest = dc_colormap[dc_translation[dc_source[frac >> FRACBITS]]];
227 dest += SCREENWIDTH;
228 frac += fracstep;
229 }
230 while (count--);
231 }
232
233 //============================================================================
234 //
235 // R_DrawTranslatedTLColumn
236 //
237 //============================================================================
238
R_DrawTranslatedTLColumn(void)239 void R_DrawTranslatedTLColumn(void)
240 {
241 int count;
242 byte *dest;
243 fixed_t frac, fracstep;
244
245 count = dc_yh - dc_yl;
246 if (count < 0)
247 return;
248
249 #ifdef RANGECHECK
250 if ((unsigned) dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
251 I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
252 #endif
253
254 dest = ylookup[dc_yl] + columnofs[dc_x];
255
256 fracstep = dc_iscale;
257 frac = dc_texturemid + (dc_yl - centery) * fracstep;
258
259 do
260 {
261 *dest = tinttable[((*dest) << 8)
262 +
263 dc_colormap[dc_translation
264 [dc_source[frac >> FRACBITS]]]];
265 dest += SCREENWIDTH;
266 frac += fracstep;
267 }
268 while (count--);
269 }
270
271 //============================================================================
272 //
273 // R_DrawTranslatedAltTLColumn
274 //
275 //============================================================================
276
277 /*
278 void R_DrawTranslatedAltTLColumn (void)
279 {
280 int count;
281 byte *dest;
282 fixed_t frac, fracstep;
283
284 count = dc_yh - dc_yl;
285 if (count < 0)
286 return;
287
288 #ifdef RANGECHECK
289 if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
290 I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
291 #endif
292
293 dest = ylookup[dc_yl] + columnofs[dc_x];
294
295 fracstep = dc_iscale;
296 frac = dc_texturemid + (dc_yl-centery)*fracstep;
297
298 do
299 {
300 *dest = tinttable[*dest
301 +(dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8)];
302 dest += SCREENWIDTH;
303 frac += fracstep;
304 } while (count--);
305 }
306 */
307
308 //--------------------------------------------------------------------------
309 //
310 // PROC R_InitTranslationTables
311 //
312 //--------------------------------------------------------------------------
313
R_InitTranslationTables(void)314 void R_InitTranslationTables(void)
315 {
316 int i;
317 byte *transLump;
318 int lumpnum;
319
320 V_LoadTintTable();
321
322 // Allocate translation tables
323 translationtables = Z_Malloc(256 * 3 * (maxplayers - 1), PU_STATIC, 0);
324
325 for (i = 0; i < 3 * (maxplayers - 1); i++)
326 {
327 lumpnum = W_GetNumForName("trantbl0") + i;
328 transLump = W_CacheLumpNum(lumpnum, PU_STATIC);
329 memcpy(translationtables + i * 256, transLump, 256);
330 W_ReleaseLumpNum(lumpnum);
331 }
332 }
333
334 /*
335 ================
336 =
337 = R_DrawSpan
338 =
339 ================
340 */
341
342 int ds_y;
343 int ds_x1;
344 int ds_x2;
345 lighttable_t *ds_colormap;
346 fixed_t ds_xfrac;
347 fixed_t ds_yfrac;
348 fixed_t ds_xstep;
349 fixed_t ds_ystep;
350 byte *ds_source; // start of a 64*64 tile image
351
352 int dscount; // just for profiling
353
R_DrawSpan(void)354 void R_DrawSpan(void)
355 {
356 fixed_t xfrac, yfrac;
357 byte *dest;
358 int count, spot;
359
360 #ifdef RANGECHECK
361 if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH
362 || (unsigned) ds_y > SCREENHEIGHT)
363 I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y);
364 // dscount++;
365 #endif
366
367 xfrac = ds_xfrac;
368 yfrac = ds_yfrac;
369
370 dest = ylookup[ds_y] + columnofs[ds_x1];
371 count = ds_x2 - ds_x1;
372 do
373 {
374 spot = ((yfrac >> (16 - 6)) & (63 * 64)) + ((xfrac >> 16) & 63);
375 *dest++ = ds_colormap[ds_source[spot]];
376 xfrac += ds_xstep;
377 yfrac += ds_ystep;
378 }
379 while (count--);
380 }
381
R_DrawSpanLow(void)382 void R_DrawSpanLow(void)
383 {
384 fixed_t xfrac, yfrac;
385 byte *dest;
386 int count, spot;
387
388 #ifdef RANGECHECK
389 if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH
390 || (unsigned) ds_y > SCREENHEIGHT)
391 I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y);
392 // dscount++;
393 #endif
394
395 xfrac = ds_xfrac;
396 yfrac = ds_yfrac;
397
398 dest = ylookup[ds_y] + columnofs[ds_x1];
399 count = ds_x2 - ds_x1;
400 do
401 {
402 spot = ((yfrac >> (16 - 6)) & (63 * 64)) + ((xfrac >> 16) & 63);
403 *dest++ = ds_colormap[ds_source[spot]];
404 xfrac += ds_xstep;
405 yfrac += ds_ystep;
406 }
407 while (count--);
408 }
409
410
411
412 /*
413 ================
414 =
415 = R_InitBuffer
416 =
417 =================
418 */
419
R_InitBuffer(int width,int height)420 void R_InitBuffer(int width, int height)
421 {
422 int i;
423
424 viewwindowx = (SCREENWIDTH - width) >> 1;
425 for (i = 0; i < width; i++)
426 columnofs[i] = viewwindowx + i;
427 if (width == SCREENWIDTH)
428 viewwindowy = 0;
429 else
430 viewwindowy = (SCREENHEIGHT - SBARHEIGHT - height) >> 1;
431 // [crispy] make sure viewwindowy is always an even number
432 viewwindowy &= ~1;
433 for (i = 0; i < height; i++)
434 ylookup[i] = I_VideoBuffer + (i + viewwindowy) * SCREENWIDTH;
435 }
436
437
438 /*
439 ==================
440 =
441 = R_DrawViewBorder
442 =
443 = Draws the border around the view for different size windows
444 ==================
445 */
446
447 boolean BorderNeedRefresh;
448
R_DrawViewBorder(void)449 void R_DrawViewBorder(void)
450 {
451 byte *src, *dest;
452 int x, y;
453
454 if (scaledviewwidth == SCREENWIDTH)
455 return;
456
457 src = W_CacheLumpName("F_022", PU_CACHE);
458 dest = I_VideoBuffer;
459
460 for (y = 0; y < SCREENHEIGHT - SBARHEIGHT; y++)
461 {
462 for (x = 0; x < SCREENWIDTH / 64; x++)
463 {
464 memcpy(dest, src + ((y & 63) << 6), 64);
465 dest += 64;
466 }
467 if (SCREENWIDTH & 63)
468 {
469 memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63);
470 dest += (SCREENWIDTH & 63);
471 }
472 }
473 for (x = (viewwindowx >> crispy->hires); x < (viewwindowx + viewwidth) >> crispy->hires; x += 16)
474 {
475 V_DrawPatch(x, (viewwindowy >> crispy->hires) - 4, W_CacheLumpName("bordt", PU_CACHE));
476 V_DrawPatch(x, (viewwindowy + viewheight) >> crispy->hires, W_CacheLumpName("bordb",
477 PU_CACHE));
478 }
479 for (y = (viewwindowy >> crispy->hires); y < (viewwindowy + viewheight) >> crispy->hires; y += 16)
480 {
481 V_DrawPatch((viewwindowx >> crispy->hires) - 4, y, W_CacheLumpName("bordl", PU_CACHE));
482 V_DrawPatch((viewwindowx + viewwidth) >> crispy->hires, y, W_CacheLumpName("bordr",
483 PU_CACHE));
484 }
485 V_DrawPatch((viewwindowx >> crispy->hires) - 4, (viewwindowy >> crispy->hires) - 4, W_CacheLumpName("bordtl",
486 PU_CACHE));
487 V_DrawPatch((viewwindowx + viewwidth) >> crispy->hires, (viewwindowy >> crispy->hires) - 4,
488 W_CacheLumpName("bordtr", PU_CACHE));
489 V_DrawPatch((viewwindowx + viewwidth) >> crispy->hires, (viewwindowy + viewheight) >> crispy->hires,
490 W_CacheLumpName("bordbr", PU_CACHE));
491 V_DrawPatch((viewwindowx >> crispy->hires) - 4, (viewwindowy + viewheight) >> crispy->hires,
492 W_CacheLumpName("bordbl", PU_CACHE));
493 }
494
495 /*
496 ==================
497 =
498 = R_DrawTopBorder
499 =
500 = Draws the top border around the view for different size windows
501 ==================
502 */
503
504 boolean BorderTopRefresh;
505
R_DrawTopBorder(void)506 void R_DrawTopBorder(void)
507 {
508 byte *src, *dest;
509 int x, y;
510
511 if (scaledviewwidth == SCREENWIDTH)
512 return;
513
514 /* if(gamemode == shareware)
515 {
516 src = W_CacheLumpName ("FLOOR04", PU_CACHE);
517 }
518 else
519 {
520 src = W_CacheLumpName ("FLAT513", PU_CACHE);
521 }
522 */
523 src = W_CacheLumpName("F_022", PU_CACHE);
524 dest = I_VideoBuffer;
525
526 for (y = 0; y < (34 << crispy->hires); y++)
527 {
528 for (x = 0; x < SCREENWIDTH / 64; x++)
529 {
530 memcpy(dest, src + ((y & 63) << 6), 64);
531 dest += 64;
532 }
533 if (SCREENWIDTH & 63)
534 {
535 memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63);
536 dest += (SCREENWIDTH & 63);
537 }
538 }
539 if (viewwindowy < 35)
540 {
541 for (x = (viewwindowx >> crispy->hires); x < (viewwindowx + viewwidth) >> crispy->hires; x += 16)
542 {
543 V_DrawPatch(x, (viewwindowy >> crispy->hires) - 4,
544 W_CacheLumpName("bordt", PU_CACHE));
545 }
546 V_DrawPatch((viewwindowx >> crispy->hires) - 4, viewwindowy >> crispy->hires, W_CacheLumpName("bordl",
547 PU_CACHE));
548 V_DrawPatch((viewwindowx + viewwidth) >> crispy->hires, viewwindowy >> crispy->hires,
549 W_CacheLumpName("bordr", PU_CACHE));
550 V_DrawPatch((viewwindowx >> crispy->hires) - 4, (viewwindowy >> crispy->hires) + 16,
551 W_CacheLumpName("bordl", PU_CACHE));
552 V_DrawPatch((viewwindowx + viewwidth) >> crispy->hires, (viewwindowy >> crispy->hires) + 16,
553 W_CacheLumpName("bordr", PU_CACHE));
554
555 V_DrawPatch((viewwindowx >> crispy->hires) - 4, (viewwindowy >> crispy->hires) - 4,
556 W_CacheLumpName("bordtl", PU_CACHE));
557 V_DrawPatch((viewwindowx + viewwidth) >> crispy->hires, (viewwindowy >> crispy->hires) - 4,
558 W_CacheLumpName("bordtr", PU_CACHE));
559 }
560 }
561