// Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // // $Id:$ // // Copyright (C) 1993-1996 by id Software, Inc. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // $Log:$ // // DESCRIPTION: // DOOM graphics stuff for X11, UNIX. // //----------------------------------------------------------------------------- static const char rcsid[] = "$Id: i_x.c,v 1.6 1997/02/03 22:45:10 b1 Exp $"; #include #include #include #include /* #include #include #include #include // Had to dig up XShm.c for this one. // It is in the libXext, but not in the XFree86 headers. #ifdef LINUX int XShmGetEventBase( Display* dpy ); // problems with g++? #endif */ #include #include #include #include #include // Vladimir //#include #include #include #include "doomstat.h" #include "i_system.h" #include "v_video.h" #include "m_argv.h" #include "d_main.h" #include "doomdef.h" #include "include/jni_doom.h" #define POINTER_WARP_COUNTDOWN 1 /** * Android key codes */ /* #define XK_Left 21 #define XK_Right 22 #define XK_Down 20 #define XK_Up 19 #define XK_Escape 4 #define XK_Return 66 #define XK_DPAD 23 #define XK_Tab 61 #define XK_space 0x3E #define XK_Delete 67 #define XK_equal 70 #define XK_minus 69 #define XK_Control_R (0x80+0x1d) */ /* Display* X_display=0; Window X_mainWindow; Colormap X_cmap; Visual* X_visual; GC X_gc; XEvent X_event; int X_screen; XVisualInfo X_visualinfo; */ /** * Class XImage */ typedef struct Image XImage; struct Image { int width; int height; byte * data; }; /** * Class Color */ typedef struct Color XColor; struct Color { int red; int green; int blue; int pixel; }; // The Image XImage * image; // Color pallete static XColor colors[256]; /** * XImage Constructor */ XImage * XCreateImage(int width, int height) { XImage * this = (XImage*) malloc(sizeof(XImage)); // set width, height this->width = width; this->height = height; // allocate image buffer this->data = (byte *)malloc (width * height); return this; } int X_width; int X_height; // MIT SHared Memory extension. //boolean doShm; /* XShmSegmentInfo X_shminfo; int X_shmeventtype; */ // Fake mouse handling. // This cannot work properly w/o DGA. // Needs an invisible mouse cursor at least. boolean grabMouse; int doPointerWarp = POINTER_WARP_COUNTDOWN; // Blocky mode, // replace each 320x200 pixel with multiply*multiply pixels. // According to Dave Taylor, it still is a bonehead thing // to use .... static int multiply=1; // // Translates the key currently in X_event // /* //int xlatekey(void) int xlatekey(int rc) { //int rc; switch(rc) // = XKeycodeToKeysym(X_display, X_event.xkey.keycode, 0)) { case XK_Left: rc = KEY_LEFTARROW; break; case XK_Right: rc = KEY_RIGHTARROW; break; case XK_Down: rc = KEY_DOWNARROW; break; case XK_Up: rc = KEY_UPARROW; break; case XK_Escape: rc = KEY_ESCAPE; break; case XK_DPAD: case XK_Return: rc = KEY_ENTER; break; case XK_Tab: rc = KEY_TAB; break; // case XK_F1: rc = KEY_F1; break; // case XK_F2: rc = KEY_F2; break; // case XK_F3: rc = KEY_F3; break; // case XK_F4: rc = KEY_F4; break; // case XK_F5: rc = KEY_F5; break; // case XK_F6: rc = KEY_F6; break; // case XK_F7: rc = KEY_F7; break; // case XK_F8: rc = KEY_F8; break; // case XK_F9: rc = KEY_F9; break; // case XK_F10: rc = KEY_F10; break; // case XK_F11: rc = KEY_F11; break; // case XK_F12: rc = KEY_F12; break; // case XK_BackSpace: case XK_Delete: rc = KEY_BACKSPACE; break; // case XK_Pause: rc = KEY_PAUSE; break; // case XK_KP_Equal: case XK_equal: rc = KEY_EQUALS; break; // case XK_KP_Subtract: case XK_minus: rc = KEY_MINUS; break; // case XK_Shift_L: // case XK_Shift_R: // rc = KEY_RSHIFT; // break; // // case XK_Control_L: case XK_Control_R: rc = KEY_RCTRL; break; // // case XK_Alt_L: // case XK_Meta_L: // case XK_Alt_R: // case XK_Meta_R: // rc = KEY_RALT; // break; default: // if (rc >= XK_space && rc <= XK_asciitilde) // rc = rc - XK_space + ' '; // if (rc >= 'A' && rc <= 'Z') // rc = rc - 'A' + 'a'; // a..z if (rc >= 29 && rc <= 54) { rc += 68; } // 0..9 else if (rc >= 7 && rc <= 16) { rc += 41; } else { // Fire rc = KEY_RCTRL; } break; } return rc; } */ void I_ShutdownGraphics(void) { printf("I_video::I_ShutdownGraphics called.\n"); /* // Detach from X server if (!XShmDetach(X_display, &X_shminfo)) I_Error("XShmDetach() failed in I_ShutdownGraphics()"); // Release shared memory. shmdt(X_shminfo.shmaddr); shmctl(X_shminfo.shmid, IPC_RMID, 0); // Paranoia. image->data = NULL; */ } // // I_StartFrame // void I_StartFrame (void) { // er? } //static int lastmousex = 0; //static int lastmousey = 0; //boolean mousemoved = false; //boolean shmFinished; /* void I_GetEvent(void) { printf("I_video::I_GetEvent called.\n"); event_t event; // put event-grabbing stuff in here XNextEvent(X_display, &X_event); switch (X_event.type) { case KeyPress: event.type = ev_keydown; event.data1 = xlatekey(); D_PostEvent(&event); // fprintf(stderr, "k"); break; case KeyRelease: event.type = ev_keyup; event.data1 = xlatekey(); D_PostEvent(&event); // fprintf(stderr, "ku"); break; case ButtonPress: event.type = ev_mouse; event.data1 = (X_event.xbutton.state & Button1Mask) | (X_event.xbutton.state & Button2Mask ? 2 : 0) | (X_event.xbutton.state & Button3Mask ? 4 : 0) | (X_event.xbutton.button == Button1) | (X_event.xbutton.button == Button2 ? 2 : 0) | (X_event.xbutton.button == Button3 ? 4 : 0); event.data2 = event.data3 = 0; D_PostEvent(&event); // fprintf(stderr, "b"); break; case ButtonRelease: event.type = ev_mouse; event.data1 = (X_event.xbutton.state & Button1Mask) | (X_event.xbutton.state & Button2Mask ? 2 : 0) | (X_event.xbutton.state & Button3Mask ? 4 : 0); // suggest parentheses around arithmetic in operand of | event.data1 = event.data1 ^ (X_event.xbutton.button == Button1 ? 1 : 0) ^ (X_event.xbutton.button == Button2 ? 2 : 0) ^ (X_event.xbutton.button == Button3 ? 4 : 0); event.data2 = event.data3 = 0; D_PostEvent(&event); // fprintf(stderr, "bu"); break; case MotionNotify: event.type = ev_mouse; event.data1 = (X_event.xmotion.state & Button1Mask) | (X_event.xmotion.state & Button2Mask ? 2 : 0) | (X_event.xmotion.state & Button3Mask ? 4 : 0); event.data2 = (X_event.xmotion.x - lastmousex) << 2; event.data3 = (lastmousey - X_event.xmotion.y) << 2; if (event.data2 || event.data3) { lastmousex = X_event.xmotion.x; lastmousey = X_event.xmotion.y; if (X_event.xmotion.x != X_width/2 && X_event.xmotion.y != X_height/2) { D_PostEvent(&event); // fprintf(stderr, "m"); mousemoved = false; } else { mousemoved = true; } } break; case Expose: case ConfigureNotify: break; default: if (doShm && X_event.type == X_shmeventtype) shmFinished = true; break; } } */ /* Cursor createnullcursor ( Display* display, Window root ) { Pixmap cursormask; XGCValues xgc; GC gc; XColor dummycolour; Cursor cursor; cursormask = XCreatePixmap(display, root, 1, 1, 1 //depth); xgc.function = GXclear; gc = XCreateGC(display, cursormask, GCFunction, &xgc); XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); dummycolour.pixel = 0; dummycolour.red = 0; dummycolour.flags = 04; cursor = XCreatePixmapCursor(display, cursormask, cursormask, &dummycolour,&dummycolour, 0,0); XFreePixmap(display,cursormask); XFreeGC(display,gc); return cursor; } */ // // I_StartTic // //boolean eventReceived = false; //extern void I_WaitVBL(int count); void I_StartTic (void) { printf("I_video::I_StartTic called.\n"); // printf("I_video::I_StartTic waiting for an event\n"); // while ( ! eventReceived) { // printf("I_video::I_StartTic waiting for an event\n"); // I_WaitVBL(100); // } /* if (!X_display) return; while (XPending(X_display)) I_GetEvent(); // Warp the pointer back to the middle of the window // or it will wander off - that is, the game will // loose input focus within X11. if (grabMouse) { if (!--doPointerWarp) { XWarpPointer( X_display, None, X_mainWindow, 0, 0, 0, 0, X_width/2, X_height/2); doPointerWarp = POINTER_WARP_COUNTDOWN; } } mousemoved = false; */ } // // I_UpdateNoBlit // void I_UpdateNoBlit (void) { // what is this? } // // I_FinishUpdate // void I_FinishUpdate (int eye) { // Get pixels int i; int size = X_width * X_height; // ARGB pixels int pixels[size]; //printf("I_FinishUpdate\n"); // get ARGS pixels for ( i = 0 ; i < size ; i ++) { byte b = image->data[i]; XColor color = colors[b]; pixels[i] = (0xFF << 24) | (color.red << 16) | (color.green << 8) | color.blue; } // Rendering is done in screens[0] which points to // imag->data thus send image->data (char *) to Java jni_send_pixels(pixels, eye); /* static int lasttic; int tics; int i; // UNUSED static unsigned char *bigscreen=0; //printf("I_video::I_FinishUpdate called last tic:%d.\n", lasttic); // draws little dots on the bottom of the screen if (devparm) { i = I_GetTime(); tics = i - lasttic; lasttic = i; if (tics > 20) tics = 20; for (i=0 ; idata[i*X_width]; y = SCREENHEIGHT; while (y--) { x = SCREENWIDTH; do { fouripixels = *ilineptr++; twoopixels = (fouripixels & 0xff000000) | ((fouripixels>>8) & 0xffff00) | ((fouripixels>>16) & 0xff); twomoreopixels = ((fouripixels<<16) & 0xff000000) | ((fouripixels<<8) & 0xffff00) | (fouripixels & 0xff); #ifdef __BIG_ENDIAN__ *olineptrs[0]++ = twoopixels; *olineptrs[1]++ = twoopixels; *olineptrs[0]++ = twomoreopixels; *olineptrs[1]++ = twomoreopixels; #else *olineptrs[0]++ = twomoreopixels; *olineptrs[1]++ = twomoreopixels; *olineptrs[0]++ = twoopixels; *olineptrs[1]++ = twoopixels; #endif } while (x-=4); olineptrs[0] += X_width/4; olineptrs[1] += X_width/4; } } else if (multiply == 3) { unsigned int *olineptrs[3]; unsigned int *ilineptr; int x, y, i; unsigned int fouropixels[3]; unsigned int fouripixels; ilineptr = (unsigned int *) (screens[0]); for (i=0 ; i<3 ; i++) olineptrs[i] = (unsigned int *) &image->data[i*X_width]; y = SCREENHEIGHT; while (y--) { x = SCREENWIDTH; do { fouripixels = *ilineptr++; fouropixels[0] = (fouripixels & 0xff000000) | ((fouripixels>>8) & 0xff0000) | ((fouripixels>>16) & 0xffff); fouropixels[1] = ((fouripixels<<8) & 0xff000000) | (fouripixels & 0xffff00) | ((fouripixels>>8) & 0xff); fouropixels[2] = ((fouripixels<<16) & 0xffff0000) | ((fouripixels<<8) & 0xff00) | (fouripixels & 0xff); #ifdef __BIG_ENDIAN__ *olineptrs[0]++ = fouropixels[0]; *olineptrs[1]++ = fouropixels[0]; *olineptrs[2]++ = fouropixels[0]; *olineptrs[0]++ = fouropixels[1]; *olineptrs[1]++ = fouropixels[1]; *olineptrs[2]++ = fouropixels[1]; *olineptrs[0]++ = fouropixels[2]; *olineptrs[1]++ = fouropixels[2]; *olineptrs[2]++ = fouropixels[2]; #else *olineptrs[0]++ = fouropixels[2]; *olineptrs[1]++ = fouropixels[2]; *olineptrs[2]++ = fouropixels[2]; *olineptrs[0]++ = fouropixels[1]; *olineptrs[1]++ = fouropixels[1]; *olineptrs[2]++ = fouropixels[1]; *olineptrs[0]++ = fouropixels[0]; *olineptrs[1]++ = fouropixels[0]; *olineptrs[2]++ = fouropixels[0]; #endif } while (x-=4); olineptrs[0] += 2*X_width/4; olineptrs[1] += 2*X_width/4; olineptrs[2] += 2*X_width/4; } } else if (multiply == 4) { // Broken. Gotta fix this some day. //void Expand4(unsigned *, double *); //Expand4 ((unsigned *)(screens[0]), (double *) (image->data)); } if (doShm) { if (!XShmPutImage( X_display, X_mainWindow, X_gc, image, 0, 0, 0, 0, X_width, X_height, True )) I_Error("XShmPutImage() failed\n"); // wait for it to finish and processes all input events shmFinished = false; do { I_GetEvent(); } while (!shmFinished); } else { // draw the image XPutImage( X_display, X_mainWindow, X_gc, image, 0, 0, 0, 0, X_width, X_height ); // sync up with server XSync(X_display, False); } */ } // // I_ReadScreen // void I_ReadScreen (byte* scr) { memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT); } // // Palette stuff. // //static XColor colors[256]; //void UploadNewPalette(Colormap cmap, byte *palette) void UploadNewPalette (byte *palette) { register int i; register int c; static boolean firstcall = true; //#ifdef __cplusplus // if (X_visualinfo.c_class == PseudoColor && X_visualinfo.depth == 8) //#else // if (X_visualinfo.class == PseudoColor && X_visualinfo.depth == 8) //#endif // { // initialize the colormap if (firstcall) { firstcall = false; for (i=0 ; i<256 ; i++) { colors[i].pixel = i; // colors[i].flags = DoRed|DoGreen|DoBlue; } } jni_printf("Updating colors for new pallete."); // set the X colormap entries for (i=0 ; i<256 ; i++) { c = gammatable[usegamma][*palette++]; colors[i].red = (c<<8) + c; c = gammatable[usegamma][*palette++]; colors[i].green = (c<<8) + c; c = gammatable[usegamma][*palette++]; colors[i].blue = (c<<8) + c; } // store the colors to the current colormap //XStoreColors(X_display, cmap, colors, 256); // } } // // I_SetPalette // void I_SetPalette (byte* palette) { printf("I_video::I_SetPalette called.\n"); jni_printf("I_video::I_SetPalette called."); //UploadNewPalette(X_cmap, palette); UploadNewPalette(palette); } // // This function is probably redundant, // if XShmDetach works properly. // ddt never detached the XShm memory, // thus there might have been stale // handles accumulating. // /* void grabsharedmemory(int size) { int key = ('d'<<24) | ('o'<<16) | ('o'<<8) | 'm'; struct shmid_ds shminfo; int minsize = 320*200; int id; int rc; // UNUSED int done=0; int pollution=5; // try to use what was here before do { id = shmget((key_t) key, minsize, 0777); // just get the id if (id != -1) { rc=shmctl(id, IPC_STAT, &shminfo); // get stats on it if (!rc) { if (shminfo.shm_nattch) { fprintf(stderr, "User %d appears to be running " "DOOM. Is that wise?\n", shminfo.shm_cpid); key++; } else { if (getuid() == shminfo.shm_perm.cuid) { rc = shmctl(id, IPC_RMID, 0); if (!rc) fprintf(stderr, "Was able to kill my old shared memory\n"); else I_Error("Was NOT able to kill my old shared memory"); id = shmget((key_t)key, size, IPC_CREAT|0777); if (id==-1) I_Error("Could not get shared memory"); rc=shmctl(id, IPC_STAT, &shminfo); break; } if (size >= shminfo.shm_segsz) { fprintf(stderr, "will use %d's stale shared memory\n", shminfo.shm_cpid); break; } else { fprintf(stderr, "warning: can't use stale " "shared memory belonging to id %d, " "key=0x%x\n", shminfo.shm_cpid, key); key++; } } } else { I_Error("could not get stats on key=%d", key); } } else { id = shmget((key_t)key, size, IPC_CREAT|0777); if (id==-1) { extern int errno; fprintf(stderr, "errno=%d\n", errno); I_Error("Could not get any shared memory"); } break; } } while (--pollution); if (!pollution) { I_Error("Sorry, system too polluted with stale " "shared memory segments.\n"); } X_shminfo.shmid = id; // attach to the shared memory segment image->data = X_shminfo.shmaddr = shmat(id, 0, 0); fprintf(stderr, "shared memory id=%d, addr=0x%x\n", id, (int) (image->data)); } */ void I_InitGraphics(void) { /* char* displayname; char* d; int n; int pnum; int x=0; int y=0; // warning: char format, different type arg char xsign=' '; char ysign=' '; int oktodraw; unsigned long attribmask; */ printf("I_video::I_InitGraphics called.\n"); jni_printf("I_video::I_InitGraphics called."); /* XSetWindowAttributes attribs; XGCValues xgcvalues; int valuemask; static int firsttime=1; if (!firsttime) return; firsttime = 0; signal(SIGINT, (void (*)(int)) I_Quit); if (M_CheckParm("-2")) multiply = 2; if (M_CheckParm("-3")) multiply = 3; if (M_CheckParm("-4")) multiply = 4; */ X_width = SCREENWIDTH * multiply; X_height = SCREENHEIGHT * multiply; /* // check for command-line display name if ( (pnum=M_CheckParm("-disp")) ) // suggest parentheses around assignment displayname = myargv[pnum+1]; else displayname = 0; // check if the user wants to grab the mouse (quite unnice) grabMouse = !!M_CheckParm("-grabmouse"); // check for command-line geometry if ( (pnum=M_CheckParm("-geom")) ) // suggest parentheses around assignment { // warning: char format, different type arg 3,5 n = sscanf(myargv[pnum+1], "%c%d%c%d", &xsign, &x, &ysign, &y); if (n==2) x = y = 0; else if (n==6) { if (xsign == '-') x = -x; if (ysign == '-') y = -y; } else I_Error("bad -geom parameter"); } // open the display X_display = XOpenDisplay(displayname); if (!X_display) { if (displayname) I_Error("Could not open display [%s]", displayname); else I_Error("Could not open display (DISPLAY=[%s])", getenv("DISPLAY")); } // use the default visual X_screen = DefaultScreen(X_display); if (!XMatchVisualInfo(X_display, X_screen, 8, PseudoColor, &X_visualinfo)) I_Error("xdoom currently only supports 256-color PseudoColor screens"); X_visual = X_visualinfo.visual; // check for the MITSHM extension doShm = XShmQueryExtension(X_display); // even if it's available, make sure it's a local connection if (doShm) { if (!displayname) displayname = (char *) getenv("DISPLAY"); if (displayname) { d = displayname; while (*d && (*d != ':')) d++; if (*d) *d = 0; if (!(!strcasecmp(displayname, "unix") || !*displayname)) doShm = false; } } fprintf(stderr, "Using MITSHM extension\n"); // create the colormap X_cmap = XCreateColormap(X_display, RootWindow(X_display, X_screen), X_visual, AllocAll); // setup attributes for main window attribmask = CWEventMask | CWColormap | CWBorderPixel; attribs.event_mask = KeyPressMask | KeyReleaseMask // | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ExposureMask; attribs.colormap = X_cmap; attribs.border_pixel = 0; // create the main window X_mainWindow = XCreateWindow( X_display, RootWindow(X_display, X_screen), x, y, X_width, X_height, 0, // borderwidth 8, // depth InputOutput, X_visual, attribmask, &attribs ); XDefineCursor(X_display, X_mainWindow, createnullcursor( X_display, X_mainWindow ) ); // create the GC valuemask = GCGraphicsExposures; xgcvalues.graphics_exposures = False; X_gc = XCreateGC( X_display, X_mainWindow, valuemask, &xgcvalues ); // map the window XMapWindow(X_display, X_mainWindow); // wait until it is OK to draw oktodraw = 0; while (!oktodraw) { XNextEvent(X_display, &X_event); if (X_event.type == Expose && !X_event.xexpose.count) { oktodraw = 1; } } // grabs the pointer so it is restricted to this window if (grabMouse) XGrabPointer(X_display, X_mainWindow, True, ButtonPressMask|ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, X_mainWindow, None, CurrentTime); if (doShm) { X_shmeventtype = XShmGetEventBase(X_display) + ShmCompletion; // create the image image = XShmCreateImage( X_display, X_visual, 8, ZPixmap, 0, &X_shminfo, X_width, X_height ); grabsharedmemory(image->bytes_per_line * image->height); // UNUSED // create the shared memory segment // X_shminfo.shmid = shmget (IPC_PRIVATE, // image->bytes_per_line * image->height, IPC_CREAT | 0777); // if (X_shminfo.shmid < 0) // { // perror(""); // I_Error("shmget() failed in InitGraphics()"); // } // fprintf(stderr, "shared memory id=%d\n", X_shminfo.shmid); // attach to the shared memory segment // image->data = X_shminfo.shmaddr = shmat(X_shminfo.shmid, 0, 0); if (!image->data) { perror(""); I_Error("shmat() failed in InitGraphics()"); } // get the X server to attach to it if (!XShmAttach(X_display, &X_shminfo)) I_Error("XShmAttach() failed in InitGraphics()"); } else { image = XCreateImage( X_display, X_visual, 8, ZPixmap, 0, (char*)malloc(X_width * X_height), X_width, X_height, 8, X_width ); } if (multiply == 1) screens[0] = (unsigned char *) (image->data); else screens[0] = (unsigned char *) malloc (SCREENWIDTH * SCREENHEIGHT); */ printf("I_Video: Creating %d, %d image\n", X_width, X_height); jni_printf("I_Video: Creating %dx%d image", X_width, X_height); image = XCreateImage(X_width, X_height); jni_init_graphics(X_width, X_height); screens[0] = (unsigned char *) (image->data); } unsigned exptable[256]; void InitExpand (void) { int i; for (i=0 ; i<256 ; i++) exptable[i] = i | (i<<8) | (i<<16) | (i<<24); } double exptable2[256*256]; void InitExpand2 (void) { int i; int j; // UNUSED unsigned iexp, jexp; double* exp; union { double d; unsigned u[2]; } pixel; printf ("building exptable2...\n"); exp = exptable2; for (i=0 ; i<256 ; i++) { pixel.u[0] = i | (i<<8) | (i<<16) | (i<<24); for (j=0 ; j<256 ; j++) { pixel.u[1] = j | (j<<8) | (j<<16) | (j<<24); *exp++ = pixel.d; } } printf ("done.\n"); } /* int inited; void Expand4 ( unsigned* lineptr, double* xline ) { double dpixel; unsigned x; unsigned y; unsigned fourpixels; unsigned step; double* exp; exp = exptable2; if (!inited) { inited = 1; InitExpand2 (); } step = 3*SCREENWIDTH/2; y = SCREENHEIGHT-1; do { x = SCREENWIDTH; do { fourpixels = lineptr[0]; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) ); xline[0] = dpixel; xline[160] = dpixel; xline[320] = dpixel; xline[480] = dpixel; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) ); xline[1] = dpixel; xline[161] = dpixel; xline[321] = dpixel; xline[481] = dpixel; fourpixels = lineptr[1]; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) ); xline[2] = dpixel; xline[162] = dpixel; xline[322] = dpixel; xline[482] = dpixel; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) ); xline[3] = dpixel; xline[163] = dpixel; xline[323] = dpixel; xline[483] = dpixel; fourpixels = lineptr[2]; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) ); xline[4] = dpixel; xline[164] = dpixel; xline[324] = dpixel; xline[484] = dpixel; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) ); xline[5] = dpixel; xline[165] = dpixel; xline[325] = dpixel; xline[485] = dpixel; fourpixels = lineptr[3]; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) ); xline[6] = dpixel; xline[166] = dpixel; xline[326] = dpixel; xline[486] = dpixel; dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) ); xline[7] = dpixel; xline[167] = dpixel; xline[327] = dpixel; xline[487] = dpixel; lineptr+=4; xline+=8; } while (x-=16); xline += step; } while (y--); } */