0307d3df2748c40a5f738dec0ef2e2c98de98cfd
[theoddone33/hhexen.git] / i_sdlgl.c
1 //**************************************************************************
2 //**
3 //** $Id$
4 //**
5 //**************************************************************************
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdarg.h>
10 #include <unistd.h>
11 #include <sys/time.h>
12 #include <SDL/SDL.h> 
13 #include <GL/gl.h>
14 #include <GL/glu.h>
15 #include "h2def.h"
16 #include "r_local.h"
17 #include "p_local.h"    // for P_AproxDistance
18 #include "sounds.h"
19 #include "i_sound.h"
20 #include "soundst.h"
21 #include "st_start.h"
22
23 // Public Data
24
25 int screenWidth  = SCREENWIDTH*2;
26 int screenHeight = SCREENHEIGHT*2;
27 int maxTexSize = 256;
28 int ratioLimit = 0;             // Zero if none.
29 int test3dfx = 0;
30
31 int DisplayTicker = 0;
32
33
34 // Code
35 extern void OGL_InitData();
36 extern void OGL_InitRenderer();
37 extern void OGL_ResetData();
38 extern void OGL_ResetLumpTexData();
39
40 void I_StartupNet (void);
41 void I_ShutdownNet (void);
42 void I_ReadExternDriver(void);
43 void GrabScreen (void);
44
45 extern int usemouse, usejoystick;
46
47 extern void **lumpcache;
48
49 int i_Vector;
50 externdata_t *i_ExternData;
51 boolean useexterndriver;
52
53 boolean mousepresent;
54
55 int ticcount;
56
57 boolean novideo; // if true, stay in text mode for debugging
58
59 #define KEY_INS         0x52
60 #define KEY_DEL         0x53
61 #define KEY_PGUP        0x49
62 #define KEY_PGDN        0x51
63 #define KEY_HOME        0x47
64 #define KEY_END         0x4f
65
66 //--------------------------------------------------------------------------
67 //
68 // PROC I_WaitVBL
69 //
70 //--------------------------------------------------------------------------
71
72 void I_WaitVBL(int vbls)
73 {
74         if( novideo )
75         {
76                 return;
77         }
78         while( vbls-- )
79         {
80         SDL_Delay( 16667/1000 );
81         }
82 }
83
84 //--------------------------------------------------------------------------
85 //
86 // PROC I_SetPalette
87 //
88 // Palette source must use 8 bit RGB elements.
89 //
90 //--------------------------------------------------------------------------
91
92 void I_SetPalette(byte *palette)
93 {
94 /*
95     SDL_Color* c;
96     SDL_Color* cend;
97     SDL_Color cmap[ 256 ];
98
99         if(novideo)
100         {
101                 return;
102         }
103         I_WaitVBL(1);
104
105     c = cmap;
106     cend = c + 256;
107         for( ; c != cend; c++ )
108         {
109                 //_outbyte(PEL_DATA, (gammatable[usegamma][*palette++])>>2);
110
111         c->r = gammatable[usegamma][*palette++];
112         c->g = gammatable[usegamma][*palette++];
113         c->b = gammatable[usegamma][*palette++];
114         }
115     SDL_SetColors( sdl_screen, cmap, 0, 256 );
116 */
117 }
118
119 /*
120 ============================================================================
121
122                                                         GRAPHICS MODE
123
124 ============================================================================
125 */
126
127 byte *pcscreen, *destscreen, *destview;
128
129 /*
130 ==============
131 =
132 = I_Update
133 =
134 ==============
135 */
136
137 int UpdateState;
138 extern int screenblocks;
139
140 void I_Update (void)
141 {
142         if(UpdateState == I_NOUPDATE)
143                 return;
144
145         SDL_GL_SwapBuffers();
146         UpdateState = I_NOUPDATE;
147 }
148
149 //--------------------------------------------------------------------------
150 //
151 // PROC I_InitGraphics
152 //
153 //--------------------------------------------------------------------------
154
155 void I_InitGraphics(void)
156 {
157     int p;
158     char text[20];
159     Uint32 flags = SDL_OPENGL;
160
161     if( novideo )
162     {
163         return;
164     }
165
166     if (M_CheckParm("-f") || M_CheckParm("--fullscreen")) {
167         flags |= SDL_FULLSCREEN;
168         setenv ("MESA_GLX_FX","fullscreen", 1);
169     } else {
170         setenv ("MESA_GLX_FX","disable",1);
171     }   
172     p = M_CheckParm ("-height");
173     if (p && p < myargc - 1)
174     {
175         screenHeight = atoi (myargv[p+1]);
176     }
177     p = M_CheckParm ("-width");
178     if (p && p < myargc - 1) {
179         screenWidth = atoi(myargv[p+1]);
180     }
181     ST_Message("Screen size:  %dx%d\n",screenWidth, screenHeight);
182
183     if(SDL_SetVideoMode(screenWidth, screenHeight, 8, flags) == NULL)
184     {
185         fprintf( stderr, "Couldn't set video mode %dx%d: %s\n",
186                  screenWidth, screenHeight, SDL_GetError() );
187         exit( 3 );
188     }
189
190     OGL_InitRenderer ();
191
192     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
193
194     // Print some OpenGL information.
195     ST_Message( "I_InitGraphics: OpenGL information:\n" );
196     ST_Message( "  Vendor: %s\n", glGetString(GL_VENDOR) );
197     ST_Message( "  Renderer: %s\n", glGetString(GL_RENDERER) );
198     ST_Message( "  Version: %s\n", glGetString(GL_VERSION) );
199     ST_Message( "  GLU Version: %s\n", gluGetString((GLenum)GLU_VERSION) );
200
201     // Check the maximum texture size.
202     glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxTexSize );
203     ST_Message("  Maximum texture size: %d\n", maxTexSize);
204     if( maxTexSize == 256 )
205     {
206             //ST_Message("  Is this Voodoo? Using size ratio limit.\n");
207             ratioLimit = 8;
208     }
209
210     if( M_CheckParm("-3dfxtest") )
211     {
212             test3dfx = 1;
213             ST_Message("  3dfx test mode.\n");
214     }
215
216     // Only grab if we want to
217     if (!M_CheckParm ("--nograb") && !M_CheckParm ("-g")) {
218             SDL_WM_GrabInput (SDL_GRAB_ON);
219     }
220
221     SDL_ShowCursor( 0 );
222     snprintf (text, 20, "HHexen v%s", HHEXEN_VERSION);
223     SDL_WM_SetCaption( text, "HHEXEN" );
224
225
226     //I_SetPalette( W_CacheLumpName("PLAYPAL", PU_CACHE) );
227 }
228
229 //--------------------------------------------------------------------------
230 //
231 // PROC I_ShutdownGraphics
232 //
233 //--------------------------------------------------------------------------
234
235 void I_ShutdownGraphics(void)
236 {
237     OGL_ResetData ();
238     OGL_ResetLumpTexData ();
239     SDL_Quit ();
240 }
241
242 //===========================================================================
243
244 //
245 //  Translates the key 
246 //
247
248 int xlatekey(SDL_keysym *key)
249 {
250
251     int rc;
252
253     switch(key->sym)
254     {
255       case SDLK_LEFT:   rc = KEY_LEFTARROW;     break;
256       case SDLK_RIGHT:  rc = KEY_RIGHTARROW;    break;
257       case SDLK_DOWN:   rc = KEY_DOWNARROW;     break;
258       case SDLK_UP:     rc = KEY_UPARROW;       break;
259       case SDLK_ESCAPE: rc = KEY_ESCAPE;        break;
260
261       case SDLK_KP_ENTER:
262       case SDLK_RETURN: rc = KEY_ENTER;         break;
263
264       case SDLK_F1:     rc = KEY_F1;            break;
265       case SDLK_F2:     rc = KEY_F2;            break;
266       case SDLK_F3:     rc = KEY_F3;            break;
267       case SDLK_F4:     rc = KEY_F4;            break;
268       case SDLK_F5:     rc = KEY_F5;            break;
269       case SDLK_F6:     rc = KEY_F6;            break;
270       case SDLK_F7:     rc = KEY_F7;            break;
271       case SDLK_F8:     rc = KEY_F8;            break;
272       case SDLK_F9:     rc = KEY_F9;            break;
273       case SDLK_F10:    rc = KEY_F10;           break;
274       case SDLK_F11:    rc = KEY_F11;           break;
275       case SDLK_F12:    rc = KEY_F12;           break;
276         
277       case SDLK_INSERT: rc = KEY_INS;           break;
278       case SDLK_DELETE: rc = KEY_DEL;           break;
279       case SDLK_PAGEUP: rc = KEY_PGUP;          break;
280       case SDLK_PAGEDOWN: rc = KEY_PGDN;        break;
281       case SDLK_HOME:   rc = KEY_HOME;          break;
282       case SDLK_END:    rc = KEY_END;           break;
283
284       case SDLK_BACKSPACE: rc = KEY_BACKSPACE;  break;
285
286       case SDLK_PAUSE:  rc = KEY_PAUSE;         break;
287
288       case SDLK_EQUALS: rc = KEY_EQUALS;        break;
289
290       case SDLK_KP_MINUS:
291       case SDLK_MINUS:  rc = KEY_MINUS;         break;
292
293       case SDLK_LSHIFT:
294       case SDLK_RSHIFT:
295         rc = KEY_RSHIFT;
296         break;
297         
298       case SDLK_LCTRL:
299       case SDLK_RCTRL:
300         rc = KEY_RCTRL;
301         break;
302         
303       case SDLK_LALT:
304       case SDLK_LMETA:
305       case SDLK_RALT:
306       case SDLK_RMETA:
307         rc = KEY_RALT;
308         break;
309         
310       default:
311         rc = key->sym;
312         break;
313     }
314
315     return rc;
316
317 }
318
319
320 /* This processes SDL events */
321 void I_GetEvent(SDL_Event *Event)
322 {
323     Uint8 buttonstate;
324     event_t event;
325     SDLMod mod;
326
327     switch (Event->type)
328     {
329       case SDL_KEYDOWN:
330         mod = SDL_GetModState ();
331         if (mod & KMOD_RCTRL || mod & KMOD_LCTRL) {
332                 if (Event->key.keysym.sym == 'g') {
333                         if (SDL_WM_GrabInput (SDL_GRAB_QUERY) == SDL_GRAB_OFF)
334                                 SDL_WM_GrabInput (SDL_GRAB_ON);
335                         else
336                                 SDL_WM_GrabInput (SDL_GRAB_OFF);
337                         break;
338                 }
339         } else if (mod & KMOD_RALT || mod & KMOD_LALT) {
340                 if (Event->key.keysym.sym == SDLK_RETURN) {
341                         SDL_WM_ToggleFullScreen(SDL_GetVideoSurface());
342                         break;
343                 }
344         }
345         event.type = ev_keydown;
346         event.data1 = xlatekey(&Event->key.keysym);
347         H2_PostEvent(&event);
348         break;
349
350       case SDL_KEYUP:
351         event.type = ev_keyup;
352         event.data1 = xlatekey(&Event->key.keysym);
353         H2_PostEvent(&event);
354         break;
355
356       case SDL_MOUSEBUTTONDOWN:
357       case SDL_MOUSEBUTTONUP:
358         buttonstate = SDL_GetMouseState(NULL, NULL);
359         event.type = ev_mouse;
360         event.data1 = 0
361             | (buttonstate & SDL_BUTTON(1) ? 1 : 0)
362             | (buttonstate & SDL_BUTTON(2) ? 2 : 0)
363             | (buttonstate & SDL_BUTTON(3) ? 4 : 0);
364         event.data2 = event.data3 = 0;
365         H2_PostEvent(&event);
366         break;
367
368       case SDL_MOUSEMOTION:
369         /* Ignore mouse warp events */
370         if ( (Event->motion.x != SCREENWIDTH/2) ||
371              (Event->motion.y != SCREENHEIGHT/2) )
372         {
373             /* Warp the mouse back to the center */
374             event.type = ev_mouse;
375             event.data1 = 0
376                 | (Event->motion.state & SDL_BUTTON(1) ? 1 : 0)
377                 | (Event->motion.state & SDL_BUTTON(2) ? 2 : 0)
378                 | (Event->motion.state & SDL_BUTTON(3) ? 4 : 0);
379             event.data2 = Event->motion.xrel << 3;
380             event.data3 = -Event->motion.yrel << 3;
381             H2_PostEvent(&event);
382         }
383         break;
384
385       case SDL_QUIT:
386         I_Quit();
387     }
388
389 }
390
391 //
392 // I_StartTic
393 //
394 void I_StartTic (void)
395 {
396     SDL_Event Event;
397
398     while ( SDL_PollEvent(&Event) )
399         I_GetEvent(&Event);
400 }
401
402
403 /*
404 ============================================================================
405
406                                         TIMER INTERRUPT
407
408 ============================================================================
409 */
410
411
412 /*
413 ================
414 =
415 = I_TimerISR
416 =
417 ================
418 */
419
420 int I_TimerISR (void)
421 {
422         ticcount++;
423         return 0;
424 }
425
426 /*
427 ============================================================================
428
429                                                         MOUSE
430
431 ============================================================================
432 */
433
434 /*
435 ================
436 =
437 = StartupMouse
438 =
439 ================
440 */
441
442 void I_StartupMouse (void)
443 {
444         mousepresent = 1;
445 }
446
447 static int makeUniqueFilename( char* filename )
448 {
449     int i;
450
451     for( i = 0; i < 100; i++ )
452     {
453         sprintf( filename, "hexen%02d.bmp", i );
454
455         if( access( filename, F_OK ) == -1 )
456         {
457             // It does not exist.
458             return 1;
459         }
460     }
461
462     return 0;
463 }
464
465 void GrabScreen ()
466 {
467     SDL_Surface *image;
468     SDL_Surface *temp;
469     int idx;
470     char filename[80];
471
472     if (makeUniqueFilename(filename)) {
473         image = SDL_CreateRGBSurface(SDL_SWSURFACE, screenWidth, screenHeight,
474                                     24, 0x0000FF, 0x00FF00, 0xFF0000,0xFFFFFF);
475         temp = SDL_CreateRGBSurface(SDL_SWSURFACE, screenWidth, screenHeight,
476                                     24, 0x0000FF, 0x00FF00, 0xFF0000, 0xFFFFFF);
477
478         glReadPixels(0, 0, screenWidth, screenHeight, GL_RGB,
479                      GL_UNSIGNED_BYTE, image->pixels);
480         for (idx = 0; idx < screenHeight; idx++)
481         {
482                memcpy(temp->pixels + 3 * screenWidth * idx,
483                         (char *)image->pixels + 3
484                         * screenWidth*(screenHeight - idx),
485                         3*screenWidth);
486         }
487         memcpy(image->pixels,temp->pixels,screenWidth * screenHeight * 3);
488         SDL_SaveBMP(image, filename);
489         SDL_FreeSurface(image);
490     }
491 }
492