]> icculus.org git repositories - btb/d2x.git/blob - arch/sdl/vid.c
Rename include/error.h to include/dxxerror.h
[btb/d2x.git] / arch / sdl / vid.c
1 /*
2  *
3  * SDL video functions.
4  *
5  *
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include <conf.h>
10 #endif
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <SDL.h>
15 #ifdef SDL_IMAGE
16 #include <SDL_image.h>
17 #endif
18
19 #include "gr.h"
20 #include "vid.h"
21 #include "u_mem.h"
22 #include "dxxerror.h"
23 #include "inferno.h"
24 #include "timer.h"
25 #include "args.h"
26
27
28 #ifdef _WIN32_WCE // should really be checking for "Pocket PC" somehow
29 # define LANDSCAPE
30 #endif
31
32 int sdl_video_flags = SDL_SWSURFACE | SDL_HWPALETTE;
33
34 SDL_Surface *screen;
35 #ifdef LANDSCAPE
36 static SDL_Surface *real_screen, *screen2;
37 #endif
38
39 int vid_installed = 0;
40
41 //added 05/19/99 Matt Mueller - locking stuff
42 #ifdef GR_LOCK
43
44 #include "checker.h"
45
46 #ifdef TEST_GR_LOCK
47 int gr_testlocklevel=0;
48 #endif
49
50 inline void gr_dolock(const char *file,int line)
51 {
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 )
58                         Error("could not lock screen (%s:%i)\n", file, line);
59         }
60 }
61
62
63 inline void gr_dounlock(void)
64 {
65         gr_dotestunlock();
66         if ( gr_testlocklevel == 0 && SDL_MUSTLOCK(screen) ) {
67                 SDL_UnlockSurface(screen);
68 #ifdef __CHECKER__
69                 chcksetunwritable(screen.pixels, screen->w * screen->h * screen->format->BytesPerPixel);
70 #endif
71         }
72 }
73
74 #endif
75 //end addition -MM
76
77
78 #ifdef LANDSCAPE
79
80 /* Create a new rotated surface for drawing */
81 SDL_Surface *CreateRotatedSurface(SDL_Surface *s)
82 {
83     return(SDL_CreateRGBSurface(s->flags, s->h, s->w, 8, 0, 0, 0, 0));
84 }
85
86 /* Used to copy the rotated scratch surface to the screen */
87 void BlitRotatedSurface(SDL_Surface *from, SDL_Surface *to)
88 {
89
90     int bpp = from->format->BytesPerPixel;
91     int w=from->w, h=from->h, pitch=to->pitch;
92     int i,j;
93     Uint8 *pfrom, *pto, *to0;
94
95     SDL_LockSurface(from);
96     SDL_LockSurface(to);
97     pfrom=(Uint8 *)from->pixels;
98     to0=(Uint8 *) to->pixels+pitch*(w-1);
99     for (i=0; i<h; i++)
100     {
101         to0+=bpp;
102         pto=to0;
103         for (j=0; j<w; j++)
104         {
105             if (bpp==1) *pto=*pfrom;
106             else if (bpp==2) *(Uint16 *)pto=*(Uint16 *)pfrom;
107             else if (bpp==4) *(Uint32 *)pto=*(Uint32 *)pfrom;
108             else if (bpp==3)
109                 {
110                     pto[0]=pfrom[0];
111                     pto[1]=pfrom[1];
112                     pto[2]=pfrom[2];
113                 }
114             pfrom+=bpp;
115             pto-=pitch;
116         }
117     }
118     SDL_UnlockSurface(from);
119     SDL_UnlockSurface(to);
120 }
121 #endif
122
123
124 void vid_update()
125 {
126 //      gr_testunlock();
127 #ifdef LANDSCAPE
128         screen2 = SDL_DisplayFormat(screen);
129         BlitRotatedSurface(screen2, real_screen);
130         //SDL_SetColors(real_screen, screen->format->palette->colors, 0, 256);
131         SDL_UpdateRect(real_screen, 0, 0, 0, 0);
132         SDL_FreeSurface(screen2);
133 #else
134         SDL_UpdateRect(screen, 0, 0, 0, 0);
135 #endif
136 }
137
138
139 int vid_check_mode(uint32_t mode)
140 {
141         int w, h;
142
143         w = SM_W(mode);
144         h = SM_H(mode);
145
146         return !SDL_VideoModeOK(w, h, 8, sdl_video_flags);
147 }
148
149
150 uint32_t Vid_current_mode;
151
152
153 int vid_set_mode(uint32_t mode)
154 {
155         int w, h;
156
157 #ifdef NOGRAPH
158         return 0;
159 #endif
160
161         if (!mode)
162                 return 0;
163
164         if (mode == Vid_current_mode)
165                 return 0;
166
167         w = SM_W(mode);
168         h = SM_H(mode);
169         Vid_current_mode = mode;
170         
171         if (screen != NULL)
172                 gr_palette_clear();
173
174         SDL_WM_SetCaption(PACKAGE_STRING, "Descent II");
175
176 #ifdef SDL_IMAGE
177         {
178 #include "descent.xpm"
179                 SDL_WM_SetIcon(IMG_ReadXPMFromArray(pixmap), NULL);
180         }
181 #endif
182
183 #ifdef LANDSCAPE
184         real_screen = SDL_SetVideoMode(h, w, 0, sdl_video_flags);
185         screen = CreateRotatedSurface(real_screen);
186 #else
187         screen = SDL_SetVideoMode(w, h, 8, sdl_video_flags);
188 #endif
189
190         if (screen == NULL)
191                 Error("Could not set %dx%dx8 video mode\n", w, h);
192
193         return gr_init_screen(BM_LINEAR, w, h, 0, 0, screen->pitch, (unsigned char *)screen->pixels);
194 }
195
196
197 int vid_check_fullscreen(void)
198 {
199         return (sdl_video_flags & SDL_FULLSCREEN)?1:0;
200 }
201
202
203 int vid_toggle_fullscreen(void)
204 {
205         sdl_video_flags ^= SDL_FULLSCREEN;
206         SDL_WM_ToggleFullScreen(screen);
207         return (sdl_video_flags & SDL_FULLSCREEN)?1:0;
208 }
209
210
211 int vid_init(void)
212 {
213         // Only do this function once!
214         if (vid_installed == 1)
215                 return -1;
216
217         if (SDL_Init(SDL_INIT_VIDEO) < 0)
218                 Error("SDL library video initialisation failed: %s.\n", SDL_GetError());
219
220         if (FindArg("-fullscreen"))
221              sdl_video_flags |= SDL_FULLSCREEN;
222
223         if (FindArg("-hwsurface"))
224              sdl_video_flags |= SDL_HWSURFACE;
225
226         vid_installed = 1;
227
228         atexit(vid_close);
229
230         return 0;
231 }
232
233
234 void vid_close(void)
235 {
236         if (vid_installed == 1)
237                 vid_installed = 0;
238 }
239
240
241 // Palette functions follow.
242
243 static int last_r = 0, last_g = 0, last_b = 0;
244
245
246 void gr_palette_clear(void)
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         ncolors = palette->ncolors;
258         memset(colors, 0, ncolors * sizeof(SDL_Color));
259
260         SDL_SetColors(screen, colors, 0, 256);
261
262         gr_palette_faded_out = 1;
263 }
264
265
266 void gr_palette_step_up( int r, int g, int b )
267 {
268         int i;
269         ubyte *p = gr_palette;
270         int temp;
271
272         SDL_Palette *palette;
273         SDL_Color colors[256];
274
275         if (gr_palette_faded_out)
276                 return;
277
278         if ( (r == last_r) && (g == last_g) && (b == last_b) )
279                 return;
280
281         last_r = r;
282         last_g = g;
283         last_b = b;
284
285         palette = screen->format->palette;
286
287         if (palette == NULL)
288                 return; // Display is not palettised
289
290         for (i = 0; i < 256; i++) {
291                 temp = (int)(*p++) + r + gr_palette_gamma.intval;
292                 if (temp < 0) temp = 0;
293                 else if (temp > 63) temp = 63;
294                 colors[i].r = temp * 4;
295
296                 temp = (int)(*p++) + g + gr_palette_gamma.intval;
297                 if (temp < 0) temp = 0;
298                 else if (temp > 63) temp = 63;
299                 colors[i].g = temp * 4;
300
301                 temp = (int)(*p++) + b + gr_palette_gamma.intval;
302                 if (temp < 0) temp = 0;
303                 else if (temp > 63) temp = 63;
304                 colors[i].b = temp * 4;
305         }
306
307         SDL_SetColors(screen, colors, 0, 256);
308 }
309
310
311 // need a min without side effects...
312 #undef min
313 static inline int min(int x, int y) { return x < y ? x : y; }
314
315
316 void gr_palette_load( ubyte *pal )      
317 {
318         int i, j;
319         SDL_Palette *palette;
320         SDL_Color colors[256];
321
322         for (i = 0; i < 768; i++) {
323                 gr_current_pal[i] = pal[i];
324                 if (gr_current_pal[i] > 63)
325                         gr_current_pal[i] = 63;
326         }
327
328         palette = screen->format->palette;
329
330         if (palette == NULL)
331                 return; // Display is not palettised
332
333         for (i = 0, j = 0; j < 256; j++) {
334                 colors[j].r = min(gr_current_pal[i++] + gr_palette_gamma.intval, 63) * 4;
335                 colors[j].g = min(gr_current_pal[i++] + gr_palette_gamma.intval, 63) * 4;
336                 colors[j].b = min(gr_current_pal[i++] + gr_palette_gamma.intval, 63) * 4;
337         }
338
339         SDL_SetColors(screen, colors, 0, 256);
340
341         gr_palette_faded_out = 0;
342         init_computed_colors();
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)
357                 return 0;
358
359 #if 1 //ifndef NDEBUG
360         if (grd_fades_disabled) {
361                 gr_palette_clear();
362                 return 0;
363         }
364 #endif
365
366         palette = screen->format->palette;
367         if (palette == NULL)
368                 return -1; // Display is not palettised
369
370         if (pal == NULL)
371                 pal = gr_current_pal;
372
373         for (i = 0; i < 768; i++) {
374                 gr_current_pal[i] = pal[i];
375                 fade_palette[i] = i2f(pal[i]);
376                 fade_palette_delta[i] = fade_palette[i] / nsteps;
377         }
378
379         for (j = 0; j < nsteps; j++) {
380                 for (i = 0, k = 0; k < 256; k++) {
381                         fade_palette[i] -= fade_palette_delta[i];
382                         if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma.intval))
383                                 fade_palette[i] = i2f(pal[i] + gr_palette_gamma.intval);
384                         c = f2i(fade_palette[i]);
385                         if (c > 63) c = 63;
386                         fade_colors[k].r = c * 4;
387                         i++;
388
389                         fade_palette[i] -= fade_palette_delta[i];
390                         if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma.intval))
391                                 fade_palette[i] = i2f(pal[i] + gr_palette_gamma.intval);
392                         c = f2i(fade_palette[i]);
393                         if (c > 63) c = 63;
394                         fade_colors[k].g = c * 4;
395                         i++;
396
397                         fade_palette[i] -= fade_palette_delta[i];
398                         if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma.intval))
399                                 fade_palette[i] = i2f(pal[i] + gr_palette_gamma.intval);
400                         c = f2i(fade_palette[i]);
401                         if (c > 63) c = 63;
402                         fade_colors[k].b = c * 4;
403                         i++;
404                 }
405
406                 SDL_SetColors(screen, fade_colors, 0, 256);
407         }
408
409         gr_palette_faded_out = 1;
410
411         SDL_FillRect(screen, NULL, 0);
412
413         return 0;
414 }
415
416
417 int gr_palette_fade_in(ubyte *pal, int nsteps, int allow_keys)
418 {
419         int i, j, k, ncolors;
420         ubyte c;
421         fix fade_palette[768];
422         fix fade_palette_delta[768];
423
424         SDL_Palette *palette;
425         SDL_Color fade_colors[256];
426
427         if (!gr_palette_faded_out)
428                 return 0;
429
430 #if 1 //ifndef NDEBUG
431         if (grd_fades_disabled) {
432                 gr_palette_load(pal);
433                 return 0;
434         }
435 #endif
436
437         palette = screen->format->palette;
438
439         if (palette == NULL)
440     return -1; // Display is not palettised
441
442         ncolors = palette->ncolors;
443
444         for (i = 0; i < 768; i++) {
445                 gr_current_pal[i] = pal[i];
446                 fade_palette[i] = 0;
447                 fade_palette_delta[i] = i2f(pal[i]) / nsteps;
448         }
449
450         for (j = 0; j < nsteps; j++) {
451                 for (i = 0, k = 0; k < 256; k++) {
452                         fade_palette[i] += fade_palette_delta[i];
453                         if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma.intval))
454                                 fade_palette[i] = i2f(pal[i] + gr_palette_gamma.intval);
455                         c = f2i(fade_palette[i]);
456                         if (c > 63) c = 63;
457                         fade_colors[k].r = c * 4;
458                         i++;
459
460                         fade_palette[i] += fade_palette_delta[i];
461                         if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma.intval))
462                                 fade_palette[i] = i2f(pal[i] + gr_palette_gamma.intval);
463                         c = f2i(fade_palette[i]);
464                         if (c > 63) c = 63;
465                         fade_colors[k].g = c * 4;
466                         i++;
467
468                         fade_palette[i] += fade_palette_delta[i];
469                         if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma.intval))
470                                 fade_palette[i] = i2f(pal[i] + gr_palette_gamma.intval);
471                         c = f2i(fade_palette[i]);
472                         if (c > 63) c = 63;
473                         fade_colors[k].b = c * 4;
474                         i++;
475                 }
476
477         SDL_SetColors(screen, fade_colors, 0, 256);
478         }
479
480         gr_palette_load(pal);
481
482         gr_palette_faded_out = 0;
483
484         return 0;
485 }
486
487
488
489 void gr_palette_read(ubyte * pal)
490 {
491         SDL_Palette *palette;
492         int i, j;
493
494         palette = screen->format->palette;
495
496         if (palette == NULL)
497                 return; // Display is not palettised
498
499         for (i = 0, j=0; i < 256; i++) {
500                 pal[j++] = palette->colors[i].r / 4;
501                 pal[j++] = palette->colors[i].g / 4;
502                 pal[j++] = palette->colors[i].b / 4;
503         }
504 }