1 /*
2  * Triplane Classic - a side-scrolling dogfighting game.
3  * Copyright (C) 1996,1997,2009  Dodekaedron Software Creations Oy
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * tjt@users.sourceforge.net
19  */
20 
21 #include <SDL.h>
22 #include <ctype.h>
23 
24 #ifdef HAVE_SDL_MIXER
25 /*
26  * SDL_mixer version 1.2.6 requires USE_RWOPS for Mix_LoadMUS_RW
27  * (1.2.7 and later do not require it)
28  */
29 #define USE_RWOPS
30 #include <SDL_mixer.h>
31 #endif
32 
33 #include <assert.h>
34 #include "sdl_compat.h"
35 #include "io/dksfile.h"
36 #include "util/wutil.h"
37 #include "io/timing.h"
38 
kbhit(void)39 int kbhit(void) {
40     SDL_Event e;
41     int ret;
42 
43     nopeuskontrolli();
44 
45     ret = SDL_PeepEvents(&e, 1, SDL_PEEKEVENT, ~0);
46     if (ret) {
47         if (e.type == SDL_KEYUP) {
48             return 1;
49         } else {
50             SDL_PollEvent(&e);
51         }
52     }
53     return 0;
54 }
55 
getch(void)56 int getch(void) {
57     SDL_Event e;
58 
59     for (;;) {
60         if (SDL_PollEvent(&e)) {
61             if (e.type == SDL_KEYUP) {
62                 int s, m;
63                 s = e.key.keysym.sym;
64                 m = e.key.keysym.mod;
65                 if (s == SDLK_RSHIFT || s == SDLK_LSHIFT) {
66                     continue;
67                 }
68                 if (m == KMOD_LSHIFT || m == KMOD_RSHIFT) {
69                     if (s >= SDLK_a && s <= SDLK_z) {
70                         s = toupper(s);
71                     }
72                 }
73                 return s;
74             }
75         }
76     }
77 }
78 
update_key_state(void)79 void update_key_state(void) {
80     SDL_Event e;
81     SDL_PumpEvents();
82     while (SDL_PollEvent(&e)) {
83         ;
84     }
85 }
86 
87 /**
88  * Initialize SDL sounds so that sdl_play_sample can be called.
89  * @return 0 on success, nonzero otherwise.
90  */
sdl_init_sounds(void)91 int sdl_init_sounds(void) {
92 #ifdef HAVE_SDL_MIXER
93     int ret;
94 
95     ret = SDL_InitSubSystem(SDL_INIT_AUDIO);
96     if (ret != 0)
97         return 1;
98 
99     /*
100      * use a 4096 byte buffer:
101      * 44100*2*2 bytes/sec / 4096 bytes = about 1/43 seconds
102      */
103     ret = Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 4096);
104     if (ret < 0)
105         return 1;
106     Mix_AllocateChannels(16);   /* max. 16 simultaneous samples */
107     return 0;
108 #else
109     printf("This version of triplane has been compiled without sound support.\n");
110     return 1;
111 #endif
112 }
113 
114 /** Deinitalize SDL sounds */
sdl_uninit_sounds(void)115 void sdl_uninit_sounds(void) {
116 #ifdef HAVE_SDL_MIXER
117     Mix_CloseAudio();
118     SDL_QuitSubSystem(SDL_INIT_AUDIO);
119 #endif
120 }
121 
122 /**
123  * Play sample.
124  * @param sample sample loaded with sdl_load_sample.
125  */
sdl_play_sample(sb_sample * sample,int looping)126 void sdl_play_sample(sb_sample * sample, int looping) {
127 #ifdef HAVE_SDL_MIXER
128     /* scale of left_volume and right_volume is [0..32] */
129     /* SDL_SetPanning wants [0..255] */
130     int ch, l = sample->left_volume * 8, r = sample->right_volume * 8;
131     if (l > 0)
132         l--;
133     if (r > 0)
134         r--;
135     ch = Mix_PlayChannel(-1, sample->chunk, looping ? -1 : 0);
136     if (ch == -1) {             /* no free channels (or possibly another error) */
137         return;                 /* ignore the error, so this sound won't be played */
138     }
139 
140     Mix_SetPanning(ch, l, r);
141 #endif
142 }
143 
144 /** Stop playing all samples started with sdl_play_sample */
sdl_stop_all_samples(void)145 void sdl_stop_all_samples(void) {
146 #ifdef HAVE_SDL_MIXER
147     Mix_HaltChannel(-1);
148 #endif
149 }
150 
151 /**
152  * Load sample with given name.
153  * @param name audio name used inside fokker.dks
154  * @return loaded sample or NULL on error.
155  */
sdl_sample_load(const char * name)156 sb_sample *sdl_sample_load(const char *name) {
157 #ifdef HAVE_SDL_MIXER
158     int len, ret;
159     uint8_t *p;
160     sb_sample *sample;
161 
162     ret = dksopen(name);
163     if (ret != 1) {
164         return NULL;
165     }
166 
167     len = dkssize();
168     p = (uint8_t *) walloc(len);
169 
170     ret = dksread(p, len);
171     assert(ret == 1);
172 
173     dksclose();
174 
175     sample = (sb_sample *) walloc(sizeof(sb_sample));
176 
177     sample->chunk = Mix_LoadWAV_RW(SDL_RWFromConstMem(p, len), 1);
178     if (sample->chunk == NULL) {
179         fprintf(stderr, "sdl_sample_load: %s\n", Mix_GetError());
180         exit(1);
181     }
182 
183     free(p);
184 
185     return sample;
186 #else
187     return NULL;
188 #endif
189 }
190 
191 /**
192  * Free sample loaded using sdl_sample_load.
193  * @param sample to be free'd.
194  */
sdl_free_sample(sb_sample * sample)195 void sdl_free_sample(sb_sample * sample) {
196 #ifdef HAVE_SDL_MIXER
197     Mix_FreeChunk(sample->chunk);
198     free(sample);
199 #endif
200 }
201 
sdl_load_mod_file(const char * name)202 sb_mod_file *sdl_load_mod_file(const char *name) {
203 #ifdef HAVE_SDL_MIXER
204     int len, ret;
205     uint8_t *p;
206     sb_mod_file *mod;
207     SDL_RWops *rwops;
208 
209     ret = dksopen(name);
210     if (ret != 1) {
211         return NULL;
212     }
213 
214     len = dkssize();
215     p = (uint8_t *) walloc(len);
216 
217     ret = dksread(p, len);
218     assert(ret == 1);
219 
220     dksclose();
221 
222     mod = (sb_mod_file *) walloc(sizeof(sb_mod_file));
223 
224     rwops = SDL_RWFromConstMem(p, len);
225     mod->music = Mix_LoadMUS_RW(rwops);
226     SDL_FreeRW(rwops);
227     if (mod->music == NULL) {
228         fprintf(stderr, "sdl_load_mod_file: %s\n", Mix_GetError());
229         exit(1);
230     }
231 
232     free(p);
233 
234     return mod;
235 #else
236     return NULL;
237 #endif
238 }
239 
sdl_free_mod_file(sb_mod_file * mod)240 void sdl_free_mod_file(sb_mod_file * mod) {
241 #ifdef HAVE_SDL_MIXER
242     Mix_FreeMusic(mod->music);
243     free(mod);
244 #endif
245 }
246 
sdl_play_music(sb_mod_file * mod)247 void sdl_play_music(sb_mod_file * mod) {
248 #ifdef HAVE_SDL_MIXER
249     sdl_stop_all_samples();
250     Mix_PlayMusic(mod->music, 1);
251 #endif
252 }
253 
sdl_stop_music(void)254 void sdl_stop_music(void) {
255 #ifdef HAVE_SDL_MIXER
256     Mix_HaltMusic();
257 #endif
258 }
259