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