Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Iskhodnyy_kod_Doom

.pdf
Скачиваний:
7
Добавлен:
13.02.2015
Размер:
1.01 Mб
Скачать

//(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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]