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