1 #include <unistd.h>
2 
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <assert.h>
6 #include <sys/ipc.h>
7 #include <sys/shm.h>
8 
9 #include <X11/Xlib.h>
10 #include <X11/Xutil.h>
11 #include <X11/keysym.h>
12 
13 #include <X11/extensions/XShm.h>
14 /*
15  * Had to dig up XShm.c for this one.
16  * It is in the libXext, but not in the XFree86 headers.
17  */
18 #ifdef NEED_SHMGETEVENTBASE
19 int XShmGetEventBase( Display* dpy );
20 #endif
21 
22 #include <stdarg.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 
27 #include <netinet/in.h>
28 #include <errno.h>
29 #include <signal.h>
30 
31 #include "doomdef.h"
32 
33 #define SHOW_FPS
34 
35 #ifdef SHOW_FPS
36 static struct timeval   starttime;
37 static long             totalframes;
38 static int              showfps = 0;
39 
reset_framecounter(void)40 static void reset_framecounter(void)
41 {
42   totalframes = 0;
43   gettimeofday(&starttime, NULL);
44 }
45 #endif
46 
47 #define POINTER_WARP_COUNTDOWN	1
48 
49 static Display       *X_display=0;
50 static Window        X_mainWindow;
51 static Colormap      X_cmap;
52 static Visual        *X_visual;
53 static GC            X_gc;
54 static XEvent        X_event;
55 static int           X_screen;
56 static XVisualInfo   X_visualinfo;
57 static XImage        *image;
58 static int           X_width;
59 static int           X_height;
60 static int           true_color=FALSE;
61 static Screen        *screen_intern;
62 static XColor        colors[256];
63 static unsigned long *xpixel;
64 
65 /* MIT SHared Memory extension. */
66 static boolean       doShm;
67 
68 static XShmSegmentInfo X_shminfo;
69 static int             X_shmeventtype;
70 static int             XShm_is_attached=FALSE;
71 
72 
73 /*
74  * Fake mouse handling.
75  * This cannot work properly w/o DGA.
76  * Needs an invisible mouse cursor at least.
77  */
78 extern long     do_grabMouse;
79 static int      doPointerWarp = POINTER_WARP_COUNTDOWN;
80 
81 /*
82  * Blocky mode,
83  * replace each 320x200 pixel with multiply*multiply pixels.
84  * According to Dave Taylor, it still is a bonehead thing
85  * to use ....
86  */
87 static int	multiply=1;
88 
89 /*
90  * pointer to palette update function (different for
91  * true- and pseudocolor)
92  */
93 static void (*up_palette)(Colormap,byte *);
94 
95 /* truecolor helper routines */
96 static int init_truec_pals(void);
97 static int free_truec_pals(void);
98 static void fill_pal_cache(int,Colormap,byte *);
99 static int get_pal_usage(void);
100 
101 static int oldgamma;
102 
103 /*#define PALETTE_DEBUG*/
104 #define PALETTE_INFO       /* display # of used cache slots at termination */
105 #define MAX_PAL_CACHE 25   /* number of palettes to cache */
106 #define INI_LRU 1000
107 #define MIN_LRU 10
108 
109 /* layout of entry in truecolor palette cache */
110 static struct paldef {
111   caddr_t id;               /* contains pointer / id of palette */
112   unsigned long *xpix_ptr;  /* pointer to matching xpixel table */
113   unsigned int lru;
114 } *pal_cache;
115 
116 
clr_pal_cache(int index,Colormap cmap)117 static inline void clr_pal_cache(int index,Colormap cmap)
118 {
119   int j;
120 
121   for (j=0; j<256; j++) {
122     XFreeColors(X_display,cmap,pal_cache[index].xpix_ptr+j,1,0);
123   }
124 }
125 
126 /*
127  *  Translates the key currently in X_event
128  */
129 
xlatekey(void)130 int xlatekey(void)
131 {
132 
133     int rc;
134 
135     switch(rc = XKeycodeToKeysym(X_display, X_event.xkey.keycode, 0))
136       {
137       case XK_Delete:   rc = KEY_DELETE;        break;
138       case XK_Insert:   rc = KEY_INSERT;        break;
139       case XK_Page_Up:  rc = KEY_PAGEUP;        break;
140       case XK_Page_Down:rc = KEY_PAGEDOWN;      break;
141       case XK_Home:     rc = KEY_HOME;          break;
142       case XK_End:      rc = KEY_END;           break;
143       case XK_Left:	rc = KEY_LEFTARROW;	break;
144       case XK_Right:	rc = KEY_RIGHTARROW;	break;
145       case XK_Down:	rc = KEY_DOWNARROW;	break;
146       case XK_Up:	rc = KEY_UPARROW;	break;
147       case XK_Escape:	rc = KEY_ESCAPE;	break;
148       case XK_Return:	rc = KEY_ENTER;		break;
149       case XK_Tab:	rc = KEY_TAB;		break;
150       case XK_F1:	rc = KEY_F1;		break;
151       case XK_F2:	rc = KEY_F2;		break;
152       case XK_F3:	rc = KEY_F3;		break;
153       case XK_F4:	rc = KEY_F4;		break;
154       case XK_F5:	rc = KEY_F5;		break;
155       case XK_F6:	rc = KEY_F6;		break;
156       case XK_F7:	rc = KEY_F7;		break;
157       case XK_F8:	rc = KEY_F8;		break;
158       case XK_F9:	rc = KEY_F9;		break;
159       case XK_F10:	rc = KEY_F10;		break;
160       case XK_F11:	rc = KEY_F11;		break;
161       case XK_F12:	rc = KEY_F12;		break;
162 
163       case XK_BackSpace:rc = KEY_BACKSPACE;     break;
164       case XK_Pause:	rc = KEY_PAUSE;		break;
165 
166       case XK_KP_Add:
167       case XK_plus:
168 	/*   rc = KEY_PLUS; break; !TODO: define in doomdef.h TODO!   */
169       case XK_KP_Equal:
170       case XK_equal:	rc = KEY_EQUALS;	break;
171 
172       case XK_KP_Subtract:
173       case XK_minus:	rc = KEY_MINUS;		break;
174 
175       case XK_KP_0:    rc = '0';               break;
176       case XK_KP_1:    rc = '1';               break;
177       case XK_KP_2:    rc = '2';               break;
178       case XK_KP_3:    rc = '3';               break;
179       case XK_KP_4:    rc = '4';               break;
180       case XK_KP_5:    rc = '5';               break;
181       case XK_KP_6:    rc = '6';               break;
182       case XK_KP_7:    rc = '7';               break;
183       case XK_KP_8:    rc = '8';               break;
184       case XK_KP_9:    rc = '9';               break;
185 
186       /* This is an ugly PC-ism. Better switch to XLookupKeysym() ? */
187       case XK_KP_Insert:       rc = '0';       break;
188       case XK_KP_End:          rc = '1';       break;
189       case XK_KP_Down:         rc = '2';       break;
190       case XK_KP_Page_Down:    rc = '3';       break;
191       case XK_KP_Left:         rc = '4';       break;
192       case XK_KP_Begin:                rc = '5';       break;
193       case XK_KP_Right:                rc = '6';       break;
194       case XK_KP_Home:         rc = '7';       break;
195       case XK_KP_Up:           rc = '8';       break;
196       case XK_KP_Page_Up:      rc = '9';       break;
197 
198       case XK_Shift_L:
199       case XK_Shift_R:
200 	rc = KEY_RSHIFT;
201 	break;
202 
203       case XK_Control_L:
204       case XK_Control_R:
205 	rc = KEY_RCTRL;
206 	break;
207 
208       case XK_Alt_L:
209       case XK_Meta_L:
210       case XK_Alt_R:
211       case XK_Meta_R:
212 	rc = KEY_RALT;
213 	break;
214 
215       default:
216 	if (rc >= XK_space && rc <= XK_asciitilde)
217 	  rc = rc - XK_space + ' ';
218 	if (rc >= 'A' && rc <= 'Z')
219 	  rc = rc - 'A' + 'a';
220 	break;
221     }
222 
223     return rc;
224 }
225 
I_ShutdownGraphics(void)226 void I_ShutdownGraphics(void)
227 {
228   if (true_color) {
229 #ifdef PALETTE_INFO
230     fprintf(stderr,"TrueColor palette cache: %d/%d entries used.\n",
231 	    get_pal_usage(),MAX_PAL_CACHE);
232 #endif
233     free_truec_pals();
234     sleep(2);
235   }
236 
237   if (XShm_is_attached) {
238     /* Detach from X server */
239     if (!XShmDetach(X_display, &X_shminfo))
240       I_Error("XShmDetach() failed in I_ShutdownGraphics()");
241 
242     /* Release shared memory. */
243     shmdt(X_shminfo.shmaddr);
244     shmctl(X_shminfo.shmid, IPC_RMID, 0);
245   }
246 
247   /* Paranoia. Yes: needed! */
248   if (image)
249     image->data = NULL;
250 }
251 
252 
253 /*
254  * I_StartFrame
255  */
I_StartFrame(void)256 void I_StartFrame (void)
257 {
258   /* er? */
259 }
260 
261 static int      lastmousex = 0;
262 static int      lastmousey = 0;
263 static boolean  mousemoved = false;
264 static boolean  shmFinished;
265 
I_GetEvent(void)266 void I_GetEvent(void)
267 {
268 
269   event_t event;
270 
271   /* put event-grabbing stuff in here */
272   XNextEvent(X_display, &X_event);
273   switch (X_event.type)
274     {
275     case KeyPress:
276       event.type = ev_keydown;
277       event.data1 = xlatekey();
278 #ifdef SHOW_FPS
279       if (event.data1 == KEY_BACKSPACE &&
280 	  gamestate == GS_LEVEL) {
281 	/* Toggle and reset the FPS counter */
282 	showfps = !showfps;
283 	reset_framecounter();
284       }
285 #endif
286       D_PostEvent(&event);
287       /* fprintf(stderr, "k"); */
288       break;
289     case KeyRelease:
290       event.type = ev_keyup;
291       event.data1 = xlatekey();
292       D_PostEvent(&event);
293       /* fprintf(stderr, "ku"); */
294       break;
295     case ButtonPress:
296       event.type = ev_mouse;
297       event.data1 =
298 	(X_event.xbutton.state & Button1Mask)
299 	| (X_event.xbutton.state & Button2Mask ? 2 : 0)
300 	| (X_event.xbutton.state & Button3Mask ? 4 : 0)
301 	| (X_event.xbutton.button == Button1)
302 	| (X_event.xbutton.button == Button2 ? 2 : 0)
303 	| (X_event.xbutton.button == Button3 ? 4 : 0);
304       event.data2 = event.data3 = 0;
305       D_PostEvent(&event);
306       /* fprintf(stderr, "b"); */
307       break;
308     case ButtonRelease:
309       event.type = ev_mouse;
310       event.data1 =
311 	(X_event.xbutton.state & Button1Mask)
312 	| (X_event.xbutton.state & Button2Mask ? 2 : 0)
313 	| (X_event.xbutton.state & Button3Mask ? 4 : 0);
314       /* suggest parentheses around arithmetic in operand of | */
315       event.data1 =
316 	event.data1
317 	^ (X_event.xbutton.button == Button1 ? 1 : 0)
318 	^ (X_event.xbutton.button == Button2 ? 2 : 0)
319 	^ (X_event.xbutton.button == Button3 ? 4 : 0);
320       event.data2 = event.data3 = 0;
321       D_PostEvent(&event);
322       /* fprintf(stderr, "bu"); */
323       break;
324     case MotionNotify:
325       event.type = ev_mouse;
326       event.data1 =
327 	(X_event.xmotion.state & Button1Mask)
328 	| (X_event.xmotion.state & Button2Mask ? 2 : 0)
329 	| (X_event.xmotion.state & Button3Mask ? 4 : 0);
330       event.data2 = (X_event.xmotion.x - lastmousex) << 2;
331       event.data3 = (lastmousey - X_event.xmotion.y) << 2;
332 
333       if (event.data2 || event.data3)
334 	{
335 	  lastmousex = X_event.xmotion.x;
336 	  lastmousey = X_event.xmotion.y;
337 	  if (X_event.xmotion.x != X_width/2 &&
338 	      X_event.xmotion.y != X_height/2)
339 	    {
340 	      D_PostEvent(&event);
341 	      /* fprintf(stderr, "m"); */
342 	      mousemoved = false;
343 	    } else
344 	      {
345 		mousemoved = true;
346 	      }
347 	}
348       break;
349 
350     case Expose:
351     case ConfigureNotify:
352       break;
353 
354     default:
355       if (doShm && X_event.type == X_shmeventtype) shmFinished = true;
356       break;
357     }
358 }
359 
createnullcursor(Display * display,Window root)360 static Cursor createnullcursor(Display* display,Window root)
361 {
362   Pixmap cursormask;
363   XGCValues xgc;
364   GC gc;
365   XColor dummycolour;
366   Cursor cursor;
367 
368   cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
369   xgc.function = GXclear;
370   gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
371   XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
372   dummycolour.pixel = 0;
373   dummycolour.red = 0;
374   dummycolour.flags = 04;
375   cursor = XCreatePixmapCursor(display, cursormask, cursormask,
376 			       &dummycolour,&dummycolour, 0,0);
377   XFreePixmap(display,cursormask);
378   XFreeGC(display,gc);
379   return cursor;
380 }
381 
382 /*
383  * I_StartTic
384  */
I_StartTic(void)385 void I_StartTic (void)
386 {
387   if (!X_display)
388     return;
389 
390   while (XPending(X_display))
391     I_GetEvent();
392 
393   /*
394    * Warp the pointer back to the middle of the window
395    *  or it will wander off - that is, the game will
396    *  loose input focus within X11.
397    */
398   if (do_grabMouse)
399     {
400       if (!--doPointerWarp)
401 	{
402 	  XWarpPointer( X_display,
403 			None,
404 			X_mainWindow,
405 			0, 0,
406 			0, 0,
407 			X_width/2, X_height/2);
408 
409 	  doPointerWarp = POINTER_WARP_COUNTDOWN;
410 	}
411     }
412 
413   mousemoved = false;
414 }
415 
416 
417 /*
418  * I_FinishUpdate
419  */
I_FinishUpdate(void)420 void I_FinishUpdate (void)
421 {
422   static int    lasttic=0;
423   int           tics,i,l,l2,c,cc,ll;
424   unsigned char p;
425   long          color;
426   boolean       devparm=1; /* You can change this to 1 for little dots on the screen ! */
427 
428   /* draws little dots on the bottom of the screen */
429   if (devparm) {
430     i = I_GetTime();
431     tics = i - lasttic;
432     lasttic = i;
433     if (tics > 20) tics = 20;
434 
435     for (i=0 ; i<tics*2 ; i+=2)
436       screen[ (screenheight-1)*screenwidth + i] = 0xff;
437     for ( ; i<20*2 ; i+=2)
438       screen[ (screenheight-1)*screenwidth + i] = 0x0;
439   }
440 
441   /* Filters the first 32 palette-entry-color'd(gray-color) pixels if wanted */
442   if (lifilter && !bilifilter)
443     V_Filter_Screen_linear(screen);
444   if (bilifilter && !lifilter)
445     V_Filter_Screen_bilinear(screen);
446 
447   if (true_color) {
448     if (multiply == 1) {
449       for (l=0,l2=0; l<screenheight; l++, l2+=screenwidth) {
450 	for (c=0; c<screenwidth; c++) {
451 	  p=screen[l2+c];
452 	  color=xpixel[p];
453 	  XPutPixel(image,c,l,color);
454 	}
455       }
456     }
457     else if (multiply == 2) {
458       for (l=0,l2=0; l<screenheight; l++, l2+=screenwidth) {
459 	for (c=0; c<screenwidth; c++) {
460 	  p=screen[l2+c];
461 	  color=xpixel[p];
462 	  XPutPixel(image,c+c,  l+l,  color);
463 	  XPutPixel(image,c+c+1,l+l,  color);
464 	  XPutPixel(image,c+c,  l+l+1,color);
465 	  XPutPixel(image,c+c+1,l+l+1,color);
466 	}
467       }
468     }
469     else if (multiply == 3) {
470       for (l=0,l2=0; l<screenheight; l++, l2+=screenwidth) {
471 	for (c=0; c<screenwidth; c++) {
472 	  p=screen[l2+c];
473 	  color=xpixel[p];
474 	  cc=c+c+c; ll=l+l+l;
475 	  XPutPixel(image,cc,  ll,  color);
476 	  XPutPixel(image,cc+1,ll,  color);
477 	  XPutPixel(image,cc+2,ll,  color);
478 	  XPutPixel(image,cc,  ll+1,color);
479 	  XPutPixel(image,cc+1,ll+1,color);
480 	  XPutPixel(image,cc+2,ll+1,color);
481 	  XPutPixel(image,cc,  ll+2,color);
482 	  XPutPixel(image,cc+1,ll+2,color);
483 	  XPutPixel(image,cc+2,ll+2,color);
484 	}
485       }
486     }
487     else {  /* multiply == 4 */
488       for (l=0,l2=0; l<screenheight; l++, l2+=screenwidth) {
489 	for (c=0; c<screenwidth; c++) {
490 	  p=screen[l2+c];
491 	  color=xpixel[p];
492 	  cc=c<<2; ll=l<<2;
493 	  XPutPixel(image,cc,  ll,  color);
494 	  XPutPixel(image,cc+1,ll,  color);
495 	  XPutPixel(image,cc+2,ll,  color);
496 	  XPutPixel(image,cc+3,ll,  color);
497 	  XPutPixel(image,cc,  ll+1,color);
498 	  XPutPixel(image,cc+1,ll+1,color);
499 	  XPutPixel(image,cc+2,ll+1,color);
500 	  XPutPixel(image,cc+3,ll+1,color);
501 	  XPutPixel(image,cc,  ll+2,color);
502 	  XPutPixel(image,cc+1,ll+2,color);
503 	  XPutPixel(image,cc+2,ll+2,color);
504 	  XPutPixel(image,cc+3,ll+2,color);
505 	  XPutPixel(image,cc,  ll+3,color);
506 	  XPutPixel(image,cc+1,ll+3,color);
507 	  XPutPixel(image,cc+2,ll+3,color);
508 	  XPutPixel(image,cc+3,ll+3,color);
509 	}
510       }
511     }
512   }
513   else {  /* not truecolor */
514     /* scales the screen size before blitting it */
515     if (multiply == 2) {
516       unsigned int *olineptrs[2];
517       unsigned int *ilineptr;
518       int x,y;
519       unsigned int twoopixels;
520       unsigned int twomoreopixels;
521       unsigned int fouripixels;
522 
523       ilineptr = (unsigned int *) (screen);
524       for (i=0 ; i<2 ; i++)
525 	olineptrs[i] = (unsigned int *) &image->data[i*X_width];
526 
527       y = screenheight;
528       while (y--) {
529 	x = screenwidth;
530 	do {
531 	  fouripixels = *ilineptr++;
532 	  twoopixels = (fouripixels & 0xff000000)
533 	    | ((fouripixels>>8) & 0xffff00)
534 	    | ((fouripixels>>16) & 0xff);
535 	  twomoreopixels = ((fouripixels<<16) & 0xff000000)
536 	    | ((fouripixels<<8) & 0xffff00)
537 	    | (fouripixels & 0xff);
538 #ifdef __BIG_ENDIAN__
539 	  *olineptrs[0]++ = twoopixels;
540 	  *olineptrs[1]++ = twoopixels;
541 	  *olineptrs[0]++ = twomoreopixels;
542 	  *olineptrs[1]++ = twomoreopixels;
543 #else
544 	  *olineptrs[0]++ = twomoreopixels;
545 	  *olineptrs[1]++ = twomoreopixels;
546 	  *olineptrs[0]++ = twoopixels;
547 	  *olineptrs[1]++ = twoopixels;
548 #endif
549 	} while (x-=4);
550 	olineptrs[0] += X_width/4;
551 	olineptrs[1] += X_width/4;
552       }
553     }
554     else if (multiply == 3) {
555       unsigned int *olineptrs[3];
556       unsigned int *ilineptr;
557       int x,y;
558       unsigned int fouropixels[3];
559       unsigned int fouripixels;
560 
561       ilineptr = (unsigned int *) (screen);
562       for (i=0 ; i<3 ; i++)
563 	olineptrs[i] = (unsigned int *) &image->data[i*X_width];
564 
565       y = screenheight;
566       while (y--) {
567 	x = screenwidth;
568 	do {
569 	  fouripixels = *ilineptr++;
570 	  fouropixels[0] = (fouripixels & 0xff000000)
571 	    | ((fouripixels>>8) & 0xff0000)
572 	    | ((fouripixels>>16) & 0xffff);
573 	  fouropixels[1] = ((fouripixels<<8) & 0xff000000)
574 	    | (fouripixels & 0xffff00)
575 	    | ((fouripixels>>8) & 0xff);
576 	  fouropixels[2] = ((fouripixels<<16) & 0xffff0000)
577 	    | ((fouripixels<<8) & 0xff00)
578 	    | (fouripixels & 0xff);
579 #ifdef __BIG_ENDIAN__
580 	  *olineptrs[0]++ = fouropixels[0];
581 	  *olineptrs[1]++ = fouropixels[0];
582 	  *olineptrs[2]++ = fouropixels[0];
583 	  *olineptrs[0]++ = fouropixels[1];
584 	  *olineptrs[1]++ = fouropixels[1];
585 	  *olineptrs[2]++ = fouropixels[1];
586 	  *olineptrs[0]++ = fouropixels[2];
587 	  *olineptrs[1]++ = fouropixels[2];
588 	  *olineptrs[2]++ = fouropixels[2];
589 #else
590 	  *olineptrs[0]++ = fouropixels[2];
591 	  *olineptrs[1]++ = fouropixels[2];
592 	  *olineptrs[2]++ = fouropixels[2];
593 	  *olineptrs[0]++ = fouropixels[1];
594 	  *olineptrs[1]++ = fouropixels[1];
595 	  *olineptrs[2]++ = fouropixels[1];
596 	  *olineptrs[0]++ = fouropixels[0];
597 	  *olineptrs[1]++ = fouropixels[0];
598 	  *olineptrs[2]++ = fouropixels[0];
599 #endif
600 	} while (x-=4);
601 	olineptrs[0] += 2*X_width/4;
602 	olineptrs[1] += 2*X_width/4;
603 	olineptrs[2] += 2*X_width/4;
604       }
605     }
606     else if (multiply == 4) {
607       /* Broken. Gotta fix this some day. */
608       void Expand4(unsigned *, double *);
609       Expand4 ((unsigned *)(screen), (double *) (image->data));
610     }
611   } /* if not truecolor */
612 
613   if (doShm) {
614     if (!XShmPutImage(X_display,
615 		      X_mainWindow,
616 		      X_gc,
617 		      image,
618 		      0, 0,
619 		      0, 0,
620 		      X_width,X_height,
621 		      True))
622       I_Error("XShmPutImage() failed\n");
623 
624     /* wait for it to finish and processes all input events */
625     shmFinished = false;
626     do {
627       I_GetEvent();
628     } while (!shmFinished);
629   }
630   else {
631     /* draw the image */
632     XPutImage(X_display,
633 	      X_mainWindow,
634 	      X_gc,
635 	      image,
636 	      0, 0,
637 	      0, 0,
638 	      X_width,X_height);
639 
640     /* sync up with server */
641     XSync(X_display, False);
642   }
643 #ifdef SHOW_FPS
644   if (showfps) {
645     struct timeval curtime;
646     double diff;
647     char str[64];
648 
649     totalframes++;
650     gettimeofday(&curtime, NULL);
651     diff = (curtime.tv_sec - starttime.tv_sec);
652     diff += ((double)curtime.tv_usec - starttime.tv_usec)/1000000;
653     if (diff != 0) {
654       sprintf(str, "FPS: %.1f", totalframes/diff);
655       XDrawString(X_display, X_mainWindow, X_gc, 0, 16, str,
656 		  strlen(str));
657     }
658   }
659 #endif
660 }
661 
662 
663 /*
664  * Palette stuff.
665  *
666  * PseudoColor version
667  */
UploadNewPalette(Colormap cmap,byte * palette)668 static void UploadNewPalette(Colormap cmap, byte *palette)
669 {
670     register int   i;
671     register int   c;
672     static boolean firstcall = TRUE;
673 
674     if (X_visualinfo.class == PseudoColor && X_visualinfo.depth == 8) {
675       /* initialize the colormap */
676       if (firstcall) {
677 	firstcall = FALSE;
678 	for (i=0 ; i<256 ; i++) {
679 	  colors[i].pixel = i;
680 	  colors[i].flags = DoRed|DoGreen|DoBlue;
681 	}
682       }
683 
684       /* set the X colormap entries */
685       for (i=0 ; i<256 ; i++)  {
686 	c = gammatable[usegamma][*palette++];
687 	colors[i].red = (c<<8) + c;
688 	c = gammatable[usegamma][*palette++];
689 	colors[i].green = (c<<8) + c;
690 	c = gammatable[usegamma][*palette++];
691 	colors[i].blue = (c<<8) + c;
692       }
693 
694       /* store the colors to the current colormap */
695       XStoreColors(X_display, cmap, colors, 256);
696     }
697     else {
698       fprintf(stderr,"UploadNewPalette: unknown visual type!\n");
699     }
700 }
701 
702 /*
703  * Truecolor "palette" update
704  */
UploadNewTruePal(Colormap cmap,byte * palette)705 static void UploadNewTruePal(Colormap cmap, byte *palette)
706 {
707   int least,lru,i,found=FALSE;
708 
709   /* use the palette pointer as palette id, i.e. a palette
710    * with another pointer value is assumed to be a different
711    * palette, and, more important, if the pointer is equal,
712    * the palette is assumed to be the same...
713    */
714 
715 #ifdef PALETTE_DEBUG
716   fprintf(stderr,"UploadNewTruePal: entered with %p -- gamma %d\n",palette,usegamma);
717 #endif
718 
719   if (usegamma != oldgamma) {  /* if gamma value changed since last invokation */
720 #ifdef PALETTE_DEBUG
721     fprintf(stderr,"\tnew gamma value -- discarding cache\n");
722 #endif
723     oldgamma=usegamma;
724     for (i=0; i<MAX_PAL_CACHE; i++) {  /* discard old palette cache */
725       if (pal_cache[i].id) clr_pal_cache(i,cmap);
726       pal_cache[i].id=0;  /* mark entry as empty */
727     }
728   }
729 
730   /* search ptr in table */
731   for (i=0; i<MAX_PAL_CACHE; i++) {
732     if (pal_cache[i].id == (caddr_t)palette) {
733 #ifdef PALETTE_DEBUG
734       fprintf(stderr,"\tfound palette, index %d\n",i);
735 #endif
736       xpixel=pal_cache[i].xpix_ptr;
737       pal_cache[i].lru=INI_LRU;
738       found=TRUE;
739     }
740     else {
741       if (pal_cache[i].lru > MIN_LRU) pal_cache[i].lru--;
742     }
743   }
744   if (found) return;
745 #ifdef PALETTE_DEBUG
746   fprintf (stderr,"\tNOT FOUND\n");
747 #endif
748 
749   /* palette not yet in my table -- search empty entry */
750   for (i=0, found=FALSE; i<MAX_PAL_CACHE; i++) {
751     if (! pal_cache[i].id) {
752       found=TRUE;
753       break;
754     }
755   }
756   if (found) {
757 #ifdef PALETTE_DEBUG
758     fprintf(stderr,"\tfound empty: index %d\n",i);
759 #endif
760     fill_pal_cache(i,cmap,palette);
761     return;
762   }
763 #ifdef PALETTE_DEBUG
764   fprintf(stderr,"\tno empty entry found \n");
765 #endif
766 
767   /* no empty entry -- search a least recently used entry */
768   for (least=-1,i=0,lru=INI_LRU; i<MAX_PAL_CACHE; i++) {
769     if (pal_cache[i].lru < lru) {
770       lru=pal_cache[i].lru;
771       least=i;
772     }
773   }
774   if (least == -1) {
775     fprintf(stderr,"UploadNewTruePal: palette cache inconsistency!\n");
776     return;
777   }
778 #ifdef PALETTE_DEBUG
779   fprintf(stderr,"\treusing entry %d\n",least);
780 #endif
781   clr_pal_cache(least,cmap);   /* free old entries */
782   fill_pal_cache(least,cmap,palette); /* alloc new entries */
783   return;
784 }
785 
fill_pal_cache(int index,Colormap cmap,byte * palette)786 static void fill_pal_cache(int index,Colormap cmap,byte *palette)
787 {
788   unsigned int i,c;
789   XColor color;
790   void *dummy;
791 
792   if (!pal_cache[index].xpix_ptr) { /* memory for palette not yet allocated */
793       {
794 	  dummy=malloc(256 * sizeof(long));
795 	  assert(dummy);
796 	  if (! (pal_cache[index].xpix_ptr=dummy))
797 	      {
798 		  fprintf(stderr,"fill_pal_cache: failed to allocate palette buffer\n");
799 		  return;
800 	      }
801       }
802   }
803 
804   xpixel=pal_cache[index].xpix_ptr;
805   pal_cache[index].id=(caddr_t)palette;  /* set id */
806 
807   for (i=0; i<256; i++) {
808     color.pixel = 0;
809     color.flags = DoRed|DoGreen|DoBlue;
810     c = gammatable[usegamma][*palette++];
811     color.red = c << 8;
812     c = gammatable[usegamma][*palette++];
813     color.green = c << 8;
814     c = gammatable[usegamma][*palette++];
815     color.blue = c << 8;
816 
817     if (XAllocColor(X_display,cmap,&color)) {
818       xpixel[i]=color.pixel;
819     }
820     else {
821       fprintf(stderr,"fill_pal_cache: cannot alloc color %d\n",i);
822     }
823   }
824 }
825 
get_pal_usage(void)826 static int get_pal_usage(void)
827 {
828   int i,count=0;
829 
830   if (pal_cache)
831     for (i=0; i<MAX_PAL_CACHE; i++)
832       if (pal_cache[i].id)
833 	count++;
834   return(count);
835 }
836 
init_truec_pals(void)837 static int init_truec_pals(void)
838 {
839   pal_cache=malloc(MAX_PAL_CACHE * sizeof(struct paldef));
840   assert(pal_cache);
841   if (!pal_cache) return(FALSE);
842   memset(pal_cache,0,MAX_PAL_CACHE * sizeof(struct paldef));
843   return(TRUE);
844 }
845 
free_truec_pals(void)846 static int free_truec_pals(void)
847 {
848   int i;
849 
850   if (pal_cache) {
851     for (i=0; i<MAX_PAL_CACHE; i++) {
852       if (pal_cache[i].xpix_ptr) {
853 	clr_pal_cache(i,X_cmap);
854 	free(pal_cache[i].xpix_ptr);
855       }
856     }
857     free(pal_cache);
858   }
859   return(TRUE);
860 }
861 
862 /*
863  * I_SetPalette
864  */
I_SetPalette(byte * palette)865 void I_SetPalette (byte* palette)
866 {
867   if (up_palette)
868     (up_palette)(X_cmap, palette);
869   else
870     fprintf(stderr,"i_x11: up_palette called before initialization!!!\n");
871 }
872 
873 
874 /*
875  * This function is probably redundant,
876  *  if XShmDetach works properly.
877  * ddt never detached the XShm memory,
878  *  thus there might have been stale
879  *  handles accumulating.
880  */
grabsharedmemory(size_t size)881 void grabsharedmemory(size_t size)
882 {
883 
884   int			key = ('d'<<24) | ('o'<<16) | ('o'<<8) | 'm';
885   struct shmid_ds	shminfo;
886   int			minsize = screenwidth * screenheight; /* 320*200; */
887   int			id;
888   int			rc;
889   /* UNUSED int done=0; */
890   int			pollution=5;
891 
892   /* try to use what was here before */
893   do
894     {
895       id = shmget((key_t) key, minsize, 0777); /* just get the id */
896       if (id != -1)
897 	{
898 	  rc=shmctl(id, IPC_STAT, &shminfo);   /* get stats on it */
899 	  if (!rc)
900 	    {
901 	      if (shminfo.shm_nattch)
902 		{
903 		  fprintf(stderr, "User %d appears to be running "
904 			  "Heretic.  Is that wise?\n", shminfo.shm_cpid);
905 		  key++;
906 		}
907 	      else
908 		{
909 		  if (getuid() == shminfo.shm_perm.cuid)
910 		    {
911 		      rc = shmctl(id, IPC_RMID, 0);
912 		      if (!rc)
913 			fprintf(stderr,
914 				"Was able to kill my old shared memory\n");
915 		      else
916 			I_Error("Was NOT able to kill my old shared memory");
917 
918 		      id = shmget((key_t)key, size, IPC_CREAT|0777);
919 		      if (id==-1)
920 			I_Error("Could not get shared memory");
921 
922 		      rc=shmctl(id, IPC_STAT, &shminfo);
923 
924 		      break;
925 
926 		    }
927 		  if (size >= shminfo.shm_segsz)
928 		    {
929 		      fprintf(stderr,
930 			      "will use %d's stale shared memory\n",
931 			      shminfo.shm_cpid);
932 		      break;
933 		    }
934 		  else
935 		    {
936 		      fprintf(stderr,
937 			      "warning: can't use stale "
938 			      "shared memory belonging to id %d, "
939 			      "key=0x%x\n",
940 			      shminfo.shm_cpid, key);
941 		      key++;
942 		    }
943 		}
944 	    }
945 	  else
946 	    {
947 	      I_Error("could not get stats on key=%d", key);
948 	    }
949 	}
950       else
951 	{
952 	  id = shmget((key_t)key, size, IPC_CREAT|0777);
953 	  if (id==-1)
954 	    {
955 	      /* extern int errno; */
956 	      fprintf(stderr, "errno=%d\n", errno);
957 	      I_Error("Could not get any shared memory");
958 	    }
959 	  break;
960 	}
961     } while (--pollution);
962 
963   if (!pollution)
964     {
965       I_Error("Sorry, system too polluted with stale "
966 	      "shared memory segments.\n");
967     }
968 
969   X_shminfo.shmid = id;
970 
971   /* attach to the shared memory segment */
972   image->data = X_shminfo.shmaddr = shmat(id, 0, 0);
973 
974   fprintf(stderr, "shared memory id=%d, addr=0x%lx\n", id,
975 	  (unsigned long) (image->data));
976 }
977 
InitGraphLib(void)978 void InitGraphLib(void)
979 {
980   /* not needed, dummy for X11 */
981 }
982 
I_InitGraphics(void)983 void I_InitGraphics(void)
984 {
985   char*		displayname;
986   char*		d;
987   int		n;
988   int		pnum;
989   int		x=0;
990   int		y=0;
991   char          *dummy_data;
992 
993 
994   /* warning: char format, different type arg */
995   /*
996    * char		        xsign=' ';
997    * char		        ysign=' ';
998    */
999   int			oktodraw;
1000   unsigned long	        attribmask;
1001   XSetWindowAttributes  attribs;
1002   XGCValues		xgcvalues;
1003   XSizeHints            hints = {flags : 0};
1004   int			valuemask;
1005   static int		firsttime=1;
1006 
1007     if (!firsttime)
1008       return;
1009     firsttime = 0;
1010 
1011     signal(SIGINT, (void (*)(int)) I_Quit);
1012 
1013     if (M_CheckParm("-2"))
1014       multiply = 2;
1015 
1016     if (M_CheckParm("-3"))
1017       multiply = 3;
1018 
1019     if (M_CheckParm("-4"))
1020       multiply = 4;
1021 
1022     if (M_CheckParm("-mode") && multiply != 1) {
1023       multiply=1;  /* multiply only works in 320x200 mode yet */
1024       fprintf(stderr,"Screen stretching disabled due to -mode switch\n");
1025     }
1026 
1027     X_width = screenwidth * multiply;
1028     X_height = screenheight * multiply;
1029 
1030     /* check for command-line display name */
1031     if ((pnum = M_CheckParm("-display")))
1032 	displayname = myargv[pnum+1];
1033     else
1034 	displayname = 0;
1035 
1036     /* check if the user wants to grab the mouse (quite unnice) */
1037     if (!do_grabMouse && M_CheckParm("-grabmouse"))
1038        do_grabMouse = 1;
1039 
1040     /* open the display */
1041     X_display = XOpenDisplay(displayname);
1042     if (!X_display)
1043       {
1044 	  if (displayname)
1045 	      I_Error("Could not open display [%s]", displayname);
1046 	  else
1047 	      I_Error("Could not open display (DISPLAY=[%s])", getenv("DISPLAY"));
1048       }
1049 
1050     /* use the default visual */
1051     screen_intern = DefaultScreenOfDisplay(X_display);
1052     X_screen = DefaultScreen(X_display);
1053     if (!XMatchVisualInfo(X_display,X_screen,8,PseudoColor,&X_visualinfo)) {
1054       true_color=TRUE;  /* OK, be slower, but try to work.... */
1055       if (XMatchVisualInfo(X_display,X_screen,8,TrueColor,&X_visualinfo)) {
1056 	fprintf(stderr,"I_InitGraphics: using 8bit truecolor visual\n");
1057       }
1058       else if (XMatchVisualInfo(X_display,X_screen,16,TrueColor,&X_visualinfo)) {
1059 	fprintf(stderr,"I_InitGraphics: using 16bit truecolor visual\n");
1060       }
1061       else if (XMatchVisualInfo(X_display,X_screen,15,TrueColor,&X_visualinfo)) {
1062 	fprintf(stderr,"I_InitGraphics: using 15bit truecolor visual\n");
1063       }
1064       else if (XMatchVisualInfo(X_display,X_screen,24,TrueColor,&X_visualinfo)) {
1065 	fprintf(stderr,"I_InitGraphics: using 24bit truecolor visual\n");
1066       }
1067       else if (XMatchVisualInfo(X_display,X_screen,32,TrueColor,&X_visualinfo)) {
1068 	fprintf(stderr,"I_InitGraphics: using 32bit truecolor visual\n");
1069       }
1070       else {
1071 	I_Error("unsupported display type (not 8, 16, 24 or 32bit colors)");
1072       }
1073     }
1074     else {
1075       fprintf(stderr,"I_InitGraphics: using 8bit pseudocolor visual, good!\n");
1076     }
1077     X_visual = X_visualinfo.visual;
1078     X_visual->red_mask=0;
1079     X_visual->blue_mask=0;
1080     X_visual->green_mask=0;
1081 
1082     if (!true_color) {
1083       up_palette=UploadNewPalette;  /* set update-palette function */
1084     }
1085     else {
1086       up_palette=UploadNewTruePal;
1087       oldgamma=usegamma;
1088       if (!init_truec_pals()) {
1089 	I_Error("Truecolor mode: cannot allocate memory for palette cache");
1090       }
1091     }
1092 
1093     /* check for the MITSHM extension */
1094     if (!M_CheckParm("-noshm"))
1095       doShm = XShmQueryExtension(X_display);
1096     else {
1097       doShm =FALSE;
1098       fprintf(stderr,"I_InitGraphics: SHM disabled via user request!\n");
1099     }
1100 
1101     /* even if it's available, make sure it's a local connection */
1102     if (doShm)
1103       {
1104 	if (!displayname) displayname = (char *) getenv("DISPLAY");
1105 	if (displayname)
1106 	  {
1107 	    d = displayname;
1108 	    while (*d && (*d != ':')) d++;
1109 	    if (*d) *d = 0;
1110 	    if (!(!strcasecmp(displayname, "unix") || !*displayname)) doShm = false;
1111 	  }
1112       }
1113 
1114     if (doShm)
1115       fprintf(stderr, "Using MITSHM extension\n");
1116     else
1117       fprintf(stderr, "MITSHM extension not available, disabled or remote display\n");
1118 
1119     /* create the colormap */
1120     if (!true_color)
1121       X_cmap = XCreateColormap(X_display,RootWindow(X_display,X_screen),
1122 			       X_visual,AllocAll);
1123     else
1124       X_cmap = DefaultColormapOfScreen(screen_intern);
1125 
1126     /* setup attributes for main window */
1127     attribmask = CWEventMask | CWColormap | CWBorderPixel;
1128     attribs.event_mask = KeyPressMask
1129       | KeyReleaseMask
1130       /* | PointerMotionMask | ButtonPressMask | ButtonReleaseMask */
1131       | ExposureMask;
1132 
1133     attribs.colormap = X_cmap;
1134     attribs.border_pixel = 0;
1135 
1136     /* set up position and size hints */
1137     hints.width = X_width;
1138     hints.height = X_height;
1139     hints.min_width = X_width;
1140     hints.max_width = X_width;
1141     hints.min_height = X_height;
1142     hints.max_height = X_height;
1143     hints.flags |= USSize | PMinSize | PMaxSize;
1144 
1145     /* check for command-line geometry */
1146     if ((pnum = M_CheckParm("-geometry")))
1147 	{
1148 	    /* not used, really */
1149 	    unsigned int w, h;
1150 	    n = XParseGeometry(myargv[pnum + 1], &x, &y, &w, &h);
1151 
1152 	    if (!(n & AllValues))
1153 		I_Error("bad -geometry parameter");
1154 
1155 	    if (n & XValue || n & YValue);
1156 	    hints.flags |= USPosition;
1157 
1158 	    if (n & WidthValue || n & HeightValue)
1159 		fprintf(stderr, "Specified width and height ignored.\n");
1160 
1161 	    hints.flags |= PWinGravity;
1162 	    switch ( n& (XNegative | YNegative))
1163 		{
1164 		case 0:
1165 		    hints.win_gravity = NorthWestGravity;
1166 		    break;
1167 		case XNegative:
1168 		    hints.win_gravity = NorthEastGravity;
1169 		    break;
1170 		case YNegative:
1171 		    hints.win_gravity = SouthWestGravity;
1172 		    break;
1173 		default:
1174 		    hints.win_gravity = SouthEastGravity;
1175 		    break;
1176 		}
1177 
1178 	    if ((n & XValue) && (n & XNegative))
1179 		x += DisplayWidth(X_display, X_screen) - X_width;
1180 	    if ((n & YValue) && (n & YNegative))
1181 		y += DisplayHeight(X_display, X_screen) - X_height;
1182 	}
1183 
1184     hints.x = x;
1185     hints.y = y;
1186 
1187     /* create the main window */
1188     X_mainWindow = XCreateWindow(X_display,
1189                                  RootWindow(X_display, X_screen),
1190                                  x, y,
1191                                  X_width, X_height,
1192                                  0, /* borderwidth */
1193                                  X_visualinfo.depth,
1194                                  InputOutput,
1195                                  X_visual,
1196                                  attribmask,
1197                                  &attribs);
1198 
1199     /* Set the Name of the main XWindow */
1200     XStoreName(X_display, X_mainWindow, "XHeretic ported by A. Werthmann");
1201 
1202     /* Set the Name of the Icon */
1203     XSetIconName(X_display, X_mainWindow, "XHeretic");
1204 
1205     /* Set window manager hints */
1206     XSetWMNormalHints(X_display, X_mainWindow, &hints);
1207 
1208 
1209     XDefineCursor(X_display, X_mainWindow,
1210 		  createnullcursor( X_display, X_mainWindow ) );
1211 
1212     /* create the GC */
1213     valuemask = GCGraphicsExposures;
1214     xgcvalues.graphics_exposures = False;
1215     X_gc = XCreateGC(X_display,X_mainWindow,valuemask,&xgcvalues);
1216 
1217     /* map the window */
1218     XMapWindow(X_display, X_mainWindow);
1219 
1220     /* wait until it is OK to draw */
1221     oktodraw = 0;
1222     while (!oktodraw)
1223       {
1224 	XNextEvent(X_display, &X_event);
1225 	if (X_event.type == Expose
1226 	    && !X_event.xexpose.count)
1227 	  {
1228 	    oktodraw = 1;
1229 	  }
1230       }
1231 
1232     /* grabs the pointer so it is restricted to this window */
1233     if (do_grabMouse)
1234       XGrabPointer(X_display, X_mainWindow, True,
1235 		   ButtonPressMask|ButtonReleaseMask|PointerMotionMask,
1236 		   GrabModeAsync, GrabModeAsync,
1237 		   X_mainWindow, None, CurrentTime);
1238 
1239     if (doShm)
1240       {
1241 
1242 	X_shmeventtype = XShmGetEventBase(X_display) + ShmCompletion;
1243 
1244 	/* create the image */
1245 	image = XShmCreateImage(X_display,
1246                                 X_visual,
1247                                 X_visualinfo.depth,
1248                                 ZPixmap,
1249                                 0,
1250                                 &X_shminfo,
1251                                 X_width,
1252                                 X_height);
1253 
1254 	grabsharedmemory(image->bytes_per_line * image->height);
1255 
1256 
1257 	/*
1258 	 * UNUSED
1259 	 * create the shared memory segment
1260 	 * X_shminfo.shmid = shmget (IPC_PRIVATE,
1261 	 * image->bytes_per_line * image->height, IPC_CREAT | 0777);
1262 	 * if (X_shminfo.shmid < 0)
1263 	 * {
1264 	 * perror("");
1265 	 * I_Error("shmget() failed in InitGraphics()");
1266 	 * }
1267 	 * fprintf(stderr, "shared memory id=%d\n", X_shminfo.shmid);
1268 	 * attach to the shared memory segment
1269 	 * image->data = X_shminfo.shmaddr = shmat(X_shminfo.shmid, 0, 0);
1270 	 */
1271 
1272 	if (!image->data)
1273 	{
1274 	    perror("");
1275 	    I_Error("shmat() failed in InitGraphics()");
1276 	}
1277 
1278 	/* get the X server to attach to it */
1279 	if (!XShmAttach(X_display, &X_shminfo))
1280 	  I_Error("XShmAttach() failed in InitGraphics()");
1281         XShm_is_attached=TRUE;
1282       }
1283     else
1284       {
1285 	  dummy_data = (char*) malloc(X_width * X_height * 4);
1286 	  assert(dummy_data);
1287 
1288 	  image = XCreateImage(X_display,
1289 			       X_visual,
1290 			       X_visualinfo.depth,
1291 			       ZPixmap,
1292 			       0,
1293 			       dummy_data,
1294 			       X_width, X_height,
1295 			       (X_visualinfo.depth == 8) ? 8 : 32,
1296 			       0 /*X_width * (X_visualinfo.depth >> 3)*/);
1297 
1298       }
1299 
1300     if (multiply == 1 && !true_color)
1301 	screen = (unsigned char *) (image->data);
1302     else
1303 	{
1304 	    screen = (unsigned char *) malloc (screenwidth * screenheight);
1305 	    assert(screen);
1306 	}
1307 }
1308 
1309 
1310 unsigned int exptable[256];
1311 
InitExpand(void)1312 void InitExpand (void)
1313 {
1314   int i;
1315 
1316   for (i=0 ; i<256 ; i++)
1317     exptable[i] = i | (i<<8) | (i<<16) | (i<<24);
1318 }
1319 
1320 double exptable2[256*256];
1321 
InitExpand2(void)1322 void InitExpand2 (void)
1323 {
1324   int     i;
1325   int     j;
1326   double* exp;
1327   union
1328   {
1329     double 		d;
1330     unsigned int    u[2];
1331   } pixel;
1332 
1333   printf ("building exptable2...\n");
1334   exp = exptable2;
1335   for (i=0 ; i<256 ; i++)
1336     {
1337       pixel.u[0] = i | (i<<8) | (i<<16) | (i<<24);
1338       for (j=0 ; j<256 ; j++)
1339 	{
1340 	  pixel.u[1] = j | (j<<8) | (j<<16) | (j<<24);
1341 	  *exp++ = pixel.d;
1342 	}
1343     }
1344   printf ("done.\n");
1345 }
1346 
1347 int	inited;
1348 
1349 void
Expand4(unsigned * lineptr,double * xline)1350 Expand4
1351 ( unsigned*	lineptr,
1352   double*	xline )
1353 {
1354   double	dpixel;
1355   unsigned	x;
1356   unsigned 	y;
1357   unsigned	fourpixels;
1358   unsigned	step;
1359   double*	exp;
1360 
1361   exp = exptable2;
1362   if (!inited)
1363     {
1364       inited = 1;
1365       InitExpand2 ();
1366     }
1367 
1368 
1369   step = 3*screenwidth/2;
1370 
1371   y = screenheight-1;
1372   do
1373     {
1374       x = screenwidth;
1375 
1376       do
1377 	{
1378 	  fourpixels = lineptr[0];
1379 
1380 	  dpixel = *(double *)( (long)exp + ( (fourpixels&0xffff0000)>>13) );
1381 	  xline[0] = dpixel;
1382 	  xline[160] = dpixel;
1383 	  xline[320] = dpixel;
1384 	  xline[480] = dpixel;
1385 
1386 	  dpixel = *(double *)( (long)exp + ( (fourpixels&0xffff)<<3 ) );
1387 	  xline[1] = dpixel;
1388 	  xline[161] = dpixel;
1389 	  xline[321] = dpixel;
1390 	  xline[481] = dpixel;
1391 
1392 	  fourpixels = lineptr[1];
1393 
1394 	  dpixel = *(double *)( (long)exp + ( (fourpixels&0xffff0000)>>13) );
1395 	  xline[2] = dpixel;
1396 	  xline[162] = dpixel;
1397 	  xline[322] = dpixel;
1398 	  xline[482] = dpixel;
1399 
1400 	  dpixel = *(double *)( (long)exp + ( (fourpixels&0xffff)<<3 ) );
1401 	  xline[3] = dpixel;
1402 	  xline[163] = dpixel;
1403 	  xline[323] = dpixel;
1404 	  xline[483] = dpixel;
1405 
1406 	  fourpixels = lineptr[2];
1407 
1408 	  dpixel = *(double *)( (long)exp + ( (fourpixels&0xffff0000)>>13) );
1409 	  xline[4] = dpixel;
1410 	  xline[164] = dpixel;
1411 	  xline[324] = dpixel;
1412 	  xline[484] = dpixel;
1413 
1414 	  dpixel = *(double *)( (long)exp + ( (fourpixels&0xffff)<<3 ) );
1415 	  xline[5] = dpixel;
1416 	  xline[165] = dpixel;
1417 	  xline[325] = dpixel;
1418 	  xline[485] = dpixel;
1419 
1420 	  fourpixels = lineptr[3];
1421 
1422 	  dpixel = *(double *)( (long)exp + ( (fourpixels&0xffff0000)>>13) );
1423 	  xline[6] = dpixel;
1424 	  xline[166] = dpixel;
1425 	  xline[326] = dpixel;
1426 	  xline[486] = dpixel;
1427 
1428 	  dpixel = *(double *)( (long)exp + ( (fourpixels&0xffff)<<3 ) );
1429 	  xline[7] = dpixel;
1430 	  xline[167] = dpixel;
1431 	  xline[327] = dpixel;
1432 	  xline[487] = dpixel;
1433 
1434 	  lineptr+=4;
1435 	  xline+=8;
1436 	} while (x-=16);
1437       xline += step;
1438     } while (y--);
1439 }
1440 
I_CheckRes()1441 void I_CheckRes()
1442 {
1443   /* nothing to do... */
1444 }
1445 
1446 
1447