|
|
1.1.1.3 root 1: // Emacs style mode select -*- C++ -*-
2: //-----------------------------------------------------------------------------
3: //
4: // $Id:$
5: //
6: // Copyright (C) 1993-1996 by id Software, Inc.
7: //
1.1.1.5 ! root 8: // This source is available for distribution and/or modification
! 9: // only under the terms of the DOOM Source Code License as
! 10: // published by id Software. All rights reserved.
1.1.1.3 root 11: //
1.1.1.5 ! root 12: // The source is distributed in the hope that it will be useful,
1.1.1.3 root 13: // but WITHOUT ANY WARRANTY; without even the implied warranty of
1.1.1.5 ! root 14: // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
! 15: // for more details.
1.1.1.3 root 16: //
17: // $Log:$
18: //
19: // DESCRIPTION:
20: // The actual span/column drawing functions.
21: // Here find the main potential for optimization,
22: // e.g. inline assembly, different algorithms.
23: //
24: //-----------------------------------------------------------------------------
1.1 root 25:
26:
1.1.1.3 root 27: static const char
28: rcsid[] = "$Id: r_draw.c,v 1.4 1997/02/03 16:47:55 b1 Exp $";
1.1 root 29:
30:
1.1.1.3 root 31: #include "doomdef.h"
1.1 root 32:
1.1.1.3 root 33: #include "i_system.h"
34: #include "z_zone.h"
35: #include "w_wad.h"
1.1 root 36:
1.1.1.3 root 37: #include "r_local.h"
1.1 root 38:
1.1.1.3 root 39: // Needs access to LFB (guess what).
40: #include "v_video.h"
1.1 root 41:
1.1.1.3 root 42: // State.
43: #include "doomstat.h"
1.1 root 44:
1.1.1.5 ! root 45: void WriteDebug(char *);
1.1 root 46:
1.1.1.3 root 47: // ?
48: #define MAXWIDTH 1120
49: #define MAXHEIGHT 832
1.1 root 50:
1.1.1.3 root 51: // status bar height at bottom of screen
52: #define SBARHEIGHT 32
1.1 root 53:
1.1.1.3 root 54: //
55: // All drawing to the view buffer is accomplished in this file.
56: // The other refresh files only know about ccordinates,
57: // not the architecture of the frame buffer.
58: // Conveniently, the frame buffer is a linear one,
59: // and we need only the base address,
60: // and the total size == width*height*depth/8.,
61: //
1.1 root 62:
63:
1.1.1.5 ! root 64: byte *viewimage;
! 65: int viewwidth;
! 66: int scaledviewwidth;
! 67: int viewheight;
! 68: int viewwindowx;
! 69: int viewwindowy;
! 70: byte *ylookup[MAXHEIGHT];
! 71: int columnofs[MAXWIDTH];
1.1.1.3 root 72:
73: // Color tables for different players,
74: // translate a limited part to another
75: // (color ramps used for suit colors).
76: //
77: byte translations[3][256];
78:
79:
1.1 root 80:
1.1.1.2 root 81:
82: //
1.1.1.3 root 83: // R_DrawColumn
84: // Source is the top of the column to scale.
1.1.1.2 root 85: //
1.1.1.3 root 86: lighttable_t* dc_colormap;
87: int dc_x;
88: int dc_yl;
89: int dc_yh;
90: fixed_t dc_iscale;
91: fixed_t dc_texturemid;
1.1.1.2 root 92:
1.1.1.3 root 93: // first pixel in a column (possibly virtual)
94: byte* dc_source;
1.1 root 95:
1.1.1.3 root 96: // just for profiling
97: int dccount;
1.1 root 98:
1.1.1.3 root 99: //
100: // A column is a vertical slice/span from a wall texture that,
101: // given the DOOM style restrictions on the view orientation,
102: // will always have constant z depth.
103: // Thus a special case loop for very fast rendering can
104: // be used. It has also been used with Wolfenstein 3D.
105: //
106: void R_DrawColumn (void)
107: {
108: int count;
109: byte* dest;
110: fixed_t frac;
111: fixed_t fracstep;
112:
113: count = dc_yh - dc_yl;
114:
115: // Zero length, column does not exceed a pixel.
116: if (count < 0)
117: return;
118:
119: #ifdef RANGECHECK
120: if ((unsigned)dc_x >= SCREENWIDTH
121: || dc_yl < 0
122: || dc_yh >= SCREENHEIGHT)
123: I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
124: #endif
125:
126: // Framebuffer destination address.
127: // Use ylookup LUT to avoid multiply with ScreenWidth.
128: // Use columnofs LUT for subwindows?
129: dest = ylookup[dc_yl] + columnofs[dc_x];
130:
131: // Determine scaling,
132: // which is the only mapping to be done.
133: fracstep = dc_iscale;
134: frac = dc_texturemid + (dc_yl-centery)*fracstep;
135:
136: // Inner loop that does the actual texture mapping,
137: // e.g. a DDA-lile scaling.
138: // This is as fast as it gets.
139: do
140: {
141: // Re-map color indices from wall texture column
142: // using a lighting/special effects LUT.
143: *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
144:
145: dest += SCREENWIDTH;
146: frac += fracstep;
147:
148: } while (count--);
149: }
150:
151:
152:
153: // UNUSED.
154: // Loop unrolled.
155: #if 0
156: void R_DrawColumn (void)
157: {
158: int count;
159: byte* source;
160: byte* dest;
161: byte* colormap;
162:
163: unsigned frac;
164: unsigned fracstep;
165: unsigned fracstep2;
166: unsigned fracstep3;
167: unsigned fracstep4;
168:
169: count = dc_yh - dc_yl + 1;
170:
171: source = dc_source;
172: colormap = dc_colormap;
173: dest = ylookup[dc_yl] + columnofs[dc_x];
174:
175: fracstep = dc_iscale<<9;
176: frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9;
177:
178: fracstep2 = fracstep+fracstep;
179: fracstep3 = fracstep2+fracstep;
180: fracstep4 = fracstep3+fracstep;
181:
182: while (count >= 8)
183: {
184: dest[0] = colormap[source[frac>>25]];
185: dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]];
186: dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]];
187: dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]];
188:
189: frac += fracstep4;
190:
191: dest[SCREENWIDTH*4] = colormap[source[frac>>25]];
192: dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]];
193: dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]];
194: dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]];
195:
196: frac += fracstep4;
197: dest += SCREENWIDTH*8;
198: count -= 8;
199: }
200:
201: while (count > 0)
202: {
203: *dest = colormap[source[frac>>25]];
204: dest += SCREENWIDTH;
205: frac += fracstep;
206: count--;
207: }
208: }
209: #endif
210:
211:
212: void R_DrawColumnLow (void)
213: {
214: int count;
215: byte* dest;
216: byte* dest2;
217: fixed_t frac;
218: fixed_t fracstep;
219:
220: count = dc_yh - dc_yl;
221:
222: // Zero length.
223: if (count < 0)
224: return;
225:
226: #ifdef RANGECHECK
227: if ((unsigned)dc_x >= SCREENWIDTH
228: || dc_yl < 0
229: || dc_yh >= SCREENHEIGHT)
230: {
231:
232: I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
233: }
234: // dccount++;
235: #endif
236: // Blocky mode, need to multiply by 2.
237: dc_x <<= 1;
238:
239: dest = ylookup[dc_yl] + columnofs[dc_x];
240: dest2 = ylookup[dc_yl] + columnofs[dc_x+1];
241:
242: fracstep = dc_iscale;
243: frac = dc_texturemid + (dc_yl-centery)*fracstep;
244:
245: do
246: {
247: // Hack. Does not work corretly.
248: *dest2 = *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
249: dest += SCREENWIDTH;
250: dest2 += SCREENWIDTH;
251: frac += fracstep;
1.1 root 252:
1.1.1.3 root 253: } while (count--);
1.1 root 254: }
255:
256:
1.1.1.3 root 257: //
258: // Spectre/Invisibility.
259: //
260: #define FUZZTABLE 50
1.1.1.5 ! root 261: #define FUZZOFF 1
1.1 root 262:
1.1.1.3 root 263: int fuzzoffset[FUZZTABLE] =
1.1 root 264: {
1.1.1.3 root 265: FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
266: FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
267: FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,
268: FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
269: FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,
270: FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,
271: FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF
272: };
1.1 root 273:
1.1.1.3 root 274: int fuzzpos = 0;
1.1 root 275:
1.1.1.5 ! root 276: void R_InitFuzzTable()
! 277: {
! 278: int i;
! 279:
! 280: for (i = 0; i < FUZZTABLE; i++)
! 281: fuzzoffset[i] *= SCREENWIDTH;
! 282: }
1.1 root 283:
1.1.1.2 root 284: //
1.1.1.3 root 285: // Framebuffer postprocessing.
286: // Creates a fuzzy image by copying pixels
287: // from adjacent ones to left and right.
288: // Used with an all black colormap, this
289: // could create the SHADOW effect,
290: // i.e. spectres and invisible players.
1.1.1.2 root 291: //
1.1.1.3 root 292: void R_DrawFuzzColumn (void)
293: {
294: int count;
295: byte* dest;
296: fixed_t frac;
297: fixed_t fracstep;
298:
299: // Adjust borders. Low...
300: if (!dc_yl)
301: dc_yl = 1;
302:
303: // .. and high.
304: if (dc_yh == viewheight-1)
305: dc_yh = viewheight - 2;
306:
307: count = dc_yh - dc_yl;
308:
309: // Zero length.
310: if (count < 0)
311: return;
312:
313:
314: #ifdef RANGECHECK
315: if ((unsigned)dc_x >= SCREENWIDTH
316: || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
317: {
318: I_Error ("R_DrawFuzzColumn: %i to %i at %i",
319: dc_yl, dc_yh, dc_x);
320: }
1.1 root 321: #endif
322:
323:
1.1.1.3 root 324: // Keep till detailshift bug in blocky mode fixed,
325: // or blocky mode removed.
326: /* WATCOM code
327: if (detailshift)
328: {
329: if (dc_x & 1)
1.1 root 330: {
1.1.1.3 root 331: outpw (GC_INDEX,GC_READMAP+(2<<8) );
332: outp (SC_INDEX+1,12);
333: }
334: else
335: {
336: outpw (GC_INDEX,GC_READMAP);
337: outp (SC_INDEX+1,3);
338: }
339: dest = destview + dc_yl*80 + (dc_x>>1);
340: }
341: else
342: {
343: outpw (GC_INDEX,GC_READMAP+((dc_x&3)<<8) );
344: outp (SC_INDEX+1,1<<(dc_x&3));
345: dest = destview + dc_yl*80 + (dc_x>>2);
346: }*/
347:
348:
349: // Does not work with blocky mode.
350: dest = ylookup[dc_yl] + columnofs[dc_x];
351:
352: // Looks familiar.
353: fracstep = dc_iscale;
354: frac = dc_texturemid + (dc_yl-centery)*fracstep;
355:
356: // Looks like an attempt at dithering,
357: // using the colormap #6 (of 0-31, a bit
358: // brighter than average).
359: do
360: {
361: // Lookup framebuffer, and retrieve
362: // a pixel that is either one column
363: // left or right of the current one.
364: // Add index from colormap to index.
365: *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
366:
367: // Clamp table lookup index.
368: if (++fuzzpos == FUZZTABLE)
369: fuzzpos = 0;
370:
371: dest += SCREENWIDTH;
372:
373: frac += fracstep;
374: } while (count--);
375: }
376:
377:
378:
1.1 root 379:
1.1.1.2 root 380: //
1.1.1.3 root 381: // R_DrawTranslatedColumn
382: // Used to draw player sprites
383: // with the green colorramp mapped to others.
384: // Could be used with different translation
385: // tables, e.g. the lighter colored version
386: // of the BaronOfHell, the HellKnight, uses
387: // identical sprites, kinda brightened up.
1.1.1.2 root 388: //
1.1.1.3 root 389: byte* dc_translation;
390: byte* translationtables;
1.1.1.2 root 391:
1.1.1.3 root 392: void R_DrawTranslatedColumn (void)
393: {
394: int count;
395: byte* dest;
396: fixed_t frac;
397: fixed_t fracstep;
398:
399: count = dc_yh - dc_yl;
400: if (count < 0)
401: return;
402:
403: #ifdef RANGECHECK
404: if ((unsigned)dc_x >= SCREENWIDTH
405: || dc_yl < 0
406: || dc_yh >= SCREENHEIGHT)
407: {
408: I_Error ( "R_DrawColumn: %i to %i at %i",
409: dc_yl, dc_yh, dc_x);
410: }
411:
412: #endif
413:
414:
415: // WATCOM VGA specific.
416: /* Keep for fixing.
417: if (detailshift)
418: {
419: if (dc_x & 1)
420: outp (SC_INDEX+1,12);
421: else
422: outp (SC_INDEX+1,3);
1.1.1.2 root 423:
1.1.1.3 root 424: dest = destview + dc_yl*80 + (dc_x>>1);
425: }
426: else
427: {
428: outp (SC_INDEX+1,1<<(dc_x&3));
429:
430: dest = destview + dc_yl*80 + (dc_x>>2);
431: }*/
432:
433:
434: // FIXME. As above.
435: dest = ylookup[dc_yl] + columnofs[dc_x];
436:
437: // Looks familiar.
438: fracstep = dc_iscale;
439: frac = dc_texturemid + (dc_yl-centery)*fracstep;
440:
441: // Here we do an additional index re-mapping.
442: do
443: {
444: // Translation tables are used
445: // to map certain colorramps to other ones,
446: // used with PLAY sprites.
447: // Thus the "green" ramp of the player 0 sprite
448: // is mapped to gray, red, black/indigo.
449: *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
450: dest += SCREENWIDTH;
451:
452: frac += fracstep;
453: } while (count--);
454: }
455:
456:
1.1.1.2 root 457:
458:
1.1 root 459: //
1.1.1.3 root 460: // R_InitTranslationTables
461: // Creates the translation tables to map
462: // the green color ramp to gray, brown, red.
463: // Assumes a given structure of the PLAYPAL.
464: // Could be read from a lump instead.
1.1 root 465: //
466: void R_InitTranslationTables (void)
467: {
1.1.1.3 root 468: int i;
469:
470: translationtables = Z_Malloc (256*3+255, PU_STATIC, 0);
471: translationtables = (byte *)(( (int)translationtables + 255 )& ~255);
472:
473: // translate just the 16 green colors
474: for (i=0 ; i<256 ; i++)
475: {
476: if (i >= 0x70 && i<= 0x7f)
477: {
478: // map green ramp to gray, brown, red
479: translationtables[i] = 0x60 + (i&0xf);
480: translationtables [i+256] = 0x40 + (i&0xf);
481: translationtables [i+512] = 0x20 + (i&0xf);
482: }
483: else
1.1.1.2 root 484: {
1.1.1.3 root 485: // Keep all other colors as is.
486: translationtables[i] = translationtables[i+256]
487: = translationtables[i+512] = i;
1.1 root 488: }
1.1.1.3 root 489: }
1.1 root 490: }
491:
492:
493:
494:
1.1.1.3 root 495: //
496: // R_DrawSpan
497: // With DOOM style restrictions on view orientation,
498: // the floors and ceilings consist of horizontal slices
499: // or spans with constant z depth.
500: // However, rotation around the world z axis is possible,
501: // thus this mapping, while simpler and faster than
502: // perspective correct texture mapping, has to traverse
503: // the texture at an angle in all but a few cases.
504: // In consequence, flats are not stored by column (like walls),
505: // and the inner loop has to step in texture space u and v.
506: //
507: int ds_y;
508: int ds_x1;
509: int ds_x2;
510:
511: lighttable_t* ds_colormap;
512:
513: fixed_t ds_xfrac;
514: fixed_t ds_yfrac;
515: fixed_t ds_xstep;
516: fixed_t ds_ystep;
1.1 root 517:
1.1.1.3 root 518: // start of a 64*64 tile image
519: byte* ds_source;
1.1 root 520:
1.1.1.3 root 521: // just for profiling
522: int dscount;
1.1 root 523:
524:
1.1.1.3 root 525: //
526: // Draws the actual span.
527: void R_DrawSpan (void)
528: {
529: fixed_t xfrac;
530: fixed_t yfrac;
531: byte* dest;
532: int count;
533: int spot;
534:
535: #ifdef RANGECHECK
536: if (ds_x2 < ds_x1
537: || ds_x1<0
538: || ds_x2>=SCREENWIDTH
539: || (unsigned)ds_y>SCREENHEIGHT)
540: {
541: I_Error( "R_DrawSpan: %i to %i at %i",
542: ds_x1,ds_x2,ds_y);
543: }
544: // dscount++;
545: #endif
546:
547:
548: xfrac = ds_xfrac;
549: yfrac = ds_yfrac;
550:
551: dest = ylookup[ds_y] + columnofs[ds_x1];
552:
553: // We do not check for zero spans here?
1.1.1.5 ! root 554: count = ds_x2 - ds_x1;
1.1.1.3 root 555:
556: do
557: {
558: // Current texture index in u,v.
559: spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
560:
561: // Lookup pixel from flat texture tile,
562: // re-index using light/colormap.
563: *dest++ = ds_colormap[ds_source[spot]];
564:
565: // Next step in u,v.
566: xfrac += ds_xstep;
567: yfrac += ds_ystep;
568:
569: } while (count--);
570: }
1.1 root 571:
572:
573:
1.1.1.3 root 574: // UNUSED.
575: // Loop unrolled by 4.
576: #if 0
577: void R_DrawSpan (void)
578: {
579: unsigned position, step;
580:
581: byte* source;
582: byte* colormap;
583: byte* dest;
584:
585: unsigned count;
586: usingned spot;
587: unsigned value;
588: unsigned temp;
589: unsigned xtemp;
590: unsigned ytemp;
591:
592: position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff);
593: step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff);
594:
595: source = ds_source;
596: colormap = ds_colormap;
597: dest = ylookup[ds_y] + columnofs[ds_x1];
598: count = ds_x2 - ds_x1 + 1;
599:
600: while (count >= 4)
601: {
602: ytemp = position>>4;
603: ytemp = ytemp & 4032;
604: xtemp = position>>26;
605: spot = xtemp | ytemp;
606: position += step;
607: dest[0] = colormap[source[spot]];
608:
609: ytemp = position>>4;
610: ytemp = ytemp & 4032;
611: xtemp = position>>26;
612: spot = xtemp | ytemp;
613: position += step;
614: dest[1] = colormap[source[spot]];
615:
616: ytemp = position>>4;
617: ytemp = ytemp & 4032;
618: xtemp = position>>26;
619: spot = xtemp | ytemp;
620: position += step;
621: dest[2] = colormap[source[spot]];
622:
623: ytemp = position>>4;
624: ytemp = ytemp & 4032;
625: xtemp = position>>26;
626: spot = xtemp | ytemp;
627: position += step;
628: dest[3] = colormap[source[spot]];
629:
630: count -= 4;
631: dest += 4;
632: }
633: while (count > 0)
634: {
635: ytemp = position>>4;
636: ytemp = ytemp & 4032;
637: xtemp = position>>26;
638: spot = xtemp | ytemp;
639: position += step;
640: *dest++ = colormap[source[spot]];
641: count--;
642: }
643: }
644: #endif
1.1 root 645:
646:
1.1.1.3 root 647: //
648: // Again..
649: //
650: void R_DrawSpanLow (void)
651: {
652: fixed_t xfrac;
653: fixed_t yfrac;
654: byte* dest;
655: int count;
656: int spot;
657:
658: #ifdef RANGECHECK
659: if (ds_x2 < ds_x1
660: || ds_x1<0
661: || ds_x2>=SCREENWIDTH
662: || (unsigned)ds_y>SCREENHEIGHT)
663: {
664: I_Error( "R_DrawSpan: %i to %i at %i",
665: ds_x1,ds_x2,ds_y);
666: }
667: // dscount++;
668: #endif
669:
670: xfrac = ds_xfrac;
671: yfrac = ds_yfrac;
672:
673: // Blocky mode, need to multiply by 2.
674: ds_x1 <<= 1;
675: ds_x2 <<= 1;
676:
677: dest = ylookup[ds_y] + columnofs[ds_x1];
678:
679:
680: count = ds_x2 - ds_x1;
681: do
682: {
683: spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
684: // Lowres/blocky mode does it twice,
685: // while scale is adjusted appropriately.
686: *dest++ = ds_colormap[ds_source[spot]];
687: *dest++ = ds_colormap[ds_source[spot]];
1.1 root 688:
1.1.1.3 root 689: xfrac += ds_xstep;
690: yfrac += ds_ystep;
691:
692: } while (count--);
1.1 root 693: }
694:
1.1.1.3 root 695: //
696: // R_InitBuffer
697: // Creats lookup tables that avoid
1.1.1.5 ! root 698: // multiplies and other hassles
1.1.1.3 root 699: // for getting the framebuffer address
700: // of a pixel to draw.
701: //
1.1.1.5 ! root 702: void R_InitBuffer( int width, int height )
! 703: {
1.1.1.3 root 704: int i;
705:
706: // Handle resize,
707: // e.g. smaller view windows
708: // with border and/or status bar.
709: viewwindowx = (SCREENWIDTH-width) >> 1;
710:
711: // Column offset. For windows.
1.1.1.5 ! root 712: for (i = 0; i < width; i++)
! 713: columnofs[i] = viewwindowx + i;
1.1.1.3 root 714:
1.1.1.5 ! root 715: // Same with base row offset.
1.1.1.3 root 716: if (width == SCREENWIDTH)
1.1.1.5 ! root 717: viewwindowy = 0;
1.1.1.3 root 718: else
1.1.1.5 ! root 719: viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1;
1.1.1.3 root 720:
1.1.1.5 ! root 721: // Precalculate all row offsets.
! 722: for (i = 0; i < height; i++)
! 723: ylookup[i] = screens[0] + (i+viewwindowy)*SCREENWIDTH;
! 724: }
1.1.1.3 root 725:
726:
1.1 root 727:
728:
1.1.1.3 root 729: //
730: // R_FillBackScreen
1.1.1.5 ! root 731: // Fills the back screen with a pattern for variable screen sizes
1.1.1.3 root 732: // Also draws a beveled edge.
733: //
1.1.1.5 ! root 734: void R_FillBackScreen(void)
! 735: {
! 736: byte* src;
1.1.1.3 root 737: byte* dest;
738: int x;
739: int y;
740: patch_t* patch;
741:
742: // DOOM border patch.
743: char name1[] = "FLOOR7_2";
744:
745: // DOOM II border patch.
746: char name2[] = "GRNROCK";
747:
748: char* name;
1.1.1.5 ! root 749:
! 750: if ((scaledviewwidth == SCREENWIDTH)&&(viewheight == SCREENHEIGHT))
! 751: return;
1.1.1.3 root 752:
1.1.1.5 ! root 753: if (gamemode == commercial)
! 754: name = name2;
1.1.1.3 root 755: else
1.1.1.5 ! root 756: name = name1;
1.1.1.3 root 757:
1.1.1.5 ! root 758: src = W_CacheLumpName(name, PU_CACHE);
! 759: dest = screens[1];
1.1.1.3 root 760:
1.1.1.5 ! root 761: //for (y = 0; y < SCREENHEIGHT-SBARHEIGHT; y++)
! 762: for (y = 0; y < SCREENHEIGHT; y++)
1.1.1.3 root 763: {
1.1.1.5 ! root 764: for (x = 0; x < SCREENWIDTH/64; x++)
! 765: {
! 766: memcpy (dest, src+((y&63)<<6), 64);
! 767: dest += 64;
! 768: }
! 769: if (SCREENWIDTH & 63)
! 770: {
! 771: memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
! 772: dest += (SCREENWIDTH&63);
! 773: }
1.1.1.3 root 774: }
775:
1.1.1.5 ! root 776: if (scaledviewwidth == SCREENWIDTH)
! 777: return;
! 778:
1.1.1.3 root 779: patch = W_CacheLumpName ("brdr_t",PU_CACHE);
780:
781: for (x=0 ; x<scaledviewwidth ; x+=8)
782: V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
783: patch = W_CacheLumpName ("brdr_b",PU_CACHE);
784:
785: for (x=0 ; x<scaledviewwidth ; x+=8)
786: V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
787: patch = W_CacheLumpName ("brdr_l",PU_CACHE);
788:
789: for (y=0 ; y<viewheight ; y+=8)
790: V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
791: patch = W_CacheLumpName ("brdr_r",PU_CACHE);
792:
793: for (y=0 ; y<viewheight ; y+=8)
794: V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
795:
796:
797: // Draw beveled edge.
798: V_DrawPatch (viewwindowx-8,
799: viewwindowy-8,
800: 1,
801: W_CacheLumpName ("brdr_tl",PU_CACHE));
802:
803: V_DrawPatch (viewwindowx+scaledviewwidth,
804: viewwindowy-8,
805: 1,
806: W_CacheLumpName ("brdr_tr",PU_CACHE));
807:
808: V_DrawPatch (viewwindowx-8,
809: viewwindowy+viewheight,
810: 1,
811: W_CacheLumpName ("brdr_bl",PU_CACHE));
812:
813: V_DrawPatch (viewwindowx+scaledviewwidth,
814: viewwindowy+viewheight,
815: 1,
816: W_CacheLumpName ("brdr_br",PU_CACHE));
817: }
818:
1.1 root 819:
1.1.1.3 root 820: //
821: // Copy a screen buffer.
822: //
1.1.1.5 ! root 823: void R_VideoErase( unsigned ofs, int count )
! 824: {
! 825: // LFB copy.
! 826: // This might not be a good idea if memcpy is not optimal, e.g. byte by byte on
! 827: // a 32bit CPU, as GNU GCC/Linux libc did at one point.
! 828: memcpy(screens[0]+ofs, screens[1]+ofs, count);
! 829: }
1.1 root 830:
831:
1.1.1.3 root 832: //
833: // R_DrawViewBorder
834: // Draws the border around the view
835: // for different size windows?
836: //
837: void
838: V_MarkRect
839: ( int x,
840: int y,
841: int width,
842: int height );
843:
844: void R_DrawViewBorder (void)
1.1.1.5 ! root 845: {
1.1.1.3 root 846: int top;
1.1.1.5 ! root 847: int side, side2;
1.1.1.3 root 848: int ofs;
849: int i;
1.1.1.5 ! root 850:
! 851: if ((SCREENWIDTH > 320) && (SCREENHEIGHT != viewheight))
! 852: {
! 853: ofs = (SCREENHEIGHT-SBARHEIGHT) * SCREENWIDTH;
! 854: side = ((SCREENWIDTH - 320) / 2);
! 855: side2 = side * 2;
! 856:
! 857: R_VideoErase(ofs, side);
! 858: ofs += (SCREENWIDTH - side);
! 859: for (i = 1;i < SBARHEIGHT;i++)
! 860: {
! 861: R_VideoErase(ofs, side2);
! 862: ofs += SCREENWIDTH;
! 863: }
! 864: R_VideoErase(ofs, side);
! 865: }
! 866:
1.1.1.3 root 867: if (scaledviewwidth == SCREENWIDTH)
1.1.1.5 ! root 868: return;
! 869:
! 870: top = ((SCREENHEIGHT-SBARHEIGHT)-viewheight)/2;
! 871: side = (SCREENWIDTH-scaledviewwidth)/2;
1.1.1.3 root 872:
873: // copy top and one line of left side
1.1.1.5 ! root 874: R_VideoErase(0, top*SCREENWIDTH+side);
1.1.1.3 root 875:
876: // copy one line of right side and bottom
1.1.1.5 ! root 877: ofs = (viewheight+top)*SCREENWIDTH-side;
! 878: R_VideoErase (ofs, top*SCREENWIDTH+side);
1.1.1.3 root 879:
880: // copy sides using wraparound
881: ofs = top*SCREENWIDTH + SCREENWIDTH-side;
882: side <<= 1;
883:
1.1.1.5 ! root 884: for (i = 1; i < viewheight; i++)
! 885: {
! 886: R_VideoErase (ofs, side);
! 887: ofs += SCREENWIDTH;
! 888: }
1.1.1.3 root 889:
890: // ?
891: V_MarkRect (0,0,SCREENWIDTH, SCREENHEIGHT-SBARHEIGHT);
1.1.1.5 ! root 892: }
1.1.1.3 root 893:
894:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.