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