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