osezer patch 005
[theoddone33/hhexen.git] / sdl / i_sdl.c
1 //**************************************************************************
2 //**
3 //** $Id$
4 //**
5 //**************************************************************************
6
7
8 #include <stdlib.h>
9 #include <stdarg.h>
10 #include <sys/time.h>
11 #include "SDL.h"
12 #include "h2def.h"
13 #include "r_local.h"
14 #include "p_local.h"    // for P_AproxDistance
15 #include "sounds.h"
16 #include "i_sound.h"
17 #include "soundst.h"
18 #include "st_start.h"
19
20 // Public Data
21
22 int DisplayTicker = 0;
23
24
25 // Code
26
27 void I_StartupNet (void);
28 void I_ShutdownNet (void);
29 void I_ReadExternDriver(void);
30 void GrabScreen (void);
31
32 extern int usemouse, usejoystick;
33
34 extern void **lumpcache;
35
36 int i_Vector;
37 externdata_t *i_ExternData;
38 boolean useexterndriver;
39
40 SDL_Surface* sdl_screen;
41
42 boolean mousepresent;
43
44 //===============================
45
46 int ticcount;
47
48
49 boolean novideo; // if true, stay in text mode for debugging
50
51 #define KEY_INS         0x52
52 #define KEY_DEL         0x53
53 #define KEY_PGUP        0x49
54 #define KEY_PGDN        0x51
55 #define KEY_HOME        0x47
56 #define KEY_END         0x4f
57
58 /*
59 ============================================================================
60
61                                                                 USER INPUT
62
63 ============================================================================
64 */
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     SDL_Color* c;
95     SDL_Color* cend;
96     SDL_Color cmap[ 256 ];
97
98         if(novideo)
99         {
100                 return;
101         }
102         I_WaitVBL(1);
103
104     c = cmap;
105     cend = c + 256;
106         for( ; c != cend; c++ )
107         {
108                 //_outbyte(PEL_DATA, (gammatable[usegamma][*palette++])>>2);
109
110         c->r = gammatable[usegamma][*palette++];
111         c->g = gammatable[usegamma][*palette++];
112         c->b = gammatable[usegamma][*palette++];
113         }
114     SDL_SetColors( sdl_screen, cmap, 0, 256 );
115 }
116
117 /*
118 ============================================================================
119
120                                                         GRAPHICS MODE
121
122 ============================================================================
123 */
124
125 byte *pcscreen, *destscreen, *destview;
126
127 /*
128 ==============
129 =
130 = I_Update
131 =
132 ==============
133 */
134
135 int UpdateState;
136 extern int screenblocks;
137
138 void I_Update (void)
139 {
140         int i;
141         byte *dest;
142         int tics;
143         static int lasttic;
144
145 //
146 // blit screen to video
147 //
148         if(DisplayTicker)
149         {
150                 if(screenblocks > 9 || UpdateState&(I_FULLSCRN|I_MESSAGES))
151                 {
152                         dest = (byte *)screen;
153                 }
154                 else
155                 {
156                         dest = (byte *)pcscreen;
157                 }
158                 tics = ticcount-lasttic;
159                 lasttic = ticcount;
160                 if(tics > 20)
161                 {
162                         tics = 20;
163                 }
164                 for(i = 0; i < tics; i++)
165                 {
166                         *dest = 0xff;
167                         dest += 2;
168                 }
169                 for(i = tics; i < 20; i++)
170                 {
171                         *dest = 0x00;
172                         dest += 2;
173                 }
174         }
175
176         //memset(pcscreen, 255, SCREENHEIGHT*SCREENWIDTH);
177
178         if(UpdateState == I_NOUPDATE)
179         {
180                 return;
181         }
182         if(UpdateState&I_FULLSCRN)
183         {
184                 memcpy(pcscreen, screen, SCREENWIDTH*SCREENHEIGHT);
185                 UpdateState = I_NOUPDATE; // clear out all draw types
186
187         SDL_UpdateRect( sdl_screen, 0, 0, SCREENWIDTH, SCREENHEIGHT );
188         }
189         if(UpdateState&I_FULLVIEW)
190         {
191                 if(UpdateState&I_MESSAGES && screenblocks > 7)
192                 {
193                         for(i = 0; i <
194                                 (viewwindowy+viewheight)*SCREENWIDTH; i += SCREENWIDTH)
195                         {
196                                 memcpy(pcscreen+i, screen+i, SCREENWIDTH);
197                         }
198                         UpdateState &= ~(I_FULLVIEW|I_MESSAGES);
199
200             SDL_UpdateRect( sdl_screen, 0, 0, SCREENWIDTH,
201                             viewwindowy+viewheight );
202                 }
203                 else
204                 {
205                         for(i = viewwindowy*SCREENWIDTH+viewwindowx; i <
206                                 (viewwindowy+viewheight)*SCREENWIDTH; i += SCREENWIDTH)
207                         {
208                                 memcpy(pcscreen+i, screen+i, viewwidth);
209                         }
210                         UpdateState &= ~I_FULLVIEW;
211
212             SDL_UpdateRect( sdl_screen, viewwindowx, viewwindowy, viewwidth,
213                             viewheight );
214                 }
215         }
216         if(UpdateState&I_STATBAR)
217         {
218                 memcpy(pcscreen+SCREENWIDTH*(SCREENHEIGHT-SBARHEIGHT),
219                         screen+SCREENWIDTH*(SCREENHEIGHT-SBARHEIGHT),
220                         SCREENWIDTH*SBARHEIGHT);
221                 UpdateState &= ~I_STATBAR;
222
223         SDL_UpdateRect( sdl_screen, 0, SCREENHEIGHT-SBARHEIGHT,
224                         SCREENWIDTH, SBARHEIGHT );
225         }
226         if(UpdateState&I_MESSAGES)
227         {
228                 memcpy(pcscreen, screen, SCREENWIDTH*28);
229                 UpdateState &= ~I_MESSAGES;
230
231         SDL_UpdateRect( sdl_screen, 0, 0, SCREENWIDTH, 28 );
232         }
233 }
234
235 //--------------------------------------------------------------------------
236 //
237 // PROC I_InitGraphics
238 //
239 //--------------------------------------------------------------------------
240
241 void I_InitGraphics(void)
242 {
243         char text[20];
244
245         if( novideo )
246         {
247                 return;
248         }
249     
250     // SDL_DOUBLEBUF does not work in full screen mode.  Does not seem to
251     // be necessary anyway.
252
253     sdl_screen = SDL_SetVideoMode(SCREENWIDTH, SCREENHEIGHT, 8, SDL_SWSURFACE);
254
255     if( sdl_screen == NULL )
256     {
257         fprintf( stderr, "Couldn't set video mode %dx%d: %s\n",
258                  SCREENWIDTH, SCREENHEIGHT, SDL_GetError() );
259         exit( 3 );
260     }
261
262     // Only grab if we want to
263     if (!M_CheckParm ("--nograb") && !M_CheckParm ("-g")) {
264             SDL_WM_GrabInput (SDL_GRAB_ON);
265     }
266
267     SDL_ShowCursor( 0 );
268     snprintf (text, 20, "HHexen v%s", HHEXEN_VERSION);
269     SDL_WM_SetCaption( text, "HHEXEN" );
270
271
272         pcscreen = destscreen = sdl_screen->pixels;
273
274         I_SetPalette( W_CacheLumpName("PLAYPAL", PU_CACHE) );
275 }
276
277 //--------------------------------------------------------------------------
278 //
279 // PROC I_ShutdownGraphics
280 //
281 //--------------------------------------------------------------------------
282
283 void I_ShutdownGraphics(void)
284 {
285         SDL_Quit ();
286 }
287
288 //--------------------------------------------------------------------------
289 //
290 // PROC I_ReadScreen
291 //
292 // Reads the screen currently displayed into a linear buffer.
293 //
294 //--------------------------------------------------------------------------
295
296 /*
297 void I_ReadScreen(byte *scr)
298 {
299         memcpy(scr, screen, SCREENWIDTH*SCREENHEIGHT);
300 }
301 */
302
303 //===========================================================================
304
305
306 //
307 //  Translates the key 
308 //
309
310 int xlatekey(SDL_keysym *key)
311 {
312
313     int rc;
314
315     switch(key->sym)
316     {
317       case SDLK_LEFT:   rc = KEY_LEFTARROW;     break;
318       case SDLK_RIGHT:  rc = KEY_RIGHTARROW;    break;
319       case SDLK_DOWN:   rc = KEY_DOWNARROW;     break;
320       case SDLK_UP:     rc = KEY_UPARROW;       break;
321       case SDLK_ESCAPE: rc = KEY_ESCAPE;        break;
322
323       case SDLK_KP_ENTER:
324       case SDLK_RETURN: rc = KEY_ENTER;         break;
325
326       case SDLK_F1:     rc = KEY_F1;            break;
327       case SDLK_F2:     rc = KEY_F2;            break;
328       case SDLK_F3:     rc = KEY_F3;            break;
329       case SDLK_F4:     rc = KEY_F4;            break;
330       case SDLK_F5:     rc = KEY_F5;            break;
331       case SDLK_F6:     rc = KEY_F6;            break;
332       case SDLK_F7:     rc = KEY_F7;            break;
333       case SDLK_F8:     rc = KEY_F8;            break;
334       case SDLK_F9:     rc = KEY_F9;            break;
335       case SDLK_F10:    rc = KEY_F10;           break;
336       case SDLK_F11:    rc = KEY_F11;           break;
337       case SDLK_F12:    rc = KEY_F12;           break;
338         
339       case SDLK_INSERT: rc = KEY_INS;           break;
340       case SDLK_DELETE: rc = KEY_DEL;           break;
341       case SDLK_PAGEUP: rc = KEY_PGUP;          break;
342       case SDLK_PAGEDOWN: rc = KEY_PGDN;        break;
343       case SDLK_HOME:   rc = KEY_HOME;          break;
344       case SDLK_END:    rc = KEY_END;           break;
345
346       case SDLK_BACKSPACE: rc = KEY_BACKSPACE;  break;
347
348       case SDLK_PAUSE:  rc = KEY_PAUSE;         break;
349
350       case SDLK_EQUALS: rc = KEY_EQUALS;        break;
351
352       case SDLK_KP_MINUS:
353       case SDLK_MINUS:  rc = KEY_MINUS;         break;
354
355       case SDLK_LSHIFT:
356       case SDLK_RSHIFT:
357         rc = KEY_RSHIFT;
358         break;
359         
360       case SDLK_LCTRL:
361       case SDLK_RCTRL:
362         rc = KEY_RCTRL;
363         break;
364         
365       case SDLK_LALT:
366       case SDLK_LMETA:
367       case SDLK_RALT:
368       case SDLK_RMETA:
369         rc = KEY_RALT;
370         break;
371         
372       default:
373         rc = key->sym;
374         break;
375     }
376
377     return rc;
378
379 }
380
381
382 /* This processes SDL events */
383 void I_GetEvent(SDL_Event *Event)
384 {
385     Uint8 buttonstate;
386     event_t event;
387     SDLMod mod;
388
389     switch (Event->type)
390     {
391       case SDL_KEYDOWN:
392         mod = SDL_GetModState ();
393         if (mod & KMOD_RCTRL || mod & KMOD_LCTRL) {
394                 if (Event->key.keysym.sym == 'g') {
395                         if (SDL_WM_GrabInput (SDL_GRAB_QUERY) == SDL_GRAB_OFF)
396                                 SDL_WM_GrabInput (SDL_GRAB_ON);
397                         else
398                                 SDL_WM_GrabInput (SDL_GRAB_OFF);
399                         break;
400                 }
401         } else if (mod & KMOD_RALT || mod & KMOD_LALT) {
402                 if (Event->key.keysym.sym == SDLK_RETURN) {
403                         SDL_WM_ToggleFullScreen(SDL_GetVideoSurface());
404                         break;
405                 }
406         }
407         event.type = ev_keydown;
408         event.data1 = xlatekey(&Event->key.keysym);
409         H2_PostEvent(&event);
410         break;
411
412       case SDL_KEYUP:
413         event.type = ev_keyup;
414         event.data1 = xlatekey(&Event->key.keysym);
415         H2_PostEvent(&event);
416         break;
417
418       case SDL_MOUSEBUTTONDOWN:
419       case SDL_MOUSEBUTTONUP:
420         buttonstate = SDL_GetMouseState(NULL, NULL);
421         event.type = ev_mouse;
422         event.data1 = 0
423             | (buttonstate & SDL_BUTTON(1) ? 1 : 0)
424             | (buttonstate & SDL_BUTTON(2) ? 2 : 0)
425             | (buttonstate & SDL_BUTTON(3) ? 4 : 0);
426         event.data2 = event.data3 = 0;
427         H2_PostEvent(&event);
428         break;
429
430       case SDL_MOUSEMOTION:
431         /* Ignore mouse warp events */
432         if ( (Event->motion.x != sdl_screen->w/2) ||
433              (Event->motion.y != sdl_screen->h/2) )
434         {
435             /* Warp the mouse back to the center */
436             event.type = ev_mouse;
437             event.data1 = 0
438                 | (Event->motion.state & SDL_BUTTON(1) ? 1 : 0)
439                 | (Event->motion.state & SDL_BUTTON(2) ? 2 : 0)
440                 | (Event->motion.state & SDL_BUTTON(3) ? 4 : 0);
441             event.data2 = Event->motion.xrel << 3;
442             event.data3 = -Event->motion.yrel << 3;
443             H2_PostEvent(&event);
444         }
445         break;
446
447       case SDL_QUIT:
448         I_Quit();
449     }
450
451 }
452
453 //
454 // I_StartTic
455 //
456 void I_StartTic (void)
457 {
458     SDL_Event Event;
459
460     while ( SDL_PollEvent(&Event) )
461         I_GetEvent(&Event);
462 }
463
464
465 /*
466 ============================================================================
467
468                                         TIMER INTERRUPT
469
470 ============================================================================
471 */
472
473
474 /*
475 ================
476 =
477 = I_TimerISR
478 =
479 ================
480 */
481
482 int I_TimerISR (void)
483 {
484         ticcount++;
485         return 0;
486 }
487
488 /*
489 ============================================================================
490
491                                                 KEYBOARD
492
493 ============================================================================
494 */
495
496 int lastpress;
497
498
499
500 /*
501 ============================================================================
502
503                                                         MOUSE
504
505 ============================================================================
506 */
507
508
509 /*
510 ================
511 =
512 = StartupMouse
513 =
514 ================
515 */
516
517
518 void I_StartupMouse (void)
519 {
520         mousepresent = 1;
521 }
522
523 void GrabScreen (void)
524 {
525 }