osezer patch 003
[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       case SDLK_RETURN: rc = KEY_ENTER;         break;
323       case SDLK_F1:     rc = KEY_F1;            break;
324       case SDLK_F2:     rc = KEY_F2;            break;
325       case SDLK_F3:     rc = KEY_F3;            break;
326       case SDLK_F4:     rc = KEY_F4;            break;
327       case SDLK_F5:     rc = KEY_F5;            break;
328       case SDLK_F6:     rc = KEY_F6;            break;
329       case SDLK_F7:     rc = KEY_F7;            break;
330       case SDLK_F8:     rc = KEY_F8;            break;
331       case SDLK_F9:     rc = KEY_F9;            break;
332       case SDLK_F10:    rc = KEY_F10;           break;
333       case SDLK_F11:    rc = KEY_F11;           break;
334       case SDLK_F12:    rc = KEY_F12;           break;
335         
336       case SDLK_INSERT: rc = KEY_INS;           break;
337       case SDLK_DELETE: rc = KEY_DEL;           break;
338       case SDLK_PAGEUP: rc = KEY_PGUP;          break;
339       case SDLK_PAGEDOWN: rc = KEY_PGDN;        break;
340       case SDLK_HOME:   rc = KEY_HOME;          break;
341       case SDLK_END:    rc = KEY_END;           break;
342
343       case SDLK_BACKSPACE: rc = KEY_BACKSPACE;  break;
344
345       case SDLK_PAUSE:  rc = KEY_PAUSE;         break;
346
347       case SDLK_EQUALS: rc = KEY_EQUALS;        break;
348
349       case SDLK_KP_MINUS:
350       case SDLK_MINUS:  rc = KEY_MINUS;         break;
351
352       case SDLK_LSHIFT:
353       case SDLK_RSHIFT:
354         rc = KEY_RSHIFT;
355         break;
356         
357       case SDLK_LCTRL:
358       case SDLK_RCTRL:
359         rc = KEY_RCTRL;
360         break;
361         
362       case SDLK_LALT:
363       case SDLK_LMETA:
364       case SDLK_RALT:
365       case SDLK_RMETA:
366         rc = KEY_RALT;
367         break;
368         
369       default:
370         rc = key->sym;
371         break;
372     }
373
374     return rc;
375
376 }
377
378
379 /* This processes SDL events */
380 void I_GetEvent(SDL_Event *Event)
381 {
382     Uint8 buttonstate;
383     event_t event;
384     SDLMod mod;
385
386     switch (Event->type)
387     {
388       case SDL_KEYDOWN:
389         mod = SDL_GetModState ();
390         if (mod & KMOD_RCTRL || mod & KMOD_LCTRL) {
391                 if (Event->key.keysym.sym == 'g') {
392                         if (SDL_WM_GrabInput (SDL_GRAB_QUERY) == SDL_GRAB_OFF)
393                                 SDL_WM_GrabInput (SDL_GRAB_ON);
394                         else
395                                 SDL_WM_GrabInput (SDL_GRAB_OFF);
396                         break;
397                 }
398         } else if (mod & KMOD_RALT || mod & KMOD_LALT) {
399                 if (Event->key.keysym.sym == SDLK_RETURN) {
400                         SDL_WM_ToggleFullScreen(SDL_GetVideoSurface());
401                         break;
402                 }
403         }
404         event.type = ev_keydown;
405         event.data1 = xlatekey(&Event->key.keysym);
406         H2_PostEvent(&event);
407         break;
408
409       case SDL_KEYUP:
410         event.type = ev_keyup;
411         event.data1 = xlatekey(&Event->key.keysym);
412         H2_PostEvent(&event);
413         break;
414
415       case SDL_MOUSEBUTTONDOWN:
416       case SDL_MOUSEBUTTONUP:
417         buttonstate = SDL_GetMouseState(NULL, NULL);
418         event.type = ev_mouse;
419         event.data1 = 0
420             | (buttonstate & SDL_BUTTON(1) ? 1 : 0)
421             | (buttonstate & SDL_BUTTON(2) ? 2 : 0)
422             | (buttonstate & SDL_BUTTON(3) ? 4 : 0);
423         event.data2 = event.data3 = 0;
424         H2_PostEvent(&event);
425         break;
426
427       case SDL_MOUSEMOTION:
428         /* Ignore mouse warp events */
429         if ( (Event->motion.x != sdl_screen->w/2) ||
430              (Event->motion.y != sdl_screen->h/2) )
431         {
432             /* Warp the mouse back to the center */
433             event.type = ev_mouse;
434             event.data1 = 0
435                 | (Event->motion.state & SDL_BUTTON(1) ? 1 : 0)
436                 | (Event->motion.state & SDL_BUTTON(2) ? 2 : 0)
437                 | (Event->motion.state & SDL_BUTTON(3) ? 4 : 0);
438             event.data2 = Event->motion.xrel << 3;
439             event.data3 = -Event->motion.yrel << 3;
440             H2_PostEvent(&event);
441         }
442         break;
443
444       case SDL_QUIT:
445         I_Quit();
446     }
447
448 }
449
450 //
451 // I_StartTic
452 //
453 void I_StartTic (void)
454 {
455     SDL_Event Event;
456
457     while ( SDL_PollEvent(&Event) )
458         I_GetEvent(&Event);
459 }
460
461
462 /*
463 ============================================================================
464
465                                         TIMER INTERRUPT
466
467 ============================================================================
468 */
469
470
471 /*
472 ================
473 =
474 = I_TimerISR
475 =
476 ================
477 */
478
479 int I_TimerISR (void)
480 {
481         ticcount++;
482         return 0;
483 }
484
485 /*
486 ============================================================================
487
488                                                 KEYBOARD
489
490 ============================================================================
491 */
492
493 int lastpress;
494
495
496
497 /*
498 ============================================================================
499
500                                                         MOUSE
501
502 ============================================================================
503 */
504
505
506 /*
507 ================
508 =
509 = StartupMouse
510 =
511 ================
512 */
513
514
515 void I_StartupMouse (void)
516 {
517         mousepresent = 1;
518 }
519
520 void GrabScreen (void)
521 {
522 }