1 /*------------------------------------------------------------------.
2 | Copyright 1997, 1998, 2000, 2001, 2002  Alexandre Duret-Lutz      |
3 |                                          <duret_g@epita.fr>       |
4 |                                                                   |
5 | This file is part of Heroes.                                      |
6 |                                                                   |
7 | Heroes is free software; you can redistribute it and/or modify it |
8 | under the terms of the GNU General Public License version 2 as    |
9 | published by the Free Software Foundation.                        |
10 |                                                                   |
11 | Heroes is distributed in the hope that it will be useful, but     |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of        |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU |
14 | General Public License for more details.                          |
15 |                                                                   |
16 | You should have received a copy of the GNU General Public License |
17 | along with this program; if not, write to the Free Software       |
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA          |
19 | 02111-1307 USA                                                    |
20 `------------------------------------------------------------------*/
21 
22 #include "system.h"
23 #include <SDL.h>
24 #include "video_low.h"
25 #include "debugmsg.h"
26 #include "errors.h"
27 #include "misc.h"
28 #include "argv.h"
29 #include "cast.h"
30 
31 static a_pixel *screen_rv = 0;	/* A pointer to the screen buffer associated
32 				   to the render visual. */
33 static int scr_w, scr_h;	/* rendering buffer width and height */
34 static int scr_stretch;
35 
36 /* screen_rv may be a direct pointer to the hardware video buffer, or
37    it may be a pointer to system (mallocated) memory, this depends on
38    the display driver (if the videomode were available or needed to be
39    emulated etc.).  If screen_rv points directly to hardware video
40    it might requires locking. */
41 
42 static SDL_Surface *visu = 0;
43 static int visu_options = SDL_HWPALETTE | SDL_DOUBLEBUF;
44 static bool SDL_initialized = false;
45 #define SDL_VIDEODRIVER "SDL_VIDEODRIVER"
46 static char *sdl_videodriver = 0;
47 
48 void
set_display_params(const char * str)49 set_display_params (const char *str)
50 {
51   sdl_videodriver = strcat_alloc (SDL_VIDEODRIVER "=", str);
52   dmsg (D_SYSTEM | D_VIDEO, "put `%s' in environment", sdl_videodriver);
53   putenv (sdl_videodriver);
54 }
55 
56 void
set_full_screen_mode(void)57 set_full_screen_mode (void)
58 {
59   visu_options |= SDL_FULLSCREEN;
60 }
61 
62 /* Fullscreen mode is toggeled by pressing Alt+Enter.
63    Thanks to Sam Lantinga */
64 static int
Handle_AltEnter(const SDL_Event * event)65 Handle_AltEnter (const SDL_Event *event)
66 {
67   if (event->type == SDL_KEYDOWN
68       && event->key.keysym.sym == SDLK_RETURN
69       && event->key.keysym.mod & KMOD_ALT) {
70     SDL_WM_ToggleFullScreen (SDL_GetVideoSurface ());
71     return 0;
72   }
73   return 1;
74 }
75 
76 /* init the SDL library, this can be called from joystick.c
77    or from init_video() */
78 void init_SDL (void);
79 void
init_SDL(void)80 init_SDL (void)
81 {
82   if (SDL_initialized)
83     return;
84   dmsg (D_SYSTEM | D_VIDEO | D_JOYSTICK | D_SOUND_TRACK | D_SOUND_EFFECT,
85 	"initialize SDL");
86   SDL_Init (SDL_INIT_VIDEO
87 #ifdef HAVE_LIBSDL_MIXER
88 	    | ((nosfx && nosound) ? 0 : SDL_INIT_AUDIO)
89 #endif
90 #ifdef HAVE_SDL_JOYSTICKOPEN
91 	    | (joyoff ? 0 : SDL_INIT_JOYSTICK)
92 #endif
93 #ifdef DEBUG
94 	    | SDL_INIT_NOPARACHUTE
95 #endif
96 	    );
97 
98   SDL_SetEventFilter(Handle_AltEnter);
99   SDL_initialized = true;
100 }
101 
102 void
init_video_low(int stretch_,int * pitch)103 init_video_low (int stretch_, int *pitch)
104 {
105   scr_stretch = stretch_;
106   scr_w = 320 * scr_stretch;
107   scr_h = 200 * scr_stretch;
108 
109   init_SDL ();
110   dmsg (D_VIDEO, "set video mode");
111   visu = SDL_SetVideoMode (scr_w, scr_h, 8, visu_options);
112   /* FIXME: the Linux/m68k binary is crashing in the vicinity */
113   if (!visu)
114     emsg (_("Failed to open visual: %s"), SDL_GetError());
115 
116   if (SDL_MUSTLOCK (visu))
117     dmsg (D_VIDEO, "visual require locking");
118   else
119     screen_rv = visu->pixels;
120 
121   *pitch = visu->pitch;
122 
123   dmsg (D_VIDEO, "set misc. video parameters");
124 
125   SDL_ShowCursor (0);
126   SDL_WM_SetCaption ("Heroes " VERSION,"Heroes");
127 
128   /* setup event processing rules.
129      FIXME: this does not really belong to display.c
130      it should rather go to keyb.c */
131   SDL_EventState ((Uint8) SDL_ALLEVENTS, SDL_IGNORE);
132   SDL_EventState (SDL_KEYDOWN, SDL_ENABLE);
133   SDL_EventState (SDL_KEYUP, SDL_ENABLE);
134   SDL_EventState (SDL_QUIT, SDL_ENABLE);
135 #ifdef HAVE_SDL_ENABLEKEYREPEAT
136   SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
137 #endif
138 }
139 
140 void
uninit_video_low(void)141 uninit_video_low (void)
142 {
143   dmsg (D_MISC, "free screen buffer");
144 
145   if (SDL_initialized) {
146     SDL_Quit ();
147     SDL_initialized = false;
148   }
149   if (sdl_videodriver) {
150     putenv (const_cast_string (SDL_VIDEODRIVER));
151     XFREE0 (sdl_videodriver);
152   }
153 }
154 
155 void
set_pal_entry(unsigned char c,unsigned char r,unsigned char g,unsigned char b)156 set_pal_entry (unsigned char c,
157 	       unsigned char r, unsigned char g, unsigned char b)
158 {
159   SDL_Color col;
160   col.r = r * 4;
161   col.g = g * 4;
162   col.b = b * 4;
163   dmsg (D_VIDEO, "set color %d=(%d,%d,%d)", c, r, g, b);
164   SDL_SetColors (visu, &col, c, 1);
165 }
166 
167 void
set_pal(const unsigned char * ptr,int p,int n)168 set_pal (const unsigned char *ptr, int p, int n)
169 {
170   signed i;
171 
172   SDL_Color cmap[256];
173   for (i = 0; i < 256; ++i) {
174     cmap[i].r = *ptr++ * 4;
175     cmap[i].g = *ptr++ * 4;
176     cmap[i].b = *ptr++ * 4;
177   }
178   dmsg (D_VIDEO, "set %d colors", n/3);
179   SDL_SetColors (visu, cmap, p/3, n/3);
180 }
181 
182 void
vsynchro_low(const a_pixel * s,a_copy_function f)183 vsynchro_low (const a_pixel *s, a_copy_function f)
184 {
185   if (SDL_MUSTLOCK (visu))
186     SDL_LockSurface (visu);
187 
188   screen_rv = visu->pixels;
189   f (s, screen_rv, 320);
190 
191   if (SDL_MUSTLOCK (visu))
192     SDL_UnlockSurface (visu);
193 
194   SDL_Flip (visu);		/* can change visu->pixels */
195 }
196 
197 void
vsynchro2_low(const a_pixel * s1,const a_pixel * s2,a_copy_function f)198 vsynchro2_low (const a_pixel *s1, const a_pixel *s2, a_copy_function f)
199 {
200   if (SDL_MUSTLOCK (visu))
201     SDL_LockSurface (visu);
202 
203   screen_rv = visu->pixels;
204   f (s1, screen_rv, 160);
205   f (s2, screen_rv + 160 * scr_stretch, 160);
206 
207   if (SDL_MUSTLOCK (visu))
208     SDL_UnlockSurface (visu);
209 
210   SDL_Flip (visu);		/* can change visu->pixels */
211 }
212