allow older sdl versions
[btb/d2x.git] / arch / sdl / gr.c
1 /*
2  * $Source: /cvs/cvsroot/d2x/arch/sdl/gr.c,v $
3  * $Revision: 1.4 $
4  * $Author: bradleyb $
5  * $Date: 2002-02-16 02:08:31 $
6  *
7  * SDL video functions.
8  *
9  * $Log: not supported by cvs2svn $
10  * Revision 1.3  2002/02/14 11:29:31  bradleyb
11  * allow gr_init lowres
12  *
13  * Revision 1.2  2001/10/31 07:41:54  bradleyb
14  * Sync with d1x
15  *
16  * Revision 1.1  2001/10/25 08:25:34  bradleyb
17  * Finished moving stuff to arch/blah.  I know, it's ugly, but It'll be easier to sync with d1x.
18  *
19  * Revision 1.5  2001/10/09 08:17:07  bradleyb
20  * changed window caption to include version info
21  *
22  * Revision 1.4  2001/01/31 13:59:23  bradleyb
23  * Fullscreen toggle added to screen res menu
24  *
25  * Revision 1.3  2001/01/29 13:47:52  bradleyb
26  * Fixed build, some minor cleanups.
27  *
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <conf.h>
32 #endif
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <SDL/SDL.h>
37
38 #ifndef SDL_VERSION_ATLEAST
39 #include "oldsdl.h"
40 #endif
41 #include "gr.h"
42 #include "grdef.h"
43 #include "palette.h"
44 #include "u_mem.h"
45 #include "error.h"
46 #include "menu.h"
47
48 //added on 9/30/98 by Matt Mueller to set the title bar.  Woohoo!
49 #include "vers_id.h"
50 //end addition -MM
51
52 #include "gamefont.h"
53
54 //added 10/05/98 by Matt Mueller - make fullscreen mode optional
55 #include "args.h"
56
57 int sdl_video_flags = SDL_SWSURFACE | SDL_HWPALETTE;
58 char checkvidmodeok=0;
59 //end addition -MM
60
61 SDL_Surface *screen;
62
63 int gr_installed = 0;
64
65 //added 05/19/99 Matt Mueller - locking stuff
66 #ifdef GR_LOCK
67 #include "checker.h"
68 #ifdef TEST_GR_LOCK
69 int gr_testlocklevel=0;
70 #endif
71 inline void gr_dolock(const char *file,int line) {
72         gr_dotestlock();
73         if ( gr_testlocklevel==1 && SDL_MUSTLOCK(screen) ) {
74 #ifdef __CHECKER__
75                 chcksetwritable(screen.pixels,screen->w*screen->h*screen->format->BytesPerPixel);
76 #endif
77                 if ( SDL_LockSurface(screen) < 0 )Error("could not lock screen (%s:%i)\n",file,line);
78         }
79 }
80 inline void gr_dounlock(void) {
81         gr_dotestunlock();
82         if (gr_testlocklevel==0 && SDL_MUSTLOCK(screen) ) {
83                 SDL_UnlockSurface(screen);
84 #ifdef __CHECKER__
85                 chcksetunwritable(screen.pixels,screen->w*screen->h*screen->format->BytesPerPixel);
86 #endif
87         }
88 }
89 #endif
90 //end addition -MM
91
92 void gr_palette_clear(); // Function prototype for gr_init;
93
94
95 void gr_update()
96 {
97         //added 05/19/99 Matt Mueller - locking stuff
98 //      gr_testunlock();
99         //end addition -MM
100  SDL_UpdateRect(screen,0,0,0,0);
101 }
102
103 extern int VGA_current_mode; // DPH: kludge - remove at all costs
104
105 int gr_set_mode(u_int32_t mode)
106 {
107         int w,h;
108
109 #ifdef NOGRAPH
110         return 0;
111 #endif
112
113         if (mode<=0)
114                 return 0;
115
116         w=SM_W(mode);
117         h=SM_H(mode);
118         VGA_current_mode = mode;
119         
120         if (screen != NULL) gr_palette_clear();
121
122 //added on 11/06/98 by Matt Mueller to set the title bar. (moved from below)
123 //sekmu: might wanna copy this litte blurb to one of the text files or something
124 //we want to set it here so that X window manager "Style" type commands work
125 //for example, in fvwm2 or fvwm95:
126 //Style "D1X*"  NoTitle, NoHandles, BorderWidth 0
127 //if you can't use -fullscreen like me (crashes X), this is a big help in
128 //getting the window centered correctly (if you use SmartPlacement)
129         SDL_WM_SetCaption(DESCENT_VERSION, "Descent II");
130 //end addition -MM
131
132 //edited 10/05/98 by Matt Mueller - make fullscreen mode optional
133           // changed by adb on 980913: added SDL_HWPALETTE (should be option?)
134         // changed by someone on 980923 to add SDL_FULLSCREEN
135         if(!checkvidmodeok || SDL_VideoModeOK(w,h,8,sdl_video_flags)){
136           screen = SDL_SetVideoMode(w, h, 8, sdl_video_flags);
137         } else {
138           screen=NULL;
139         }
140         // end changes by someone
141         // end changes by adb
142 //end edit -MM
143         if (screen == NULL) {
144            Error("Could not set %dx%dx8 video mode\n",w,h);
145            exit(1);
146         }
147         memset( grd_curscreen, 0, sizeof(grs_screen));
148         grd_curscreen->sc_mode = mode;
149         grd_curscreen->sc_w = w;
150         grd_curscreen->sc_h = h;
151         grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4);
152         grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0;
153         grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0;
154         grd_curscreen->sc_canvas.cv_bitmap.bm_w = w;
155         grd_curscreen->sc_canvas.cv_bitmap.bm_h = h;
156         grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = screen->pitch;
157         grd_curscreen->sc_canvas.cv_bitmap.bm_type = BM_LINEAR;
158         grd_curscreen->sc_canvas.cv_bitmap.bm_data = (unsigned char *)screen->pixels;
159         gr_set_current_canvas(NULL);
160         //gr_enable_default_palette_loading();
161
162 //added on 9/30/98 by Matt Mueller to hide the mouse if its over the game window
163         SDL_ShowCursor(0);
164 //end addition -MM
165 //--moved up--added on 9/30/98 by Matt Mueller to set the title bar.  Woohoo!
166 //--moved up--  SDL_WM_SetCaption(DESCENT_VERSION " " D1X_DATE, NULL);
167 //--moved up--end addition -MM
168
169 //      gamefont_choose_game_font(w,h);
170         return 0;
171 }
172
173 int gr_check_fullscreen(void){
174         return (sdl_video_flags & SDL_FULLSCREEN)?1:0;
175 }
176
177 int gr_toggle_fullscreen(void){
178         sdl_video_flags^=SDL_FULLSCREEN;
179 #if (SDL_COMPILEDVERSION < SDL_VERSIONNUM(1,0,5))
180         grd_curscreen->sc_mode=0;//hack to get it to reset screen mode
181 #else
182         SDL_WM_ToggleFullScreen(screen);
183 #endif
184         return (sdl_video_flags & SDL_FULLSCREEN)?1:0;
185 }
186
187 int gr_init(void)
188 {
189  int retcode;
190  int mode = MenuHires?SM(640,480):SM(320,200);
191         // Only do this function once!
192         if (gr_installed==1)
193                 return -1;
194
195         if (SDL_Init(SDL_INIT_VIDEO) < 0)
196         {
197                 Error("SDL library video initialisation failed: %s.",SDL_GetError());
198         }
199         MALLOC( grd_curscreen,grs_screen,1 );
200         memset( grd_curscreen, 0, sizeof(grs_screen));
201
202 //added 10/05/98 by Matt Mueller - make fullscreen mode optional
203         if (FindArg("-fullscreen"))
204              sdl_video_flags|=SDL_FULLSCREEN;
205 //end addition -MM
206         //added 05/19/99 Matt Mueller - make HW surface optional
207         if (FindArg("-hwsurface"))
208              sdl_video_flags|=SDL_HWSURFACE;
209         //end addition -MM
210         if (FindArg("-nosdlvidmodecheck"))
211                 checkvidmodeok=0;
212         
213         // Set the mode.
214         if ((retcode=gr_set_mode(mode)))
215         {
216                 return retcode;
217         }
218         grd_curscreen->sc_canvas.cv_color = 0;
219         grd_curscreen->sc_canvas.cv_drawmode = 0;
220         grd_curscreen->sc_canvas.cv_font = NULL;
221         grd_curscreen->sc_canvas.cv_font_fg_color = 0;
222         grd_curscreen->sc_canvas.cv_font_bg_color = 0;
223         gr_set_current_canvas( &grd_curscreen->sc_canvas );
224
225         gr_installed = 1;
226         // added on 980913 by adb to add cleanup
227         atexit(gr_close);
228         // end changes by adb
229
230         return 0;
231 }
232
233 void gr_close()
234 {
235         if (gr_installed==1)
236         {
237                 gr_installed = 0;
238                 d_free(grd_curscreen);
239         }
240 }
241
242 // Palette functions follow.
243
244 static int last_r=0, last_g=0, last_b=0;
245
246 void gr_palette_clear()
247 {
248  SDL_Palette *palette;
249  SDL_Color colors[256];
250  int ncolors;
251
252  palette = screen->format->palette;
253
254  if (palette == NULL) {
255     return; // Display is not palettised
256  }
257
258  ncolors = palette->ncolors;
259  memset(colors, 0, ncolors * sizeof(SDL_Color));
260
261  SDL_SetColors(screen, colors, 0, 256);
262
263  gr_palette_faded_out = 1;
264 }
265
266
267 void gr_palette_step_up( int r, int g, int b )
268 {
269  int i;
270  ubyte *p = gr_palette;
271  int temp;
272
273  SDL_Palette *palette;
274  SDL_Color colors[256];
275
276  if (gr_palette_faded_out) return;
277
278  if ( (r==last_r) && (g==last_g) && (b==last_b) ) return;
279
280  last_r = r;
281  last_g = g;
282  last_b = b;
283
284  palette = screen->format->palette;
285
286  if (palette == NULL) {
287     return; // Display is not palettised
288  }
289
290  for (i=0; i<256; i++) {
291    temp = (int)(*p++) + r + gr_palette_gamma;
292    if (temp<0) temp=0;
293    else if (temp>63) temp=63;
294    colors[i].r = temp * 4;
295    temp = (int)(*p++) + g + gr_palette_gamma;
296    if (temp<0) temp=0;
297    else if (temp>63) temp=63;
298    colors[i].g = temp * 4;
299    temp = (int)(*p++) + b + gr_palette_gamma;
300    if (temp<0) temp=0;
301    else if (temp>63) temp=63;
302    colors[i].b = temp * 4;
303  }
304
305  SDL_SetColors(screen, colors, 0, 256);
306 }
307
308 //added on 980913 by adb to fix palette problems
309 // need a min without side effects...
310 #undef min
311 static inline int min(int x, int y) { return x < y ? x : y; }
312 //end changes by adb
313
314 void gr_palette_load( ubyte *pal )      
315 {
316  int i, j;
317  SDL_Palette *palette;
318  SDL_Color colors[256];
319
320  for (i=0; i<768; i++ ) {
321      gr_current_pal[i] = pal[i];
322      if (gr_current_pal[i] > 63) gr_current_pal[i] = 63;
323  }
324
325  palette = screen->format->palette;
326
327  if (palette == NULL) {
328     return; // Display is not palettised
329  }
330
331  for (i = 0, j = 0; j < 256; j++) {
332      //changed on 980913 by adb to fix palette problems
333      colors[j].r = (min(gr_current_pal[i++] + gr_palette_gamma, 63)) * 4;
334      colors[j].g = (min(gr_current_pal[i++] + gr_palette_gamma, 63)) * 4;
335      colors[j].b = (min(gr_current_pal[i++] + gr_palette_gamma, 63)) * 4;
336      //end changes by adb
337  }
338  SDL_SetColors(screen, colors, 0, 256);
339
340  gr_palette_faded_out = 0;
341  init_computed_colors();
342 }
343
344
345
346 int gr_palette_fade_out(ubyte *pal, int nsteps, int allow_keys)
347 {
348  int i, j, k;
349  ubyte c;
350  fix fade_palette[768];
351  fix fade_palette_delta[768];
352
353  SDL_Palette *palette;
354  SDL_Color fade_colors[256];
355
356  if (gr_palette_faded_out) return 0;
357
358  palette = screen->format->palette;
359  if (palette == NULL) {
360     return -1; // Display is not palettised
361  }
362
363  if (pal==NULL) pal=gr_current_pal;
364
365  for (i=0; i<768; i++ ) {
366      gr_current_pal[i] = pal[i];
367      fade_palette[i] = i2f(pal[i]);
368      fade_palette_delta[i] = fade_palette[i] / nsteps;
369  }
370  for (j=0; j<nsteps; j++ )      {
371      for (i=0, k = 0; k<256; k++ )      {
372          fade_palette[i] -= fade_palette_delta[i];
373          if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma) )
374             fade_palette[i] = i2f(pal[i] + gr_palette_gamma);
375          c = f2i(fade_palette[i]);
376          if (c > 63) c = 63;
377          fade_colors[k].r = c * 4;
378          i++;
379
380          fade_palette[i] -= fade_palette_delta[i];
381          if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma) )
382             fade_palette[i] = i2f(pal[i] + gr_palette_gamma);
383          c = f2i(fade_palette[i]);
384          if (c > 63) c = 63;
385          fade_colors[k].g = c * 4;
386          i++;
387
388          fade_palette[i] -= fade_palette_delta[i];
389          if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma) )
390             fade_palette[i] = i2f(pal[i] + gr_palette_gamma);
391          c = f2i(fade_palette[i]);
392          if (c > 63) c = 63;
393          fade_colors[k].b = c * 4;
394          i++;
395      }
396
397   SDL_SetColors(screen, fade_colors, 0, 256);
398  }
399
400  gr_palette_faded_out = 1;
401  return 0;
402 }
403
404
405
406 int gr_palette_fade_in(ubyte *pal, int nsteps, int allow_keys)
407 {
408  int i, j, k, ncolors;
409  ubyte c;
410  fix fade_palette[768];
411  fix fade_palette_delta[768];
412
413  SDL_Palette *palette;
414  SDL_Color fade_colors[256];
415
416  if (!gr_palette_faded_out) return 0;
417
418  palette = screen->format->palette;
419
420  if (palette == NULL) {
421     return -1; // Display is not palettised
422  }
423
424  ncolors = palette->ncolors;
425
426  for (i=0; i<768; i++ ) {
427      gr_current_pal[i] = pal[i];
428      fade_palette[i] = 0;
429      fade_palette_delta[i] = i2f(pal[i]) / nsteps;
430  }
431
432  for (j=0; j<nsteps; j++ )      {
433      for (i=0, k = 0; k<256; k++ )      {
434          fade_palette[i] += fade_palette_delta[i];
435          if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma) )
436             fade_palette[i] = i2f(pal[i] + gr_palette_gamma);
437          c = f2i(fade_palette[i]);
438          if (c > 63) c = 63;
439          fade_colors[k].r = c * 4;
440          i++;
441
442          fade_palette[i] += fade_palette_delta[i];
443          if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma) )
444             fade_palette[i] = i2f(pal[i] + gr_palette_gamma);
445          c = f2i(fade_palette[i]);
446          if (c > 63) c = 63;
447          fade_colors[k].g = c * 4;
448          i++;
449
450          fade_palette[i] += fade_palette_delta[i];
451          if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma) )
452             fade_palette[i] = i2f(pal[i] + gr_palette_gamma);
453          c = f2i(fade_palette[i]);
454          if (c > 63) c = 63;
455          fade_colors[k].b = c * 4;
456          i++;
457      }
458
459   SDL_SetColors(screen, fade_colors, 0, 256);
460  }
461  //added on 980913 by adb to fix palette problems
462  gr_palette_load(pal);
463  //end changes by adb
464
465  gr_palette_faded_out = 0;
466  return 0;
467 }
468
469
470
471 void gr_palette_read(ubyte * pal)
472 {
473  SDL_Palette *palette;
474  int i, j;
475
476  palette = screen->format->palette;
477
478  if (palette == NULL) {
479     return; // Display is not palettised
480  }
481
482  for (i = 0, j=0; i < 256; i++) {
483      pal[j++] = palette->colors[i].r / 4;
484      pal[j++] = palette->colors[i].g / 4;
485      pal[j++] = palette->colors[i].b / 4;
486  }
487 }