Iskhodnyy_kod_Doom
.pdf//(just after displaying a frame).
//Time consuming syncronous operations
//are performed here (joystick reading).
//Can call D_PostEvent.
//
void I_StartFrame (void);
//
//Called by D_DoomLoop,
//called before processing each tic in a frame.
//Quick syncronous operations are performed here.
//Can call D_PostEvent. void I_StartTic (void);
//Asynchronous interrupt functions should maintain private queues
//that are read by the synchronous functions
//to be converted into events.
//Either returns a null ticcmd,
//or calls a loadable driver to build it.
//This ticcmd will then be modified by the gameloop
//for normal input.
ticcmd_t* I_BaseTiccmd (void);
//Called by M_Responder when quit is selected.
//Clean exit, displays sell blurb.
void I_Quit (void);
// |
Allocates from low |
memory under dos, |
// |
just mallocs under |
unix |
byte* I_AllocLow (int |
length); |
void I_Tactile (int on, int off, int total);
void I_Error (char *error, ...);
#endif //-----------------------------------------------------------------------------
//
// $Log:$
//
//-----------------------------------------------------------------------------
7.8 i video.c
// 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
201
// 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 <stdlib.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/shm.h>
#include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/keysym.h>
#include <X11/extensions/XShm.h>
//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 <stdarg.h> #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h>
#include <netinet/in.h> #include <errnos.h> #include <signal.h>
#include "doomstat.h" #include "i_system.h" #include "v_video.h" #include "m_argv.h"
#include "d_main.h"
#include "doomdef.h" |
|
|
#define POINTER_WARP_COUNTDOWN |
1 |
|
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; |
|
XImage* |
image; |
|
int |
X_width; |
|
int |
X_height; |
|
// MIT SHared Memory extension. |
|
|
boolean |
doShm; |
|
XShmSegmentInfo |
X_shminfo; |
|
int |
X_shmeventtype; |
|
202
//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 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_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;
203
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’;
break;
}
return rc;
}
void I_ShutdownGraphics(void)
{
// 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)
{
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:
204
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:
205
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
//
void I_StartTic (void)
{
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;
}
206
//
// I_UpdateNoBlit
//
void I_UpdateNoBlit (void)
{
// what is this?
}
//
// I_FinishUpdate
//
void I_FinishUpdate (void)
{
static int |
lasttic; |
int |
tics; |
int |
i; |
//UNUSED static unsigned char *bigscreen=0;
//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 ; i<tics*2 ; i+=2)
screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0xff; for ( ; i<20*2 ; i+=2)
screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0x0;
}
// scales the screen size before blitting it if (multiply == 2)
{
unsigned int *olineptrs[2]; unsigned int *ilineptr;
int x, y, i;
unsigned int twoopixels; unsigned int twomoreopixels; unsigned int fouripixels;
ilineptr = (unsigned int *) (screens[0]); for (i=0 ; i<2 ; i++)
olineptrs[i] = (unsigned int *) &image->data[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;
207
*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);
208
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.
209
// |
|
|
static |
XColor |
colors[256]; |
void UploadNewPalette(Colormap cmap, 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;
}
}
//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)
{
UploadNewPalette(X_cmap, 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; |
210